dattatable 2.9.45 → 2.9.47

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.
Files changed (70) hide show
  1. package/build/common/list.d.ts +2 -1
  2. package/build/common/list.js +21 -7
  3. package/build/dashboard/accordion.js +2 -11
  4. package/build/dashboard/index.d.ts +14 -0
  5. package/build/dashboard/index.js +57 -4
  6. package/build/dashboard/tiles.d.ts +30 -0
  7. package/build/dashboard/tiles.js +167 -0
  8. package/build/lib.d.ts +1 -0
  9. package/dist/dattatable.js +14 -3
  10. package/dist/dattatable.min.js +1 -1
  11. package/docs/assets/navigation.js +1 -1
  12. package/docs/assets/search.js +1 -1
  13. package/docs/classes/Accordion.html +2 -2
  14. package/docs/classes/AuditLog.html +2 -2
  15. package/docs/classes/CanvasForm.html +2 -2
  16. package/docs/classes/Comments.html +2 -2
  17. package/docs/classes/Dashboard.html +8 -4
  18. package/docs/classes/DataTable.html +3 -3
  19. package/docs/classes/Documents.html +6 -6
  20. package/docs/classes/FilterSlideout.html +2 -2
  21. package/docs/classes/Footer.html +2 -2
  22. package/docs/classes/Header.html +2 -2
  23. package/docs/classes/InstallationRequired.html +2 -2
  24. package/docs/classes/ItemForm.html +4 -4
  25. package/docs/classes/List.html +5 -4
  26. package/docs/classes/ListSecurity.html +2 -2
  27. package/docs/classes/LoadingDialog.html +2 -2
  28. package/docs/classes/Modal.html +2 -2
  29. package/docs/classes/Navigation.html +3 -3
  30. package/docs/classes/Tiles.html +13 -0
  31. package/docs/classes/Timeout.html +2 -2
  32. package/docs/enums/ActionButtonTypes.html +2 -2
  33. package/docs/functions/formatBytes.html +1 -1
  34. package/docs/functions/formatDateValue.html +1 -1
  35. package/docs/functions/formatTimeValue.html +1 -1
  36. package/docs/functions/getContextInfo.html +1 -1
  37. package/docs/functions/getFileExt.html +1 -1
  38. package/docs/functions/waitForTheme.html +1 -1
  39. package/docs/index.html +1 -1
  40. package/docs/interfaces/IAccordion.html +2 -2
  41. package/docs/interfaces/IAccordionProps.html +2 -2
  42. package/docs/interfaces/IAuditLogItem.html +3 -3
  43. package/docs/interfaces/IAuditLogItemCreation.html +2 -2
  44. package/docs/interfaces/IAuditLogProps.html +2 -2
  45. package/docs/interfaces/IAuditLogViewProps.html +2 -2
  46. package/docs/interfaces/ICommentsItem.html +2 -2
  47. package/docs/interfaces/IDashboardProps.html +3 -2
  48. package/docs/interfaces/IDataTable.html +2 -2
  49. package/docs/interfaces/IDataTableProps.html +2 -2
  50. package/docs/interfaces/IDocumentsProps.html +2 -2
  51. package/docs/interfaces/IFilterItem.html +2 -2
  52. package/docs/interfaces/IFilterProps.html +2 -2
  53. package/docs/interfaces/IFooterProps.html +2 -2
  54. package/docs/interfaces/IHeaderProps.html +2 -2
  55. package/docs/interfaces/IInstallProps.html +2 -2
  56. package/docs/interfaces/IItemFormCreateProps.html +2 -2
  57. package/docs/interfaces/IItemFormEditProps.html +2 -2
  58. package/docs/interfaces/IItemFormTab.html +2 -2
  59. package/docs/interfaces/IItemFormTabInfo.html +2 -2
  60. package/docs/interfaces/IItemFormViewProps.html +2 -2
  61. package/docs/interfaces/IListProps.html +2 -2
  62. package/docs/interfaces/IListSecurity.html +2 -2
  63. package/docs/interfaces/IListSecurityItem.html +2 -2
  64. package/docs/interfaces/IShowDialogProps.html +2 -2
  65. package/docs/interfaces/ITiles.html +3 -0
  66. package/docs/interfaces/ITilesProps.html +9 -0
  67. package/docs/modules.html +4 -1
  68. package/docs/variables/DattaTable.html +1 -1
  69. package/docs/variables/ListSecurityDefaultGroups.html +1 -1
  70. package/package.json +54 -54
