Skip to content

Commit 21343b1

Browse files
committed
refactored core.ts and added test cases
1 parent dbfc138 commit 21343b1

29 files changed

+793
-208
lines changed

example/example.css

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
.jsf-categorization {display: flex; flex-direction: row;}
1717
.jsf-categorization > * {border: 1px solid;}
1818
.jsf-categorization > .jsf-categorization-master {flex: 1;}
19-
.jsf-categorization > .jsf-categorization-master > ul {list-style-type: none;}
20-
.jsf-categorization > .jsf-categorization-master > ul > li {cursor: pointer;}
21-
.jsf-categorization > .jsf-categorization-master > ul > li.selected {font-weight: bold;}
19+
.jsf-categorization > .jsf-categorization-master ul {list-style-type: none; font-weight: normal;}
20+
.jsf-categorization > .jsf-categorization-master ul > li {cursor: pointer;}
21+
.jsf-categorization > .jsf-categorization-master ul > li.selected {font-weight: bold;}
2222
.jsf-categorization > .jsf-categorization-detail {flex: 3;}
2323
*[hidden] {display: none;}

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
"file-loader": "^0.10.0",
1919
"jsdom": "^9.11.0",
2020
"jsdom-global": "2.1.1",
21-
"html-loader": "^0.4.5",
2221
"nyc": "^10.1.2",
2322
"source-map-loader": "^0.1.6",
2423
"tslint": "^4.4.2",

src/core.ts

Lines changed: 4 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -1,171 +1,8 @@
1-
import { UISchemaElement, ControlElement } from './models/uischema';
2-
import { JsonSchema } from './models/jsonSchema';
3-
import { getValuePropertyPair } from './path.util';
1+
import {UISchemaElement} from './models/uischema';
2+
import {JsonSchema} from './models/jsonSchema';
43
import {UiSchemaRegistry, UiSchemaRegistryImpl} from './core/uischema.registry';
5-
6-
export enum RUNTIME_TYPE {
7-
VALIDATION_ERROR, VISIBLE, ENABLED
8-
}
9-
export interface RuntimeListener {
10-
notify(type: RUNTIME_TYPE);
11-
}
12-
export class Runtime {
13-
private _validationErrors: Array<string> = [];
14-
private _visible = true;
15-
private _enabled = true;
16-
private _listeners: Array<RuntimeListener> = [];
17-
18-
get visible(): boolean {return this._visible; };
19-
get enabled(): boolean {return this._enabled; };
20-
get validationErrors(): Array<string> {return this._validationErrors; };
21-
22-
set visible(visible: boolean) {
23-
this._visible = visible;
24-
this.notifyListeners(RUNTIME_TYPE.VISIBLE);
25-
};
26-
27-
set enabled(enabled: boolean) {
28-
this._enabled = enabled;
29-
this.notifyListeners(RUNTIME_TYPE.ENABLED);
30-
};
31-
32-
set validationErrors(validationErrors: Array<string>) {
33-
this._validationErrors = validationErrors;
34-
this.notifyListeners(RUNTIME_TYPE.VALIDATION_ERROR);
35-
};
36-
37-
addListener(listener: RuntimeListener): void {
38-
this._listeners.push(listener);
39-
}
40-
41-
removeListener(listener: RuntimeListener): void {
42-
this._listeners.splice(this._listeners.indexOf(listener), 1);
43-
}
44-
45-
private notifyListeners(type: RUNTIME_TYPE): void {
46-
this._listeners.forEach(listener => listener.notify(type));
47-
}
48-
}
49-
50-
export abstract class Renderer extends HTMLElement implements RuntimeListener {
51-
protected uischema: UISchemaElement;
52-
protected dataService: DataService;
53-
protected dataSchema: JsonSchema;
54-
setUiSchema(uischema: UISchemaElement) {
55-
this.uischema = uischema;
56-
}
57-
58-
setDataService(dataService: DataService) {
59-
this.dataService = dataService;
60-
}
61-
62-
setDataSchema(dataSchema: JsonSchema) {
63-
this.dataSchema = dataSchema;
64-
}
65-
66-
notify(type: RUNTIME_TYPE): void {
67-
//
68-
}
69-
70-
connectedCallback(): void {
71-
if (!this.uischema.hasOwnProperty('runtime')) {
72-
const runtime = new Runtime();
73-
this.uischema['runtime'] = runtime;
74-
}
75-
const runtime = <Runtime>this.uischema['runtime'];
76-
runtime.addListener(this);
77-
this.render();
78-
}
79-
disconnectedCallback(): void {
80-
this.dispose();
81-
const runtime = <Runtime>this.uischema['runtime'];
82-
runtime.removeListener(this);
83-
}
84-
85-
abstract render(): HTMLElement;
86-
abstract dispose(): void;
87-
}
88-
export interface RendererTester {
89-
(element: UISchemaElement, schema: JsonSchema): number;
90-
}
91-
class RendererService {
92-
private renderers= [];
93-
registerRenderer(tester: RendererTester, renderer: string): void {
94-
this.renderers.push({tester: tester, renderer: renderer});
95-
}
96-
unregisterRenderer(tester: RendererTester, renderer: string): void {
97-
this.renderers.splice(this.renderers.indexOf({tester: tester, renderer: renderer}), 1);
98-
}
99-
getBestRenderer(uischema: UISchemaElement,
100-
schema: JsonSchema,
101-
dataService: DataService): HTMLElement {
102-
let bestRenderer: string;
103-
let specificity = -1;
104-
this.renderers.forEach(renderer => {
105-
const rSpec = renderer.tester(uischema, schema);
106-
if (rSpec > specificity) {
107-
bestRenderer = renderer.renderer;
108-
specificity = rSpec;
109-
}
110-
});
111-
let renderer: HTMLElement;
112-
if (bestRenderer === undefined) {
113-
renderer = document.createElement('label');
114-
renderer.textContent = 'Unknown Schema: ' + JSON.stringify(uischema);
115-
} else {
116-
const cRenderer = <Renderer> document.createElement(bestRenderer);
117-
cRenderer.setUiSchema(uischema);
118-
cRenderer.setDataSchema(schema);
119-
cRenderer.setDataService(dataService);
120-
renderer = cRenderer;
121-
}
122-
return renderer;
123-
}
124-
}
125-
126-
export interface DataChangeListener {
127-
isRelevantKey: (uischema: ControlElement) => boolean;
128-
notifyChange(uischema: ControlElement, newValue: any, data: any): void;
129-
}
130-
export class DataService {
131-
private changeListeners: Array<DataChangeListener>= [];
132-
constructor(private data: any) {
133-
}
134-
notifyChange(uischema: ControlElement, newValue: any): void {
135-
const pair = getValuePropertyPair(this.data, uischema.scope.$ref);
136-
if (Array.isArray(pair.instance[pair.property])) {
137-
pair.instance[pair.property].push(newValue);
138-
} else {
139-
pair.instance[pair.property] = newValue;
140-
}
141-
142-
this.changeListeners.forEach(listener => {
143-
if (listener.isRelevantKey(uischema)) {
144-
listener.notifyChange(uischema, newValue, this.data);
145-
}
146-
});
147-
}
148-
registerChangeListener(listener: DataChangeListener): void {
149-
this.changeListeners.push(listener);
150-
}
151-
unregisterChangeListener(listener: DataChangeListener): void {
152-
this.changeListeners.splice(this.changeListeners.indexOf(listener), 1);
153-
}
154-
getValue(uischema: ControlElement): any {
155-
const pair = getValuePropertyPair(this.data, uischema.scope.$ref);
156-
if (pair.property === undefined) {
157-
return pair.instance;
158-
}
159-
return pair.instance[pair.property];
160-
}
161-
initialRootRun(): void {
162-
this.changeListeners.forEach(listener => {
163-
if (listener.isRelevantKey(null)) {
164-
listener.notifyChange(null, null, this.data);
165-
}
166-
});
167-
}
168-
}
4+
import {DataService} from './core/data.service';
5+
import {RendererService} from './core/renderer.service';
1696

