Skip to content

Commit

Permalink
fix #42
Browse files Browse the repository at this point in the history
  • Loading branch information
mavarazy committed Dec 15, 2018
1 parent 62732f7 commit 42e042a
Show file tree
Hide file tree
Showing 9 changed files with 218 additions and 59 deletions.
19 changes: 12 additions & 7 deletions playground/app/conf/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,18 @@
"type": "string",
"title": "Encounter"
},
"firstName": {
"type": "string",
"title": "First name"
},
"lastName": {
"type": "string",
"title": "Last name"
"general": {
"type": "object",
"properties": {
"firstName": {
"type": "string",
"title": "First name"
},
"lastName": {
"type": "string",
"title": "Last name"
}
}
},
"age": {
"type": "integer",
Expand Down
31 changes: 21 additions & 10 deletions playground/app/conf/uiSchema.json
Original file line number Diff line number Diff line change
@@ -1,30 +1,41 @@
{
"encounter": {
"nav": "Encounter"
"nav": "Encounter",
"classNames": "col-md-12"
},
"firstName": {
"nav": "First name"
},
"lastName": {
"nav": "Last name"
"general": {
"nav": "general",
"firstName": {
"nav": [ "general", "First name"],
"classNames": "col-md-12"
},
"lastName": {
"nav": [ "general", "Last name"],
"classNames": "col-md-12"
}
},
"age": {
"nav": "Age"
"nav": "Age",
"classNames": "col-md-12"
},
"nickName": {
"type": "string",
"nav": "nickname"
"nav": "nickname",
"classNames": "col-md-12"
},
"bio": {
"type": "string",
"nav": "Bio"
"nav": "Bio",
"classNames": "col-md-12"
},
"password": {
"type": "string",
"nav": "Password",
"classNames": "col-md-12",
"minLength": 3
},
"telephone": {
"nav": "Telephone"
"nav": "Telephone",
"classNames": "col-md-12"
}
}
4 changes: 2 additions & 2 deletions src/render/FormWithNav.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Navs from "./Navs";
import HiddenField from "./HiddenField";
import NavField from "./NavField";

const formWithTabs = (FormComponent, NavComponent = Navs) => {
const formWithNav = (FormComponent, NavComponent = Navs) => {
class FormWithTabs extends Component {
render() {
let { fields = {}, uiSchema } = this.props;
Expand All @@ -28,4 +28,4 @@ const formWithTabs = (FormComponent, NavComponent = Navs) => {
return FormWithTabs;
};

export default formWithTabs;
export default formWithNav;
38 changes: 6 additions & 32 deletions src/splitter/NavTree.js
Original file line number Diff line number Diff line change
@@ -1,58 +1,32 @@
import { GENERIC_NAV, findFieldNavs } from "../utils";
import { orderNavByName, toNavConfOrDefault } from "./extractSubNavs";
import { extractTree, findRelTree } from "./extractTree";
import { asNavField, toHiddenUiSchema } from "./util";
import extractSubUiSchema from "./extractSubUiSchema";
import extractSubNavs from "./extractSubNavs";

function asNavField(field, navConfs, uiSchema) {
uiSchema[field] = {
navConfs,
"ui:field": "nav",
origUiSchema: uiSchema[field],
};
}

function asHiddenField(field, uiSchema) {
uiSchema[field] = {
"ui:widget": "hidden",
"ui:field": "hidden",
};
}

function toHiddenUiSchema({ properties }, uiSchema) {
let cleanUiSchema = Object.keys(properties).reduce((agg, field) => {
asHiddenField(field, agg);
return agg;
}, Object.assign({}, uiSchema));
return cleanUiSchema;
}

export default class NavTree {
constructor(schema, uiSchema) {
this.tree = extractTree(schema, uiSchema);
this.schema = schema;
this.uiSchema = uiSchema;

this.updateActiveNav = this.updateActiveNav.bind(this);
this.findActiveNav = this.findActiveNav.bind(this);
this.toSubForms = this.toSubForms.bind(this);
}

updateActiveNav(activeNavs, relTree) {
updateActiveNav = (activeNavs, relTree) => {
relTree = relTree ? relTree : findRelTree(this.tree, activeNavs);
let orderedNavs = orderNavByName(Object.keys(relTree), this.uiSchema);
let nextNav = orderedNavs.find(nav => nav !== GENERIC_NAV);
if (nextNav) {
activeNavs.push(nextNav);
this.updateActiveNav(activeNavs, relTree[nextNav]);
}
}
};

findActiveNav(field) {
findActiveNav = field => {
return findFieldNavs(field, this.uiSchema).map(nav =>
toNavConfOrDefault(nav, this.uiSchema)
);
}
};

buildUiSchema = (
activeNav,
Expand All @@ -65,7 +39,7 @@ export default class NavTree {
if (tree[GENERIC_NAV]) {
let { fields, aliases } = tree[GENERIC_NAV];

extractSubUiSchema(fields, aliases, this.uiSchema, uiSchema);
extractSubUiSchema(fields, aliases, this.uiSchema, uiSchema, this.schema);

if (navConfs.length > 0) {
asNavField(fields[0], navConfs, uiSchema);
Expand Down
38 changes: 34 additions & 4 deletions src/splitter/extractSubUiSchema.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,34 @@
function restoreFields(fields, uiSchema, origUiSchema) {
fields.forEach(field => (uiSchema[field] = origUiSchema[field]));
import { toHiddenUiSchema } from "./util";

const restoreField = (field, uiSchema, origUiSchema, schema) => {
const separatorIndex = field.indexOf(".");
if (separatorIndex === -1) {
uiSchema[field] = origUiSchema[field];
} else {
const parentField = field.substr(0, separatorIndex);
const childField = field.substr(separatorIndex + 1);
const parentFieldSchema = schema.properties[parentField];

if (uiSchema[parentField]["ui:widget"] === "hidden") {
delete uiSchema[parentField]["ui:widget"];
delete uiSchema[parentField]["ui:field"];
uiSchema[parentField] = toHiddenUiSchema(
parentFieldSchema,
origUiSchema[parentField]
);
}

restoreField(
childField,
uiSchema[parentField],
origUiSchema[parentField],
parentFieldSchema
);
}
};

function restoreFields(fields, uiSchema, origUiSchema, schema) {
fields.forEach(field => restoreField(field, uiSchema, origUiSchema, schema));
return uiSchema;
}

Expand All @@ -14,9 +43,10 @@ export default function extractSubUiSchema(
fields,
aliases,
origUiSchema,
uiSchema = {}
uiSchema = {},
schema
) {
restoreFields(fields, uiSchema, origUiSchema);
restoreFields(fields, uiSchema, origUiSchema, schema);
replaceAliases(aliases, uiSchema, origUiSchema);

return uiSchema;
Expand Down
14 changes: 10 additions & 4 deletions src/splitter/extractTree.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,17 @@ function pushField(tree, field, uiAlias) {
}
}

function fillSchemaConf(tree, schema, uiSchema) {
function fillSchemaConf(tree, schema, uiSchema, prefix = "") {
Object.keys(schema.properties).forEach(field => {
let navs = findFieldNavs(field, uiSchema);
let subTree = findRelTree(tree, navs);
pushField(subTree, field);
const fieldSchema = schema.properties[field];
const fieldUiSchema = uiSchema[field];
if (fieldSchema.type === "object" && fieldUiSchema) {
fillSchemaConf(tree, fieldSchema, fieldUiSchema, field + ".");
} else {
let navs = findFieldNavs(field, uiSchema);
let subTree = findRelTree(tree, navs);
pushField(subTree, prefix ? prefix + field : field);
}
}, {});
}

Expand Down
30 changes: 30 additions & 0 deletions src/splitter/util.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export const asNavField = (field, navConfs, uiSchema) => {
const separatorIndex = field.indexOf(".");
if (separatorIndex === -1) {
uiSchema[field] = {
navConfs,
"ui:field": "nav",
origUiSchema: uiSchema[field],
};
} else {
const parentField = field.substr(0, separatorIndex);
const childField = field.substr(separatorIndex + 1);

asNavField(childField, navConfs, uiSchema[parentField]);
}
};

function asHiddenField(field, uiSchema) {
uiSchema[field] = {
"ui:widget": "hidden",
"ui:field": "hidden",
};
}

export const toHiddenUiSchema = ({ properties }, uiSchema) => {
let cleanUiSchema = Object.keys(properties).reduce((agg, field) => {
asHiddenField(field, agg);
return agg;
}, Object.assign({}, uiSchema));
return cleanUiSchema;
};
62 changes: 62 additions & 0 deletions test/splitter/extractSubUiSchema.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,65 @@ test("extract with aliases", () => {
extractSubUiSchema(["firstName"], { firstName: "firstNameAlias" }, uiSchema)
).toEqual({ firstName: { classNames: "col-md-10" } });
});

test("extract nested", () => {
const schema = {
type: "object",
title: "Nested Pagination",
properties: {
general: {
type: "object",
properties: {
firstName: {
type: "string",
title: "First name",
},
lastName: {
type: "string",
title: "Last name",
},
},
},
},
};

const origUiSchema = {
general: {
nav: "general",
firstName: {
nav: ["general", "First name"],
},
lastName: {
nav: ["general", "Last name"],
},
},
};

const uiSchema = {
general: {
"ui:widget": "hidden",
"ui:field": "hidden",
},
};

expect(
extractSubUiSchema(
["general.firstName"],
{},
origUiSchema,
uiSchema,
schema
)
).toEqual({
general: {
nav: "general",
firstName: {
nav: ["general", "First name"],
},
lastName: {
"ui:widget": "hidden",
"ui:field": "hidden",
},
},
});
});
41 changes: 41 additions & 0 deletions test/splitter/util.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { toHiddenUiSchema } from "../../src/splitter/util";
import { withNav } from "../utils";

let schema = {
type: "object",
properties: {
firstName: { type: "string" },
lastName: { type: "string" },
nickName: { type: "string" },
},
};

let uiSchema = {
firstName: withNav("first"),
lastName: withNav("last"),
nickName: withNav("nick"),
navConf: {
order: ["first", "last", "nick"],
},
};

test("toHiddenUiSchema hides all the schema fields", () => {
const hiddenUiSchema = toHiddenUiSchema(schema, uiSchema);
expect(hiddenUiSchema).toEqual({
firstName: {
"ui:widget": "hidden",
"ui:field": "hidden",
},
lastName: {
"ui:widget": "hidden",
"ui:field": "hidden",
},
nickName: {
"ui:widget": "hidden",
"ui:field": "hidden",
},
navConf: {
order: ["first", "last", "nick"],
},
});
});

0 comments on commit 42e042a

Please sign in to comment.