@@ -55,13 +55,14 @@ export declare class List<T = Types.SP.ListItem> {
55
55
  constructor(props: IListProps<T>);
56
56
  private clear;
57
57
  createItem(values: any): PromiseLike<T>;
58
- newForm(props: IItemFormCreateProps): void;
59
58
  editForm(props: IItemFormEditProps): void;
59
+ getField(name: string): Types.SP.Field;
60
60
  private init;
61
61
  private loadItem;
62
62
  private loadItems;
63
63
  private loadItemsByQuery;
64
64
  private loadItemsByView;
65
+ newForm(props: IItemFormCreateProps): void;
65
66
  refresh(query?: Types.IODataQuery): PromiseLike<T[]>;
66
67
  private refreshContextInfo;
67
68
  refreshItem(itemId: number, query?: Types.IODataQuery): PromiseLike<T>;
@@ -192,13 +192,6 @@ var List = /** @class */ (function () {
192
192
  _this.ListInfo.Items().add(values).execute(resolve, reject);
193
193
  });
194
194
  };
195
- // Displays the new form
196
- List.prototype.newForm = function (props) {
197
- // Clear the modal/canvas
198
- this.clear();
199
- // Display the form
200
- _1.ItemForm.create(props).then(null, this._onLoadFormError);
201
- };
202
195
  // Displays the edit form
203
196
  List.prototype.editForm = function (props) {
204
197
  // Clear the modal/canvas
@@ -206,6 +199,20 @@ var List = /** @class */ (function () {
206
199
  // Display the form
207
200
  _1.ItemForm.edit(props).then(null, this._onLoadFormError);
208
201
  };
202
+ // Gets a list field by internal or title
203
+ List.prototype.getField = function (name) {
204
+ // Parse the fields
205
+ for (var i = 0; i < this.ListFields.length; i++) {
206
+ var field = this.ListFields[i];
207
+ // See if this is the target field
208
+ if (field.InternalName == name || field.Title == name) {
209
+ // Return the field
210
+ return field;
211
+ }
212
+ }
213
+ // Not found
214
+ return null;
215
+ };
209
216
  // Initializes the list component
210
217
  List.prototype.init = function () {
211
218
  var _this = this;
@@ -373,6 +380,13 @@ var List = /** @class */ (function () {
373
380
  }, true);
374
381
  });
375
382
  };
383
+ // Displays the new form
384
+ List.prototype.newForm = function (props) {
385
+ // Clear the modal/canvas
386
+ this.clear();
387
+ // Display the form
388
+ _1.ItemForm.create(props).then(null, this._onLoadFormError);
389
+ };
376
390
  // Refresh the data
