1 import { Action } from '../../../../framework/src/flux/action';
2 import { Dispatch } from '../../../../framework/src/flux/store';
3 import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
4 import { PushAction, ReplaceAction } from '../../../../framework/src/actions/navigationActions';
5 import { AddErrorInfoAction } from '../../../../framework/src/actions/errorActions';
7 import { DisplayModeType, DisplaySpecification } from '../handlers/viewDescriptionHandler';
9 import { restService } from '../services/restServices';
10 import { YangParser } from '../yang/yangParser';
11 import { Module } from '../models/yang';
15 isViewElementReference,
18 } from '../models/uiModels';
25 getReferencedDataList,
26 resolveViewDescription,
28 } from '../utilities/viewEngineHelper';
30 export class EnableValueSelector extends Action {
31 constructor(public listSpecification: ViewSpecification, public listData: any[], public keyProperty: string, public onValueSelected : (value: any) => void ) {
36 export class SetCollectingSelectionData extends Action {
37 constructor(public busy: boolean) {
42 export class SetSelectedValue extends Action {
43 constructor(public value: any) {
48 export class UpdateDeviceDescription extends Action {
49 constructor( public nodeId: string, public modules: { [name:string]: Module }, public views: ViewSpecification[]) {
54 export class UpdateViewDescription extends Action {
55 constructor(public vPath: string, public viewData: any, public displaySpecification: DisplaySpecification = { displayMode: DisplayModeType.doNotDisplay }) {
60 export class UpdateOutputData extends Action {
61 constructor(public outputData: any) {
66 export class UpdateNewData extends Action {
67 constructor(public newData: any) {
72 export const updateNodeIdAsyncActionCreator = (nodeId: string) => async (dispatch: Dispatch, _getState: () => IApplicationStoreState ) => {
74 dispatch(new UpdateDeviceDescription('', {}, []));
75 dispatch(new SetCollectingSelectionData(true));
77 const { availableCapabilities, unavailableCapabilities, importOnlyModules } = await restService.getCapabilitiesByMountId(nodeId);
79 if (!availableCapabilities || availableCapabilities.length <= 0) {
80 dispatch(new SetCollectingSelectionData(false));
81 dispatch(new UpdateDeviceDescription(nodeId, {}, []));
82 dispatch(new UpdateViewDescription('', [], {
83 displayMode: DisplayModeType.displayAsMessage,
84 renderMessage: `NetworkElement : "${nodeId}" has no capabilities.`,
86 throw new Error(`NetworkElement : [${nodeId}] has no capabilities.`);
89 const parser = new YangParser(
91 availableCapabilities.reduce((acc, cur) => {
92 acc[cur.capability] = cur.version;
94 }, {} as { [key: string]: string }),
95 unavailableCapabilities || undefined,
96 importOnlyModules || undefined,
99 for (let i = 0; i < availableCapabilities.length; ++i) {
100 const capRaw = availableCapabilities[i];
102 await parser.addCapability(capRaw.capability, capRaw.version);
104 console.error(`Error in ${capRaw.capability} ${capRaw.version}`, err);
108 parser.postProcess();
110 dispatch(new SetCollectingSelectionData(false));
112 if (process.env.NODE_ENV === 'development' ) {
113 console.log(parser, parser.modules, parser.views);
116 return dispatch(new UpdateDeviceDescription(nodeId, parser.modules, parser.views));
119 export const postProcessDisplaySpecificationActionCreator = (vPath: string, viewData: any, displaySpecification: DisplaySpecification) => async (dispatch: Dispatch, _getState: () => IApplicationStoreState) => {
121 if (displaySpecification.displayMode === DisplayModeType.displayAsObject) {
122 displaySpecification = {
123 ...displaySpecification,
124 viewSpecification: await filterViewElements(vPath, viewData, displaySpecification.viewSpecification),
128 dispatch(new UpdateViewDescription(vPath, viewData, displaySpecification));
131 export const updateViewActionAsyncCreator = (vPath: string) => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
132 const pathParts = splitVPath(vPath, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
133 const { configuration: { deviceDescription: { nodeId, modules, views } } } = getState();
134 let dataPath = `/rests/data/network-topology:network-topology/topology=topology-netconf/node=${nodeId}/yang-ext:mount`;
136 let inputViewSpecification: ViewSpecification | undefined = undefined;
137 let outputViewSpecification: ViewSpecification | undefined = undefined;
139 let viewSpecification: ViewSpecification = views[0];
140 let viewElement: ViewElement;
142 let dataMember: string;
143 let extractList: boolean = false;
145 let currentNS: string | null = null;
146 let defaultNS: string | null = null;
148 let newData: any = null;
150 dispatch(new SetCollectingSelectionData(true));
152 for (let ind = 0; ind < pathParts.length; ++ind) {
153 const [property, key] = pathParts[ind];
154 const namespaceInd = property && property.indexOf(':') || -1;
155 const namespace: string | null = namespaceInd > -1 ? (currentNS = property.slice(0, namespaceInd)) : currentNS;
157 if (ind === 0) { defaultNS = namespace; }
159 viewElement = viewSpecification.elements[property] || viewSpecification.elements[`${namespace}:${property}`];
160 if (!viewElement) throw Error('Property [' + property + '] does not exist.');
164 newData = newData[property];
166 } else if (viewElement.isList && !key) {
167 // handle new list element without key
168 if (pathParts[ind][1] === null) {
170 // create new data if not already exists
171 newData = getState().configuration.viewDescription.newData;
172 if (!newData && viewElement && 'viewId' in viewElement) {
173 newData = createViewData(namespace, views[+viewElement.viewId], views);
174 dispatch(new UpdateNewData(newData));
177 } else if ((pathParts.length) - 1 > ind) {
178 // handle list without key which is not a new element
179 dispatch(new SetCollectingSelectionData(false));
180 throw new Error('No key for list [' + property + ']');
183 if (viewElement && isViewElementList(viewElement) && viewSpecification.parentView === '0') {
184 // check if there is a reference as key
185 const listSpecification = views[+viewElement.viewId];
186 const keyElement = viewElement.key && listSpecification.elements[viewElement.key];
187 if (keyElement && isViewElementReference(keyElement)) {
188 const refList = await getReferencedDataList(keyElement.referencePath, dataPath, modules, views);
190 throw new Error(`Could not find refList for [${keyElement.referencePath}].`);
193 throw new Error(`Key property not found for [${keyElement.referencePath}].`);
195 dispatch(new EnableValueSelector(refList.view, refList.data, refList.key, (refKey) => {
196 window.setTimeout(() => dispatch(new PushAction(`${vPath}[${refKey.replace(/\//ig, '%2F')}]`)));
199 // Found a list at root level of a module w/o a reference key.
200 dataPath += `?&fields=${encodeURIComponent(viewElement.id)}(${encodeURIComponent(viewElement.key || '')})`;
201 const restResult = (await restService.getConfigData(dataPath));
202 if (restResult && restResult.status === 200 && restResult.data && restResult.data[viewElement.id] ) {
203 // spoof the not existing view here
204 const refData = restResult.data[viewElement.id];
205 if (!Array.isArray(refData) || !refData.length) {
206 throw new Error('Found a list at root level of a module containing no keys.');
208 if (refData.length > 1) {
209 const refView : ViewSpecification = {
215 [viewElement.key!] : {
219 label: viewElement.key,
221 } as ViewElementString,
224 dispatch(new EnableValueSelector(refView, refData, viewElement.key!, (refKey) => {
225 window.setTimeout(() => dispatch(new PushAction(`${vPath}[${refKey.replace(/\//ig, '%2F')}]`)));
228 window.setTimeout(() => dispatch(new PushAction(`${vPath}[${refData[0]?.id.replace(/\//ig, '%2F')}]`)));
231 throw new Error('Found a list at root level of a module and could not determine the keys.');
233 dispatch(new SetCollectingSelectionData(false));
239 dataPath += `/${property}${key ? `=${key.replace(/\//ig, '%2F')}` : ''}`;
241 // in case of the root element the required namespace will be added later,
242 // while extracting the data
243 dataMember = namespace === defaultNS
245 : `${namespace}:${viewElement.label}`;
249 if (viewElement && 'viewId' in viewElement) {
250 viewSpecification = views[+viewElement.viewId];
251 } else if (viewElement.uiType === 'rpc') {
252 viewSpecification = views[+(viewElement.inputViewId || 0)];
254 // create new instance & flatten
255 inputViewSpecification = viewElement.inputViewId != null && {
256 ...views[+(viewElement.inputViewId || 0)],
257 elements: flattenViewElements(defaultNS, '', views[+(viewElement.inputViewId || 0)].elements, views, viewElement.label),
259 outputViewSpecification = viewElement.outputViewId != null && {
260 ...views[+(viewElement.outputViewId || 0)],
261 elements: flattenViewElements(defaultNS, '', views[+(viewElement.outputViewId || 0)].elements, views, viewElement.label),
268 // create display specification
269 const ds: DisplaySpecification = {
270 displayMode: DisplayModeType.displayAsObject,
271 viewSpecification: resolveViewDescription(defaultNS, vPath, viewSpecification),
272 keyProperty: isViewElementList(viewElement!) && viewElement.key || undefined,
275 // update display specification
276 return dispatch(postProcessDisplaySpecificationActionCreator(vPath, newData, ds));
280 // do not get any data from netconf if there is no view specified || this is the root element [0] || this is an rpc
281 if (viewSpecification && !(viewSpecification.id === '0' || viewElement!.uiType === 'rpc')) {
282 const restResult = (await restService.getConfigData(dataPath));
283 if (restResult.status === 409) {
284 // special case: if this is a list without any response
285 if (isViewElementList(viewElement!)) {
286 // create display specification
287 const ds: DisplaySpecification = {
288 displayMode: extractList ? DisplayModeType.displayAsList : DisplayModeType.displayAsObject,
289 viewSpecification: resolveViewDescription(defaultNS, vPath, viewSpecification),
290 keyProperty: viewElement.key,
292 // update display specification
293 return dispatch(postProcessDisplaySpecificationActionCreator(vPath, [], ds));
295 // create display specification
296 const ds: DisplaySpecification = {
297 displayMode: DisplayModeType.displayAsObject,
298 viewSpecification: resolveViewDescription(defaultNS, vPath, viewSpecification),
300 // update display specification
301 return dispatch(postProcessDisplaySpecificationActionCreator(vPath, { }, ds));
304 } else if (!restResult.data) {
305 // special case: if this is a list without any response
306 if (extractList && restResult.status === 404) {
307 if (!isViewElementList(viewElement!)) {
308 throw new Error(`vPath: [${vPath}]. ViewElement has no key.`);
310 // create display specification
311 const ds: DisplaySpecification = {
312 displayMode: extractList ? DisplayModeType.displayAsList : DisplayModeType.displayAsObject,
313 viewSpecification: resolveViewDescription(defaultNS, vPath, viewSpecification),
314 keyProperty: viewElement.key,
317 // update display specification
318 return dispatch(postProcessDisplaySpecificationActionCreator(vPath, [], ds));
320 throw new Error(`Did not get response from Server. Status: [${restResult.status}]`);
321 } else if (checkResponseCode(restResult)) {
322 const message = restResult.data.errors && restResult.data.errors.error && restResult.data.errors.error[0] && restResult.data.errors.error[0]['error-message'] || '';
323 throw new Error(`Server Error. Status: [${restResult.status}]\n${message}`);
325 // https://tools.ietf.org/html/rfc7951#section-4 the root element may contain a namespace or not !
326 data = restResult.data[`${defaultNS}:${dataMember!}`];
327 if (data === undefined) {
328 data = restResult.data[dataMember!]; // extract dataMember w/o namespace
332 // extract the first element list[key]
333 data = data instanceof Array
337 // extract the list -> key: list
339 ? data[viewElement!.id] || data[viewElement!.label] || [] // if the list is empty, it does not exist
342 } else if (viewElement! && viewElement!.uiType === 'rpc') {
343 // set data to defaults
345 if (inputViewSpecification) {
346 Object.keys(inputViewSpecification.elements).forEach(key => {
347 const elm = inputViewSpecification && inputViewSpecification.elements[key];
348 if (elm && elm.default != undefined) {
349 data[elm.id] = elm.default;
355 // create display specification
356 const ds: DisplaySpecification = viewElement! && viewElement!.uiType === 'rpc'
359 displayMode: DisplayModeType.displayAsRPC,
360 inputViewSpecification: inputViewSpecification && resolveViewDescription(defaultNS, vPath, inputViewSpecification),
361 outputViewSpecification: outputViewSpecification && resolveViewDescription(defaultNS, vPath, outputViewSpecification),
365 displayMode: extractList ? DisplayModeType.displayAsList : DisplayModeType.displayAsObject,
366 viewSpecification: resolveViewDescription(defaultNS, vPath, viewSpecification),
367 keyProperty: isViewElementList(viewElement!) && viewElement.key || undefined,
369 // eslint-disable-next-line max-len
370 apidocPath: isViewElementList(viewElement!) && `/apidoc/explorer/index.html?urls.primaryName=$$$standard$$$#/mounted%20${nodeId}%20${viewElement!.module || 'MODULE_NOT_DEFINED'}/$$$action$$$_${dataPath.replace(/^\//, '').replace(/[\/=\-\:]/g, '_')}_${viewElement! != null ? `${viewElement.id.replace(/[\/=\-\:]/g, '_')}_` : '' }` || undefined,
373 // update display specification
374 return dispatch(postProcessDisplaySpecificationActionCreator(vPath, data, ds));
375 // https://server.com/#/configuration/Sim12600/core-model:network-element/ltp[LTP-MWPS-TTP-01]
376 // https://server.com/#/configuration/Sim12600/core-model:network-element/ltp[LTP-MWPS-TTP-01]/lp
379 dispatch(new AddErrorInfoAction({ title: 'Problem', message: error.message || `Could not process ${dataPath}` }));
380 dispatch(new SetCollectingSelectionData(false));
386 export const updateDataActionAsyncCreator = (vPath: string, data: any) => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
387 const pathParts = splitVPath(vPath, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
388 const { configuration: { deviceDescription: { nodeId, views } } } = getState();
389 let dataPath = `/rests/data/network-topology:network-topology/topology=topology-netconf/node=${nodeId}/yang-ext:mount`;
390 let viewSpecification: ViewSpecification = views[0];
391 let viewElement: ViewElement;
392 let dataMember: string;
393 let embedList: boolean = false;
394 let isNew: string | false = false;
396 let currentNS: string | null = null;
397 let defaultNS: string | null = null;
399 let newData: any = null;
400 let newElement: any = null;
402 dispatch(new SetCollectingSelectionData(true));
404 for (let ind = 0; ind < pathParts.length; ++ind) {
405 let [property, key] = pathParts[ind];
406 const namespaceInd = property && property.indexOf(':') || -1;
407 const namespace: string | null = namespaceInd > -1 ? (currentNS = property.slice(0, namespaceInd)) : currentNS;
409 if (ind === 0) { defaultNS = namespace; }
410 viewElement = viewSpecification.elements[property] || viewSpecification.elements[`${namespace}:${property}`];
411 if (!viewElement) throw Error('Property [' + property + '] does not exist.');
415 if (pathParts.length - 1 === ind) {
416 newElement[property] = data;
417 return dispatch(new UpdateNewData(newData));
419 newElement[property] = Array.isArray(newElement[property]) ? [ ...newElement[property] ] : { ...newElement[property] };
421 } else if (isViewElementList(viewElement) && !key) {
423 if (viewElement && viewElement.isList && viewSpecification.parentView === '0') {
424 throw new Error('Found a list at root level of a module w/o a reference key.');
429 const stateData = getState().configuration.viewDescription.newData;
430 newElement = newData = Array.isArray(stateData) ? [ ...stateData ] : { ...stateData };
432 if (vPath.endsWith('[]') && pathParts.length - 1 === ind) {
433 // handle new element with any number of arguments
434 let keyList = viewElement.key?.split(' ');
435 let dataPathParam = keyList?.map(id => data[id]).join(',');
436 key = viewElement.key && String(dataPathParam) || '';
439 dispatch(new SetCollectingSelectionData(false));
440 throw new Error('No value for key [' + viewElement.key + '] in list [' + property + ']');
444 } else if (pathParts.length - 1 > ind) {
445 dispatch(new SetCollectingSelectionData(false));
446 throw new Error('No key for list [' + property + ']');
450 dataPath += `/${property}${key ? `=${key.replace(/\//ig, '%2F')}` : ''}`;
451 dataMember = viewElement.label;
454 if (viewElement && 'viewId' in viewElement) {
455 viewSpecification = views[+viewElement.viewId];
459 // remove read-only elements
460 const removeReadOnlyElements = (pViewSpecification: ViewSpecification, isList: boolean, pData: any) => {
462 return pData.map((elm : any) => removeReadOnlyElements(pViewSpecification, false, elm));
464 return Object.keys(pData).reduce<{ [key: string]: any }>((acc, cur)=>{
465 const [nsOrName, name] = cur.split(':', 1);
466 const element = pViewSpecification.elements[cur] || pViewSpecification.elements[nsOrName] || pViewSpecification.elements[name];
467 if (!element && process.env.NODE_ENV === 'development' ) {
468 throw new Error('removeReadOnlyElements: Could not determine element for data.');
470 if (element && element.config) {
471 if (element.uiType === 'object') {
472 const view = views[+element.viewId];
474 throw new Error('removeReadOnlyElements: Internal Error could not determine viewId: ' + element.viewId);
476 acc[cur] = removeReadOnlyElements(view, element.isList != null && element.isList, pData[cur]);
478 acc[cur] = pData[cur];
485 data = removeReadOnlyElements(viewSpecification, embedList, data);
488 // embed the list -> key: list
490 ? { [viewElement!.label]: data }
493 // embed the first element list[key]
494 data = isNew || newData
498 // do not extract root member (0)
499 if (viewSpecification && viewSpecification.id !== '0') {
500 const updateResult = await restService.setConfigData(dataPath, { [`${currentNS}:${dataMember!}`]: data }); // addDataMember using currentNS
501 if (checkResponseCode(updateResult)) {
502 const message = updateResult.data && updateResult.data.errors && updateResult.data.errors.error && updateResult.data.errors.error[0] && updateResult.data.errors.error[0]['error-message'] || '';
503 throw new Error(`Server Error. Status: [${updateResult.status}]\n${message || updateResult.message || ''}`);
508 dispatch(new UpdateNewData(null));
512 return dispatch(new ReplaceAction(`/configuration/${nodeId}/${vPath.replace(/\[\]$/i, `[${isNew}]`)}`)); // navigate to new element
515 // create display specification
516 const ds: DisplaySpecification = {
517 displayMode: embedList ? DisplayModeType.displayAsList : DisplayModeType.displayAsObject,
518 viewSpecification: resolveViewDescription(defaultNS, vPath, viewSpecification),
519 keyProperty: isViewElementList(viewElement!) && viewElement.key || undefined,
522 // update display specification
523 return dispatch(new UpdateViewDescription(vPath, data, ds));
526 dispatch(new AddErrorInfoAction({ title: 'Problem', message: error.message || `Could not change ${dataPath}` }));
529 dispatch(new SetCollectingSelectionData(false));
534 export const removeElementActionAsyncCreator = (vPath: string) => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
535 const pathParts = splitVPath(vPath, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
536 const { configuration: { deviceDescription: { nodeId, views } } } = getState();
537 let dataPath = `/rests/data/network-topology:network-topology/topology=topology-netconf/node=${nodeId}/yang-ext:mount`;
538 let viewSpecification: ViewSpecification = views[0];
539 let viewElement: ViewElement;
541 let currentNS: string | null = null;
543 dispatch(new SetCollectingSelectionData(true));
545 for (let ind = 0; ind < pathParts.length; ++ind) {
546 let [property, key] = pathParts[ind];
547 const namespaceInd = property && property.indexOf(':') || -1;
548 const namespace: string | null = namespaceInd > -1 ? (currentNS = property.slice(0, namespaceInd)) : currentNS;
550 viewElement = viewSpecification.elements[property] || viewSpecification.elements[`${namespace}:${property}`];
551 if (!viewElement) throw Error('Property [' + property + '] does not exist.');
553 if (isViewElementList(viewElement) && !key) {
554 if (viewElement && viewElement.isList && viewSpecification.parentView === '0') {
555 throw new Error('Found a list at root level of a module w/o a reference key.');
557 if (pathParts.length - 1 > ind) {
558 dispatch(new SetCollectingSelectionData(false));
559 throw new Error('No key for list [' + property + ']');
560 } else if (vPath.endsWith('[]') && pathParts.length - 1 === ind) {
561 // remove the whole table
565 dataPath += `/${property}${key ? `=${key.replace(/\//ig, '%2F')}` : ''}`;
567 if (viewElement && 'viewId' in viewElement) {
568 viewSpecification = views[+viewElement.viewId];
569 } else if (viewElement.uiType === 'rpc') {
570 viewSpecification = views[+(viewElement.inputViewId || 0)];
574 const updateResult = await restService.removeConfigElement(dataPath);
575 if (checkResponseCode(updateResult)) {
576 const message = updateResult.data && updateResult.data.errors && updateResult.data.errors.error && updateResult.data.errors.error[0] && updateResult.data.errors.error[0]['error-message'] || '';
577 throw new Error(`Server Error. Status: [${updateResult.status}]\n${message || updateResult.message || ''}`);
580 dispatch(new AddErrorInfoAction({ title: 'Problem', message: error.message || `Could not remove ${dataPath}` }));
582 dispatch(new SetCollectingSelectionData(false));
586 export const executeRpcActionAsyncCreator = (vPath: string, data: any) => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
587 const pathParts = splitVPath(vPath, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
588 const { configuration: { deviceDescription: { nodeId, views } } } = getState();
589 let dataPath = `/rests/operations/network-topology:network-topology/topology=topology-netconf/node=${nodeId}/yang-ext:mount`;
590 let viewSpecification: ViewSpecification = views[0];
591 let viewElement: ViewElement;
592 let dataMember: string;
593 let embedList: boolean = false;
594 let isNew: string | false = false;
596 let currentNS: string | null = null;
597 let defaultNS: string | null = null;
599 dispatch(new SetCollectingSelectionData(true));
601 for (let ind = 0; ind < pathParts.length; ++ind) {
602 let [property, key] = pathParts[ind];
603 const namespaceInd = property && property.indexOf(':') || -1;
604 const namespace: string | null = namespaceInd > -1 ? (currentNS = property.slice(0, namespaceInd)) : currentNS;
606 if (ind === 0) { defaultNS = namespace; }
607 viewElement = viewSpecification.elements[property] || viewSpecification.elements[`${namespace}:${property}`];
608 if (!viewElement) throw Error('Property [' + property + '] does not exist.');
610 if (isViewElementList(viewElement) && !key) {
612 // if (viewElement && viewElement.isList && viewSpecification.parentView === "0") {
613 // throw new Error("Found a list at root level of a module w/o a reference key.");
615 // if (pathParts.length - 1 > ind) {
616 // dispatch(new SetCollectingSelectionData(false));
617 // throw new Error("No key for list [" + property + "]");
618 // } else if (vPath.endsWith("[]") && pathParts.length - 1 === ind) {
619 // // handle new element
620 // key = viewElement.key && String(data[viewElement.key]) || "";
623 // dispatch(new SetCollectingSelectionData(false));
624 // throw new Error("No value for key [" + viewElement.key + "] in list [" + property + "]");
629 dataPath += `/${property}${key ? `=${key.replace(/\//ig, '%2F')}` : ''}`;
630 dataMember = viewElement.label;
633 if (viewElement && 'viewId' in viewElement) {
634 viewSpecification = views[+viewElement.viewId];
635 } else if (viewElement.uiType === 'rpc') {
636 viewSpecification = views[+(viewElement.inputViewId || 0)];
640 // re-inflate formerly flatten rpc data
641 data = data && Object.keys(data).reduce < { [name: string ]: any }>((acc, cur) => {
642 const innerPathParts = cur.split('.');
644 const updatePath = (obj: any, key: string) => {
645 obj[key] = (pos >= innerPathParts.length)
647 : updatePath(obj[key] || {}, innerPathParts[pos++]);
650 updatePath(acc, innerPathParts[pos++]);
654 // embed the list -> key: list
656 ? { [viewElement!.label]: data }
659 // embed the first element list[key]
664 // do not post root member (0)
665 if ((viewSpecification && viewSpecification.id !== '0') || (dataMember! && !data)) {
666 const updateResult = await restService.executeRpc(dataPath, { [`${defaultNS}:input`]: data || {} });
667 if (checkResponseCode(updateResult)) {
668 const message = updateResult.data && updateResult.data.errors && updateResult.data.errors.error && updateResult.data.errors.error[0] && updateResult.data.errors.error[0]['error-message'] || '';
669 throw new Error(`Server Error. Status: [${updateResult.status}]\n${message || updateResult.message || ''}`);
671 dispatch(new UpdateOutputData(updateResult.data));
673 throw new Error('There is NO RPC specified.');
677 // // update display specification
680 dispatch(new AddErrorInfoAction({ title: 'Problem', message: error.message || `Could not change ${dataPath}` }));
683 dispatch(new SetCollectingSelectionData(false));