@platforma-sdk/ui-vue 1.50.0 → 1.51.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.
@@ -30,7 +30,7 @@ import type {
30
30
  ManagedGridOptions,
31
31
  } from 'ag-grid-enterprise';
32
32
  import { AgGridVue } from 'ag-grid-vue3';
33
- import { computed, effectScope, ref, shallowRef, toRefs, watch } from 'vue';
33
+ import { computed, effectScope, ref, shallowRef, toRefs, watch, watchEffect } from 'vue';
34
34
  import { AgGridTheme } from '../../aggrid';
35
35
  import PlAgCsvExporter from '../PlAgCsvExporter/PlAgCsvExporter.vue';
36
36
  import { PlAgGridColumnManager } from '../PlAgGridColumnManager';
@@ -108,6 +108,9 @@ const props = defineProps<{
108
108
  /** @see {@link PlAgOverlayLoadingParams.loadingText} */
109
109
  loadingText?: string;
110
110
 
111
+ /** @see {@link PlAgOverlayLoadingParams.runningText} */
112
+ runningText?: string;
113
+
111
114
  /** @see {@link PlAgOverlayLoadingParams.notReadyText} */
112
115
  notReadyText?: string;
113
116
 
@@ -200,7 +203,7 @@ const gridOptions = shallowRef<GridOptions<PlAgDataTableV2Row>>({
200
203
  loadingError: '...',
201
204
  },
202
205
  rowModelType: 'serverSide',
203
- // cacheBlockSize should be tha same as PlMultiSequenceAlignment limit
206
+ // cacheBlockSize should be the same as PlMultiSequenceAlignment limit
204
207
  // so that selectAll will add all rows to selection
205
208
  cacheBlockSize: 1000,
206
209
  maxBlocksInCache: 100,
@@ -210,8 +213,9 @@ const gridOptions = shallowRef<GridOptions<PlAgDataTableV2Row>>({
210
213
  getRowId: (params) => params.data.id,
211
214
  loading: true,
212
215
  loadingOverlayComponentParams: {
213
- notReady: true,
216
+ variant: 'not-ready',
214
217
  loadingText: props.loadingText,
218
+ runningText: props.runningText,
215
219
  notReadyText: props.notReadyText,
216
220
  } satisfies PlAgOverlayLoadingParams,
217
221
  loadingOverlayComponent: PlOverlayLoading,
@@ -224,11 +228,6 @@ const gridOptions = shallowRef<GridOptions<PlAgDataTableV2Row>>({
224
228
  suppressQuotes: true,
225
229
  fileName: 'table.csv',
226
230
  },
227
- statusBar: {
228
- statusPanels: [
229
- { statusPanel: PlAgRowCount, align: 'left' },
230
- ],
231
- },
232
231
  onGridReady: (event) => {
233
232
  const api = event.api;
234
233
  autoSizeRowNumberColumn(api);
@@ -313,26 +312,6 @@ watch(
313
312
  },
314
313
  );
315
314
 
316
- // Make loadingOverlayComponentParams reactive
317
- let oldOptions: GridOptions | null = null;
318
- watch(
319
- () => [gridApi.value, gridOptions.value] as const,
320
- ([gridApi, options]) => {
321
- // Wait for AgGrid reinitialization, gridApi will eventially become initialized
322
- if (!gridApi || gridApi.isDestroyed()) return;
323
- if (options.loading && oldOptions?.loading && !isJsonEqual(
324
- options.loadingOverlayComponentParams,
325
- oldOptions?.loadingOverlayComponentParams,
326
- )) {
327
- // Hack to reapply loadingOverlayComponentParams
328
- gridApi.setGridOption('loading', false);
329
- gridApi.setGridOption('loading', true);
330
- }
331
- oldOptions = options;
332
- },
333
- { immediate: true },
334
- );
335
-
336
315
  // Make cellRendererSelector reactive
337
316
  const cellRendererSelector = computed(() => props.cellRendererSelector ?? null);
338
317
  watch(
@@ -428,7 +407,7 @@ const generation = ref(0);
428
407
  watch(
429
408
  () => [gridApi.value, settings.value] as const,
430
409
  ([gridApi, settings]) => {
431
- // Wait for AgGrid reinitialization, gridApi will eventially become initialized
410
+ // Wait for AgGrid reinitialization, gridApi will eventually become initialized
432
411
  if (!gridApi || gridApi.isDestroyed()) return;
433
412
  // Verify that this is not a false watch trigger
434
413
  if (isJsonEqual(settings, oldSettings)) return;
@@ -439,12 +418,12 @@ watch(
439
418
  dataRenderedTracker.reset();
440
419
 
441
420
  // No data source selected -> reset state to default
442
- if (!settings.sourceId) {
421
+ if (settings.sourceId === null) {
443
422
  gridApi.updateGridOptions({
444
423
  loading: true,
445
424
  loadingOverlayComponentParams: {
446
425
  ...gridOptions.value.loadingOverlayComponentParams,
447
- notReady: true,
426
+ variant: settings.pending ? 'running' : 'not-ready',
448
427
  } satisfies PlAgOverlayLoadingParams,
449
428
  columnDefs: undefined,
450
429
  serverSideDatasource: undefined,
@@ -467,7 +446,7 @@ watch(
467
446
  loading: true,
468
447
  loadingOverlayComponentParams: {
469
448
  ...gridOptions.value.loadingOverlayComponentParams,
470
- notReady: false,
449
+ variant: 'loading',
471
450
  } satisfies PlAgOverlayLoadingParams,
472
451
  });
473
452
  if (selection.value && oldSettings?.sourceId) {
@@ -583,15 +562,17 @@ watch(
583
562
  () => ({
584
563
  gridApi: gridApi.value,
585
564
  loadingText: props.loadingText,
565
+ runningText: props.runningText,
586
566
  notReadyText: props.notReadyText,
587
567
  noRowsText: props.noRowsText,
588
568
  }),
589
- ({ gridApi, loadingText, notReadyText, noRowsText }) => {
569
+ ({ gridApi, loadingText, runningText, notReadyText, noRowsText }) => {
590
570
  if (!gridApi || gridApi.isDestroyed()) return;
591
571
  gridApi.updateGridOptions({
592
572
  loadingOverlayComponentParams: {
593
573
  ...gridOptions.value.loadingOverlayComponentParams,
594
574
  loadingText,
575
+ runningText,
595
576
  notReadyText,
596
577
  },
597
578
  noRowsOverlayComponentParams: {
@@ -601,6 +582,19 @@ watch(
601
582
  });
602
583
  },
603
584
  );
585
+
586
+ watchEffect(() => {
587
+ if (!gridApi.value || gridApi.value?.isDestroyed()) return;
588
+ gridApi.value.updateGridOptions({
589
+ statusBar: gridOptions.value.loading
590
+ ? undefined
591
+ : {
592
+ statusPanels: [
593
+ { statusPanel: PlAgRowCount, align: 'left' },
594
+ ],
595
+ },
596
+ });
597
+ });
604
598
  </script>
605
599
 
606
600
  <template>
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
- import { PlPlaceholder } from '@milaboratories/uikit';
2
+ import { PL_PLACEHOLDER_TEXTS, PlPlaceholder } from '@milaboratories/uikit';
3
3
  import type { PlPlaceholderProps } from '@milaboratories/uikit';
4
- import { computed, ref } from 'vue';
4
+ import { ref } from 'vue';
5
5
  import style from './pl-ag-overlay-loading.module.scss';
6
6
  import type { PlAgOverlayLoadingParams } from './types';
7
7
 
@@ -14,32 +14,35 @@ const props = defineProps<{
14
14
 
15
15
  const params = ref(props.params);
16
16
 
17
- const placeholderTexts = computed<
18
- Pick<PlPlaceholderProps, 'title' | 'subtitle'>
19
- >(() => {
20
- const loadingText = params.value.loadingText;
21
- if (!loadingText) {
22
- return {};
23
- }
24
- if (typeof loadingText === 'string') {
25
- return { title: loadingText };
26
- }
27
- return loadingText;
28
- });
29
-
30
17
  defineExpose({
31
18
  refresh: (newParams: PlAgOverlayLoadingParams) => {
32
19
  params.value = newParams;
33
20
  },
34
21
  });
22
+
23
+ function normalizePlaceholderText(
24
+ text: string | Pick<PlPlaceholderProps, 'title' | 'subtitle'>,
25
+ ): Pick<PlPlaceholderProps, 'title' | 'subtitle'> {
26
+ if (typeof text === 'string') return { title: text };
27
+ return text;
28
+ }
35
29
  </script>
36
30
 
37
31
  <template>
38
32
  <div :class="style.container">
39
- <div v-if="params.notReady" :class="style.notReadyWrapper">
33
+ <div v-if="params.variant === 'not-ready'" :class="style.notReadyWrapper">
40
34
  <div :class="style.iconCatInBag" />
41
35
  <h3 :class="style.text">{{ params.notReadyText || 'No datasource' }}</h3>
42
36
  </div>
43
- <PlPlaceholder v-else v-bind="placeholderTexts" variant="table" />
37
+ <PlPlaceholder
38
+ v-else
39
+ v-bind="normalizePlaceholderText(
40
+ {
41
+ loading: params.loadingText ?? PL_PLACEHOLDER_TEXTS.LOADING,
42
+ running: params.runningText ?? PL_PLACEHOLDER_TEXTS.RUNNING,
43
+ }[params.variant],
44
+ )"
45
+ variant="table"
46
+ />
44
47
  </div>
45
48
  </template>
@@ -1,17 +1,18 @@
1
- import {
2
- type JsonCompatible,
3
- type AxisId,
4
- type CanonicalizedJson,
5
- type ListOptionBase,
6
- type PlDataTableModel,
7
- type PlDataTableSheet,
8
- type PlDataTableSheetState,
9
- type PlTableFilter,
10
- type PlTableFilterType,
11
- type PTableColumnId,
12
- type PTableColumnSpec,
13
- type PTableKey,
14
- type PTableValue,
1
+ import type {
2
+ JsonCompatible,
3
+ AxisId,
4
+ CanonicalizedJson,
5
+ ListOptionBase,
6
+ PlDataTableModel,
7
+ PlDataTableSheet,
8
+ PlDataTableSheetState,
9
+ PlTableFilter,
10
+ PlTableFilterType,
11
+ PTableColumnId,
12
+ PTableColumnSpec,
13
+ PTableKey,
14
+ PTableValue,
15
+ OutputWithStatus,
15
16
  } from '@platforma-sdk/model';
16
17
  import type { PTableHidden } from './sources/common';
17
18
  import type { ComputedRef, MaybeRefOrGetter } from 'vue';
@@ -25,7 +26,7 @@ export type PlDataTableFilterConfig = {
25
26
  };
26
27
 
27
28
  export type PlDataTableSettingsV2Base =
28
- | { sourceId: null }
29
+ | { sourceId: null; pending: boolean }
29
30
  | {
30
31
  /** Unique source id for state caching */
31
32
  sourceId: string;
@@ -46,7 +47,7 @@ export type PlDataTableSettingsV2 = PlDataTableSettingsV2Base & {
46
47
 
47
48
  type OptionsBasic = {
48
49
  /** Block output created by `createPlDataTableV2` */
49
- model: MaybeRefOrGetter<PlDataTableModel | undefined>;
50
+ model: MaybeRefOrGetter<OutputWithStatus<PlDataTableModel | undefined>>;
50
51
  /**
51
52
  * Sheets for partitioned data sources.
52
53
  * Do not set if data source is never partitioned.
@@ -104,9 +105,11 @@ export function usePlDataTableSettingsV2<T>(options: OptionsAdvanced<T> | Option
104
105
  }
105
106
  : () => ({});
106
107
  return computed(() => {
107
- const modelValue = deepClone(toValue(options.model));
108
+ const model = deepClone(toValue(options.model));
108
109
  let settingsBase: PlDataTableSettingsV2Base;
109
- if ('sourceId' in options) {
110
+ if (!model.ok) {
111
+ settingsBase = { sourceId: null, pending: false };
112
+ } else if ('sourceId' in options) {
110
113
  const sourceIdValue = deepClone(toValue(options.sourceId));
111
114
  if (options.sheets) {
112
115
  const sheetsValue = deepClone(toValue(options.sheets));
@@ -114,17 +117,17 @@ export function usePlDataTableSettingsV2<T>(options: OptionsAdvanced<T> | Option
114
117
  ? {
115
118
  sourceId: canonicalize(sourceIdValue)!,
116
119
  sheets: sheetsValue,
117
- model: modelValue,
120
+ model: model.value,
118
121
  }
119
- : { sourceId: null };
122
+ : { sourceId: null, pending: !model.stable };
120
123
  } else {
121
124
  settingsBase = sourceIdValue
122
125
  ? {
123
126
  sourceId: canonicalize(sourceIdValue)!,
124
127
  sheets: [],
125
- model: modelValue,
128
+ model: model.value,
126
129
  }
127
- : { sourceId: null };
130
+ : { sourceId: null, pending: !model.stable };
128
131
  }
129
132
  } else {
130
133
  if (options.sheets) {
@@ -133,17 +136,17 @@ export function usePlDataTableSettingsV2<T>(options: OptionsAdvanced<T> | Option
133
136
  ? {
134
137
  sourceId: canonicalize('static')!,
135
138
  sheets: sheetsValue,
136
- model: modelValue,
139
+ model: model.value,
137
140
  }
138
- : { sourceId: null };
141
+ : { sourceId: null, pending: !model.stable };
139
142
  } else {
140
- settingsBase = modelValue
143
+ settingsBase = model.value
141
144
  ? {
142
145
  sourceId: canonicalize('static')!,
143
146
  sheets: [],
144
- model: modelValue,
147
+ model: model.value,
145
148
  }
146
- : { sourceId: null };
149
+ : { sourceId: null, pending: !model.stable };
147
150
  }
148
151
  }
149
152
  return {
@@ -211,14 +214,21 @@ export type PlAgOverlayLoadingParams = {
211
214
  /**
212
215
  * Required flag, that shows catInBag icon with message if `true`, shows PlSplash component if `false`.
213
216
  */
214
- notReady?: boolean;
217
+ variant: 'not-ready' | 'running' | 'loading';
215
218
  /**
216
- * Prop to override default "Loading" text
219
+ * Prop to override default "Loading data..." text and the subtitles
217
220
  */
218
221
  loadingText?: string | {
219
222
  title: string;
220
223
  subtitle: string | string[];
221
224
  };
225
+ /**
226
+ * Prop to override default "Running analysis..." text and the subtitles
227
+ */
228
+ runningText?: string | {
229
+ title: string;
230
+ subtitle: string | string[];
231
+ };
222
232
  /**
223
233
  * Prop to override default "No datasource" text (So why props name is notReady? Good question)
224
234
  */