// check if-feature | when | and resolve all references.
view = { ...view };
view.elements = Object.keys(view.elements).reduce<{ [name: string]: ViewElement }>((acc, cur) => {
- const elm = view.elements[cur];
+ const resolveHistory : ViewElement[] = [];
+ let elm = view.elements[cur];
const key = defaultNS && cur.replace(new RegExp(`^${defaultNS}:`, "i"),"") || cur;
- if (isViewElementReference(elm)) {
- acc[key] = { ...(elm.ref(vPath) || elm), id: key };
- } else {
- acc[key] = { ...elm, id: key };
- }
+ while (isViewElementReference(elm)) {
+ const result = (elm.ref(vPath));
+ if (result) {
+ const [referencedElement, referencedPath] = result;
+ if (resolveHistory.some(hist => hist === referencedElement)) {
+ console.error(`Circle reference found at: ${vPath}`, resolveHistory);
+ break;
+ }
+ elm = referencedElement;
+ vPath = referencedPath;
+ resolveHistory.push(elm);
+ }
+ }
+
+ acc[key] = { ...elm, id: key };
+
return acc;
}, {});
return view;
inputValue: TValue,
readOnly: boolean,
disabled: boolean,
- onChange(newValue: TValue): void
-};
+ onChange(newValue: TValue): void,
+ isKey?: boolean
+};
\ No newline at end of file
import { IfWhenTextInput } from "./ifWhenTextInput";
import { checkRange, checkPattern } from "./verifyer";
-type stringEntryProps = BaseProps & { isKey: boolean };
+type stringEntryProps = BaseProps;
export const UiElementString = (props: stringEntryProps) => {
<Tooltip title={isTooltipVisible ? element.description || '' : ''}>
<IfWhenTextInput element={element} onChangeTooltipVisuability={setTooltipVisibility}
spellCheck={false} autoFocus margin="dense"
- id={element.id} label={props.isKey ? "🔑 " + element.label : element.label} type="text" value={props.inputValue}
+ id={element.id} label={props?.isKey ? "🔑 " + element.label : element.label} type="text" value={props.inputValue}
style={{ width: 485, marginLeft: 20, marginRight: 20 }}
onChange={(e: any) => { verifyValues(e.target.value) }}
error={isError}
/>
</Tooltip>
);
-}
\ No newline at end of file
+}
export type ViewElementReference = ViewElementBase & {
"uiType": "reference";
"referencePath": string;
- "ref": (currentPath: string) => ViewElement | null;
+ "ref": (currentPath: string) => [ViewElement , string] | undefined;
}
export type ViewElementUnion = ViewElementBase & {
export type ViewSpecification = {
"id": string;
+ "ns"?: string;
"name"?: string;
"title"?: string;
"parentView"?: string;
"language": string;
"ifFeature"?: string;
"when"?: string;
- "uses"?: (string[]) & { [ResolveFunction]?: () => void };
+ "uses"?: (string[]) & { [ResolveFunction]?: (parent: string) => void };
"elements": { [name: string]: ViewElement };
readonly "canEdit": boolean;
}
? (
<Element
key={uiElement.id}
+ isKey={isKey}
inputValue={viewData[uiElement.id] == null ? '' : viewData[uiElement.id]}
value={uiElement}
readOnly={!canEdit}
/> )
: null ;
}
-
- // // do not show elements w/o any value from the backend
- // if (viewData[uiElement.id] == null && !editMode) {
- // return null;
- // } else if (isViewElementEmpty(uiElement)) {
- // return null;
- // } else if (uiElement.isList) {
- // /* element is a leaf-list */
- // return <UiElementLeafList
- // key={uiElement.id}
- // inputValue={viewData[uiElement.id] || ''}
- // value={uiElement}
- // readOnly={!canEdit}
- // disabled={editMode && !canEdit}
- // onChange={(e) => { this.changeValueFor(uiElement.id, e) }}
- // />;
- // } else if (isViewElementSelection(uiElement)) {
-
- // return <UiElementSelection
- // key={uiElement.id}
- // inputValue={viewData[uiElement.id] || ''}
- // value={uiElement}
- // readOnly={!canEdit}
- // disabled={editMode && !canEdit}
- // onChange={(e) => { this.changeValueFor(uiElement.id, e) }}
- // />
-
- // } else if (isViewElementBoolean(uiElement)) {
- // return <UiElementBoolean
- // key={uiElement.id}
- // inputValue={viewData[uiElement.id] == null ? '' : viewData[uiElement.id]}
- // value={uiElement}
- // readOnly={!canEdit}
- // disabled={editMode && !canEdit}
- // onChange={(e) => { this.changeValueFor(uiElement.id, e) }} />
-
- // } else if (isViewElementString(uiElement)) {
- // return <UiElementString
- // key={uiElement.id}
- // inputValue={viewData[uiElement.id] == null ? '' : viewData[uiElement.id]}
- // value={uiElement}
- // isKey={isKey}
- // readOnly={!canEdit}
- // disabled={editMode && !canEdit}
- // onChange={(e) => { this.changeValueFor(uiElement.id, e) }} />
-
- // } else if (isViewElementNumber(uiElement)) {
- // return <UiElementNumber
- // key={uiElement.id}
- // value={uiElement}
- // inputValue={viewData[uiElement.id] == null ? '' : viewData[uiElement.id]}
- // readOnly={!canEdit}
- // disabled={editMode && !canEdit}
- // onChange={(e) => { this.changeValueFor(uiElement.id, e) }} />
- // } else if (isViewElementUnion(uiElement)) {
- // return <UIElementUnion
- // key={uiElement.id}
- // isKey={false}
- // value={uiElement}
- // inputValue={viewData[uiElement.id] == null ? '' : viewData[uiElement.id]}
- // readOnly={!canEdit}
- // disabled={editMode && !canEdit}
- // onChange={(e) => { this.changeValueFor(uiElement.id, e) }} />
- // } else {
- // if (process.env.NODE_ENV !== "production") {
- // console.error(`Unknown element type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`)
- // }
- // return null;
- // }
};
// private renderUIReference = (uiElement: ViewElement, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
}
export const ConfigurationApplication = withStyles(styles)(withRouter(connect(mapProps, mapDispatch)(ConfigurationApplicationComponent)));
-export default ConfigurationApplication;
\ No newline at end of file
+export default ConfigurationApplication;
// process all groupings
this._groupingsToResolve.filter(vs => vs.uses && vs.uses[ResolveFunction]).forEach(vs => {
- try { vs.uses![ResolveFunction]!(); } catch (error) {
- console.warn(`Error resolving: [${error.message}]`);
+ try { vs.uses![ResolveFunction] !== undefined && vs.uses![ResolveFunction]!("|"); } catch (error) {
+ console.warn(`Error resolving: [${vs.name}] [${error.message}]`);
}
});
}
const key = this.extractValue(cur, "key") || undefined;
if (elmConfig && !key) {
- console.error(new Error(`Module: [${context.name}]${currentPath}. Found configurable list without key.`));
+ console.warn(`Module: [${context.name}]${currentPath}. Found configurable list without key. Assume config shell be false.`);
elmConfig = false;
}
const [currentView, subViews] = this.extractSubViews(cur, currentId, context, `${currentPath}/${context.name}:${cur.arg}`);
const viewSpec: ViewSpecification = {
id: String(currentId),
parentView: String(parentId),
+ ns: context.name,
name: statement.arg != null ? statement.arg : undefined,
title: statement.arg != null ? statement.arg : undefined,
language: "en-us",
if (usesRefs && usesRefs.length > 0) {
viewSpec.uses = (viewSpec.uses || []);
- const resolveFunctions : (()=>void)[] = [];
+ const resolveFunctions : ((parentElementPath: string)=>void)[] = [];
for (let i = 0; i < usesRefs.length; ++i) {
const groupingName = usesRefs[i].arg;
}
viewSpec.uses.push(this.resolveReferencePath(groupingName, context));
-
- resolveFunctions.push(() => {
+
+ resolveFunctions.push((parentElementPath: string) => {
const groupingViewSpec = this.resolveGrouping(groupingName, context);
if (groupingViewSpec) {
// resolve recursive
const resolveFunc = groupingViewSpec.uses && groupingViewSpec.uses[ResolveFunction];
- resolveFunc && resolveFunc();
+ resolveFunc && resolveFunc(parentElementPath);
Object.keys(groupingViewSpec.elements).forEach(key => {
const elm = groupingViewSpec.elements[key];
});
}
- viewSpec.uses[ResolveFunction] = () => {
- resolveFunctions.forEach(res => {
- try {
- res();
- } catch (error) {
- console.error(error);
- }
+ viewSpec.uses[ResolveFunction] = (parentElementPath: string) => {
+ const currentElementPath = `${parentElementPath} -> ${viewSpec.ns}:${viewSpec.name}`;
+ resolveFunctions.forEach(resolve => {
+ try {
+ resolve(currentElementPath);
+ } catch (error) {
+ console.error(error);
+ }
});
+ // console.log("Resolved "+currentElementPath, viewSpec);
viewSpec?.uses![ResolveFunction] = undefined;
}
uiType: "reference",
referencePath: refPath,
ref(this: ViewElement, currentPath: string) {
- const resolved = resolve(refPath, currentPath);
- return resolved && {
- ...resolved,
+ const elementPath = `${currentPath}/${cur.arg}`;
+
+ const result = resolve(refPath, elementPath);
+ if (!result) return undefined;
+
+ const [resolvedElement, resolvedPath] = result;
+ return resolvedElement && [{
+ ...resolvedElement,
id: this.id,
label: this.label,
config: this.config,
isList: this.isList,
default: this.default,
description: this.description,
- } as ViewElement;
+ } as ViewElement , resolvedPath] || undefined;
}
};
return res;
const vPathParts = splitVPath(vPath, vPathParser).map(p => ({ ns: p[1], property: p[2], ind: p[3] }));
const resultPathParts = !vPath.startsWith("/")
- ? splitVPath(currentPath, vPathParser).map(p => ({ ns: p[1], property: p[2], ind: p[3] }))
+ ? splitVPath(currentPath, vPathParser).map(p => { moduleName = p[1] || moduleName ; return { ns: moduleName, property: p[2], ind: p[3] } })
: [];
for (let i = 0; i < vPathParts.length; ++i) {
const view: ViewSpecification = this._views[+element.viewId];
if (moduleName !== pathPart.ns) {
moduleName = pathPart.ns;
- element = view.elements[`${moduleName}:${pathPart.property}`];
- } else {
- element = view.elements[pathPart.property] || view.elements[`${moduleName}:${pathPart.property}`];
- }
+ }
+ element = view.elements[pathPart.property] || view.elements[`${moduleName}:${pathPart.property}`];
} else {
throw new Error("Could not resolve reference.\r\n" + vPath);
}
if (!element) throw new Error("Could not resolve path [" + pathPart.property + "] in [" + currentPath + "] \r\n" + vPath);
}
- return element;
+ moduleName = ""; // create the vPath for the resolved element, do not add the element itself this will be done later in the res(...) function
+ return [element, resultPathParts.slice(0,-1).map(p => `${moduleName !== p.ns ? `${moduleName=p.ns}:` : ""}${p.property}${p.ind || ''}`).join("/")];
}
private resolveView(vPath: string) {