quasar-ui-danx 0.4.13 → 0.4.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,6 @@
1
1
  import { computed, Ref, ref, shallowRef, watch } from "vue";
2
- import { RouteLocationNormalizedLoaded, RouteParams, Router } from "vue-router";
2
+ import { RouteParams, Router } from "vue-router";
3
+ import { danxOptions } from "../../config";
3
4
  import { getItem, setItem, storeObject, waitForRef } from "../../helpers";
4
5
  import {
5
6
  ActionController,
@@ -7,7 +8,6 @@ import {
7
8
  AnyObject,
8
9
  FilterGroup,
9
10
  ListControlsFilter,
10
- ListControlsInitializeOptions,
11
11
  ListControlsOptions,
12
12
  ListControlsPagination,
13
13
  PagedItems
@@ -16,8 +16,6 @@ import { getFilterFromUrl } from "./listHelpers";
16
16
 
17
17
  export function useListControls(name: string, options: ListControlsOptions): ActionController {
18
18
  let isInitialized = false;
19
- let vueRoute: RouteLocationNormalizedLoaded | null | undefined;
20
- let vueRouter: Router | null | undefined;
21
19
  const PAGE_SETTINGS_KEY = `dx-${name}-pager`;
22
20
  const pagedItems = shallowRef<PagedItems | null>(null);
23
21
  const activeFilter = ref<ListControlsFilter>({});
@@ -112,11 +110,9 @@ export function useListControls(name: string, options: ListControlsOptions): Act
112
110
 
113
111
  /**
114
112
  * Loads the filter field options for the current filter.
115
- *
116
- * @returns {Promise<void>}
117
113
  */
118
114
  async function loadFieldOptions() {
119
- if (!options.routes.fieldOptions || !isInitialized) return;
115
+ if (!options.routes.fieldOptions) return;
120
116
  isLoadingFilters.value = true;
121
117
  try {
122
118
  fieldOptions.value = await options.routes.fieldOptions(activeFilter.value) || {};
@@ -184,9 +180,9 @@ export function useListControls(name: string, options: ListControlsOptions): Act
184
180
  /**
185
181
  * Sets the pagination settings to the given values.
186
182
  */
187
- function setPagination(updated: ListControlsPagination) {
183
+ function setPagination(updated: Partial<ListControlsPagination>) {
188
184
  // @ts-expect-error Seems like a bug in the typescript linting?
189
- pagination.value = updated;
185
+ pagination.value = { ...pagination.value, ...updated };
190
186
  }
191
187
 
192
188
  /**
@@ -250,9 +246,6 @@ export function useListControls(name: string, options: ListControlsOptions): Act
250
246
  * Loads the filter and pagination settings from local storage.
251
247
  */
252
248
  function loadSettings() {
253
- // Only load settings when the class is fully initialized
254
- if (!isInitialized) return;
255
-
256
249
  const settings = getItem(PAGE_SETTINGS_KEY);
257
250
 
258
251
  // Load the filter settings from local storage
@@ -402,26 +395,26 @@ export function useListControls(name: string, options: ListControlsOptions): Act
402
395
  }
403
396
 
404
397
  // Initialize the list actions and load settings, lists, summaries, filter fields, etc.
405
- function initialize(initOptions?: ListControlsInitializeOptions) {
406
- vueRouter = initOptions?.vueRouter;
407
- vueRoute = initOptions?.vueRouter?.currentRoute.value;
398
+ function initialize() {
399
+ const vueRouter = getVueRouter();
408
400
  isInitialized = true;
409
401
  loadSettings();
410
402
 
411
403
  /**
412
404
  * Watch the id params in the route and set the active item to the item with the given id.
413
405
  */
414
- if (options.routes.details && vueRoute && vueRouter) {
415
- const { params, meta } = vueRoute;
416
-
417
- const controlRouteName = vueRoute.name;
418
- vueRouter.afterEach((to) => {
419
- if (to.name === controlRouteName) {
420
- setPanelFromRoute(to.params, to.meta);
421
- }
422
- });
406
+ if (options.routes.details) {
407
+ const { params, meta, name: controlRouteName } = vueRouter.currentRoute.value;
408
+
409
+ if (controlRouteName === name) {
410
+ vueRouter.afterEach((to) => {
411
+ if (to.name === controlRouteName) {
412
+ setPanelFromRoute(to.params, to.meta);
413
+ }
414
+ });
423
415
 
424
- setPanelFromRoute(params, meta);
416
+ setPanelFromRoute(params, meta);
417
+ }
425
418
  }
426
419
  }
427
420
 
@@ -429,12 +422,12 @@ export function useListControls(name: string, options: ListControlsOptions): Act
429
422
  * Updates the URL bar and route to the given params.
430
423
  */
431
424
  function updateRouteParams(params: AnyObject) {
432
- if (vueRouter && vueRoute) {
433
- vueRouter.push({
434
- name: (Array.isArray(vueRoute.name) ? vueRoute.name[0] : vueRoute.name) || "home",
435
- params
436
- });
437
- }
425
+ const vueRouter = getVueRouter();
426
+ const { name: routeName } = vueRouter.currentRoute.value;
427
+ vueRouter.push({
428
+ name: (Array.isArray(routeName) ? routeName[0] : routeName) || "home",
429
+ params
430
+ });
438
431
  }
439
432
 
440
433
  function setPanelFromRoute(params: RouteParams, meta: AnyObject) {
@@ -445,6 +438,13 @@ export function useListControls(name: string, options: ListControlsOptions): Act
445
438
  }
446
439
  }
447
440
 
441
+ function getVueRouter(): Router {
442
+ if (!danxOptions.value.router) {
443
+ throw new Error("Vue Router must be configured in danxOptions");
444
+ }
445
+ return danxOptions.value.router;
446
+ }
447
+
448
448
  return {
449
449
  // State
450
450
  name,
@@ -474,6 +474,7 @@ export function useListControls(name: string, options: ListControlsOptions): Act
474
474
  loadSummary,
475
475
  loadListAndSummary,
476
476
  loadMore,
477
+ loadFieldOptions,
477
478
  getActiveItemDetails,
478
479
  refreshAll,
479
480
  exportList,
@@ -8,10 +8,12 @@
8
8
  :key="'nav-item-' + item.label"
9
9
  class="nav-menu-item-box"
10
10
  >
11
- <div
11
+ <a
12
12
  class="nav-menu-item flex flex-nowrap"
13
+ :href="resolveUrl(item)"
13
14
  :class="item.class || itemClass"
14
- @click="item.onClick"
15
+ :target="item.target || '_self'"
16
+ @click="onClick($event, item)"
15
17
  >
16
18
  <div
17
19
  v-if="item.icon"
@@ -36,7 +38,7 @@
36
38
  >
37
39
  {{ item.tooltip?.text || item.label }}
38
40
  </QTooltip>
39
- </div>
41
+ </a>
40
42
  <QSeparator
41
43
  v-if="item.separator"
42
44
  :key="'separator-' + item.label"
@@ -47,55 +49,96 @@
47
49
  </template>
48
50
  <script setup>
49
51
  import { computed } from "vue";
52
+ import { danxOptions } from "../../config";
50
53
 
51
54
  const props = defineProps({
52
- collapsed: Boolean,
53
- itemClass: {
54
- type: String,
55
- default: "hover:bg-gray-200"
56
- },
57
- activeClass: {
58
- type: String,
59
- default: "bg-blue-200"
60
- },
61
- items: {
62
- type: Array,
63
- required: true
64
- }
55
+ collapsed: Boolean,
56
+ itemClass: {
57
+ type: String,
58
+ default: "hover:bg-gray-200"
59
+ },
60
+ activeClass: {
61
+ type: String,
62
+ default: "bg-blue-200"
63
+ },
64
+ items: {
65
+ type: Array,
66
+ required: true
67
+ }
65
68
  });
66
69
 
70
+ const router = danxOptions.value.router;
67
71
  const allowedItems = computed(() => props.items.filter((item) => !item.hidden));
72
+
73
+ function getItemRoute(item) {
74
+ if (!router) {
75
+ console.error("Router is not available. Configure in danx options.");
76
+ return;
77
+ }
78
+
79
+ return typeof item.route === "function" ? item.route() : item.route;
80
+ }
81
+
82
+ function onClick(e, item) {
83
+ if (!item.url && !e.ctrlKey) {
84
+ e.preventDefault();
85
+ }
86
+
87
+ if (item.disabled || e.ctrlKey) {
88
+ return;
89
+ }
90
+
91
+ if (item.onClick) {
92
+ item.onClick();
93
+ }
94
+
95
+ if (item.route) {
96
+ router.push(getItemRoute(item));
97
+ }
98
+ }
99
+
100
+ function resolveUrl(item) {
101
+ if (item.url) {
102
+ return item.url;
103
+ }
104
+
105
+ if (item.route) {
106
+ return router.resolve(getItemRoute(item))?.href || "#";
107
+ }
108
+
109
+ return "#";
110
+ }
68
111
  </script>
69
112
 
70
113
  <style lang="scss">
71
114
  .nav-menu-item {
72
- padding: 1em;
73
- border-radius: 0.5em;
74
- font-weight: bold;
75
- font-size: 14px;
76
- transition: all 150ms, color 0ms;
77
- cursor: pointer;
78
-
79
- &.is-disabled {
80
- @apply bg-inherit;
81
- }
82
-
83
- .label {
84
- @apply transition-all;
85
- }
86
-
87
- .nav-icon {
88
- @apply w-5 h-5 flex-shrink-0;
89
- }
115
+ padding: 1em;
116
+ border-radius: 0.5em;
117
+ font-weight: bold;
118
+ font-size: 14px;
119
+ transition: all 150ms, color 0ms;
120
+ cursor: pointer;
121
+
122
+ &.is-disabled {
123
+ @apply bg-inherit;
124
+ }
125
+
126
+ .label {
127
+ @apply transition-all;
128
+ }
129
+
130
+ .nav-icon {
131
+ @apply w-5 h-5 flex-shrink-0;
132
+ }
90
133
  }
91
134
 
92
135
  .is-collapsed {
93
- .nav-link {
94
- width: 3.8em;
95
- }
136
+ .nav-link {
137
+ width: 3.8em;
138
+ }
96
139
 
97
- .label {
98
- @apply opacity-0;
99
- }
140
+ .label {
141
+ @apply opacity-0;
142
+ }
100
143
  }
101
144
  </style>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <ContentDrawer
3
- position="right"
3
+ :position="position"
4
4
  show
5
5
  overlay
6
6
  content-class="h-full"
@@ -82,6 +82,7 @@ export interface Props {
82
82
  activeItem: ActionTargetItem;
83
83
  tabsClass?: string | object,
84
84
  panelsClass?: string | object,
85
+ position?: "standard" | "right" | "left";
85
86
  panels: ActionPanel[]
86
87
  }
87
88
 
@@ -89,8 +90,9 @@ defineEmits(["update:model-value", "close"]);
89
90
  const props = withDefaults(defineProps<Props>(), {
90
91
  title: "",
91
92
  modelValue: null,
92
- tabsClass: "w-[13.5rem]",
93
- panelsClass: "w-[35.5rem]"
93
+ tabsClass: "w-[13.5rem] flex-shrink-0",
94
+ panelsClass: "w-[80rem]",
95
+ position: "right"
94
96
  });
95
97
 
96
98
  const activePanel = ref(props.modelValue);
@@ -0,0 +1,21 @@
1
+ <template>
2
+ <Transition name="autoHeight">
3
+ <slot />
4
+ </Transition>
5
+ </template>
6
+
7
+ <style lang="scss">
8
+ .autoHeight-enter-active,
9
+ .autoHeight-leave-active {
10
+ transition: height .3s linear;
11
+ height: calc-size(auto);
12
+ }
13
+
14
+ .autoHeight-enter-to, .autoHeight-leave-from {
15
+ height: calc-size(auto);
16
+ }
17
+
18
+ .autoHeight-enter-from, .autoHeight-leave-to {
19
+ height: 0;
20
+ }
21
+ </style>
@@ -1,3 +1,4 @@
1
+ export { default as AutoHeightTransition } from "./AutoHeightTransition.vue";
1
2
  export { default as ListTransition } from "./ListTransition.vue";
2
3
  export { default as MaxHeightTransition } from "./MaxHeightTransition.vue";
3
4
  export { default as SlideTransition } from "./SlideTransition.vue";
@@ -3,6 +3,7 @@ import { DanxOptions } from "../types";
3
3
 
4
4
  export const danxOptions = shallowRef<DanxOptions>({
5
5
  tinyMceApiKey: "set-api-key-in-danx-options",
6
+ router: undefined,
6
7
  request: {
7
8
  baseUrl: "",
8
9
  headers: {},
@@ -1,7 +1,7 @@
1
1
  import { useDebounceFn } from "@vueuse/core";
2
2
  import { uid } from "quasar";
3
3
  import { isReactive, Ref, shallowRef } from "vue";
4
- import type { ActionOptions, ActionOptionsPartial, ActionTarget, AnyObject, ResourceAction } from "../types";
4
+ import type { ActionOptions, ActionTarget, AnyObject, ResourceAction } from "../types";
5
5
  import { FlashMessages } from "./FlashMessages";
6
6
  import { storeObject } from "./objectStore";
7
7
 
@@ -11,36 +11,34 @@ export const activeActionVnode: Ref = shallowRef(null);
11
11
  * Hook to perform an action on a set of targets
12
12
  * This helper allows you to perform actions by name on a set of targets using a provided list of actions
13
13
  */
14
- export function useActions(actions: ActionOptions[], globalOptions: ActionOptionsPartial | null = null) {
14
+ export function useActions(actions: ActionOptions[], globalOptions: Partial<ActionOptions> | null = null) {
15
15
  const namespace = uid();
16
16
 
17
17
  /**
18
18
  * Resolve the action object based on the provided name (or return the object if the name is already an object)
19
19
  */
20
- function getAction(actionName: string | ActionOptions | ResourceAction): ResourceAction {
21
- let actionOptions: ActionOptions | ResourceAction;
22
-
20
+ function getAction(actionName: string, actionOptions?: Partial<ActionOptions>): ResourceAction {
23
21
  /// Resolve the action options or resource action based on the provided input
24
- if (typeof actionName === "string") {
25
- actionOptions = actions.find(a => a.name === actionName) || { name: actionName };
26
- } else {
27
- actionOptions = actionName;
22
+ const baseOptions = actions.find(a => a.name === actionName) || { name: actionName };
23
+
24
+ if (actionOptions) {
25
+ Object.assign(baseOptions, actionOptions);
28
26
  }
29
27
 
30
28
  // If the action is already reactive, return it
31
- if (isReactive(actionOptions) && "__type" in actionOptions) return actionOptions as ResourceAction;
29
+ if (isReactive(baseOptions) && "__type" in baseOptions) return baseOptions as ResourceAction;
32
30
 
33
31
  const resourceAction: ResourceAction = storeObject({
34
32
  ...globalOptions,
35
- ...actionOptions,
33
+ ...baseOptions,
36
34
  trigger: (target, input) => performAction(resourceAction, target, input),
37
35
  isApplying: false,
38
36
  __type: "__Action:" + namespace
39
37
  });
40
38
 
41
39
  // Assign Trigger function if it doesn't exist
42
- if (actionOptions.debounce) {
43
- resourceAction.trigger = useDebounceFn((target, input) => performAction(resourceAction, target, input), actionOptions.debounce);
40
+ if (baseOptions.debounce) {
41
+ resourceAction.trigger = useDebounceFn((target, input) => performAction(resourceAction, target, input), baseOptions.debounce);
44
42
  }
45
43
 
46
44
  return resourceAction;
@@ -63,7 +61,7 @@ export function useActions(actions: ActionOptions[], globalOptions: ActionOption
63
61
  }
64
62
  }
65
63
 
66
- return filteredActions.map((a: ActionOptions) => getAction(a));
64
+ return filteredActions.map((a: ActionOptions) => getAction(a.name));
67
65
  }
68
66
 
69
67
  /**
@@ -121,6 +119,11 @@ export function useActions(actions: ActionOptions[], globalOptions: ActionOption
121
119
  result = await onConfirmAction(action, target, input);
122
120
  }
123
121
 
122
+ // If the request was aborted (likely due to a newer request), just return immediately without changing state
123
+ if (result?.abort) {
124
+ return result;
125
+ }
126
+
124
127
  action.isApplying = false;
125
128
  setTargetSavingState(target, false);
126
129
 
@@ -187,8 +190,16 @@ async function onConfirmAction(action: ActionOptions, target: ActionTarget, inpu
187
190
  result = await action.onAction(action.alias || action.name, target, input);
188
191
  }
189
192
  } catch (e) {
190
- console.error(e);
191
- result = { error: `An error occurred while performing the action ${action.label}. Please try again later.` };
193
+ if (("" + e).match(/Request was aborted/)) {
194
+ result = { abort: true };
195
+ } else {
196
+ console.error(e);
197
+ result = { error: `An error occurred while performing the action ${action.label}. Please try again later.` };
198
+ }
199
+ }
200
+
201
+ if (result?.abort) {
202
+ return result;
192
203
  }
193
204
 
194
205
  // If there is no return value or the result marks it as successful, we show a success message
@@ -203,11 +214,11 @@ async function onConfirmAction(action: ActionOptions, target: ActionTarget, inpu
203
214
  }
204
215
 
205
216
  if (action.onSuccess) {
206
- action.onSuccess(result, target, input);
217
+ await action.onSuccess(result, target, input);
207
218
  }
208
219
 
209
220
  if (isBatch && action.onBatchSuccess) {
210
- action.onBatchSuccess(result, target, input);
221
+ await action.onBatchSuccess(result, target, input);
211
222
  }
212
223
  } else {
213
224
  const errors = [];
@@ -230,12 +241,12 @@ async function onConfirmAction(action: ActionOptions, target: ActionTarget, inpu
230
241
  FlashMessages.combine("error", errors);
231
242
 
232
243
  if (action.onError) {
233
- action.onError(result, target, input);
244
+ await action.onError(result, target, input);
234
245
  }
235
246
  }
236
247
 
237
248
  if (action.onFinish) {
238
- action.onFinish(result, target, input);
249
+ await action.onFinish(result, target, input);
239
250
  }
240
251
 
241
252
  return result;
@@ -339,21 +339,24 @@ export function fJSON(string: string | object) {
339
339
  /**
340
340
  * Convert markdown formatted string into a valid JSON object
341
341
  */
342
- export function parseMarkdownJSON(string: string | object): object | null | undefined {
342
+ export function parseMarkdownJSON(string: string | object): object | null | false {
343
+ if (!string) return null;
343
344
  if (typeof string === "object") return string as object;
344
345
 
345
346
  try {
346
347
  return JSON.parse(parseMarkdownCode(string));
347
348
  } catch (e) {
348
- return undefined;
349
+ return false;
349
350
  }
350
351
  }
351
352
 
352
- export function parseMarkdownYAML(string: string): object | null | undefined {
353
+ export function parseMarkdownYAML(string: string): object | null | false {
354
+ if (!string) return null;
355
+
353
356
  try {
354
357
  return parseYAML(parseMarkdownCode(string)) || (string ? undefined : null);
355
358
  } catch (e) {
356
- return undefined;
359
+ return false;
357
360
  }
358
361
  }
359
362
 
@@ -1,3 +1,4 @@
1
+ import { uid } from "quasar";
1
2
  import { ShallowReactive, shallowReactive } from "vue";
2
3
  import { TypedObject } from "../types";
3
4
 
@@ -12,6 +13,9 @@ export function storeObject<T extends TypedObject>(newObject: T): ShallowReactiv
12
13
  const type = newObject.__type;
13
14
  if (!id || !type) return shallowReactive(newObject);
14
15
 
16
+ if (!newObject.__id) {
17
+ newObject.__id = uid();
18
+ }
15
19
  if (!newObject.__timestamp) {
16
20
  newObject.__timestamp = newObject.updated_at || 0;
17
21
  }
@@ -34,6 +38,9 @@ export function storeObject<T extends TypedObject>(newObject: T): ShallowReactiv
34
38
  for (const index in value) {
35
39
  newObject[key][index] = storeObject(value[index]);
36
40
  }
41
+ } else if (value?.__type) {
42
+ // @ts-expect-error newObject[key] is guaranteed to be a TypedObject
43
+ newObject[key] = storeObject(value);
37
44
  }
38
45
  }
39
46
 
@@ -45,7 +45,7 @@ export const request: RequestApi = {
45
45
  // If the request was aborted too late, but there was still another request that was made after the current,
46
46
  // then abort the current request with an abort flag
47
47
  if (timestamp < request.abortControllers[abortKey].timestamp) {
48
- throw new Error("Request was aborted due to a newer request being made: " + timestamp + " < " + request.abortControllers[abortKey].timestamp);
48
+ return { abort: true };
49
49
  }
50
50
 
51
51
  // Otherwise, the current is the most recent request, so we can delete the abort controller
@@ -1,3 +1,4 @@
1
+ import { storeObject } from "../helpers";
1
2
  import { ListControlsRoutes } from "../types";
2
3
  import { downloadFile } from "./downloadPdf";
3
4
  import { request } from "./request";
@@ -13,6 +14,10 @@ export function useActionRoutes(baseUrl: string): ListControlsRoutes {
13
14
  details(target) {
14
15
  return request.get(`${baseUrl}/${target.id}/details`);
15
16
  },
17
+ async detailsAndStore(target) {
18
+ const item = await request.get(`${baseUrl}/${target.id}/details`);
19
+ return storeObject(item);
20
+ },
16
21
  fieldOptions() {
17
22
  return request.get(`${baseUrl}/field-options`);
18
23
  },
@@ -13,6 +13,7 @@ export interface ActionPanel {
13
13
 
14
14
  export interface ActionTargetItem extends TypedObject {
15
15
  isSaving?: boolean;
16
+ updated_at?: string;
16
17
  }
17
18
 
18
19
  export type ActionTarget = ActionTargetItem[] | ActionTargetItem | null;
@@ -41,10 +42,6 @@ export interface ActionOptions {
41
42
  onFinish?: (result: any, targets: ActionTarget, input: any) => any;
42
43
  }
43
44
 
44
- export interface ActionOptionsPartial extends ActionOptions {
45
- name?: string;
46
- }
47
-
48
45
  export interface ResourceAction extends ActionOptions {
49
46
  isApplying: boolean;
50
47
  trigger: (target?: ActionTarget, input?: any) => Promise<any>;
@@ -1,11 +1,13 @@
1
1
  import { QNotifyCreateOptions } from "quasar";
2
+ import { Router } from "vue-router";
2
3
  import { FileUploadOptions } from "./files";
3
4
  import { RequestOptions } from "./requests";
4
5
 
5
6
  export interface DanxOptions {
6
7
  tinyMceApiKey?: string;
7
8
  fileUpload?: FileUploadOptions;
8
- request?: RequestOptions,
9
+ request?: RequestOptions;
10
+ router?: Router;
9
11
  flashMessages?: {
10
12
  default?: QNotifyCreateOptions;
11
13
  success?: QNotifyCreateOptions;
@@ -1,5 +1,4 @@
1
1
  import { ComputedRef, Ref, ShallowRef } from "vue";
2
- import { Router } from "vue-router";
3
2
  import { ActionTargetItem } from "./actions";
4
3
  import { AnyObject, LabelValueItem } from "./shared";
5
4
 
@@ -29,6 +28,8 @@ export interface ListControlsRoutes {
29
28
 
30
29
  details?(target: ActionTargetItem): Promise<ActionTargetItem>;
31
30
 
31
+ detailsAndStore?(target: ActionTargetItem): Promise<ActionTargetItem>;
32
+
32
33
  more?(pager: ListControlsPagination): Promise<ActionTargetItem[]>;
33
34
 
34
35
  fieldOptions?(filter?: AnyObject): Promise<AnyObject>;
@@ -67,10 +68,6 @@ export interface PagedItems {
67
68
  } | undefined;
68
69
  }
69
70
 
70
- export interface ListControlsInitializeOptions {
71
- vueRouter?: Router;
72
- }
73
-
74
71
  export interface ActionController {
75
72
  name: string;
76
73
  label: string;
@@ -95,15 +92,16 @@ export interface ActionController {
95
92
  activePanel: ShallowRef<string | null>;
96
93
 
97
94
  // Actions
98
- initialize: (options: ListControlsInitializeOptions) => void;
95
+ initialize: () => void;
99
96
  resetPaging: () => void;
100
- setPagination: (updated: ListControlsPagination) => void;
97
+ setPagination: (updated: Partial<ListControlsPagination>) => void;
101
98
  setSelectedRows: (selection: ActionTargetItem[]) => void;
102
99
  clearSelectedRows: () => void;
103
100
  loadList: (filter?: ListControlsFilter) => Promise<void>;
104
101
  loadSummary: (filter?: ListControlsFilter) => Promise<void>;
105
102
  loadListAndSummary: (filter?: ListControlsFilter) => Promise<void>;
106
103
  loadMore: (index: number, perPage?: number) => Promise<boolean>;
104
+ loadFieldOptions: () => Promise<void>;
107
105
  getActiveItemDetails: () => Promise<void>;
108
106
  refreshAll: () => Promise<void[]>;
109
107
  exportList: (filter?: ListControlsFilter) => Promise<void>;
@@ -18,6 +18,7 @@ export interface FormField {
18
18
  clearable?: boolean;
19
19
  required?: boolean;
20
20
  required_group?: string;
21
+ default_value?: any;
21
22
  toggleIndeterminate?: boolean;
22
23
  inline?: boolean;
23
24
  maxLength?: number;
@@ -5,6 +5,7 @@ export interface TypedObject {
5
5
  name?: string;
6
6
  __type: string;
7
7
  __timestamp?: number;
8
+ __id?: string;
8
9
 
9
10
  [key: string]: TypedObject[] | any;
10
11
  }