pict-section-recordset 1.0.0 → 1.0.2
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/ServeExamples.js +1 -1
- package/example_applications/mocks/book-edit-view.html +145 -0
- package/example_applications/mocks/book-read-view.html +139 -0
- package/example_applications/mocks/list-view.html +125 -0
- package/example_applications/simple_entity/Simple-RecordSet-Application.js +33 -27
- package/example_applications/simple_entity/html/index.html +3 -3
- package/package.json +12 -8
- package/source/Pict-Section-RecordSet.js +6 -2
- package/source/application/Pict-Application-RecordSet.js +23 -4
- package/source/providers/RecordSet-RecordProvider-Base.js +217 -0
- package/source/providers/RecordSet-RecordProvider-MeadowEndpoints.js +339 -0
- package/source/providers/RecordSet-Router.js +64 -0
- package/source/services/RecordsSet-MetaController.js +268 -0
- package/source/views/RecordSet-Filter.js +91 -0
- package/source/views/RecordSet-RecordBaseView.js +84 -0
- package/source/views/RecordsSet-MacroView.js +63 -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 +127 -0
- package/source/views/list/RecordSet-List-RecordList.js +79 -0
- package/source/views/list/RecordSet-List-RecordListEntry.js +86 -0
- package/source/views/list/RecordSet-List-RecordListHeader.js +77 -0
- package/source/views/list/RecordSet-List-Title.js +66 -0
- package/source/views/list/RecordSet-List.js +310 -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 +162 -0
- package/test/PictSectionRecordSet-Basic_tests.js +6 -2
- 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 +9 -1
- package/types/application/Pict-Application-RecordSet.d.ts +5 -5
- 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/providers/RecordSet-Router.d.ts +36 -0
- package/types/providers/RecordSet-Router.d.ts.map +1 -0
- package/types/services/RecordsSet-MetaController.d.ts +36 -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/RecordSet-RecordBaseView.d.ts +49 -0
- package/types/views/RecordSet-RecordBaseView.d.ts.map +1 -0
- package/types/views/RecordsSet-MacroView.d.ts +34 -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 +33 -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 +33 -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 +47 -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 +44 -0
- package/types/views/read/RecordSet-Read.d.ts.map +1 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
|
|
2
|
+
const libPictProvider = require('pict-provider');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Default configuration for the RecordSetProvider provider.
|
|
6
|
+
* @type {Record<string, any>}
|
|
7
|
+
*/
|
|
8
|
+
const _DefaultProviderConfiguration = {
|
|
9
|
+
ProviderIdentifier: 'Pict-RecordSetProvider',
|
|
10
|
+
AutoInitialize: true,
|
|
11
|
+
AutoInitializeOrdinal: 0,
|
|
12
|
+
AutoSolveWithApp: false,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @typedef {Object} RecordSetSearchRangeFacet
|
|
17
|
+
* @property {string} Field - The field to facet on. Only indexed fields can be faceted.
|
|
18
|
+
* @property {any} Start - The start of the range. (ex. 1900)
|
|
19
|
+
* @property {any} End - The end of the range. (ex. 2025)
|
|
20
|
+
* @property {any} Gap - The gap between range values. (ex. 25)
|
|
21
|
+
* TODO: Support auto-generating ranges based on the data at rest?
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @typedef {Object} RecordSetSearchFacetPayload
|
|
26
|
+
* @property {boolean} [ReturnRecords] - If false, search will return facets only, not records.
|
|
27
|
+
* @property {Array<string>} Fields - Requests to facet on all unique values of the given fields.
|
|
28
|
+
* @property {Array<RecordSetSearchRangeFacet>} Ranges - Requests to facet on given ranges of field values.
|
|
29
|
+
* TODO: support facet on custom query?
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @typedef {Object} RecordSetResult
|
|
34
|
+
* @property {Array<Record<string, any>>} Records - The records returned from the provider.
|
|
35
|
+
* @property {Record<string, Record<string, number>> & { ByRange?: Record<string, number> }} Facets - The facets returned from the provider.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @typedef {Object} RecordSetFilter
|
|
40
|
+
* @property {string} [Entity] - The entity name. Can be used as an override to achieve LiteExtended, etc.
|
|
41
|
+
* @property {string} [FilterString] - A meadow endpoint style filter to apply.
|
|
42
|
+
* @property {number} [Offset] - The starting record number for pagination.
|
|
43
|
+
* @property {number} [PageSize] - The starting record number for pagination.
|
|
44
|
+
* @property {RecordSetSearchFacetPayload} [Facets] - The faceting config for the search.
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Base record set provider.
|
|
49
|
+
* @extends libPictProvider
|
|
50
|
+
*/
|
|
51
|
+
class RecordSetProviderBase extends libPictProvider
|
|
52
|
+
{
|
|
53
|
+
/**
|
|
54
|
+
* Creates an instance of RecordSetProvider.
|
|
55
|
+
* @param {import('fable')} pFable - The Fable object.
|
|
56
|
+
* @param {Record<string, any>} [pOptions] - Custom options for the provider.
|
|
57
|
+
* @param {string} [pServiceHash] - The service hash.
|
|
58
|
+
*/
|
|
59
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
60
|
+
{
|
|
61
|
+
const tmpOptions = Object.assign({}, JSON.parse(JSON.stringify(_DefaultProviderConfiguration)), pOptions);
|
|
62
|
+
|
|
63
|
+
super(pFable, tmpOptions, pServiceHash);
|
|
64
|
+
|
|
65
|
+
/** @type {Record<string, any>} */
|
|
66
|
+
this.options;
|
|
67
|
+
/** @type {import('fable')} */
|
|
68
|
+
this.fable;
|
|
69
|
+
/** @type {import('pict')} */
|
|
70
|
+
this.pict;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Get a record by its ID or GUID.
|
|
75
|
+
*
|
|
76
|
+
* @param {string|number} pIDOrGuid - The ID or GUID of the record.
|
|
77
|
+
*/
|
|
78
|
+
async getRecord(pIDOrGuid)
|
|
79
|
+
{
|
|
80
|
+
this.pict.log.info(`RecordSetProviderBase.getRecord(${pIDOrGuid})`);
|
|
81
|
+
return { };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Get a record by its ID or GUID.
|
|
86
|
+
*
|
|
87
|
+
* @param {string|number} pGuid - The ID or GUID of the record.
|
|
88
|
+
*/
|
|
89
|
+
async getRecordByGUID(pGuid)
|
|
90
|
+
{
|
|
91
|
+
this.pict.log.info(`RecordSetProviderBase.getRecordByGUID(${pGuid})`);
|
|
92
|
+
return { };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Read records from the provider.
|
|
97
|
+
*
|
|
98
|
+
* @param {RecordSetFilter} pOptions - Options for the read operation.
|
|
99
|
+
* @return {Promise<RecordSetResult>} - The result of the read operation.
|
|
100
|
+
*/
|
|
101
|
+
async getRecords(pOptions)
|
|
102
|
+
{
|
|
103
|
+
this.pict.log.info(`RecordSetProviderBase.getRecords(${JSON.stringify(pOptions)})`);
|
|
104
|
+
return { Records: [], Facets: { } };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Read records from the provider.
|
|
109
|
+
*
|
|
110
|
+
* @param {string} [pFilterString] - The filter string to apply.
|
|
111
|
+
* @param {number} [pOffset] - The starting record number for pagination.
|
|
112
|
+
* @param {number} [pPageSize] - The number of records to return.
|
|
113
|
+
* @return {Promise<RecordSetResult>} - The result of the read operation.
|
|
114
|
+
*/
|
|
115
|
+
async getRecordsInline(pFilterString = '', pOffset = 0, pPageSize = 250)
|
|
116
|
+
{
|
|
117
|
+
this.pict.log.info(`RecordSetProviderBase.getRecordsInline(${pFilterString}, ${pOffset}, ${pPageSize})`);
|
|
118
|
+
return { Records: [], Facets: { } };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Read records from the provider.
|
|
123
|
+
*
|
|
124
|
+
* @param {RecordSetFilter} pOptions - Options for the read operation.
|
|
125
|
+
*/
|
|
126
|
+
async getRecordSetCount(pOptions)
|
|
127
|
+
{
|
|
128
|
+
this.pict.log.info(`RecordSetProviderBase.getRecordSetCount(${JSON.stringify(pOptions)})`);
|
|
129
|
+
return { Count: 0 };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Create a new record.
|
|
134
|
+
*
|
|
135
|
+
* @param {Record<string, any>} pRecord - The record to create.
|
|
136
|
+
*/
|
|
137
|
+
async createRecord(pRecord)
|
|
138
|
+
{
|
|
139
|
+
this.pict.log.info(`RecordSetProviderBase.createRecord(${JSON.stringify(pRecord)})`);
|
|
140
|
+
return pRecord;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Update a record.
|
|
145
|
+
*
|
|
146
|
+
* @param {Record<string, any>} pRecord - The record to update.
|
|
147
|
+
*/
|
|
148
|
+
async updateRecord(pRecord)
|
|
149
|
+
{
|
|
150
|
+
this.pict.log.info(`RecordSetProviderBase.updateRecord(${JSON.stringify(pRecord)})`);
|
|
151
|
+
return pRecord;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Delete a record.
|
|
156
|
+
*
|
|
157
|
+
* @param {Record<string, any>} pRecord - The record to delete.
|
|
158
|
+
*/
|
|
159
|
+
async deleteRecord(pRecord)
|
|
160
|
+
{
|
|
161
|
+
this.pict.log.info(`RecordSetProviderBase.deleteRecord(${JSON.stringify(pRecord)})`);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Read a record.
|
|
166
|
+
*
|
|
167
|
+
* @param {string|number} pIDOrGuid - The ID or GUID of the record.
|
|
168
|
+
*/
|
|
169
|
+
async readRecord(pIDOrGuid)
|
|
170
|
+
{
|
|
171
|
+
this.pict.log.info(`RecordSetProviderBase.readRecord(${pIDOrGuid})`);
|
|
172
|
+
return { };
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Read records from the provider.
|
|
177
|
+
*
|
|
178
|
+
* @param {RecordSetFilter} pOptions - Options for the read operation.
|
|
179
|
+
* @return {Promise<RecordSetResult>} - The result of the read operation.
|
|
180
|
+
*/
|
|
181
|
+
async readRecords(pOptions)
|
|
182
|
+
{
|
|
183
|
+
this.pict.log.info(`RecordSetProviderBase.readRecords(${JSON.stringify(pOptions)})`);
|
|
184
|
+
return { Records: [], Facets: { } };
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Clone a record.
|
|
189
|
+
*
|
|
190
|
+
* @param {Record<string, any>} pRecord - The record to clone.
|
|
191
|
+
*/
|
|
192
|
+
async cloneRecord(pRecord)
|
|
193
|
+
{
|
|
194
|
+
return this.createRecord(this.cleanRecord(pRecord));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Remove any intrinsic identifiers from a record.
|
|
199
|
+
*
|
|
200
|
+
* @param {Record<string, any>} pRecord - The record to clean.
|
|
201
|
+
*/
|
|
202
|
+
cleanRecord(pRecord)
|
|
203
|
+
{
|
|
204
|
+
return pRecord;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* @return {Record<string, any>} The schema of the record.
|
|
209
|
+
*/
|
|
210
|
+
get recordSchema()
|
|
211
|
+
{
|
|
212
|
+
return { };
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
module.exports = RecordSetProviderBase;
|
|
217
|
+
module.exports.default_configuration = _DefaultProviderConfiguration;
|
|
@@ -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,64 @@
|
|
|
1
|
+
const libPictProvider = require('pict-provider');
|
|
2
|
+
const libPictRouter = require('pict-router');
|
|
3
|
+
|
|
4
|
+
const _DEFAULT_PROVIDER_CONFIGURATION =
|
|
5
|
+
{
|
|
6
|
+
ProviderIdentifier: 'Pict-RecordSet-Router',
|
|
7
|
+
|
|
8
|
+
AutoInitialize: true,
|
|
9
|
+
AutoInitializeOrdinal: 0
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
class PictRecordSetRouter extends libPictProvider
|
|
13
|
+
{
|
|
14
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
15
|
+
{
|
|
16
|
+
let tmpOptions = Object.assign({}, _DEFAULT_PROVIDER_CONFIGURATION, pOptions);
|
|
17
|
+
super(pFable, tmpOptions, pServiceHash);
|
|
18
|
+
|
|
19
|
+
/** @type {Record<string, any>} */
|
|
20
|
+
this.options;
|
|
21
|
+
/** @type {import('pict') & { PictSectionRecordSet: InstanceType<import('../Pict-Section-RecordSet.js')> }} */
|
|
22
|
+
this.pict;
|
|
23
|
+
|
|
24
|
+
this.pictRouter = null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
onInitialize()
|
|
28
|
+
{
|
|
29
|
+
if (!('PictRouter' in this.pict.providers))
|
|
30
|
+
{
|
|
31
|
+
this.pictRouter = this.pict.addProvider('PictRouter', { RouterMode: 'memory' }, libPictRouter);
|
|
32
|
+
}
|
|
33
|
+
else
|
|
34
|
+
{
|
|
35
|
+
this.pictRouter = this.pict.providers.PictRouter;
|
|
36
|
+
}
|
|
37
|
+
return super.onInitialize();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
addRoutes(pRouter)
|
|
41
|
+
{
|
|
42
|
+
// TODO: Create some kind of state tracking to see if these routes have already been added
|
|
43
|
+
//this.pictRouter.addRoute('/PSRS/:RecordSet/List/:Begin/:Cap', "{~LV:Record~}");
|
|
44
|
+
this.pict.views['RSP-RecordSet-List'].addRoutes(pRouter);
|
|
45
|
+
this.pict.views['RSP-RecordSet-Read'].addRoutes(pRouter);
|
|
46
|
+
this.pict.views['RSP-RecordSet-Edit'].addRoutes(pRouter);
|
|
47
|
+
this.pict.views['RSP-RecordSet-Dashboard'].addRoutes(pRouter);
|
|
48
|
+
|
|
49
|
+
this.pict.PictSectionRecordSet.addRoutes(pRouter);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Navigate to a given route (set the browser URL string, add to history, trigger router)
|
|
54
|
+
*
|
|
55
|
+
* @param {string} pRoute - The route to navigate to
|
|
56
|
+
*/
|
|
57
|
+
navigate(pRoute)
|
|
58
|
+
{
|
|
59
|
+
this.pictRouter.navigate(pRoute);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
module.exports = PictRecordSetRouter;
|
|
64
|
+
module.exports.default_configuration = _DEFAULT_PROVIDER_CONFIGURATION;
|