pict-section-recordset 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/launch.json +46 -0
- package/debug/Harness.js +0 -7
- package/example_applications/list_view/index.html +125 -0
- package/example_applications/simple_entity/Simple-RecordSet-Application.js +32 -26
- package/example_applications/simple_entity/html/index.html +3 -3
- package/package.json +9 -6
- package/source/Pict-Section-RecordSet.js +6 -2
- package/source/application/Pict-Application-RecordSet.js +11 -0
- package/source/providers/RecordSet-RecordProvider-Base.js +217 -0
- package/source/providers/RecordSet-RecordProvider-MeadowEndpoints.js +339 -0
- package/source/services/RecordsSet-MetaController.js +196 -0
- package/source/views/RecordSet-Filter.js +91 -0
- package/source/views/RecordsSet-MacroView.js +0 -0
- package/source/views/dashboard/RecordSet-Dashboard-HeaderDashboard.js +63 -0
- package/source/views/dashboard/RecordSet-Dashboard-RecordSetDashboard.js +63 -0
- package/source/views/dashboard/RecordSet-Dashboard-TabBarDashboard.js +63 -0
- package/source/views/dashboard/RecordSet-Dashboard.js +63 -0
- package/source/views/edit/RecordSet-Edit-HeaderEdit.js +63 -0
- package/source/views/edit/RecordSet-Edit-RecordEdit.js +63 -0
- package/source/views/edit/RecordSet-Edit-RecordEditControls.js +63 -0
- package/source/views/edit/RecordSet-Edit-RecordEditExtra.js +63 -0
- package/source/views/edit/RecordSet-Edit-TabBarEdit.js +63 -0
- package/source/views/edit/RecordSet-Edit.js +63 -0
- package/source/views/list/RecordSet-List-HeaderList.js +63 -0
- package/source/views/list/RecordSet-List-PaginationBottom.js +67 -0
- package/source/views/list/RecordSet-List-PaginationTop.js +115 -0
- package/source/views/list/RecordSet-List-RecordList.js +79 -0
- package/source/views/list/RecordSet-List-RecordListEntry.js +92 -0
- package/source/views/list/RecordSet-List-RecordListHeader.js +87 -0
- package/source/views/list/RecordSet-List-Title.js +67 -0
- package/source/views/list/RecordSet-List.js +167 -0
- package/source/views/read/RecordSet-Read-HeaderRead.js +63 -0
- package/source/views/read/RecordSet-Read-RecordRead.js +63 -0
- package/source/views/read/RecordSet-Read-RecordReadExtra.js +63 -0
- package/source/views/read/RecordSet-Read-TabBarRead.js +63 -0
- package/source/views/read/RecordSet-Read.js +63 -0
- package/test/PictSectionRecordSet-Basic_tests.js +1 -1
- package/test/PictSectionRecordSet-RecordProvider-Meadow_tests.js +203 -0
- package/tsconfig.build.json +16 -0
- package/tsconfig.json +1 -1
- package/types/Pict-Section-RecordSet.d.ts +5 -1
- package/types/application/Pict-Application-RecordSet.d.ts.map +1 -1
- package/types/providers/RecordSet-RecordProvider-Base.d.ts +207 -0
- package/types/providers/RecordSet-RecordProvider-Base.d.ts.map +1 -1
- package/types/providers/RecordSet-RecordProvider-MeadowEndpoints.d.ts +100 -0
- package/types/providers/RecordSet-RecordProvider-MeadowEndpoints.d.ts.map +1 -0
- package/types/services/RecordsSet-MetaController.d.ts +30 -0
- package/types/services/RecordsSet-MetaController.d.ts.map +1 -0
- package/types/views/RecordSet-Filter.d.ts +34 -0
- package/types/views/RecordSet-Filter.d.ts.map +1 -0
- package/types/views/RecordsSet-MacroView.d.ts +1 -0
- package/types/views/RecordsSet-MacroView.d.ts.map +1 -0
- package/types/views/dashboard/RecordSet-Dashboard-HeaderDashboard.d.ts +34 -0
- package/types/views/dashboard/RecordSet-Dashboard-HeaderDashboard.d.ts.map +1 -0
- package/types/views/dashboard/RecordSet-Dashboard-RecordSetDashboard.d.ts +34 -0
- package/types/views/dashboard/RecordSet-Dashboard-RecordSetDashboard.d.ts.map +1 -0
- package/types/views/dashboard/RecordSet-Dashboard-TabBarDashboard.d.ts +34 -0
- package/types/views/dashboard/RecordSet-Dashboard-TabBarDashboard.d.ts.map +1 -0
- package/types/views/dashboard/RecordSet-Dashboard.d.ts +34 -0
- package/types/views/dashboard/RecordSet-Dashboard.d.ts.map +1 -0
- package/types/views/edit/RecordSet-Edit-HeaderEdit.d.ts +34 -0
- package/types/views/edit/RecordSet-Edit-HeaderEdit.d.ts.map +1 -0
- package/types/views/edit/RecordSet-Edit-RecordEdit.d.ts +34 -0
- package/types/views/edit/RecordSet-Edit-RecordEdit.d.ts.map +1 -0
- package/types/views/edit/RecordSet-Edit-RecordEditControls.d.ts +34 -0
- package/types/views/edit/RecordSet-Edit-RecordEditControls.d.ts.map +1 -0
- package/types/views/edit/RecordSet-Edit-RecordEditExtra.d.ts +34 -0
- package/types/views/edit/RecordSet-Edit-RecordEditExtra.d.ts.map +1 -0
- package/types/views/edit/RecordSet-Edit-TabBarEdit.d.ts +34 -0
- package/types/views/edit/RecordSet-Edit-TabBarEdit.d.ts.map +1 -0
- package/types/views/edit/RecordSet-Edit.d.ts +34 -0
- package/types/views/edit/RecordSet-Edit.d.ts.map +1 -0
- package/types/views/list/RecordSet-List-HeaderList.d.ts +34 -0
- package/types/views/list/RecordSet-List-HeaderList.d.ts.map +1 -0
- package/types/views/list/RecordSet-List-PaginationBottom.d.ts +34 -0
- package/types/views/list/RecordSet-List-PaginationBottom.d.ts.map +1 -0
- package/types/views/list/RecordSet-List-PaginationTop.d.ts +34 -0
- package/types/views/list/RecordSet-List-PaginationTop.d.ts.map +1 -0
- package/types/views/list/RecordSet-List-RecordList.d.ts +34 -0
- package/types/views/list/RecordSet-List-RecordList.d.ts.map +1 -0
- package/types/views/list/RecordSet-List-RecordListEntry.d.ts +34 -0
- package/types/views/list/RecordSet-List-RecordListEntry.d.ts.map +1 -0
- package/types/views/list/RecordSet-List-RecordListHeader.d.ts +34 -0
- package/types/views/list/RecordSet-List-RecordListHeader.d.ts.map +1 -0
- package/types/views/list/RecordSet-List-Title.d.ts +34 -0
- package/types/views/list/RecordSet-List-Title.d.ts.map +1 -0
- package/types/views/list/RecordSet-List.d.ts +43 -0
- package/types/views/list/RecordSet-List.d.ts.map +1 -0
- package/types/views/read/RecordSet-Read-HeaderRead.d.ts +34 -0
- package/types/views/read/RecordSet-Read-HeaderRead.d.ts.map +1 -0
- package/types/views/read/RecordSet-Read-RecordRead.d.ts +34 -0
- package/types/views/read/RecordSet-Read-RecordRead.d.ts.map +1 -0
- package/types/views/read/RecordSet-Read-RecordReadExtra.d.ts +34 -0
- package/types/views/read/RecordSet-Read-RecordReadExtra.d.ts.map +1 -0
- package/types/views/read/RecordSet-Read-TabBarRead.d.ts +34 -0
- package/types/views/read/RecordSet-Read-TabBarRead.d.ts.map +1 -0
- package/types/views/read/RecordSet-Read.d.ts +34 -0
- package/types/views/read/RecordSet-Read.d.ts.map +1 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
|
|
2
|
+
const libRecordSetProviderBase = require('./RecordSet-RecordProvider-Base.js');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {(error?: Error, result?: any) => void} RestClientCallback
|
|
6
|
+
*
|
|
7
|
+
* @typedef {import('./RecordSet-RecordProvider-Base.js').RecordSetFilter} RecordSetFilter
|
|
8
|
+
* @typedef {import('./RecordSet-RecordProvider-Base.js').RecordSetResult} RecordSetResult
|
|
9
|
+
*
|
|
10
|
+
* @typedef {{
|
|
11
|
+
* getJSON(pOptionsOrURL: string | Record<string, any>, fCallback: RestClientCallback): void,
|
|
12
|
+
* putJSON(pOptions: Record<string, any>, fCallback: RestClientCallback): void,
|
|
13
|
+
* postJSON(pOptions: Record<string, any>, fCallback: RestClientCallback): void,
|
|
14
|
+
* patchJSON(pOptions: Record<string, any>, fCallback: RestClientCallback): void,
|
|
15
|
+
* headJSON(pOptions: Record<string, any>, fCallback: RestClientCallback): void,
|
|
16
|
+
* delJSON(pOptions: Record<string, any>, fCallback: RestClientCallback): void,
|
|
17
|
+
* getRawText(pOptionsOrURL: string | Record<string, any>, fCallback: RestClientCallback): void,
|
|
18
|
+
* }} RestClient
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Class representing a data change detection provider for Pict dynamic forms.
|
|
23
|
+
* @extends libRecordSetProviderBase
|
|
24
|
+
*/
|
|
25
|
+
class RecordSetProvider extends libRecordSetProviderBase
|
|
26
|
+
{
|
|
27
|
+
/**
|
|
28
|
+
* Creates an instance of RecordSetProvider.
|
|
29
|
+
* @param {import('fable')} pFable - The Fable object.
|
|
30
|
+
* @param {Record<string, any>} [pOptions] - Custom options for the provider.
|
|
31
|
+
* @param {string} [pServiceHash] - The service hash.
|
|
32
|
+
*/
|
|
33
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
34
|
+
{
|
|
35
|
+
super(pFable, pOptions, pServiceHash);
|
|
36
|
+
|
|
37
|
+
/** @type {RestClient} */
|
|
38
|
+
this.restClient;
|
|
39
|
+
/** @type {Record<string, any>} */
|
|
40
|
+
this.options;
|
|
41
|
+
/** @type {import('fable')} */
|
|
42
|
+
this.fable;
|
|
43
|
+
/** @type {import('pict')} */
|
|
44
|
+
this.pict;
|
|
45
|
+
//TODO: make this typedef better
|
|
46
|
+
/** @type {Record<string, any>} */
|
|
47
|
+
this._Schema = { };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @typedef {(error?: Error, result?: T) => void} RecordSetCallback
|
|
52
|
+
* @template T = Record<string, any>
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Get a record by its ID or GUID.
|
|
57
|
+
*
|
|
58
|
+
* @param {string|number} pIDOrGuid - The ID or GUID of the record.
|
|
59
|
+
*/
|
|
60
|
+
async getRecord(pIDOrGuid)
|
|
61
|
+
{
|
|
62
|
+
if (!this.options.Entity)
|
|
63
|
+
{
|
|
64
|
+
throw new Error('Entity is not defined in the provider options.');
|
|
65
|
+
}
|
|
66
|
+
if (typeof pIDOrGuid === 'string' && isNaN(parseInt(pIDOrGuid)))
|
|
67
|
+
{
|
|
68
|
+
return this.getRecordByGUID(pIDOrGuid);
|
|
69
|
+
}
|
|
70
|
+
if (this.pict.LogNoisiness > 1)
|
|
71
|
+
{
|
|
72
|
+
this.pict.log.info(`Reading ${this.options.Entity} record by ID`, { ID: pIDOrGuid });
|
|
73
|
+
}
|
|
74
|
+
return new Promise((resolve, reject) =>
|
|
75
|
+
{
|
|
76
|
+
this.restClient.getJSON(`${this.options.URLPrefix}${this.options.Entity}/${pIDOrGuid}`, (error, response, result) =>
|
|
77
|
+
{
|
|
78
|
+
if (error)
|
|
79
|
+
{
|
|
80
|
+
return reject(error);
|
|
81
|
+
}
|
|
82
|
+
resolve(result);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Get a record by its ID or GUID.
|
|
89
|
+
*
|
|
90
|
+
* @param {string|number} pGuid - The ID or GUID of the record.
|
|
91
|
+
*/
|
|
92
|
+
async getRecordByGUID(pGuid)
|
|
93
|
+
{
|
|
94
|
+
if (!this.options.Entity)
|
|
95
|
+
{
|
|
96
|
+
throw new Error('Entity is not defined in the provider options.');
|
|
97
|
+
}
|
|
98
|
+
if (this.pict.LogNoisiness > 1)
|
|
99
|
+
{
|
|
100
|
+
this.pict.log.info(`Reading ${this.options.Entity} record by GUID`, { GUID: pGuid });
|
|
101
|
+
}
|
|
102
|
+
return new Promise((resolve, reject) =>
|
|
103
|
+
{
|
|
104
|
+
this.restClient.getJSON(`${this.options.URLPrefix}${this.options.Entity}s/FilteredTo/FBV~GUID${this.options.Entity}~EQ~${encodeURIComponent(pGuid)}`, (error, response, result) =>
|
|
105
|
+
{
|
|
106
|
+
if (error)
|
|
107
|
+
{
|
|
108
|
+
return reject(error);
|
|
109
|
+
}
|
|
110
|
+
resolve(result[0]);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Read records from the provider.
|
|
117
|
+
*
|
|
118
|
+
* @param {RecordSetFilter} pOptions - Options for the read operation.
|
|
119
|
+
* @return {Promise<RecordSetResult>} - The result of the read operation.
|
|
120
|
+
*/
|
|
121
|
+
async getRecords(pOptions)
|
|
122
|
+
{
|
|
123
|
+
if (!this.options.Entity && !pOptions.Entity)
|
|
124
|
+
{
|
|
125
|
+
throw new Error('Entity is not defined in the provider options.');
|
|
126
|
+
}
|
|
127
|
+
if (this.pict.LogNoisiness > 1)
|
|
128
|
+
{
|
|
129
|
+
this.pict.log.info(`Reading ${this.options.Entity} records`, { Options: pOptions });
|
|
130
|
+
}
|
|
131
|
+
const filterString = pOptions.FilterString ? `/FilteredTo/${pOptions.FilterString}` : '';
|
|
132
|
+
const pagination = `/${pOptions.Offset || 0}/${pOptions.PageSize || 250}`;
|
|
133
|
+
//TODO: lite support / other variants?
|
|
134
|
+
return new Promise((resolve, reject) =>
|
|
135
|
+
{
|
|
136
|
+
this.restClient.getJSON(`${this.options.URLPrefix}${this.options.Entity || pOptions.Entity}s${filterString}${pagination}`, (error, response, result) =>
|
|
137
|
+
{
|
|
138
|
+
if (error)
|
|
139
|
+
{
|
|
140
|
+
return reject(error);
|
|
141
|
+
}
|
|
142
|
+
resolve({ Records: result, Facets: { } });
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Read records from the provider.
|
|
149
|
+
*
|
|
150
|
+
* @param {string} [pFilterString] - The filter string to apply.
|
|
151
|
+
* @param {number} [pOffset] - The starting record number for pagination.
|
|
152
|
+
* @param {number} [pPageSize] - The number of records to return.
|
|
153
|
+
* @return {Promise<RecordSetResult>} - The result of the read operation.
|
|
154
|
+
*/
|
|
155
|
+
async getRecordsInline(pFilterString = '', pOffset = 0, pPageSize = 250)
|
|
156
|
+
{
|
|
157
|
+
return this.getRecords({ FilterString: pFilterString, Offset: pOffset, PageSize: pPageSize });
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Read records from the provider.
|
|
162
|
+
*
|
|
163
|
+
* @param {RecordSetFilter} pOptions - Options for the read operation.
|
|
164
|
+
*/
|
|
165
|
+
async getRecordSetCount(pOptions)
|
|
166
|
+
{
|
|
167
|
+
if (!this.options.Entity && !pOptions.Entity)
|
|
168
|
+
{
|
|
169
|
+
throw new Error('Entity is not defined in the provider options.');
|
|
170
|
+
}
|
|
171
|
+
if (this.pict.LogNoisiness > 1)
|
|
172
|
+
{
|
|
173
|
+
this.pict.log.info(`Counting ${this.options.Entity} records`, { Options: pOptions });
|
|
174
|
+
}
|
|
175
|
+
const filterString = pOptions.FilterString ? `/FilteredTo/${pOptions.FilterString}` : '';
|
|
176
|
+
//TODO: lite support / other variants?
|
|
177
|
+
return new Promise((resolve, reject) =>
|
|
178
|
+
{
|
|
179
|
+
this.restClient.getJSON(`${this.options.URLPrefix}${this.options.Entity || pOptions.Entity}s/Count${filterString}`, (error, response, result) =>
|
|
180
|
+
{
|
|
181
|
+
if (error)
|
|
182
|
+
{
|
|
183
|
+
return reject(error);
|
|
184
|
+
}
|
|
185
|
+
resolve(result);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Create a new record.
|
|
192
|
+
*
|
|
193
|
+
* @param {Record<string, any>} pRecord - The record to create.
|
|
194
|
+
*/
|
|
195
|
+
async createRecord(pRecord)
|
|
196
|
+
{
|
|
197
|
+
return new Promise((resolve, reject) =>
|
|
198
|
+
{
|
|
199
|
+
if (this.pict.LogNoisiness > 1)
|
|
200
|
+
{
|
|
201
|
+
this.pict.log.info(`Creating record ${this.options.Entity}`, { Record: pRecord });
|
|
202
|
+
}
|
|
203
|
+
this.restClient.postJSON({
|
|
204
|
+
url: `${this.options.URLPrefix}${this.options.Entity}`,
|
|
205
|
+
body: pRecord,
|
|
206
|
+
}, (error, response, result) =>
|
|
207
|
+
{
|
|
208
|
+
if (error)
|
|
209
|
+
{
|
|
210
|
+
return reject(error);
|
|
211
|
+
}
|
|
212
|
+
resolve(result);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Update a record.
|
|
219
|
+
*
|
|
220
|
+
* @param {Record<string, any>} pRecord - The record to update.
|
|
221
|
+
*/
|
|
222
|
+
async updateRecord(pRecord)
|
|
223
|
+
{
|
|
224
|
+
if (this.pict.LogNoisiness > 1)
|
|
225
|
+
{
|
|
226
|
+
this.pict.log.info(`Updating record ${this.options.Entity} ${pRecord[`ID${this.options.Entity}`]}`);
|
|
227
|
+
}
|
|
228
|
+
return new Promise((resolve, reject) =>
|
|
229
|
+
{
|
|
230
|
+
this.restClient.putJSON({
|
|
231
|
+
url: `${this.options.URLPrefix}${this.options.Entity}`,
|
|
232
|
+
body: pRecord,
|
|
233
|
+
}, (error, response, result) =>
|
|
234
|
+
{
|
|
235
|
+
if (error)
|
|
236
|
+
{
|
|
237
|
+
return reject(error);
|
|
238
|
+
}
|
|
239
|
+
resolve(result);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Delete a record.
|
|
246
|
+
*
|
|
247
|
+
* @param {Record<string, any>} pRecord - The record to delete.
|
|
248
|
+
*/
|
|
249
|
+
async deleteRecord(pRecord)
|
|
250
|
+
{
|
|
251
|
+
if (this.pict.LogNoisiness > 1)
|
|
252
|
+
{
|
|
253
|
+
this.pict.log.info(`Deleting record ${this.options.Entity} ${pRecord[`ID${this.options.Entity}`]}`);
|
|
254
|
+
}
|
|
255
|
+
return new Promise((resolve, reject) =>
|
|
256
|
+
{
|
|
257
|
+
this.restClient.delJSON({
|
|
258
|
+
url: `${this.options.URLPrefix}${this.options.Entity}/${pRecord[`ID${this.options.Entity}`]}`,
|
|
259
|
+
body: pRecord,
|
|
260
|
+
}, (error, response, result) =>
|
|
261
|
+
{
|
|
262
|
+
if (error)
|
|
263
|
+
{
|
|
264
|
+
return reject(error);
|
|
265
|
+
}
|
|
266
|
+
resolve(result);
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Read a record.
|
|
273
|
+
*
|
|
274
|
+
* @param {string|number} pIDOrGuid - The ID or GUID of the record.
|
|
275
|
+
*/
|
|
276
|
+
async readRecord(pIDOrGuid)
|
|
277
|
+
{
|
|
278
|
+
return this.getRecord(pIDOrGuid);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Read records from the provider.
|
|
283
|
+
*
|
|
284
|
+
* @param {RecordSetFilter} pOptions - Options for the read operation.
|
|
285
|
+
* @return {Promise<RecordSetResult>} - The result of the read operation.
|
|
286
|
+
*/
|
|
287
|
+
async readRecords(pOptions)
|
|
288
|
+
{
|
|
289
|
+
return this.getRecords(pOptions);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Clone a record.
|
|
294
|
+
*
|
|
295
|
+
* @param {Record<string, any>} pRecord - The record to clone.
|
|
296
|
+
*/
|
|
297
|
+
async cloneRecord(pRecord)
|
|
298
|
+
{
|
|
299
|
+
return this.createRecord(this.cleanRecord(pRecord));
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Remove any intrinsic identifiers from a record.
|
|
304
|
+
*
|
|
305
|
+
* @param {Record<string, any>} pRecord - The record to clean.
|
|
306
|
+
*/
|
|
307
|
+
cleanRecord(pRecord)
|
|
308
|
+
{
|
|
309
|
+
delete pRecord[`ID${this.options.Entity}`];
|
|
310
|
+
delete pRecord[`GUID${this.options.Entity}`];
|
|
311
|
+
return pRecord;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* @param {(error?: Error) => void} fCallback - The callback function.
|
|
316
|
+
*/
|
|
317
|
+
onInitializeAsync(fCallback)
|
|
318
|
+
{
|
|
319
|
+
this.fable.log.info('Initializing RecordSetProvider-MeadowEndpoints');
|
|
320
|
+
this.restClient = this.fable.RestClient;
|
|
321
|
+
this.restClient.getJSON(`${this.options.URLPrefix}${this.options.Entity}/Schema`, (error, response, result) =>
|
|
322
|
+
{
|
|
323
|
+
if (error)
|
|
324
|
+
{
|
|
325
|
+
this._Schema = { };
|
|
326
|
+
return fCallback(error);
|
|
327
|
+
}
|
|
328
|
+
this._Schema = result;
|
|
329
|
+
return fCallback(null);
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
get recordSchema()
|
|
334
|
+
{
|
|
335
|
+
return this._Schema;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
module.exports = RecordSetProvider;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
const libFableServiceProviderBase = require('fable-serviceproviderbase');
|
|
2
|
+
|
|
3
|
+
const viewRecordSetList = require('../views/list/RecordSet-List.js');
|
|
4
|
+
const viewRecordSetEdit = require('../views/edit/RecordSet-Edit.js');
|
|
5
|
+
const viewRecordSetRead = require('../views/read/RecordSet-Read.js');
|
|
6
|
+
const viewRecordSetDashboard = require('../views/dashboard/RecordSet-Dashboard.js');
|
|
7
|
+
|
|
8
|
+
//_Pict.addProvider('BooksProvider', { Entity: 'Book', URLPrefix: 'http://www.datadebase.com:8086/1.0/' }, require('../source/providers/RecordSet-RecordProvider-MeadowEndpoints.js'));
|
|
9
|
+
const providerBase = require('../providers/RecordSet-RecordProvider-Base.js');
|
|
10
|
+
const providerMeadowEndpoints = require('../providers/RecordSet-RecordProvider-MeadowEndpoints.js');
|
|
11
|
+
|
|
12
|
+
const providerPictRouter = require('pict-router');
|
|
13
|
+
|
|
14
|
+
const { type } = require('os');
|
|
15
|
+
|
|
16
|
+
class RecordSetMetacontroller extends libFableServiceProviderBase
|
|
17
|
+
{
|
|
18
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
19
|
+
{
|
|
20
|
+
// Intersect default options, parent constructor, service information
|
|
21
|
+
super(pFable, pOptions, pServiceHash);
|
|
22
|
+
|
|
23
|
+
/** @type {import('pict') & { addAndInstantiateSingletonService: (hash: string, options: any, prototype: any) => any }} */
|
|
24
|
+
this.fable;
|
|
25
|
+
/** @type {any} */
|
|
26
|
+
this.log;
|
|
27
|
+
/** @type {any} */
|
|
28
|
+
this.options;
|
|
29
|
+
/** @type {string} */
|
|
30
|
+
this.UUID;
|
|
31
|
+
|
|
32
|
+
this.childViews = {
|
|
33
|
+
list: null,
|
|
34
|
+
edit: null,
|
|
35
|
+
read: null,
|
|
36
|
+
dashboard: null
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
this.recordSetProviders = {};
|
|
40
|
+
this.recordSetProviderConfigurations = {};
|
|
41
|
+
|
|
42
|
+
this.has_initialized = false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/*
|
|
46
|
+
"DefaultRecordSetConfigurations":
|
|
47
|
+
[
|
|
48
|
+
{
|
|
49
|
+
"RecordSet": "Book",
|
|
50
|
+
|
|
51
|
+
"RecordSetType": "MeadowEndpoint", // Could be "Custom" which would require a provider to already be created for the record set.
|
|
52
|
+
"RecordSetMeadowEntity": "Book", // This leverages the /Schema endpoint to get the record set columns.
|
|
53
|
+
|
|
54
|
+
"RecordSetURLPrefix": "http://www.datadebase.com:8086/1.0/"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"RecordSet": "Author",
|
|
58
|
+
|
|
59
|
+
"RecordSetType": "MeadowEndpoint",
|
|
60
|
+
"RecordSetMeadowEntity": "Author",
|
|
61
|
+
|
|
62
|
+
"RecordSetURLPrefix": "http://www.datadebase.com:8086/1.0/"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"RecordSet": "RandomizedValues",
|
|
66
|
+
|
|
67
|
+
"RecordSetType": "Custom" // This means the `PS-RSP-RandomizedValues` provider will be checked for to get records.
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
*/
|
|
71
|
+
loadRecordSetConfiguration(pRecordSetConfiguration)
|
|
72
|
+
{
|
|
73
|
+
if (typeof pRecordSetConfiguration !== 'object')
|
|
74
|
+
{
|
|
75
|
+
this.fable.log.error(`RecordSetMetacontroller: ${this.UUID} loadRecordSetConfiguration called with invalid configuration.`);
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
if ((!('RecordSet' in pRecordSetConfiguration)) || (pRecordSetConfiguration.RecordSet === ''))
|
|
79
|
+
{
|
|
80
|
+
this.fable.log.error(`RecordSetMetacontroller: ${this.UUID} loadRecordSetConfiguration called with invalid configuration. Missing RecordSet.`);
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const providerConfiguration = Object.assign({}, {Hash: `RSP-Provider-${pRecordSetConfiguration.RecordSet}`}, pRecordSetConfiguration);
|
|
85
|
+
this.recordSetProviderConfigurations[providerConfiguration.RecordSet] = providerConfiguration;
|
|
86
|
+
|
|
87
|
+
switch (pRecordSetConfiguration.RecordSetType)
|
|
88
|
+
{
|
|
89
|
+
case 'MeadowEndpoint':
|
|
90
|
+
// Create a Meadow Endpoints provider
|
|
91
|
+
// Allow the Record Set to optionally point to a different entity
|
|
92
|
+
if (`RecordSetMeadowEntity` in pRecordSetConfiguration)
|
|
93
|
+
{
|
|
94
|
+
providerConfiguration.Entity = pRecordSetConfiguration.RecordSetMeadowEntity;
|
|
95
|
+
}
|
|
96
|
+
else
|
|
97
|
+
{
|
|
98
|
+
providerConfiguration.Entity = pRecordSetConfiguration.RecordSet;
|
|
99
|
+
}
|
|
100
|
+
// Default the URLPrefix to the base URLPrefix
|
|
101
|
+
if (`URLPrefix` in pRecordSetConfiguration)
|
|
102
|
+
{
|
|
103
|
+
providerConfiguration.URLPrefix = pRecordSetConfiguration.RecordSetURLPrefix;
|
|
104
|
+
}
|
|
105
|
+
else
|
|
106
|
+
{
|
|
107
|
+
providerConfiguration.URLPrefix = '/1.0/';
|
|
108
|
+
}
|
|
109
|
+
this.recordSetProviders[pRecordSetConfiguration.RecordSet] = this.fable.addProvider(providerConfiguration.Hash, providerConfiguration, providerMeadowEndpoints);
|
|
110
|
+
break;
|
|
111
|
+
default:
|
|
112
|
+
case 'Custom':
|
|
113
|
+
// Create a custom provider
|
|
114
|
+
if (`ProviderHash` in providerConfiguration)
|
|
115
|
+
{
|
|
116
|
+
if (!(providerConfiguration.ProviderHash in this.fable.servicesMap))
|
|
117
|
+
{
|
|
118
|
+
this.fable.log.error(`RecordSetMetacontroller: ${this.UUID} loadRecordSetConfiguration called with invalid configuration. ProviderHash ${providerConfiguration.ProviderHash} not found. Falling back to base.`);
|
|
119
|
+
this.recordSetProviders[providerConfiguration.RecordSet] = this.fable.servicesMap[providerConfiguration.ProviderHash];
|
|
120
|
+
}
|
|
121
|
+
else
|
|
122
|
+
{
|
|
123
|
+
this.recordSetProviders[providerConfiguration.RecordSet] = this.fable.addProvider(providerConfiguration.Hash, providerConfiguration, providerBase);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else
|
|
127
|
+
{
|
|
128
|
+
this.recordSetProviders[providerConfiguration.RecordSet] = this.fable.addProvider(providerConfiguration.Hash, providerConfiguration, providerBase);
|
|
129
|
+
}
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
loadRecordSetConfigurationArray(pRecordSetConfigurationArray)
|
|
137
|
+
{
|
|
138
|
+
if (!Array.isArray(pRecordSetConfigurationArray))
|
|
139
|
+
{
|
|
140
|
+
this.fable.log.error(`RecordSetMetacontroller: ${this.UUID} loadRecordSetConfigurationArray called with invalid configuration.`);
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
if (pRecordSetConfigurationArray.length === 0)
|
|
144
|
+
{
|
|
145
|
+
this.fable.log.error(`RecordSetMetacontroller: ${this.UUID} loadRecordSetConfigurationArray called with empty configuration.`);
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
for (let i = 0; i < pRecordSetConfigurationArray.length; i++)
|
|
149
|
+
{
|
|
150
|
+
if (!this.loadRecordSetConfiguration(pRecordSetConfigurationArray[i]))
|
|
151
|
+
{
|
|
152
|
+
this.fable.log.error(`RecordSetMetacontroller: ${this.UUID} loadRecordSetConfigurationArray called with invalid configuration:`,pRecordSetConfigurationArray[i]);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
initialize()
|
|
158
|
+
{
|
|
159
|
+
if (this.has_initialized)
|
|
160
|
+
{
|
|
161
|
+
this.fable.log.warn(`RecordSetMetacontroller: ${this.UUID} already initialized and initialized was called a second time.`);
|
|
162
|
+
return this;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Add the subviews internally and externally
|
|
166
|
+
this.childViews.list = this.fable.addView('RSP-RecordSet-List', this.options, viewRecordSetList);
|
|
167
|
+
this.childViews.edit = this.fable.addView('RSP-RecordSet-Edit', this.options, viewRecordSetEdit);
|
|
168
|
+
this.childViews.read = this.fable.addView('RSP-RecordSet-Read', this.options, viewRecordSetRead);
|
|
169
|
+
this.childViews.dashboard = this.fable.addView('RSP-RecordSet-Dashboard', this.options, viewRecordSetDashboard);
|
|
170
|
+
|
|
171
|
+
// Initialize the subviews
|
|
172
|
+
this.childViews.list.initialize();
|
|
173
|
+
this.childViews.edit.initialize();
|
|
174
|
+
this.childViews.read.initialize();
|
|
175
|
+
this.childViews.dashboard.initialize();
|
|
176
|
+
|
|
177
|
+
if (this.fable.settings.hasOwnProperty('DefaultRecordSetConfigurations'))
|
|
178
|
+
{
|
|
179
|
+
this.loadRecordSetConfigurationArray(this.fable.settings.DefaultRecordSetConfigurations);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Load pict-router if it isn't loaded
|
|
183
|
+
if (!('Pict-Router' in this.fable.providers))
|
|
184
|
+
{
|
|
185
|
+
this.fable.addProvider('Pict-Router', {}, providerPictRouter);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
this.has_initialized = true;
|
|
189
|
+
|
|
190
|
+
return this;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
module.exports = RecordSetMetacontroller;
|
|
195
|
+
|
|
196
|
+
RecordSetMetacontroller.default_configuration = { };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const libPictView = require('pict-view');
|
|
2
|
+
|
|
3
|
+
const _DEFAULT_CONFIGURATION_SUBSET_Filter = (
|
|
4
|
+
{
|
|
5
|
+
ViewIdentifier: 'PRSP-SUBSET-Filter',
|
|
6
|
+
|
|
7
|
+
DefaultRenderable: 'PRSP_Renderable_Filter',
|
|
8
|
+
DefaultDestinationAddress: '#PRSP_Filter_Container',
|
|
9
|
+
DefaultTemplateRecordAddress: false,
|
|
10
|
+
|
|
11
|
+
// If this is set to true, when the App initializes this will.
|
|
12
|
+
// While the App initializes, initialize will be called.
|
|
13
|
+
AutoInitialize: false,
|
|
14
|
+
AutoInitializeOrdinal: 0,
|
|
15
|
+
|
|
16
|
+
// If this is set to true, when the App autorenders (on load) this will.
|
|
17
|
+
// After the App initializes, render will be called.
|
|
18
|
+
AutoRender: false,
|
|
19
|
+
AutoRenderOrdinal: 0,
|
|
20
|
+
|
|
21
|
+
AutoSolveWithApp: false,
|
|
22
|
+
AutoSolveOrdinal: 0,
|
|
23
|
+
|
|
24
|
+
CSS: false,
|
|
25
|
+
CSSPriority: 500,
|
|
26
|
+
|
|
27
|
+
Templates:
|
|
28
|
+
[
|
|
29
|
+
{
|
|
30
|
+
Hash: 'PRSP-SUBSET-Filter-Template',
|
|
31
|
+
Template: /*html*/`
|
|
32
|
+
<!-- DefaultPackage pict view template: [PRSP-SUBSET-Filter-Template] -->
|
|
33
|
+
<section id="PRSP_Filter_Container">
|
|
34
|
+
<form id="PRSP_Filter_Form">
|
|
35
|
+
{~T:PRSP-SUBSET-Filter-Template-Input-Fieldset~}
|
|
36
|
+
{~T:PRSP-SUBSET-Filter-Template-Button-Fieldset~}
|
|
37
|
+
</form>
|
|
38
|
+
</section>
|
|
39
|
+
<!-- DefaultPackage end view template: [PRSP-SUBSET-Filter-Template] -->
|
|
40
|
+
`
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
Hash: 'PRSP-SUBSET-Filter-Template-Input-Fieldset',
|
|
44
|
+
Template: /*html*/`
|
|
45
|
+
<!-- DefaultPackage pict view template: [PRSP-SUBSET-Filter-Template-Input-Fieldset] -->
|
|
46
|
+
<fieldset>
|
|
47
|
+
<label for="filter">Filter:</label>
|
|
48
|
+
<input type="text" name="filter">
|
|
49
|
+
</fieldset>
|
|
50
|
+
<!-- DefaultPackage end view template: [PRSP-SUBSET-Filter-Template-Input-Fieldset] -->
|
|
51
|
+
`
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
Hash: 'PRSP-SUBSET-Filter-Template-Button-Fieldset',
|
|
55
|
+
Template: /*html*/`
|
|
56
|
+
<!-- DefaultPackage pict view template: [PRSP-SUBSET-Filter-Template-Button-Fieldset] -->
|
|
57
|
+
<fieldset>
|
|
58
|
+
<button type="button" id="PRSP_Filter_Button_Reset">Reset</button>
|
|
59
|
+
<button type="submit" id="PRSP_Filter_Button_Apply">Apply</button>
|
|
60
|
+
</fieldset>
|
|
61
|
+
<!-- DefaultPackage end view template: [PRSP-SUBSET-Filter-Template-Button-Fieldset] -->
|
|
62
|
+
`
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
|
|
66
|
+
Renderables:
|
|
67
|
+
[
|
|
68
|
+
{
|
|
69
|
+
RenderableHash: 'PRSP_Renderable_Filter',
|
|
70
|
+
TemplateHash: 'PRSP-SUBSET-Filter-Template',
|
|
71
|
+
DestinationAddress: '#PRSP_Filter_Container',
|
|
72
|
+
RenderMethod: 'replace'
|
|
73
|
+
}
|
|
74
|
+
],
|
|
75
|
+
|
|
76
|
+
Manifests: {}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
class viewRecordSetSUBSETFilter extends libPictView
|
|
80
|
+
{
|
|
81
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
82
|
+
{
|
|
83
|
+
let tmpOptions = Object.assign({}, _DEFAULT_CONFIGURATION_SUBSET_Filter, pOptions);
|
|
84
|
+
super(pFable, tmpOptions, pServiceHash);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = viewRecordSetSUBSETFilter;
|
|
89
|
+
|
|
90
|
+
module.exports.default_configuration = _DEFAULT_CONFIGURATION_SUBSET_Filter;
|
|
91
|
+
|
|
File without changes
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const libPictView = require('pict-view');
|
|
2
|
+
|
|
3
|
+
const _DEFAULT_CONFIGURATION_Dashboard_HeaderDashboard = (
|
|
4
|
+
{
|
|
5
|
+
ViewIdentifier: 'PRSP-Dashboard-HeaderDashboard',
|
|
6
|
+
|
|
7
|
+
DefaultRenderable: 'PRSP_Renderable_HeaderDashboard',
|
|
8
|
+
DefaultDestinationAddress: '#PRSP_HeaderDashboard_Container',
|
|
9
|
+
DefaultTemplateRecordAddress: false,
|
|
10
|
+
|
|
11
|
+
// If this is set to true, when the App initializes this will.
|
|
12
|
+
// While the App initializes, initialize will be called.
|
|
13
|
+
AutoInitialize: false,
|
|
14
|
+
AutoInitializeOrdinal: 0,
|
|
15
|
+
|
|
16
|
+
// If this is set to true, when the App autorenders (on load) this will.
|
|
17
|
+
// After the App initializes, render will be called.
|
|
18
|
+
AutoRender: false,
|
|
19
|
+
AutoRenderOrdinal: 0,
|
|
20
|
+
|
|
21
|
+
AutoSolveWithApp: false,
|
|
22
|
+
AutoSolveOrdinal: 0,
|
|
23
|
+
|
|
24
|
+
CSS: false,
|
|
25
|
+
CSSPriority: 500,
|
|
26
|
+
|
|
27
|
+
Templates:
|
|
28
|
+
[
|
|
29
|
+
{
|
|
30
|
+
Hash: 'PRSP-Dashboard-HeaderDashboard-Template',
|
|
31
|
+
Template: /*html*/`
|
|
32
|
+
<!-- DefaultPackage pict view template: [PRSP-Dashboard-HeaderDashboard-Template] -->
|
|
33
|
+
<!-- DefaultPackage end view template: [PRSP-Dashboard-HeaderDashboard-Template] -->
|
|
34
|
+
`
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
|
|
38
|
+
Renderables:
|
|
39
|
+
[
|
|
40
|
+
{
|
|
41
|
+
RenderableHash: 'PRSP_Renderable_HeaderDashboard',
|
|
42
|
+
TemplateHash: 'PRSP-Dashboard-HeaderDashboard-Template',
|
|
43
|
+
DestinationAddress: '#PRSP_HeaderDashboard_Container',
|
|
44
|
+
RenderMethod: 'replace'
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
|
|
48
|
+
Manifests: {}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
class viewRecordSetDashboardHeaderDashboard extends libPictView
|
|
52
|
+
{
|
|
53
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
54
|
+
{
|
|
55
|
+
let tmpOptions = Object.assign({}, _DEFAULT_CONFIGURATION_Dashboard_HeaderDashboard, pOptions);
|
|
56
|
+
super(pFable, tmpOptions, pServiceHash);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
module.exports = viewRecordSetDashboardHeaderDashboard;
|
|
61
|
+
|
|
62
|
+
module.exports.default_configuration = _DEFAULT_CONFIGURATION_Dashboard_HeaderDashboard;
|
|
63
|
+
|