cignium-hypermedia-client
Advanced tools
Comparing version 1.13.1 to 1.14.0
@@ -56,3 +56,3 @@ { | ||
}, | ||
"version": "1.13.1" | ||
"version": "1.14.0" | ||
} |
@@ -51,3 +51,3 @@ # Cignium Hypermedia Client | ||
There are two methods available on the global `Cignium` object: `init` and `navigate`. | ||
There are four methods available on the global `Cignium` object: `init`, `navigate`, `get` and `set`. | ||
@@ -61,2 +61,11 @@ **Init** accepts two parameters, `element` and `configuration` | ||
**Get** (without parameters) returns an object representation of all the fields in the current form. | ||
**Get** (with `path` parameter) returns the value of a property | ||
* **Path**: string array that describes the path to a property | ||
**Set** sets the value of a property | ||
* **Path**: string array that describes the path to a property | ||
+ **Value**: new value of the property | ||
### Declaratively | ||
@@ -91,4 +100,6 @@ | ||
| `data-endpoint` | `endpoint` | string | Specifies the starting point of the API that should be rendered. | | ||
| `data-action-list-position` | `actionListPosition` | string | Specifies the position of the action buttons. Accepted values are: `top` (default), `bottom` and `both`. | | ||
| | `onValueChange` | function | Callback function executed after a value has been updated. The callback receives 2 parameters: `id` (of the updated element) and `value` (after the change). | | ||
| | `onUrlChange` | function | Callback function executed after the url has changed. Receives 1 parameter: `url` (after the navigation). | | ||
| | `onRedirect` | function | Callback function executed when the client will attempt a redirect. Receives 2 parameters: `url` (where the client would normally redirect) and `content` (of that url). If the function exists, the client will NOT automatically redirect. Optional return value: `{ title, content }`. | | ||
@@ -112,2 +123,3 @@ ### Styling | ||
* ct-document-header-text | ||
* ct-document-footer | ||
* ct-activity-indicator | ||
@@ -114,0 +126,0 @@ * ct-section |
const mediaType = 'application/vnd.cignium.resource+json' | ||
export async function request(method, href, data) { | ||
export async function request(method, href, data, config) { | ||
const request = { | ||
@@ -19,2 +19,12 @@ body: data && JSON.stringify(data), | ||
if (config && config.onRedirect) { | ||
let content = await response.text() | ||
content = config.onRedirect(response.url, content) | ||
if (content) { | ||
content.type = 'html' | ||
content.links = [{ rel: 'self', href: response.url }] | ||
} | ||
return content | ||
} | ||
location.href = response.url | ||
@@ -21,0 +31,0 @@ |
@@ -33,7 +33,9 @@ import { request } from './http' | ||
async function processRequest({ data, href, id, method, resourceKey, onDone }) { | ||
async function processRequest({ data, href, id, method, resourceKey, name, config }) { | ||
try { | ||
const response = await request(method, href, data) | ||
const response = await request(method, href, data, config) | ||
onDone && onDone() | ||
if (config && config.onValueChange && data) { | ||
config.onValueChange(name, data[Object.keys(data)[0]]) | ||
} | ||
@@ -83,8 +85,8 @@ if (response == null) { | ||
export function executeAction(href) { | ||
requestResource({ href, method: 'post', resourceKey: 'current' }) | ||
export function executeAction(href, config) { | ||
requestResource({ href, method: 'post', resourceKey: 'current', config }) | ||
} | ||
export function navigate(href) { | ||
requestResource({ href, method: 'get', resourceKey: 'current' }) | ||
export function navigate(href, config) { | ||
requestResource({ href, method: 'get', resourceKey: 'current', config }) | ||
} | ||
@@ -99,3 +101,5 @@ | ||
method: 'post', | ||
onDone: config.onValueChange.bind(null, name, value)}) | ||
name, | ||
config, | ||
}) | ||
} | ||
@@ -102,0 +106,0 @@ else if (links.submit) { |
@@ -11,7 +11,9 @@ import { Component } from 'react' | ||
export default class Document extends Component { | ||
componentDidUpdate(prevProps, prevState) { | ||
const prev = getHref(prevProps.resource) | ||
const curr = getHref(this.props.resource) | ||
if (prev !== curr) { | ||
this.props.config.onUrlChange(curr) | ||
componentDidUpdate(previousProps, previousState) { | ||
if (this.props.config.onUrlChange) { | ||
const previous = getHref(previousProps.resource) | ||
const current = getHref(this.props.resource) | ||
if (previous !== current) { | ||
this.props.config.onUrlChange(current) | ||
} | ||
} | ||
@@ -27,2 +29,8 @@ } | ||
const Element = factory(resource) | ||
const actions = <ActionList links={resource.links} config={config} /> | ||
const footer = config.actionListPosition !== 'top' && ( | ||
<div className='ct-document-footer'> | ||
{actions} | ||
</div> | ||
) | ||
@@ -35,5 +43,6 @@ return ( | ||
</div> | ||
<ActionList links={resource.links} /> | ||
{config.actionListPosition !== 'bottom' && actions} | ||
</div> | ||
<Element property={resource} config={config} topLevel /> | ||
{footer} | ||
<JsonDebugger resource={resource} /> | ||
@@ -40,0 +49,0 @@ </div> |
import { executeAction, submit } from '../../api' | ||
export default ({ links }) => ( | ||
export default ({ links, config }) => ( | ||
<div className='ct-action-list'> | ||
@@ -10,3 +10,3 @@ {links.actions.map(action => { | ||
key={action.href} | ||
onClick={() => executeAction(action.href)}> | ||
onClick={() => executeAction(action.href, config)}> | ||
{action.title} | ||
@@ -13,0 +13,0 @@ </button> |
import { render } from 'react-dom' | ||
import { navigate } from './api' | ||
import { navigate, update } from './api' | ||
import App from './app' | ||
import OptionsParser from './api/options-parser' | ||
import state from './state' | ||
import '../themes/default/app.css' | ||
@@ -15,7 +16,15 @@ | ||
} | ||
if (typeof options.onValueChange !== 'function') { | ||
options.onValueChange = () => {} | ||
else { | ||
if (typeof options.onValueChange !== 'function') { | ||
delete options.onValueChange | ||
} | ||
if (typeof options.onUrlChange !== 'function') { | ||
delete options.onUrlChange | ||
} | ||
if (typeof options.onRedirect !== 'function') { | ||
delete options.onRedirect | ||
} | ||
} | ||
if (typeof options.onUrlChange !== 'function') { | ||
options.onUrlChange = () => {} | ||
if (['top', 'bottom', 'both'].indexOf(options.actionListPosition) < 0) { | ||
options.actionListPosition = 'top' | ||
} | ||
@@ -26,6 +35,70 @@ | ||
if (options.endpoint) { | ||
navigate(options.endpoint) | ||
navigate(options.endpoint, options) | ||
} | ||
} | ||
function _get(data) { | ||
const obj = {} | ||
data.properties.forEach(p => { | ||
switch (p.type) { | ||
case 'html': | ||
case 'plain': | ||
obj[p.name] = p.content | ||
break | ||
case 'object': | ||
obj[p.name] = _get(p) | ||
break | ||
case 'array' : | ||
obj[p.name] = p.items.map(_get) | ||
break | ||
default: | ||
obj[p.name] = p.value | ||
break | ||
} | ||
}) | ||
return obj | ||
} | ||
function _getProperty(data, path) { | ||
path.forEach(step => { | ||
switch (data.type) { | ||
case 'object': | ||
data = data.properties.find(p => p.name === step) | ||
break | ||
case 'array' : | ||
data = data.items[step] | ||
break | ||
default: | ||
throw Error(`Property '${data.name}' can not contain properties`) | ||
} | ||
if (!data) { | ||
throw Error(`Property '${step}' does not exist`) | ||
} | ||
}) | ||
return data | ||
} | ||
function get(path) { | ||
let data = state.get().resources | ||
data = data[data.current] | ||
if (path) { | ||
return _getProperty(data, path).value | ||
} | ||
return _get(data, path) | ||
} | ||
function set(path, value) { | ||
let data = state.get().resources | ||
data = data[data.current] | ||
const property = _getProperty(data, path) | ||
if (property.value !== value) { | ||
update(property.links, property.id, value, property.name) | ||
} | ||
} | ||
document.addEventListener('DOMContentLoaded', () => { | ||
@@ -41,2 +114,4 @@ const element = document.querySelector('[data-endpoint]') | ||
navigate, | ||
get, | ||
set, | ||
} |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
536133
2855
150