forms-angular 0.12.0-beta.32 → 0.12.0-beta.321

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.
@@ -1,10 +1,65 @@
1
1
  declare module fng {
2
- var formsAngular: angular.IModule;
2
+ export interface IFng extends angular.IModule {
3
+ beforeProcess?: (scope: IFormScope, cb: (err?: Error) => void) => void;
4
+ beforeHandleIncomingDataPromises?: () => angular.IPromise<any>[];
5
+ pseudo?: (token: string, upperFirst: boolean) => string;
6
+ title?: { prefix?: string; suffix?: string };
7
+ // when provided, the named function (assumed to be present on $rootscope) will be used to determine the visibility
8
+ // of menu items and control groups
9
+ hiddenSecurityFuncName?: string;
10
+ // when provided, the named function (assumed to be present on $rootscope) will be used to determine the disabled
11
+ // state of menu items and individual form input controls
12
+ disabledSecurityFuncName?: string;
13
+ // when provided, the named function (assumed to be present on $rootscope) will be called each time a new page
14
+ // or popup is accessed, providing the host app with the opportunity to confirm whether there are ANY hidden elements
15
+ // at all on that page. where there are not, we can optimise by skipping logic relating to DOM element visibility.
16
+ skipHiddenSecurityFuncName?: string;
17
+ // when provided, the named function (assumed to be present on $rootscope) will be called each time a new page
18
+ // or popup is accessed, providing the host app with the opportunity to confirm whether there are ANY disabled elements
19
+ // at all on that page. where there are not, we can optimise by skipping logic relating to disabling DOM elements.
20
+ skipDisabledSecurityFuncName?: string;
21
+ // when provided, the named function (assumed to be present on $rootscope) will be called each time a new page
22
+ // or popup is accessed, providing the host app with the opportunity to confirm whether there are ANY elements on that
23
+ // page that require their child elements to be disabled. where there are not, we can optimise by skipping
24
+ // disabled ancestor checks.
25
+ skipDisabledAncestorSecurityFuncName?: string;
26
+ // how the function identified by elemSecurityFuncName should be bound. "instant" means that it will be called
27
+ // as the markup is being constructed, with 'hidden' elements not included in the markup at all, and disabled elements
28
+ // given a simple DISABLED attribute. this is the most efficient approach. "one-time" will add ng-hide and
29
+ // ng-disabled directives to the relevant elements, with one-time binding to the security function. this is
30
+ // also reasonably efficient (but not as efficient as "instant", due to the need for watches). "normal" will not use
31
+ // one-time binding, which has the potential to be highly resource-intensive on large forms. which
32
+ // option is chosen will depend upon when the function identified by elemSecurityFuncName will be ready to
33
+ // make the necessary determination.
34
+ elemSecurityFuncBinding?: "instant" | "one-time" | "normal";
35
+ hideableAttr?: string; // an attribute to mark all elements that can be hidden using security
36
+ disableableAttr?: string; // an attribute to mark all elements that can be disabled using security
37
+ disableableAncestorAttr?: string; // an attribute to mark all elements whose children can all be disabled using "disabled + children" security
38
+ // if an element's id is a partial match on any of this array's contents, it will never be marked with hideableAttr/disableableAttr
39
+ ignoreIdsForHideableOrDisableableAttrs?: string[];
40
+ keyboardShortCuts? : {
41
+ letter: string;
42
+ keycode: number;
43
+ id: string;
44
+ desc: string;
45
+ } [];
46
+ }
47
+ var formsAngular: IFng;
3
48
 
4
49
  /*
5
50
  Type definitions for types that are used on both the client and the server
6
51
  */
52
+ type formStyle = "inline" | "vertical" | "horizontal" | "horizontalCompact" | "stacked";
53
+
54
+ export interface IBaseArrayLookupReference {
55
+ property: string;
56
+ value: string;
57
+ }
7
58
 
59
+ interface ILookupItem {
60
+ id: string;
61
+ text: string;
62
+ }
8
63
  /*
9
64
  IInternalLookupreference makes it possible to look up from a list (of key / value pairs) in the current record. For example
10
65
 
@@ -18,9 +73,8 @@ declare module fng {
18
73
  favouriteShelf: {type: Schema.Types.ObjectId, internalRef: {property: 'shelves', value:'location'};
19
74
  });
20
75
  */
21
- export interface IFngInternalLookupReference {
22
- property: string;
23
- value: string;
76
+ export interface IFngInternalLookupReference extends IBaseArrayLookupReference {
77
+ noConvert?: boolean; // can be used by a tricksy hack to get around nesting limitations
24
78
  }
25
79
 
26
80
  /*
@@ -33,14 +87,12 @@ declare module fng {
33
87
  shelf: {type: Schema.Types.ObjectId, lookupListRef: {collection:'k_referencing_self_collection', id:'$warehouse', property: 'shelves', value:'location'}},
34
88
  };
35
89
  */
36
- export interface IFngLookupListReference {
37
- collection: string; // collection that contains the list
90
+ export interface IFngLookupListReference extends IBaseArrayLookupReference {
91
+ collection: string; // collection that contains the list
38
92
  /*
39
93
  Some means of calculating _id in collection. If it starts with $ then it is property in record
40
94
  */
41
95
  id: string;
42
- property: string;
43
- value: string;
44
96
  }
45
97
 
46
98
  /*
@@ -59,7 +111,7 @@ declare module fng {
59
111
  */
60
112
  export interface IFngShowWhen {
61
113
  lhs: any;
62
- comp: 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte';
114
+ comp: "eq" | "ne" | "gt" | "gte" | "lt" | "lte";
63
115
  rhs: any;
64
116
  }
65
117
 
@@ -67,12 +119,15 @@ declare module fng {
67
119
  link allows the setting up of hyperlinks for lookup reference fields
68
120
  */
69
121
  export interface IFngLinkSetup {
70
- linkOnly?: boolean; // if true then the input element is not generated (this overrides label)
71
- label?: boolean; // Make a link out of the label (causes text to be overridden) (this overrides text)
72
- form?: string; // can be used to generate a link to a custom schema
73
- text?: string; // the literal value used for the link. If this property is omitted then text is generated from the field values of the document referred to by the link.
122
+ linkOnly?: boolean; // if true then the input element is not generated (this overrides label)
123
+ label?: boolean; // Make a link out of the label (causes text to be overridden) (this overrides text)
124
+ form?: string; // can be used to generate a link to a custom schema
125
+ linktab?: string; // can be used to generate a link to a tab on a form
126
+ text?: string; // the literal value used for the link. If this property is omitted then text is generated from the field values of the document referred to by the link.
74
127
  }
75
128
 
129
+ export type FieldSizeString = "mini" | "small" | "medium" | "large" | "xlarge" | "xxlarge" | "block-level"; // sets control width. Default is 'medium''
130
+
76
131
  export interface IFngSchemaTypeFormOpts {
77
132
  /*
78
133
  The input type to be generated - which must be compatible with the Mongoose type.
@@ -91,34 +146,36 @@ declare module fng {
91
146
  */
92
147
  type?: string;
93
148
 
94
- hidden?: boolean; // inhibits this schema key from appearing on the generated form.
95
- label?: string | null; // overrides the default input label. label:null suppresses the label altogether.
96
- ref?: string; // reference to another collection
97
- internalRef? : IFngInternalLookupReference;
149
+ hidden?: boolean; // inhibits this schema key from appearing on the generated form.
150
+ label?: string | null; // overrides the default input label. label:null suppresses the label altogether.
151
+ ref?: string; // reference to another collection
152
+ internalRef?: IFngInternalLookupReference;
98
153
  lookupListRef?: IFngLookupListReference;
99
154
  id?: string; // specifies the id of the input field (which defaults to f_name)
100
155
 
101
- placeHolder?: string // adds placeholder text to the input (depending on data type).
102
- help?: string; // adds help text under the input.
103
- helpInline?: string; // adds help to the right of the input.
104
- popup?: string; // adds popup help as specified.
105
- order?: number; // allows user to specify the order / tab order of this field in the form. This overrides the position in the Mongoose schema.
106
- size?: 'mini' | 'small' | 'medium' | 'large' | 'xlarge' | 'xxlarge' | 'block-level'; // sets control width. Default is 'medium''
107
- readonly?: boolean; // adds the readonly attribute to the generated input (currently doesn't work with date - and perhaps other types).
108
- rows?: number | 'auto'; // sets the number of rows in inputs (such as textarea) that support this. Setting rows to "auto" makes the textarea expand to fit the content, rather than create a scrollbar.
109
- tab?: string; // Used to divide a large form up into a tabset with multiple tabs
110
- showWhen?: IFngShowWhen | string; // allows conditional display of fields based on values elsewhere. string must be an abular expression.
156
+ placeHolder?: string; // adds placeholder text to the input (depending on data type).
157
+ help?: string; // adds help text under the input.
158
+ helpInline?: string; // adds help to the right of the input.
159
+ popup?: string; // adds title (popup help) as specified.
160
+ ariaLabel?: string; // adds aria-label as specified.
161
+ order?: number; // allows user to specify the order / tab order of this field in the form. This overrides the position in the Mongoose schema.
162
+ size?: FieldSizeString;
163
+ readonly?: boolean | string; // adds the readonly or ng-readonly attribute to the generated input (currently doesn't work with date - and perhaps other types).
164
+ rows?: number | "auto"; // sets the number of rows in inputs (such as textarea) that support this. Setting rows to "auto" makes the textarea expand to fit the content, rather than create a scrollbar.
165
+ tab?: string; // Used to divide a large form up into a tabset with multiple tabs
166
+ showWhen?: IFngShowWhen | string; // allows conditional display of fields based on values elsewhere. string must be an abular expression.
111
167
 
112
168
  /*
113
169
  add: 'class="myClass"' allows custom styling of a specific input
114
170
  Angular model options can be used - for example add: 'ng-model-options="{updateOn: \'default blur\', debounce: { \'default\': 500, \'blur\': 0 }}" '
115
171
  custom validation directives, such as the timezone validation in this schema
116
172
  */
117
- add?: string; // allows arbitrary attributes to be added to the input tag.
173
+ add?: string; // allows arbitrary attributes to be added to the input tag.
118
174
 
119
- class?: string; // allows arbitrary classes to be added to the input tag.
120
- inlineRadio?: boolean; // (only valid when type is radio) should be set to true to present all radio button options in a single line
175
+ class?: string; // allows arbitrary classes to be added to the input tag.
176
+ inlineRadio?: boolean; // (only valid when type is radio) should be set to true to present all radio button options in a single line
121
177
  link?: IFngLinkSetup; // handles displaying links for ref lookups
178
+ asText?: boolean; // (only valid when type is ObjectId) should be set to true to force a simple text input rather than a select. presumed for advanced cases where the objectid is going to be pasted in.
122
179
 
123
180
  /*
124
181
  With a select / radio type you can specify the options.
@@ -141,11 +198,22 @@ declare module fng {
141
198
  /*
142
199
  The next few options relate to the handling and display of arrays (including arrays of subdocuments)
143
200
  */
144
- noAdd?: boolean; // inhibits an Add button being generated for arrays.
201
+ noAdd?: boolean | string; // inhibits an Add button being generated for arrays.
202
+ noneIndicator?: boolean; // show "None" where there's no add button and no array items
145
203
  unshift?: boolean; // (for arrays of sub documents) puts an add button in the sub schema header which allows insertion of new sub documents at the beginning of the array.
146
- noRemove?: boolean; // inhibits a Remove button being generated for array elements.
147
- formstyle?: 'inline' | 'vertical' | 'horizontal' | 'horizontalCompact'; // (only valid on a sub schema) sets style of sub form.
148
- sortable? : boolean; // Allows drag and drop sorting of arrays - requires angular-ui-sortable
204
+ noRemove?: boolean | string; // inhibits a Remove button being generated for array elements.
205
+ formstyle?: formStyle; // (only valid on a sub schema) sets style of sub form.
206
+ sortable?: boolean | string; // Allows drag and drop sorting of arrays - requires angular-ui-sortable
207
+ ngClass?: string; // Allows for conditional per-item styling through the addition of an ng-class expression to the class list of li elements created for each item in the array
208
+ filterable?: boolean; // Add a data-ng-hide to all array elements, referring to subDoc._hidden. Does not actually (yet) provide a UI for managing this property, however (which needs to be done via an external directive)
209
+ subDocContainerType?:
210
+ | "fieldset"
211
+ | "well"
212
+ | "well-large"
213
+ | "well-small"
214
+ | string
215
+ | ((info) => { before: ""; after: "" }); // allows each element in the array to be nested in a container
216
+ subDocContainerProps?: any; // the parameters that will be passed if subDocContainerType is a function
149
217
 
150
218
  /*
151
219
  The next section relates to the display of sub documents
@@ -153,6 +221,12 @@ declare module fng {
153
221
  customSubDoc?: string; // Allows you to specify custom HTML (which may include directives) for the sub doc
154
222
  customHeader?: string; // Allows you to specify custom HTML (which may include directives) for the header of a group of sub docs
155
223
  customFooter?: string; // Allows you to specify custom HTML (which may include directives) for the footer of a group of sub docs
224
+
225
+ /*
226
+ Suppresses warnings about attenpting deep nesting which would be logged to console in some circumstances when a
227
+ directive fakes deep nesting
228
+ */
229
+ suppressNestingWarning?: boolean;
156
230
  }
157
231
 
158
232
  // Schema passed from server - derived from Mongoose schema
@@ -160,31 +234,56 @@ declare module fng {
160
234
  name: string;
161
235
  schema?: Array<IFieldViewInfo>;
162
236
  array?: boolean;
163
- showIf? : any;
237
+ showIf?: any;
164
238
  required?: boolean;
165
- step? : number;
239
+ step?: number;
166
240
  }
167
241
 
242
+ export type fieldType =
243
+ | "string"
244
+ | "text"
245
+ | "textarea"
246
+ | "number"
247
+ | "select"
248
+ | "link"
249
+ | "date"
250
+ | "checkbox"
251
+ | "password"
252
+ | "radio";
253
+
168
254
  // Schema used internally on client - often derived from IFieldViewInfo passed from server
169
255
  export interface IFormInstruction extends IFieldViewInfo {
170
- id? : string; // id of generated DOM element
171
- type?: 'string' | 'text' | 'textarea' | 'number' | 'select' | 'link' | 'date' | 'checkbox' | 'password';
172
- rows? : number
173
- label: string;
256
+ id?: string; // id of generated DOM element
257
+ nonUniqueId?: string; // where this field is part of a sub-sub-schema, id is likely to include $index from the sub-schema, to ensure uniqueness. provide it here without reference to $parent.$index for use in security evaluations.
258
+ type?: fieldType;
259
+ defaultValue?: any;
260
+ rows?: number;
261
+ label?: string;
174
262
  options?: any;
175
263
  ids?: any;
176
264
  hidden?: boolean;
177
265
  tab?: string;
178
- add? : string;
179
- ref? : any;
180
- link? : any;
266
+ add?: string;
267
+ ref?: any;
268
+ link?: any;
181
269
  linktext?: string;
182
270
  linklabel?: boolean;
183
- form?: string; // the form that is linked to
184
- select2? : any; // deprecated
185
- schema?: IFormInstruction[]; // If the field is an array of fields
271
+ form?: string; // the form that is linked to
272
+ select2?: any; // deprecated
273
+ schema?: IFormInstruction[]; // If the field is an array of fields
274
+ intType?: "date";
275
+ coloffset?: number;
276
+ [directiveOptions: string]: any;
277
+ }
278
+
279
+ interface IContainerInstructions {
280
+ before?: string;
281
+ after?: string;
282
+ omit?: boolean;
186
283
  }
187
284
 
285
+ export type HiddenTabReintroductionMethod = "none" | "tab";
286
+
188
287
  export interface IContainer {
189
288
  /*
190
289
  Type of container, which determines markup. This is currently only available when the schema is generated by
@@ -192,15 +291,25 @@ declare module fng {
192
291
  In the case of a string which does not match one of the predefined options
193
292
  the generated container div is given the class of the name
194
293
  */
195
- containerType: 'fieldset' | 'well' | 'tabset' | 'tab' | 'well-large' | 'well-small' | string;
294
+ containerType: "fieldset" | "well" | "tabset" | "tab" | "+tab" | "well-large" | "well-small" | string | ((info: IContainer) => IContainerInstructions);
196
295
  title?: string;
197
-
296
+ /*
297
+ Applies only to tabs - causing them to be rendered with a x for closing ('hiding') the tab in question.
298
+ Where hideable is true, hiddenTabArrayProp can be used to specify a property name (which can include ".", and which
299
+ will be assumed to identiy an array) that should be used to store the ids of closed ('hidden') tabs.
300
+ Where this is not specified, record.hiddenTabs will be used.
301
+ If hiddenTabReintroductionMethod is set to "tab", an additional tab will be added to the end of the tabset
302
+ with a + heading, and clicking on this will provide a UI for re-introducing hidden tabs.
303
+ */
304
+ hideable?: boolean;
305
+ hiddenTabArrayProp?: string;
306
+ hiddenTabReintroductionMethod?: HiddenTabReintroductionMethod;
198
307
  /*
199
308
  h1...h6 will use a header style
200
309
  anything else will be used as a paragraph stype
201
310
  */
202
- titleTagOrClass? : string;
203
- content: IFormInstruction[];
311
+ titleTagOrClass?: string;
312
+ content: IFormSchemaElement[];
204
313
  }
205
314
 
206
315
  export type IFormSchemaElement = IFormInstruction | IContainer;
@@ -211,57 +320,85 @@ declare module fng {
211
320
  export interface IEnumInstruction {
212
321
  repeat: string;
213
322
  value: string;
214
- label? : string;
323
+ label?: string;
215
324
  }
216
325
 
217
326
  export interface IFngCtrlState {
218
327
  master: any;
219
- allowLocationChange: boolean; // Do we allow location change or prompt for permission
328
+ allowLocationChange: boolean; // Do we allow location change or prompt for permission
220
329
  }
221
- export interface IRecordHandler {
330
+ export interface IRecordHandlerService {
222
331
  convertToMongoModel(schema: IControlledFormSchema, anObject: any, prefixLength: number, scope: IFormScope): any;
223
332
  createNew(dataToSave: any, options: any, scope: IFormScope, ctrlState: IFngCtrlState): void;
224
- deleteRecord(model: any, id: any, scope: IFormScope, ctrlState: any): void;
225
- updateDocument(dataToSave : any, options: any, scope: IFormScope, ctrlState: IFngCtrlState) : void;
226
- readRecord($scope: IFormScope, ctrlState);
333
+ deleteRecord(id: string, scope: IFormScope, ctrlState: IFngCtrlState): void;
334
+ updateDocument(dataToSave: any, options: any, scope: IFormScope, ctrlState: IFngCtrlState): void;
335
+ beginReadingRecord($scope: IFormScope): void;
336
+ finishReadingThenProcessRecord($scope: IFormScope, ctrlState): void;
227
337
  scrollTheList($scope: IFormScope);
228
338
  getListData(record, fieldName, listSchema?, $scope?: IFormScope);
229
339
  suffixCleanId(inst, suffix);
230
- setData(object, fieldname, element, value);
340
+ setData(object, fieldname: string, element, value);
341
+ getData(object, fieldname: string, element?: any);
231
342
  setUpLookupOptions(lookupCollection, schemaElement, $scope: IFormScope, ctrlState, handleSchema);
232
- setUpLookupListOptions: (ref: IFngLookupListReference, formInstructions: IFormInstruction, $scope: IFormScope, ctrlState: IFngCtrlState) => void;
343
+ setUpLookupListOptions: (
344
+ ref: IFngLookupListReference,
345
+ formInstructions: IFormInstruction,
346
+ $scope: IFormScope,
347
+ ctrlState: IFngCtrlState
348
+ ) => void;
233
349
  handleInternalLookup($scope: IFormScope, formInstructions, ref): void;
234
350
  preservePristine(element, fn): void;
235
351
  convertIdToListValue(id, idsArray, valuesArray, fname);
236
- decorateScope($scope:IFormScope, $uibModal, recordHandlerInstance : IRecordHandler, ctrlState);
237
- fillFormFromBackendCustomSchema(schema, $scope:IFormScope, formGeneratorInstance, recordHandlerInstance, ctrlState);
352
+ decorateScope($scope: IFormScope, $uibModal, recordHandlerInstance: IRecordHandlerService, ctrlState);
353
+ fillFormFromBackendCustomSchema(
354
+ schema,
355
+ $scope: IFormScope,
356
+ formGeneratorInstance,
357
+ recordHandlerInstance,
358
+ ctrlState
359
+ );
238
360
  fillFormWithBackendSchema($scope: IFormScope, formGeneratorInstance, recordHandlerInstance, ctrlState);
239
361
  handleError($scope: IFormScope);
362
+ convertToAngularModel($scope: IFormScope);
363
+ convertToAngularModelWithSchema(schema: IControlledFormSchema, data, $scope: IFormScope)
240
364
  }
241
365
 
242
- export interface IFormGenerator {
243
- generateEditUrl(obj, $scope:IFormScope): string;
366
+ export interface IFormGeneratorService {
367
+ generateEditUrl(obj, $scope: IFormScope): string;
368
+ generateViewUrl(obj, $scope: IFormScope): string;
244
369
  generateNewUrl($scope: IFormScope): string;
245
370
  handleFieldType(formInstructions, mongooseType, mongooseOptions, $scope: IFormScope, ctrlState);
246
- handleSchema(description: string, source, destForm, destList, prefix, doRecursion: boolean, $scope: IFormScope, ctrlState);
371
+ handleSchema(
372
+ description: string,
373
+ source,
374
+ destForm,
375
+ destList,
376
+ prefix,
377
+ doRecursion: boolean,
378
+ $scope: IFormScope,
379
+ ctrlState
380
+ );
247
381
  updateDataDependentDisplay(curValue, oldValue, force, $scope: IFormScope);
248
- add(fieldName, $event, $scope: IFormScope);
249
- unshift(fieldName, $event, $scope: IFormScope);
250
- remove(fieldName, value, $event, $scope: IFormScope);
382
+ add(fieldName: string, $event, $scope: IFormScope, modelOverride?: any);
383
+ unshift(fieldName: string, $event, $scope: IFormScope, modelOverride?: any);
384
+ remove(fieldName: string, value, $event, $scope: IFormScope, modelOverride?: any);
251
385
  hasError(formName, name, index, $scope: IFormScope);
252
- decorateScope($scope: IFormScope, formGeneratorInstance, recordHandlerInstance: IRecordHandler, sharedStuff);
386
+ decorateScope($scope: IFormScope, formGeneratorInstance: IFormGeneratorService, recordHandlerInstance: IRecordHandlerService, sharedStuff, pseudoUrl?: string);
253
387
  }
254
388
 
255
389
  export interface IFngSingleLookupHandler {
256
390
  formInstructions: IFormInstruction;
257
391
  lastPart: string;
258
392
  possibleArray: string;
393
+ // If the looked-up record changes, we use these fields to see if the old lookup value also exists in the new lookup record
394
+ oldValue?: string | string[];
395
+ oldId?: string | string[];
259
396
  }
260
397
 
261
398
  export interface IFngLookupHandler {
262
399
  lookupOptions: string[];
263
400
  lookupIds: string[];
264
- handlers: IFngSingleLookupHandler[]
401
+ handlers: IFngSingleLookupHandler[];
265
402
  }
266
403
 
267
404
  export interface IFngInternalLookupHandlerInfo extends IFngLookupHandler {
@@ -272,16 +409,32 @@ declare module fng {
272
409
  ref: IFngLookupListReference;
273
410
  }
274
411
 
412
+ // we cannot use an enum here, so this will have to do. these are the values expected to be returned by the
413
+ // function on $rootScope with the name formsAngular.disabledSecurityFuncName.
414
+ // false = not disabled,
415
+ // true = disabled,
416
+ // "+" = this and all child elements disabled
417
+ export type DisabledOutcome = boolean | "+";
418
+
419
+ export interface ISecurableScope extends angular.IScope {
420
+ // added by ISecurityService
421
+ isSecurelyHidden: (elemId: string) => boolean;
422
+ isSecurelyDisabled: (elemId: string) => boolean;
423
+ requiresDisabledChildren: (elemId: string) => boolean;
424
+ }
425
+
275
426
  /*
276
427
  The scope which contains form data
277
428
  */
278
- export interface IFormScope extends angular.IScope {
429
+ export interface IFormScope extends ISecurableScope {
279
430
  sharedData: any;
280
- modelNameDisplay : string;
431
+ modelNameDisplay: string;
281
432
  modelName: string;
282
433
  formName: string;
283
434
  alertTitle: any;
435
+ errorVisible: boolean;
284
436
  errorMessage: any;
437
+ errorHideTimer: number;
285
438
  save: any;
286
439
  newRecord: boolean;
287
440
  initialiseNewRecord?: any;
@@ -292,17 +445,16 @@ declare module fng {
292
445
  isCancelDisabled: any;
293
446
  isNewDisabled: any;
294
447
  isSaveDisabled: any;
295
- disabledText: any;
448
+ whyDisabled: string;
296
449
  unconfirmedDelete: boolean;
297
450
  getVal: any;
298
451
  sortableOptions: any;
299
- tabDeselect: any;
300
- tabs?: Array<any>; // In the case of forms that contain a tab set
301
- tab?: string; // title of the active tab - from the route
452
+ tabs?: Array<any>; // In the case of forms that contain a tab set
453
+ tab?: string; // title of the active tab - from the route
302
454
  activeTabNo?: number;
303
- topLevelFormName: string; // The name of the form
455
+ topLevelFormName: string; // The name of the form
304
456
  record: any;
305
- originalData: any; // the unconverted data read from the server
457
+ originalData: any; // the unconverted data read from the server
306
458
  phase: any;
307
459
  disableFunctions: any;
308
460
  dataEventFunctions: any;
@@ -314,13 +466,18 @@ declare module fng {
314
466
  conversions: any;
315
467
  pageSize: any;
316
468
  pagesLoaded: any;
469
+ redirectOptions?: { redirect?: string; allowChange?: boolean };
317
470
  cancel: () => any;
318
- showError: (error: any, alertTitle? : string) => void;
471
+ showError: (error: any, alertTitle?: string) => void;
319
472
  prepareForSave: (cb: (error: string, dataToSave?: any) => void) => void;
473
+ setDefaults: (formSchema: IFormSchema, base?: string) => any;
320
474
  formSchema: IControlledFormSchema;
321
475
  baseSchema: () => Array<any>;
322
476
  setFormDirty: any;
477
+ dirtyChecked?: boolean;
323
478
  add: any;
479
+ hideTab: (event, tabTitle: string, hiddenTabArrayProp: string) => void;
480
+ addTab: (event, tabTitle: string, hiddenTabArrayProp: string) => void;
324
481
  hasError: any;
325
482
  unshift: any;
326
483
  remove: any;
@@ -329,23 +486,40 @@ declare module fng {
329
486
  skipCols: any;
330
487
  setPristine: any;
331
488
  generateEditUrl: any;
489
+ generateViewUrl: any;
332
490
  generateNewUrl: any;
333
491
  scrollTheList: any;
334
492
  getListData: any;
335
- dismissError: any;
493
+ phaseWatcher: any;
494
+ dismissError: () => void;
495
+ stickError: () => void;
496
+ clearTimeout: () => void;
336
497
  handleHttpError: (response: any) => void;
337
498
  dropConversionWatcher: () => void;
499
+ readingRecord?: angular.IPromise<any>;
500
+ onSchemaFetch?: (description: string, source: IFieldViewInfo[]) => void;
501
+ onSchemaProcessed?: (description: string, formSchema: IFormInstruction[]) => void;
502
+ updateQueryForTab?: (tab: string) => void;
503
+ showLoading? : boolean; // a spinner that fades in
504
+ showSpinner? : boolean; // an immediate spinner
505
+ tabDeselect?: ($event: any, $selectedIndex: number) => void;
506
+ setUpCustomLookupOptions?: (
507
+ schemaElement: IFormInstruction,
508
+ ids: string[],
509
+ options: string[],
510
+ baseScope: any
511
+ ) => void;
338
512
  }
339
513
 
340
514
  export interface IContextMenuDivider {
341
515
  divider: boolean;
342
516
  }
343
- export interface IContextMenuOption {
344
- // For it to make any sense, a menu option needs one of the next two properties
345
- url?: string;
346
- fn?: () => void;
517
+ export interface IContextMenuBaseOption {
518
+ // provided to the security hook (see elemSecurityFuncName) - optional where that is not being used
519
+ id?: string;
347
520
 
348
- text: string;
521
+ text?: string;
522
+ textFunc?: () => string;
349
523
  isDisabled?: () => boolean;
350
524
  isHidden?: () => boolean;
351
525
 
@@ -354,11 +528,28 @@ declare module fng {
354
528
  creating: boolean;
355
529
  editing: boolean;
356
530
  }
531
+ export interface IContextSubMenuOption extends IContextMenuBaseOption {
532
+ items: ContextMenuItem[];
533
+ }
534
+ export interface IContextMenuOption extends IContextMenuBaseOption{
535
+ // For it to make any sense, a menu option needs one of the next three properties
536
+ url?: string;
537
+ fn?: (...args: any) => void;
538
+ urlFunc?: () => string;
539
+ broadcast?: string;
540
+ args?: any[];
541
+ }
542
+ export type ContextMenuItem = IContextMenuOption | IContextSubMenuOption | IContextMenuDivider;
543
+
544
+ export interface IModelCtrlService {
545
+ loadControllerAndMenu: (sharedData: any, titleCaseModelName: string, level: number, needDivider: boolean, scope: angular.IScope) => void;
546
+ }
357
547
 
358
548
  export interface IModelController extends IFormScope {
359
- onBaseCtrlReady? : (baseScope: IFormScope) => void; // Optional callback after form is instantiated
360
- onAllReady? : (baseScope: IFormScope) => void; // Optional callback after form is instantiated and populated
361
- contextMenu? : Array<IContextMenuOption | IContextMenuDivider>
549
+ onBaseCtrlReady?: (baseScope: IFormScope) => void; // Optional callback after form is instantiated
550
+ onAllReady?: (baseScope: IFormScope) => void; // Optional callback after form is instantiated and populated
551
+ contextMenu?: ContextMenuItem[];
552
+ contextMenuPromise?: Promise<ContextMenuItem[]>;
362
553
  }
363
554
 
364
555
  export interface IBaseFormOptions {
@@ -366,13 +557,13 @@ declare module fng {
366
557
  * The style of the form layout. Supported values are horizontalcompact, horizontal, vertical, inline
367
558
  */
368
559
  //TODO supported values should be in an enum
369
- formstyle?: string;
560
+ formstyle?: formStyle;
370
561
  /**
371
562
  * Model on form scope (defaults to record).
372
563
  * <li><strong>model</strong> the object in the scope to be bound to the model controller. Specifying
373
564
  * the model inhibits the generation of the <strong>form</strong> tag unless the <strong>forceform</strong> attribute is set to true</li>
374
565
  */
375
- model? : string;
566
+ model?: string;
376
567
  /**
377
568
  * The name to be given to the form - defaults to myForm
378
569
  */
@@ -381,60 +572,272 @@ declare module fng {
381
572
  * Normally first field in a form gets autofocus set. Use this to prevent this
382
573
  */
383
574
  noautofocus?: string;
575
+ /*
576
+ Suppress the generation of element ids
577
+ (sometimes required when using nested form-inputs in a directive)
578
+ */
579
+ noid?: boolean;
384
580
  }
385
581
 
386
582
  export interface IFormAttrs extends IFormOptions, angular.IAttributes {
387
583
  /**
388
584
  * Schema used by the form
389
585
  */
390
- schema : string;
391
- forceform?: string; // Must be true or omitted. Forces generation of the <strong>form</strong> tag when model is specified
586
+ schema: string;
587
+ forceform?: string; // Must be true or omitted. Forces generation of the <strong>form</strong> tag when model is specified
588
+ noid?: boolean;
392
589
  }
393
590
 
394
591
  export interface IFormOptions extends IBaseFormOptions {
395
- schema? : string;
592
+ schema?: string;
396
593
  subkey?: string;
397
594
  subkeyno?: number;
398
- subschema? : string;
399
- subschemaroot? : string;
595
+ subschema?: string;
596
+ subschemaroot?: string;
597
+ viewform?: boolean;
598
+ suppressNestingWarning?: boolean;
400
599
  }
401
600
 
402
601
  export interface IBuiltInRoute {
403
602
  route: string;
404
- state: string;
405
- templateUrl: string;
406
- options? : any;
603
+ state?: string;
604
+ templateUrl?: string;
605
+ options?: {
606
+ authenticate?: boolean;
607
+ templateUrl?: string | (() => void);
608
+ template?: string;
609
+ controller?: string;
610
+ }
407
611
  }
408
612
 
409
613
  export interface IRoutingConfig {
410
- hashPrefix: string;
614
+ hashPrefix?: string;
411
615
  html5Mode: boolean;
412
- routing: string; // What sort of routing do we want? ngroute or uirouter.
413
- // TODO Should be enum
414
- prefix: string; // How do we want to prefix out routes? If not empty string then first character must be slash (which is added if not)
415
- // for example '/db' that gets prepended to all the generated routes. This can be used to
416
- // prevent generated routes (which have a lot of parameters) from clashing with other routes in
417
- // the web app that have nothing to do with CRUD forms
616
+ routing: string; // What sort of routing do we want? ngroute or uirouter.
617
+ // TODO Should be enum
618
+ prefix: string; // How do we want to prefix out routes? If not empty string then first character must be slash (which is added if not)
619
+ // for example '/db' that gets prepended to all the generated routes. This can be used to
620
+ // prevent generated routes (which have a lot of parameters) from clashing with other routes in
621
+ // the web app that have nothing to do with CRUD forms
418
622
  fixedRoutes?: Array<IBuiltInRoute>;
419
- templateFolder?: string; // The folder where the templates for base-list, base-edit and base-analysis live. Internal templates used by default. For pre 0.7.0 behaviour use 'partials/'
420
- add2fngRoutes?: any; // An object to add to the generated routes. One use case would be to add {authenticate: true}
421
- // so that the client authenticates for certain routes
623
+ templateFolder?: string; // The folder where the templates for base-list, base-edit and base-analysis live. Internal templates used by default. For pre 0.7.0 behaviour use 'partials/'
624
+ add2fngRoutes?: any; // An object to add to the generated routes. One use case would be to add {authenticate: true}
625
+ // so that the client authenticates for certain routes
422
626
 
423
- variantsForDemoWebsite? : any; // Just for demo website
424
- variants?: any; // Just for demo website
627
+ variantsForDemoWebsite?: any; // Just for demo website
628
+ variants?: any; // Just for demo website
629
+ onDelete?: string; // Supports literal (such as '/') or 'new' (which will go to a /new of the model) default is to go to the list view
425
630
  }
426
631
 
427
632
  export interface IFngRoute {
428
- newRecord?: boolean;
429
- analyse?: boolean;
430
- modelName?: string;
431
- reportSchemaName? : string;
432
- id? : string;
433
- formName? : string;
434
- tab? : string;
435
- variant? : string; // TODO should be enum of supported frameworks
633
+ newRecord?: boolean;
634
+ analyse?: boolean;
635
+ modelName?: string;
636
+ reportSchemaName?: string;
637
+ id?: string;
638
+ formName?: string;
639
+ tab?: string;
640
+ variant?: string; // TODO should be enum of supported frameworks
641
+ }
642
+
643
+ interface IBuildingBlocks {
644
+ common: string;
645
+ sizeClassBS3: string;
646
+ sizeClassBS2: string;
647
+ compactClass: string;
648
+ formControl: string;
649
+ modelString: string;
650
+ disableableAncestorStr: string;
651
+ }
652
+
653
+ interface IProcessedAttrs {
654
+ info: IFormInstruction;
655
+ options: IFormOptions;
656
+ directiveOptions: any;
657
+ }
658
+
659
+ interface IGenDisableStrParams {
660
+ forceNg?: boolean;
661
+ nonUniqueIdSuffix?: string;
662
+ }
663
+
664
+
665
+ interface IPluginHelperService {
666
+ extractFromAttr: (
667
+ attr: any,
668
+ directiveName: string,
669
+ scope: fng.IFormScope
670
+ ) => { info: IFormInstruction; options: IFormOptions; directiveOptions: any };
671
+ buildInputMarkup: (
672
+ scope: angular.IScope,
673
+ attrs: any,
674
+ params: {
675
+ processedAttrs?: IProcessedAttrs;
676
+ fieldInfoOverrides?: Partial<IFormInstruction>;
677
+ optionOverrides?: Partial<IFormOptions>;
678
+ addButtons?: boolean;
679
+ needsX?: boolean;
680
+ },
681
+ generateInputControl: (buildingBlocks: IBuildingBlocks) => string
682
+ ) => string;
683
+ genIdString: (scope: angular.IScope, processedAttrs: IProcessedAttrs, idSuffix: string) => string;
684
+ genDisabledStr: (
685
+ scope: angular.IScope,
686
+ processedAttrs: IProcessedAttrs,
687
+ idSuffix: string,
688
+ params?: fng.IGenDisableStrParams
689
+ ) => string;
690
+ genIdAndDisabledStr: (
691
+ scope: angular.IScope,
692
+ processedAttrs: IProcessedAttrs,
693
+ idSuffix: string,
694
+ params?: fng.IGenDisableStrParams
695
+ ) => string;
696
+ genDateTimePickerDisabledStr: (scope: angular.IScope, processedAttrs: IProcessedAttrs, idSuffix: string) => string;
697
+ genDateTimePickerIdAndDisabledStr: (
698
+ scope: angular.IScope,
699
+ processedAttrs: IProcessedAttrs,
700
+ idSuffix: string
701
+ ) => string;
702
+ genUiSelectIdAndDisabledStr: (
703
+ scope: angular.IScope,
704
+ processedAttrs: IProcessedAttrs,
705
+ idSuffix: string
706
+ ) => string;
707
+ handlePseudos: (scope: fng.IFormScope, str: string) => string;
708
+ genDisableableAncestorStr: (processedAttrs: IProcessedAttrs) => string;
709
+ }
710
+
711
+ interface ISecurityVisibility {
712
+ omit?: boolean;
713
+ visibilityAttr?: string;
714
+ }
715
+
716
+ interface IGenerateDisableAttrParams {
717
+ attr?: string;
718
+ attrRequiresValue?: boolean;
719
+ forceNg?: boolean;
720
+ }
721
+
722
+ type SecurityType = "hidden" | "disabled";
723
+
724
+ interface ISecurityService {
725
+ canDoSecurity: (type: SecurityType) => boolean;
726
+ canDoSecurityNow: (scope: fng.ISecurableScope, type: SecurityType) => boolean;
727
+ isSecurelyHidden: (elemId: string, pseudoUrl?: string) => boolean;
728
+ isSecurelyDisabled: (elemId: string, pseudoUrl?: string) => boolean;
729
+ decorateSecurableScope: (securableScope: ISecurableScope, params?: { pseudoUrl?: string, overrideSkipping?: boolean }) => void;
730
+ doSecurityWhenReady: (cb: () => void) => void;
731
+ considerVisibility: (id: string, scope: fng.ISecurableScope) => ISecurityVisibility;
732
+ considerContainerVisibility: (contentIds: string[], scope: fng.ISecurableScope) => fng.ISecurityVisibility;
733
+ getDisableableAttrs: (id: string) => string;
734
+ getHideableAttrs: (id: string) => string;
735
+ getDisableableAncestorAttrs: (id: string) => string;
736
+ generateDisabledAttr: (id: string, scope: fng.ISecurableScope, params?: IGenerateDisableAttrParams) => string;
436
737
  }
437
738
 
739
+ interface IListQueryOptions {
740
+ limit?: number;
741
+ find?: any; // e.g., { "careWorker.isCareWorker": true }
742
+ aggregate?: any;
743
+ projection?: any;
744
+ order?: any; // e.g., { familyName: -1, givenName: -1 }
745
+ skip?: number;
746
+ concatenate?: boolean; // whether the list fields should be concatenated into a single .text property
747
+ }
748
+
749
+ interface ISubmissionsService {
750
+ // return all of the list attributes of the record from db.<modelName>.<id>
751
+ // where returnRaw is true, the document (albeit with only its list attributes present) will be returned without transformation
752
+ // otherwise, the list fields will be concatenated (space-seperated) and returned as the list property of a record { list: string }
753
+ // e.g., "John Doe", in the case of a person
754
+ getListAttributes: (
755
+ modelName: string,
756
+ id: string,
757
+ returnRaw?: boolean
758
+ ) => angular.IHttpPromise<{ list: string } | any>;
759
+ readRecord: (modelName: string, id: string, formName?: string) => angular.IHttpPromise<any>;
760
+ getAll: (modelName: string, _options: any) => angular.IHttpPromise<any[]>;
761
+ getAllListAttributes: (ref: string) => angular.IHttpPromise<ILookupItem[]>;
762
+ getAllPickListAttributes: (ref: string) => angular.IHttpPromise<ILookupItem[]>;
763
+ getPagedAndFilteredList: (
764
+ modelName: string,
765
+ options: IListQueryOptions
766
+ ) => angular.IHttpPromise<any[]>;
767
+ getPagedAndFilteredListFull: (
768
+ modelName: string,
769
+ options: IListQueryOptions
770
+ ) => angular.IHttpPromise<any[]>;
771
+ deleteRecord: (model: string, id: string, formName: string) => angular.IHttpPromise<void>;
772
+ updateRecord: (modelName: string, id: string, dataToSave: any, formName?: string) => angular.IHttpPromise<any>;
773
+ createRecord: (modelName: string, dataToSave: any, formName?: string) => angular.IHttpPromise<any>;
774
+ useCache: (val: boolean) => void;
775
+ clearCache: () => void;
776
+ getCache: () => boolean;
777
+ }
778
+
779
+ interface IRoutingServiceProvider {
780
+ start: (options: IRoutingConfig) => void;
781
+ addRoutes: (fixedRoutes: Array<IBuiltInRoute>, fngRoutes:Array<IBuiltInRoute>) => void;
782
+ registerAction: (action: string) => void;
783
+ $get: () => IRoutingService;
784
+ }
785
+
786
+ interface IRoutingService {
787
+ router: () => string;
788
+ prefix: () => string;
789
+ parsePathFunc: () => (location: string) => void;
790
+ html5hash: () => string;
791
+ buildUrl: (path: string) => string;
792
+ buildOperationUrl: (
793
+ operation: string,
794
+ modelName: string,
795
+ formName: string,
796
+ id: string,
797
+ tabName?: string
798
+ ) => string;
799
+ redirectTo: () => (operation: string, scope: IFormScope, LocationService: angular.ILocationService, id?: string, tab?: string) => void;
800
+ }
801
+
802
+ interface ICssFrameworkServiceProvider {
803
+ setOptions: (options: { framework: string }) => void;
804
+ $get: () => ICssFrameworkService;
805
+ }
806
+
807
+ interface ICssFrameworkService {
808
+ framework: () => string;
809
+ span: (cols: number) => string;
810
+ offset: (cols: number) => string;
811
+ rowFluid: () => string;
812
+ }
813
+
814
+ interface IFngUiSelectHelperService {
815
+ windowChanged: (width: number, height: number) => boolean;
816
+ addClientLookup: (lkpName: string, lkpData: any) => void;
817
+ clearCache: () => void;
818
+ lookupFunc: (value: string, formSchema: IFormInstruction, cb: (formSchema: IFormInstruction, value: ILookupItem ) => void) => void;
819
+ doOwnConversion: (scope: IFormScope, processedAttrs: any, ref: string) => void;
820
+ }
821
+
822
+ interface IFormMarkupHelperService {
823
+ isHorizontalStyle: (formStyle: string, includeStacked: boolean) => boolean;
824
+ isArrayElement: (scope: angular.IScope, info: fng.IFormInstruction, options: fng.IFormOptions) => boolean;
825
+ fieldChrome: (scope: fng.IFormScope, info: fng.IFormInstruction, options: fng.IFormOptions) => { omit?: boolean, template?: string, closeTag?: string };
826
+ label: (scope: fng.IFormScope, fieldInfo: fng.IFormInstruction, addButtonMarkup: boolean, options: fng.IFormOptions) => string;
827
+ glyphClass: () => string;
828
+ allInputsVars: (scope: angular.IScope, fieldInfo: fng.IFormInstruction, options: fng.IFormOptions, modelString: string, idString: string, nameString: string) => Partial<fng.IBuildingBlocks>;
829
+ inputChrome: (value: string, fieldInfo: fng.IFormInstruction, options: fng.IFormOptions, markupVars) => string;
830
+ generateSimpleInput: (common: string, fieldInfo: fng.IFormInstruction, options: fng.IFormOptions) => string;
831
+ controlDivClasses: (options: fng.IFormOptions, fieldInfo: fng.IFormInstruction) => string[];
832
+ handleInputAndControlDiv: (inputMarkup: string, controlDivClasses: string[]) => string;
833
+ handleArrayInputAndControlDiv: (inputMarkup: string, controlDivClasses: string[], scope: fng.IFormScope, info: fng.IFormInstruction, options: fng.IFormOptions) => string;
834
+ addTextInputMarkup: (allInputsVars: Partial<fng.IBuildingBlocks>, fieldInfo: fng.IFormInstruction, requiredStr: string) => string;
835
+ handleReadOnlyDisabled: (partialFieldInfo: { name: string, id?: string, nonUniqueId?: string, readonly?: boolean | string }, scope: fng.IFormScope) => string[];
836
+ generateArrayElementIdString: (idString: string, info: fng.IFormInstruction, options: fng.IFormOptions) => string;
837
+ genDisableableAncestorStr: (id: string) => string;
838
+ generateNgShow: (showWhen: IFngShowWhen, model: string) => string;
839
+ handlePseudos: (scope: fng.IFormScope, str: string, dynamicFuncName?: string) => string;
840
+ }
438
841
  }
439
842
 
440
- declare var formsAngular: angular.IModule;
843
+ declare var formsAngular: fng.IFng;