1707
export interface JsonFormService {
1718
dispose(): void;

src/core/data.service.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import {ControlElement} from '../models/uischema';
2+
import { getValuePropertyPair } from '../path.util';
3+
4+
export interface DataChangeListener {
5+
isRelevantKey(uischema: ControlElement): boolean;
6+
notifyChange(uischema: ControlElement, newValue: any, data: any): void;
7+
}
8+
export class DataService {
9+
private changeListeners: Array<DataChangeListener>= [];
10+
constructor(private data: any) {
11+
}
12+
notifyChange(uischema: ControlElement, newValue: any): void {
13+
const pair = getValuePropertyPair(this.data, uischema.scope.$ref);
14+
pair.instance[pair.property] = newValue;
15+
16+
this.changeListeners.forEach(listener => {
17+
if (listener.isRelevantKey(uischema)) {
18+
listener.notifyChange(uischema, newValue, this.data);
19+
}
20+
});
21+
}
22+
registerChangeListener(listener: DataChangeListener): void {
23+
this.changeListeners.push(listener);
24+
}
25+
unregisterChangeListener(listener: DataChangeListener): void {
26+
this.changeListeners.splice(this.changeListeners.indexOf(listener), 1);
27+
}
28+
getValue(uischema: ControlElement): any {
29+
const pair = getValuePropertyPair(this.data, uischema.scope.$ref);
30+
if (pair.property === undefined) {
31+
return pair.instance;
32+
}
33+
return pair.instance[pair.property];
34+
}
35+
initialRootRun(): void {
36+
this.changeListeners.forEach(listener => {
37+
if (listener.isRelevantKey(null)) {
38+
listener.notifyChange(null, null, this.data);
39+
}
40+
});
41+
}
42+
}

src/core/renderer.service.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import {UISchemaElement} from '../models/uischema';
2+
import {JsonSchema} from '../models/jsonSchema';
3+
import {DataService} from './data.service';
4+
import {Renderer} from './renderer';
5+
6+
export interface RendererTester {
7+
(element: UISchemaElement, schema: JsonSchema): number;
8+
}
9+
export class RendererService {
10+
private renderers= [];
11+
registerRenderer(tester: RendererTester, renderer: string): void {
12+
this.renderers.push({tester: tester, renderer: renderer});
13+
}
14+
unregisterRenderer(tester: RendererTester, renderer: string): void {
15+
this.renderers.splice(this.renderers.indexOf({tester: tester, renderer: renderer}), 1);
16+
}
17+
getBestRenderer(uischema: UISchemaElement,
18+
schema: JsonSchema,
19+
dataService: DataService): HTMLElement {
20+
let bestRenderer: string;
21+
let specificity = -1;
22+
this.renderers.forEach(renderer => {
23+
const rSpec = renderer.tester(uischema, schema);
24+
if (rSpec > specificity) {
25+
bestRenderer = renderer.renderer;
26+
specificity = rSpec;
27+
}
28+
});
29+
let renderer: HTMLElement;
30+
if (bestRenderer === undefined) {
31+
renderer = document.createElement('label');
32+
renderer.textContent = 'Unknown Schema: ' + JSON.stringify(uischema);
33+
} else {
34+
const cRenderer = <Renderer> document.createElement(bestRenderer);
35+
cRenderer.setUiSchema(uischema);
36+
cRenderer.setDataSchema(schema);
37+
cRenderer.setDataService(dataService);
38+
renderer = cRenderer;
39+
}
40+
return renderer;
41+
}
42+
}

src/core/renderer.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { UISchemaElement } from '../models/uischema';
2+
import { JsonSchema } from '../models/jsonSchema';
3+
import {DataService} from './data.service';
4+
import {Runtime, RUNTIME_TYPE, RuntimeListener} from './runtime';
5+
6+
export abstract class Renderer extends HTMLElement implements RuntimeListener {
7+
protected uischema: UISchemaElement;
8+
protected dataService: DataService;
9+
protected dataSchema: JsonSchema;
10+
setUiSchema(uischema: UISchemaElement) {
11+
this.uischema = uischema;
12+
}
13+
14+
setDataService(dataService: DataService) {
15+
this.dataService = dataService;
16+
}
17+
18+
setDataSchema(dataSchema: JsonSchema) {
19+
this.dataSchema = dataSchema;
20+
}
21+
22+
notify(type: RUNTIME_TYPE): void {
23+
//
24+
}
25+
26+
connectedCallback(): void {
27+
if (!this.uischema.hasOwnProperty('runtime')) {
28+
const runtime = new Runtime();
29+
this.uischema['runtime'] = runtime;
30+
}
31+
const runtime = <Runtime>this.uischema['runtime'];
32+
runtime.addListener(this);
33+
this.render();
34+
}
35+
disconnectedCallback(): void {
36+
this.dispose();
37+
const runtime = <Runtime>this.uischema['runtime'];
38+
runtime.removeListener(this);
39+
}
40+
41+
abstract render(): HTMLElement;
42+
abstract dispose(): void;
43+
}

src/core/runtime.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
export enum RUNTIME_TYPE {
2+
VALIDATION_ERROR, VISIBLE, ENABLED
3+
}
4+
export interface RuntimeListener {
5+
notify(type: RUNTIME_TYPE): void;
6+
}
7+
export class Runtime {
8+
private _validationErrors: Array<string> = [];
9+
private _visible = true;
10+
private _enabled = true;
11+
private _listeners: Array<RuntimeListener> = [];
12+
13+
get visible(): boolean {return this._visible; };
14+
get enabled(): boolean {return this._enabled; };
15+
get validationErrors(): Array<string> {return this._validationErrors; };
16+
17+
set visible(visible: boolean) {
18+
this._visible = visible;
19+
this.notifyListeners(RUNTIME_TYPE.VISIBLE);
20+
};
21+
22+
set enabled(enabled: boolean) {
23+
this._enabled = enabled;
24+
this.notifyListeners(RUNTIME_TYPE.ENABLED);
25+
};
26+
27+
set validationErrors(validationErrors: Array<string>) {
28+
this._validationErrors = validationErrors;
29+
this.notifyListeners(RUNTIME_TYPE.VALIDATION_ERROR);
30+
};
31+
32+
addListener(listener: RuntimeListener): void {
33+
this._listeners.push(listener);
34+
}
35+
36+
removeListener(listener: RuntimeListener): void {
37+
this._listeners.splice(this._listeners.indexOf(listener), 1);
38+
}
39+
40+
private notifyListeners(type: RUNTIME_TYPE): void {
41+
this._listeners.forEach(listener => listener.notify(type));
42+
}
43+
}

0 commit comments

Comments
 (0)