377
391
  List.prototype.refresh = function (query) {
378
392
  var _this = this;
@@ -33,19 +33,10 @@ var Accordion = /** @class */ (function () {
33
33
  var items = this._props.el.querySelectorAll(".accordion-item");
34
34
  for (var i = 0; i < items.length; i++) {
35
35
  var elItem = items[i];
36
+ // Clear the item
37
+ this.clearItem(elItem);
36
38
  // Show the item
37
39
  elItem.classList.remove("d-none");
38
- // Remove the first/last item classes
39
- elItem.classList.remove("first-item");
40
- elItem.classList.remove("last-item");
41
- // See if a class name exists
42
- if (className) {
43
- // See if this item doesn't matches
44
- if (!elItem.classList.contains(className)) {
45
- // Hide the item
46
- elItem.classList.add("d-none");
47
- }
48
- }
49
40
  }
50
41
  // Render the items
51
42
  this.renderItems();
@@ -8,6 +8,7 @@ export * from "./footer";
8
8
  export * from "./header";
9
9
  export * from "./navigation";
10
10
  export * from "./table";
11
+ export * from "./tiles";
11
12
  export interface IDashboardProps {
12
13
  accordion?: {
13
14
  bodyField?: string;
@@ -70,6 +71,15 @@ export interface IDashboardProps {
70
71
  onRendered?: (el?: HTMLElement, dt?: any) => void;
71
72
  rows?: any[];
72
73
  };
74
+ tiles?: {
75
+ bodyField?: string;
76
+ filterField?: string;
77
+ items: any[];
78
+ onCardRender?: (el?: HTMLElement, item?: any) => void;
79
+ paginationLimit?: number;
80
+ subTitleField?: string;
81
+ titleField?: string;
82
+ };
73
83
  onRendered?: (el?: HTMLElement) => void;
74
84
  useModal?: boolean;
75
85
  }
@@ -82,7 +92,9 @@ export declare class Dashboard {
82
92
  private _filters;
83
93
  private _navigation;
84
94
  private _props;
95
+ private _tiles;
85
96
  private IsAccordion;
97
+ private IsTiles;
86
98
  constructor(props: IDashboardProps);
87
99
  private applyFilters;
88
100
  private render;
@@ -100,6 +112,8 @@ export declare class Dashboard {
100
112
  filterAccordion(value?: string): void;
101
113
  filterAccordionMulti(value?: string[]): void;
102
114
  filterMulti(idx: number, values?: string[]): void;
115
+ filterTiles(value?: string): void;
116
+ filterTilesMulti(value?: string[]): void;
103
117
  getFilter(key: string): Components.ICheckboxGroup;
104
118
  getSearchValue(): string;
105
119
  hideFilter(): void;
@@ -34,6 +34,7 @@ var footer_1 = require("./footer");
34
34
  var header_1 = require("./header");
35
35
  var navigation_1 = require("./navigation");
36
36
  var table_1 = require("./table");
37
+ var tiles_1 = require("./tiles");
37
38
  // Export the components
38
39
  __exportStar(require("./accordion"), exports);
39
40
  __exportStar(require("./filter"), exports);
@@ -41,6 +42,7 @@ __exportStar(require("./footer"), exports);
41
42
  __exportStar(require("./header"), exports);
42
43
  __exportStar(require("./navigation"), exports);
43
44
  __exportStar(require("./table"), exports);
45
+ __exportStar(require("./tiles"), exports);
44
46
  /**
45
47
  * Dashboard
46
48
  */
@@ -53,6 +55,7 @@ var Dashboard = /** @class */ (function () {
53
55
  this._filters = null;
54
56
  this._navigation = null;
55
57
  this._props = null;
58
+ this._tiles = null;
56
59
  // Set the properties
57
60
  this._props = props;
58
61
  // Set the flag
@@ -67,7 +70,10 @@ var Dashboard = /** @class */ (function () {
67
70
  props.onRendered ? props.onRendered(_this._props.el) : null;
68
71
  }, 10);
69
72
  }
73
+ // Determines if we are rendering an accordion
70
74
  Dashboard.prototype.IsAccordion = function () { return this._props.accordion ? true : false; };
75
+ // Determines if we are rendering tiles
76
+ Dashboard.prototype.IsTiles = function () { return this._props.tiles ? true : false; };
71
77
  // Applies the default active filters
72
78
  Dashboard.prototype.applyFilters = function () {
73
79
  var _a;
@@ -105,14 +111,16 @@ var Dashboard = /** @class */ (function () {
105
111
  filters: this._props.filters ? this._props.filters.items : [],
106
112
  onClear: this._props.filters ? this._props.filters.onClear : null,
107
113
  onRendered: this._props.filters ? this._props.filters.onRendered : null,
108
- onFilter: !this.IsAccordion ? null : function (value) {
114
+ onFilter: this.IsAccordion ? function (value) {
109
115
  _this._accordion.filter(value);
110
- }
116
+ } : (this.IsTiles ? function (value) {
117
+ _this._tiles.filter(value);
118
+ } : null)
111
119
  });
112
120
  // Render the template
113
121
  var elTemplate = document.createElement("div");
114
122
  elTemplate.classList.add("dashboard");
115
- elTemplate.innerHTML = "\n <div class=\"row\">\n <div id=\"navigation\" class=\"col\"></div>\n </div>\n <div class=\"row\">\n <div id=\"header\" class=\"col mx-75\"></div>\n </div>\n <div class=\"row\">\n <div id=\"sub-navigation\" class=\"col\"></div>\n </div>\n <div class=\"row\">\n <div id=\"".concat(this.IsAccordion ? "accordion" : "datatable", "\" class=\"col\"></div>\n </div>\n <div class=\"row\">\n <div id=\"footer\" class=\"col\"></div>\n </div>").trim();
123
+ elTemplate.innerHTML = "\n <div class=\"row\">\n <div id=\"navigation\" class=\"col\"></div>\n </div>\n <div class=\"row\">\n <div id=\"header\" class=\"col mx-75\"></div>\n </div>\n <div class=\"row\">\n <div id=\"sub-navigation\" class=\"col\"></div>\n </div>\n <div class=\"row\">\n <div id=\"".concat(this.IsAccordion ? "accordion" : (this.IsTiles ? "tiles" : "datatable"), "\" class=\"col\"></div>\n </div>\n <div class=\"row\">\n <div id=\"footer\" class=\"col\"></div>\n </div>").trim();
116
124
  this._props.el.appendChild(elTemplate);
117
125
  // Set/Default the visibility flags
118
126
  var headerIsVisible = (this._props.hideHeader == null || this._props.hideHeader == true) && this._props.header == null ? false : true;
@@ -149,6 +157,11 @@ var Dashboard = /** @class */ (function () {
149
157
  // Search the accordion
150
158
  _this._accordion.search(value);
151
159
  }
160
+ // Else, see if we are rendering tiles
161
+ else if (_this.IsTiles) {
162
+ // Search the tiles
163
+ _this._tiles.search(value);
164
+ }
152
165
  else {
153
166
  // Search the data table
154
167
  _this._dt.search(value);
@@ -225,6 +238,11 @@ var Dashboard = /** @class */ (function () {
225
238
  // Search the accordion
226
239
  _this._accordion.search(value);
227
240
  }
241
+ // Else, see if we are rendering tiles
242
+ else if (_this.IsTiles) {
243
+ // Search the tiles
244
+ _this._tiles.search(value);
245
+ }
228
246
  else {
229
247
  // Search the data table
230
248
  _this._dt.search(value);
@@ -241,6 +259,11 @@ var Dashboard = /** @class */ (function () {
241
259
  // Render the accordion
242
260
  this._accordion = new accordion_1.Accordion(__assign({ el: this._props.el.querySelector("#accordion") }, this._props.accordion));
243
261
  }
262
+ // Else, see if we are rendering tiles
263
+ else if (this.IsTiles) {
264
+ // Render the tiles
265
+ this._tiles = new tiles_1.Tiles(__assign({ el: this._props.el.querySelector("#tiles") }, this._props.tiles));
266
+ }
244
267
  else {
245
268
  // Render the data table
246
269
  this._dt = new table_1.DataTable({
@@ -301,7 +324,11 @@ var Dashboard = /** @class */ (function () {
301
324
  // Filter the accordion
302
325
  this._accordion.filter(value);
303
326
  }
304
- // Else, filter the table
327
+ // Else, see if we are rendering tiles
328
+ else if (this.IsTiles) {
329
+ // Search the tiles
330
+ this._tiles.search(value);
331
+ }
305
332
  else {
306
333
  // If no value is specified, then we don't want to filter by exact value
307
334
  exactMatchFl && value ? this._dt.filterExact(idx, value) : this._dt.filter(idx, value);
@@ -330,11 +357,32 @@ var Dashboard = /** @class */ (function () {
330
357
  // Filter the accordion
331
358
  //this._accordion.filterMulti(value);
332
359
  }
360
+ // Else, see if we have tiles
361
+ else if (this.IsTiles) {
362
+ // Filter the tiles
363
+ //this._tiles.filterMulti(value);
364
+ }
333
365
  else {
334
366
  // Filter the table
335
367
  this._dt.filterMulti(idx, values);
336
368
  }
337
369
  };
370
+ // Filter the tiles
371
+ Dashboard.prototype.filterTiles = function (value) {
372
+ // See if we have tiles
373
+ if (this.IsTiles) {
374
+ // Filter the tiles
375
+ this._tiles.filter(value);
376
+ }
377
+ };
378
+ // Filter the tiles
379
+ Dashboard.prototype.filterTilesMulti = function (value) {
380
+ // See if we have tiles
381
+ if (this.IsTiles) {
382
+ // Filter the tiles
383
+ //this._tiles.filterMulti(value);
384
+ }
385
+ };
338
386
  // Returns a filter checkbox group by its key
339
387
  Dashboard.prototype.getFilter = function (key) { return this._filters.getFilter(key); };
340
388
  // Returns the current search value
@@ -359,6 +407,11 @@ var Dashboard = /** @class */ (function () {
359
407
  // Search the accordion
360
408
  this._accordion.search(value);
361
409
  }
410
+ // Else, see if we have tiles
411
+ else if (this.IsTiles) {
412
+ // Search the tiles
413
+ this._tiles.search(value);
414
+ }
362
415
  else {
363
416
  // Search the table
364
417
  this._dt.search(value);
@@ -0,0 +1,30 @@
1
+ export interface ITiles {
2
+ filter?: (string: any) => void;
3
+ search?: (value: string) => void;
4
+ }
5
+ export interface ITilesProps {
6
+ bodyField?: string;
7
+ el: HTMLElement;
8
+ filterField?: string;
9
+ items: any[];
10
+ onCardRender?: (el?: HTMLElement, item?: any) => void;
11
+ paginationLimit?: number;
12
+ subTitleField?: string;
13
+ titleField?: string;
14
+ }
15
+ /**
16
+ * Tiles
17
+ */
18
+ export declare class Tiles implements ITiles {
19
+ private _tiles;
20
+ private _activeFilterClass;
21
+ private _activeSearchFilter;
22
+ private _pagination;
23
+ private _props;
24
+ constructor(props: ITilesProps);
25
+ filter(value: string): void;
26
+ private render;
27
+ private renderTiles;
28
+ private updateTiles;
29
+ search(value: string): void;
30
+ }
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Tiles = void 0;
4
+ var gd_sprest_bs_1 = require("gd-sprest-bs");
5
+ /**
6
+ * Tiles
7
+ */
8
+ var Tiles = /** @class */ (function () {
9
+ // Constructor
10
+ function Tiles(props) {
11
+ this._tiles = null;
12
+ this._activeFilterClass = null;
13
+ this._activeSearchFilter = null;
14
+ this._pagination = null;
15
+ // Save the properties
16
+ this._props = props;
17
+ // Render the tile
18
+ this.render();
19
+ }
20
+ // Filters the tile
21
+ Tiles.prototype.filter = function (value) {
22
+ var className = value ? value.toLowerCase().replace(/ /g, "-") : null;
23
+ this._activeFilterClass = className;
24
+ // Parse all tile items
25
+ var items = this._props.el.querySelectorAll(".card");
26
+ for (var i = 0; i < items.length; i++) {
27
+ var elItem = items[i];
28
+ // Show the item
29
+ elItem.classList.remove("d-none");
30
+ }
31
+ // Update the tiles
32
+ this.updateTiles();
33
+ };
34
+ // Renders the dashboard
35
+ Tiles.prototype.render = function () {
36
+ // Render the tile
37
+ this.renderTiles();
38
+ // Update the tiles
39
+ this.updateTiles();
40
+ };
41
+ // Renders the tiles
42
+ Tiles.prototype.renderTiles = function () {
43
+ // Parse the items
44
+ var cards = [];
45
+ for (var i = 0; i < this._props.items.length; i++) {
46
+ var item = this._props.items[i];
47
+ var itemClassNames = [];
48
+ // Get the filters
49
+ var filters = item[this._props.filterField] || [];
50
+ filters = filters["results"] || filters;
51
+ // See if the filter field is specified
52
+ if (this._props.filterField) {
53
+ // Parse the selected filters
54
+ for (var j = 0; j < filters.length; j++) {
55
+ var filter = filters[j].toLowerCase().replace(/ /g, '-');
56
+ // Add the filter as a class name
57
+ if (filter) {
58
+ itemClassNames.push(filter);
59
+ }
60
+ }
61
+ }
62
+ // Add an tile
63
+ cards.push({
64
+ className: itemClassNames.join(" "),
65
+ body: [{
66
+ content: (this._props.bodyField ? item[this._props.bodyField || "Description"] : null) || "",
67
+ data: filters,
68
+ subTitle: item[this._props.subTitleField] || "",
69
+ title: item[this._props.titleField || "Title"] || "",
70
+ onRender: this._props.onCardRender
71
+ }]
72
+ });
73
+ }
74
+ // Render the tiles
75
+ this._tiles = gd_sprest_bs_1.Components.CardGroup({
76
+ el: this._props.el,
77
+ cards: cards
78
+ });
79
+ };
80
+ // Updates the visibility of the tiles
81
+ Tiles.prototype.updateTiles = function () {
82
+ var paginationLimit = this._props.paginationLimit || 10;
83
+ // Get the pagination element
84
+ var elPagination = this._props.el.querySelector(".tiles-pagination");
85
+ if (elPagination) {
86
+ // Clear the element
87
+ while (elPagination.firstChild) {
88
+ elPagination.removeChild(elPagination.firstChild);
89
+ }
90
+ }
91
+ else {
92
+ // Create the element
93
+ elPagination = document.createElement("div");
94
+ elPagination.classList.add("tiles-pagination");
95
+ this._props.el.appendChild(elPagination);
96
+ }
97
+ // Get the elements as an array
98
+ var elItems = Array.from(this._tiles.el.querySelectorAll(this._activeFilterClass ? "." + this._activeFilterClass : ".card"));
99
+ // See if a search value exists
100
+ if (this._activeSearchFilter) {
101
+ // Parse the items
102
+ for (var i = elItems.length - 1; i >= 0; i--) {
103
+ var elItem = elItems[i];
104
+ // See if the item doesn't contains the search value
105
+ if (elItem.innerText.toLowerCase().indexOf(this._activeSearchFilter) < 0) {
106
+ // Hide the item
107
+ elItem.classList.add("d-none");
108
+ // Exclude the item from the array
109
+ elItems.splice(i, 1);
110
+ }
111
+ }
112
+ }
113
+ // Parse the active items to show
114
+ for (var i = 0; i < paginationLimit; i++) {
115
+ var elItem = elItems[i];
116
+ // Ensure the item exists
117
+ if (elItem) {
118
+ // Show the item
119
+ elItem.classList.remove("d-none");
120
+ }
121
+ else {
122
+ // Set the class for the last item
123
+ if (elItems[i - 1]) {
124
+ elItems[i - 1].classList.add("last-item");
125
+ }
126
+ // Break from the loop
127
+ break;
128
+ }
129
+ }
130
+ // Parse the active items to hide
131
+ for (var i = paginationLimit; i < elItems.length; i++) {
132
+ var elItem = elItems[i];
133
+ // Hide the item
134
+ elItem.classList.add("d-none");
135
+ }
136
+ // Render the pagination
137
+ this._pagination = gd_sprest_bs_1.Components.Pagination({
138
+ el: elPagination,
139
+ className: "d-flex justify-content-end pt-2",
140
+ numberOfPages: Math.ceil(elItems.length / paginationLimit),
141
+ onClick: function (pageNumber) {
142
+ // Parse the items
143
+ for (var i = 0; i < elItems.length; i++) {
144
+ var elItem = elItems[i];
145
+ // Hide the item
146
+ elItem.classList.add("d-none");
147
+ }
148
+ // Parse the items to show
149
+ var startIdx = (pageNumber - 1) * paginationLimit;
150
+ for (var i = startIdx; i < startIdx + paginationLimit && i < elItems.length; i++) {
151
+ var elItem = elItems[i];
152
+ // Show the item
153
+ elItem.classList.remove("d-none");
154
+ }
155
+ }
156
+ });
157
+ };
158
+ // Searches the tile
159
+ Tiles.prototype.search = function (value) {
160
+ // Set the search value
161
+ this._activeSearchFilter = (value || "").toLowerCase();
162
+ // Update the tiles
163
+ this.updateTiles();
164
+ };
165
+ return Tiles;
166
+ }());
167
+ exports.Tiles = Tiles;
package/build/lib.d.ts CHANGED
@@ -12,6 +12,7 @@ export declare const DattaTable: {
12
12
  Header: typeof Dashboard.Header;
13
13
  Navigation: typeof Dashboard.Navigation;
14
14
  DataTable: typeof Dashboard.DataTable;
15
+ Tiles: typeof Dashboard.Tiles;
15
16
  AuditLog: typeof AuditLog.AuditLog;
16
17
  CanvasForm: typeof Common.CanvasForm;
17
18
  Comments: typeof Common.Comments;