@datagrok/hit-triage 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@datagrok/hit-triage",
3
3
  "friendlyName": "HitTriage",
4
- "version": "1.2.0",
4
+ "version": "1.2.1",
5
5
  "author": {
6
6
  "name": "Davit Rizhinashvili",
7
7
  "email": "drizhinashvili@datagrok.ai"
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "dependencies": {
19
19
  "@datagrok-libraries/compute-utils": "^1.8.3",
20
- "@datagrok-libraries/utils": "^4.2.13",
20
+ "@datagrok-libraries/utils": "^4.2.29",
21
21
  "cash-dom": "latest",
22
22
  "css-loader": "^6.5.1",
23
23
  "datagrok-api": "^1.19.2",
@@ -11,7 +11,7 @@ import '../../css/hit-triage.css';
11
11
  import {_package} from '../package';
12
12
  import {addBreadCrumbsToRibbons, checkRibbonsHaveSubmit, modifyUrl, toFormatedDateString} from './utils';
13
13
  import {HitDesignSubmitView} from './hit-design-views/submit-view';
14
- import {HitDesignTilesView} from './hit-design-views/tiles-view';
14
+ import {getTilesViewDialog} from './hit-design-views/tiles-view';
15
15
  import {HitAppBase} from './hit-app-base';
16
16
  import {HitBaseView} from './base-view';
17
17
  import {chemFunctionsDialog} from './dialogs/functions-dialog';
@@ -26,8 +26,6 @@ export class HitDesignApp extends HitAppBase<HitDesignTemplate> {
26
26
  get infoView(): HitDesignInfoView {return this._infoView;}
27
27
  private _designView?: DG.TableView;
28
28
  public _submitView?: HitDesignSubmitView;
29
- private _tilesView?: HitDesignTilesView;
30
- private _tilesViewTab: DG.ViewBase | null = null;
31
29
  private _designViewName = 'Design';
32
30
  private _filePath = 'System.AppData/HitTriage/Hit Design/campaigns';
33
31
  private _campaignId?: string;
@@ -39,7 +37,6 @@ export class HitDesignApp extends HitAppBase<HitDesignTemplate> {
39
37
  private _extraStageColsCount = 0;
40
38
 
41
39
  private currentDesignViewId?: string;
42
- private currentTilesViewId?: string;
43
40
  public mainView: DG.ViewBase;
44
41
  private get version() {return this._campaign?.version ?? 0;};
45
42
 
@@ -58,22 +55,14 @@ export class HitDesignApp extends HitAppBase<HitDesignTemplate> {
58
55
 
59
56
  grok.events.onCurrentViewChanged.subscribe(async () => {
60
57
  try {
61
- if (grok.shell.v?.name === this.currentDesignViewId || grok.shell.v?.name === this.currentTilesViewId) {
58
+ if (grok.shell.v?.name === this.currentDesignViewId) {
62
59
  grok.shell.windows.showHelp = false;
63
60
 
64
61
  this.setBaseUrl();
65
62
  modifyUrl(CampaignIdKey, this._campaignId ?? this._campaign?.name ?? '');
66
- if (this.currentTilesViewId && grok.shell.v?.name === this.currentTilesViewId)
67
- await this._tilesView?.render();
68
- else {
69
- const sketchStateString = this._tilesView?.sketchStateString;
70
- if (sketchStateString && sketchStateString != '' && this.campaign)
71
- this.campaign.tilesViewerFormSketch = sketchStateString;
72
- }
73
63
 
74
64
  const {sub} = addBreadCrumbsToRibbons(grok.shell.v, 'Hit Design', grok.shell.v?.name, () => {
75
65
  grok.shell.v = this.mainView;
76
- this._tilesView?.close();
77
66
  this._designView?.close();
78
67
  this._infoView.init();
79
68
  sub.unsubscribe();
@@ -209,77 +198,74 @@ export class HitDesignApp extends HitAppBase<HitDesignTemplate> {
209
198
  this.saveCampaign(undefined, false);
210
199
  };
211
200
 
212
-
213
- setTimeout(async () => {
214
- view._onAdded();
215
- await new Promise((r) => setTimeout(r, 1000)); // needed for substruct filter
216
-
217
- const layoutViewState = this._campaign?.layout ?? this.template?.layoutViewState;
218
- if (layoutViewState) {
219
- try {
220
- const layout = DG.ViewLayout.fromViewState(layoutViewState);
221
- view.loadLayout(layout);
222
- } catch (e) {
223
- console.error(e);
224
- }
201
+ view._onAdded();
202
+ const layoutViewState = this._campaign?.layout ?? this.template?.layoutViewState;
203
+ if (layoutViewState) {
204
+ try {
205
+ const layout = DG.ViewLayout.fromViewState(layoutViewState);
206
+ view.loadLayout(layout);
207
+ } catch (e) {
208
+ grok.shell.error('Failed to apply layout. Falling back to default layout.');
209
+ console.error(e);
225
210
  }
211
+ }
226
212
 
227
- if (isNew)
228
- grok.functions.call('Chem:editMoleculeCell', {cell: view.grid.cell(this._molColName, 0)});
213
+ if (isNew)
214
+ grok.functions.call('Chem:editMoleculeCell', {cell: view.grid.cell(this._molColName, 0)});
229
215
 
230
- subs.push(this.dataFrame!.onRowsAdded.pipe(filter(() => !this.isJoining))
231
- .subscribe(() => { // TODO, insertion of rows in the middle
232
- try {
233
- this.processedValues = this.dataFrame!.getCol(this.molColName).toList();
234
- if (this.template!.stages?.length > 0) {
235
- for (let i = 0; i < this.dataFrame!.rowCount; i++) {
236
- const colVal = this.dataFrame!.col(TileCategoriesColName)!.get(i);
237
- if (!colVal || colVal === '' || this.dataFrame!.col(TileCategoriesColName)?.isNone(i))
238
- this.dataFrame!.set(TileCategoriesColName, i, this.template!.stages[0]);
239
- }
240
- }
241
- let lastAddedCell: DG.GridCell | null = null;
216
+ subs.push(this.dataFrame!.onRowsAdded.pipe(filter(() => !this.isJoining))
217
+ .subscribe(() => { // TODO, insertion of rows in the middle
218
+ try {
219
+ this.processedValues = this.dataFrame!.getCol(this.molColName).toList();
220
+ if (this.template!.stages?.length > 0) {
242
221
  for (let i = 0; i < this.dataFrame!.rowCount; i++) {
243
- const cell = view.grid.cell(this.molColName, i);
244
- if (!cell)
245
- continue;
246
- if (cell.cell.value === '' || cell.cell.value === null)
247
- lastAddedCell = cell;
222
+ const colVal = this.dataFrame!.col(TileCategoriesColName)!.get(i);
223
+ if (!colVal || colVal === '' || this.dataFrame!.col(TileCategoriesColName)?.isNone(i))
224
+ this.dataFrame!.set(TileCategoriesColName, i, this.template!.stages[0]);
248
225
  }
249
- if (lastAddedCell)
250
- grok.functions.call('Chem:editMoleculeCell', {cell: lastAddedCell});
251
- } catch (e) {
252
- console.error(e);
253
226
  }
254
- //const lastCell = view.grid.cell(this.molColName, this.dataFrame!.rowCount - 1);
255
- //view.grid.onCellValueEdited
256
- }));
257
- this.dataFrame && subs.push(this.dataFrame?.onRowsRemoved.subscribe(() => {
258
- try {
259
- this.processedValues = this.dataFrame!.getCol(this.molColName).toList();
227
+ let lastAddedCell: DG.GridCell | null = null;
228
+ for (let i = 0; i < this.dataFrame!.rowCount; i++) {
229
+ const cell = view.grid.cell(this.molColName, i);
230
+ if (!cell)
231
+ continue;
232
+ if (cell.cell.value === '' || cell.cell.value === null)
233
+ lastAddedCell = cell;
234
+ }
235
+ if (lastAddedCell)
236
+ grok.functions.call('Chem:editMoleculeCell', {cell: lastAddedCell});
260
237
  } catch (e) {
261
238
  console.error(e);
262
239
  }
240
+ //const lastCell = view.grid.cell(this.molColName, this.dataFrame!.rowCount - 1);
241
+ //view.grid.onCellValueEdited
263
242
  }));
264
- subs.push(grok.events.onContextMenu.subscribe((args) => {
265
- try {
266
- const viewer: DG.Viewer = args?.args?.context;
267
- if (!viewer)
268
- return;
269
- if (viewer?.type !== DG.VIEWER.GRID)
270
- return;
271
- if (!viewer.tableView || viewer.tableView.id !== view.id)
272
- return;
273
- if (args?.args?.item?.tableColumn?.name !== this.molColName || !args?.args?.item?.isTableCell)
274
- return;
275
- const menu: DG.Menu = args?.args?.menu;
276
- if (!menu)
277
- return;
278
- menu.item('Add new row', () => {
243
+ this.dataFrame && subs.push(this.dataFrame?.onRowsRemoved.subscribe(() => {
244
+ try {
245
+ this.processedValues = this.dataFrame!.getCol(this.molColName).toList();
246
+ } catch (e) {
247
+ console.error(e);
248
+ }
249
+ }));
250
+ subs.push(grok.events.onContextMenu.subscribe((args) => {
251
+ try {
252
+ const viewer: DG.Viewer = args?.args?.context;
253
+ if (!viewer)
254
+ return;
255
+ if (viewer?.type !== DG.VIEWER.GRID)
256
+ return;
257
+ if (!viewer.tableView || viewer.tableView.id !== view.id)
258
+ return;
259
+ if (args?.args?.item?.tableColumn?.name !== this.molColName || !args?.args?.item?.isTableCell)
260
+ return;
261
+ const menu: DG.Menu = args?.args?.menu;
262
+ if (!menu)
263
+ return;
264
+ menu.item('Add new row', () => {
279
265
  this.dataFrame!.rows.addNew(null, true);
280
- });
281
- menu.item('Duplicate molecule', () => {
282
- try {
266
+ });
267
+ menu.item('Duplicate molecule', () => {
268
+ try {
283
269
  this.dataFrame!.rows.addNew(null, true);
284
270
  let lastCell: DG.GridCell | null = null;
285
271
  for (let i = 0; i < this.dataFrame!.rowCount; i++) {
@@ -292,105 +278,109 @@ export class HitDesignApp extends HitAppBase<HitDesignTemplate> {
292
278
  if (lastCell)
293
279
  lastCell.cell.value = args?.args?.item?.cell?.value ?? '';
294
280
  // grok.functions.call('Chem:editMoleculeCell', {cell: lastCell});
281
+ } catch (e) {
282
+ console.error(e);
283
+ }
284
+ });
285
+
286
+ const cellIndex = args?.args?.item?.tableRowIndex;
287
+ const cellValue = args?.args?.item?.cell?.value;
288
+ if (cellValue && (cellIndex ?? -1) > -1) {
289
+ menu.item('Re-Run Calculations', async () => {
290
+ try {
291
+ await performSingleCellCalculations(cellIndex, cellValue);
295
292
  } catch (e) {
296
293
  console.error(e);
297
294
  }
298
295
  });
296
+ }
297
+ } catch (e: any) {
298
+ grok.log.error(e);
299
+ }
300
+ }));
299
301
 
300
- const cellIndex = args?.args?.item?.tableRowIndex;
301
- const cellValue = args?.args?.item?.cell?.value;
302
- if (cellValue && (cellIndex ?? -1) > -1) {
303
- menu.item('Re-Run Calculations', async () => {
302
+ if (!view?.grid) {
303
+ grok.shell.error('Applied layout created view without grid. Resetting layout.');
304
+ view.resetLayout();
305
+ }
306
+ view?.grid && subs.push(view.grid.onCellValueEdited.subscribe(async (gc) => {
307
+ try {
308
+ if (gc.tableColumn?.name === TileCategoriesColName) {
309
+ await this.saveCampaign(undefined, false);
310
+ return;
311
+ }
312
+ if (gc.tableColumn?.name !== this.molColName)
313
+ return;
314
+ const newValue = gc.cell.value;
315
+ const newValueIdx = gc.tableRowIndex!;
316
+ let newVid = this.dataFrame!.col(ViDColName)?.get(newValueIdx);
317
+ let foundMatch = false;
318
+ // try to find existing molecule
319
+ if (newValue) {
320
+ try {
321
+ const canonicals = gc.tableColumn.toList().map((cv) => {
304
322
  try {
305
- await performSingleCellCalculations(cellIndex, cellValue);
323
+ return grok.chem.convert(cv, grok.chem.Notation.Unknown, grok.chem.Notation.Smiles);
306
324
  } catch (e) {
307
- console.error(e);
325
+ return '';
308
326
  }
309
- });
310
- }
311
- } catch (e: any) {
312
- grok.log.error(e);
313
- }
314
- }));
315
- subs.push(view.grid.onCellValueEdited.subscribe(async (gc) => {
316
- try {
317
- if (gc.tableColumn?.name === TileCategoriesColName) {
318
- await this.saveCampaign(undefined, false);
319
- return;
320
- }
321
- if (gc.tableColumn?.name !== this.molColName)
322
- return;
323
- const newValue = gc.cell.value;
324
- const newValueIdx = gc.tableRowIndex!;
325
- let newVid = this.dataFrame!.col(ViDColName)?.get(newValueIdx);
326
- let foundMatch = false;
327
- // try to find existing molecule
328
- if (newValue) {
329
- try {
330
- const canonicals = gc.tableColumn.toList().map((cv) => {
331
- try {
332
- return grok.chem.convert(cv, grok.chem.Notation.Unknown, grok.chem.Notation.Smiles);
333
- } catch (e) {
334
- return '';
335
- }
336
- },
337
- );
338
- const canonicalNewValue =
327
+ },
328
+ );
329
+ const canonicalNewValue =
339
330
  grok.chem.convert(newValue, grok.chem.Notation.Unknown, grok.chem.Notation.Smiles);
340
- if (canonicals?.length === this.dataFrame!.rowCount) {
341
- for (let i = 0; i < canonicals.length; i++) {
342
- if (canonicals[i] === canonicalNewValue &&
331
+ if (canonicals?.length === this.dataFrame!.rowCount) {
332
+ for (let i = 0; i < canonicals.length; i++) {
333
+ if (canonicals[i] === canonicalNewValue &&
343
334
  i !== newValueIdx && this.dataFrame!.col(ViDColName)?.get(i)) {
344
- newVid = this.dataFrame!.col(ViDColName)?.get(i);
345
- foundMatch = true;
346
- break;
347
- }
335
+ newVid = this.dataFrame!.col(ViDColName)?.get(i);
336
+ foundMatch = true;
337
+ break;
348
338
  }
349
339
  }
350
- } catch (e) {
351
- console.error(e);
352
340
  }
341
+ } catch (e) {
342
+ console.error(e);
353
343
  }
354
- // if the vid was duplicated, generate a new one
355
- if (this.duplicateVidCache && !foundMatch &&
344
+ }
345
+ // if the vid was duplicated, generate a new one
346
+ if (this.duplicateVidCache && !foundMatch &&
356
347
  this.duplicateVidCache.valueCounts[this.duplicateVidCache.indexes[newValueIdx]] > 1)
357
- newVid = null;
348
+ newVid = null;
358
349
 
359
- if (!newVid || newVid === '')
360
- newVid = getNewVid(this.dataFrame!.col(ViDColName)!);
350
+ if (!newVid || newVid === '')
351
+ newVid = getNewVid(this.dataFrame!.col(ViDColName)!);
361
352
 
362
353
  this.dataFrame!.col(ViDColName)!.set(newValueIdx, newVid, false);
363
354
 
364
355
  performSingleCellCalculations(newValueIdx, newValue);
365
- } catch (e) {
366
- console.error(e);
367
- }
368
- }));
356
+ } catch (e) {
357
+ console.error(e);
358
+ }
359
+ }));
369
360
 
370
- subs.push(view.grid.onCellRender.subscribe((args) => {
371
- try {
372
- // color duplicate vid values
373
- const cell = args.cell;
374
- if (!cell || !cell.isTableCell || !cell.tableColumn || !this.duplicateVidCache ||
361
+ view?.grid && subs.push(view.grid.onCellRender.subscribe((args) => {
362
+ try {
363
+ // color duplicate vid values
364
+ const cell = args.cell;
365
+ if (!cell || !cell.isTableCell || !cell.tableColumn || !this.duplicateVidCache ||
375
366
  cell.tableColumn.name !== ViDColName || (cell.tableRowIndex ?? -1) < 0)
376
- return;
367
+ return;
377
368
 
378
- if (this.duplicateVidCache.valueCounts[this.duplicateVidCache.indexes[cell.tableRowIndex!]] > 1) {
379
- args.cell.style.backColor =
369
+ if (this.duplicateVidCache.valueCounts[this.duplicateVidCache.indexes[cell.tableRowIndex!]] > 1) {
370
+ args.cell.style.backColor =
380
371
  DG.Color.setAlpha(DG.Color.getCategoricalColor(this.duplicateVidCache.indexes[cell.tableRowIndex!])
381
372
  , 150);
382
- }
383
- } catch (e) {}
384
- }));
373
+ }
374
+ } catch (e) {}
375
+ }));
385
376
 
386
377
 
387
- const onRemoveSub = grok.events.onViewRemoved.subscribe((v) => {
388
- if (v.id === view.id) {
389
- subs.forEach((s) => s.unsubscribe());
390
- onRemoveSub.unsubscribe();
391
- }
392
- });
393
- }, 300);
378
+ const onRemoveSub = grok.events.onViewRemoved.subscribe((v) => {
379
+ if (v.id === view?.id) {
380
+ subs.forEach((s) => s.unsubscribe());
381
+ onRemoveSub.unsubscribe();
382
+ }
383
+ });
394
384
  const ribbons = view?.getRibbonPanels();
395
385
  if (ribbons) {
396
386
  const hasSubmit = checkRibbonsHaveSubmit(ribbons);
@@ -487,16 +477,7 @@ export class HitDesignApp extends HitAppBase<HitDesignTemplate> {
487
477
  });
488
478
  }, 'Edit campaign permissions');
489
479
  const tilesButton = ui.bigButton('Progress tracker', () => {
490
- if (this.currentTilesViewId && grok.shell.view(this.currentTilesViewId))
491
- grok.shell.view(this.currentTilesViewId)?.close();
492
-
493
- this._tilesView = new HitDesignTilesView(this);
494
- this._tilesView.parentCall = this.parentCall;
495
- this._tilesViewTab = grok.shell.addView(this._tilesView);
496
- this.currentTilesViewId = this._tilesViewTab.name;
497
- this._tilesView.onActivated();
498
-
499
- grok.shell.v = grok.shell.view(this.currentTilesViewId)!;
480
+ getTilesViewDialog(this, () => this._designView ?? null);
500
481
  });
501
482
 
502
483
  const submitButton = ui.bigButton('Submit', () => {
@@ -520,7 +501,10 @@ export class HitDesignApp extends HitAppBase<HitDesignTemplate> {
520
501
  ribbonButtons.unshift(permissionsButton);
521
502
  ribbonButtons.unshift(calculateRibbon);
522
503
  ribbonButtons.unshift(addNewRowButton);
504
+
505
+
523
506
  ribbons.push(ribbonButtons);
507
+ // remove project save button from the ribbon
524
508
  view.setRibbonPanels(ribbons);
525
509
  }
526
510
  }
@@ -636,7 +620,7 @@ export class HitDesignApp extends HitAppBase<HitDesignTemplate> {
636
620
  enrichedDf.columns.toList().forEach((col) => columnSemTypes[col.name] = col.semType);
637
621
  const colTypeMap: {[_: string]: string} = {};
638
622
  enrichedDf.columns.toList().forEach((col) => colTypeMap[col.name] = col.type);
639
- const sketchStateString = this._tilesView?.sketchStateString ?? this.campaign?.tilesViewerFormSketch ?? undefined;
623
+ const sketchStateString = this.campaign?.tilesViewerFormSketch ?? undefined;
640
624
 
641
625
  // if its first time save author as current user, else keep the same
642
626
  const authorUserId = this.campaign?.authorUserId ?? grok.shell.user.id;
@@ -4,114 +4,100 @@ import * as DG from 'datagrok-api/dg';
4
4
  import {HitDesignApp} from '../hit-design-app';
5
5
  import {_package} from '../../package';
6
6
  import {TileCategoriesColName} from '../consts';
7
- import {HitBaseView} from '../base-view';
8
- import {HitDesignTemplate} from '../types';
9
- import {checkRibbonsHaveSubmit} from '../utils';
10
7
  import './utils.css';
11
8
 
12
- export class HitDesignTilesView extends HitBaseView<HitDesignTemplate, HitDesignApp> {
13
- private v: DG.Viewer | null = null;
14
- constructor(app: HitDesignApp) {
15
- super(app);
16
- this.name = 'Progress Tracker';
9
+ export function getTilesViewDialog(app: HitDesignApp, getTableView: () => DG.TableView | null) {
10
+ const tilesViewerSketchStateString = app.campaign?.tilesViewerFormSketch;
11
+ let sketchState: any | null = null;
12
+ if (tilesViewerSketchStateString && tilesViewerSketchStateString.length > 0) {
13
+ try {
14
+ sketchState = JSON.parse(tilesViewerSketchStateString);
15
+ } catch (e) {
16
+ console.error('Failed to parse sketch state string', e);
17
+ }
18
+ }
19
+ if (sketchState) {
20
+ // after saving, some columns might be removed in the meantime, so we need to update the
21
+ //sketch state and remove them so that the viewer can be initialized correctly.
22
+ if (sketchState.elementStates && (sketchState.elementStates.length ?? 0) > 0) {
23
+ sketchState.elementStates = sketchState.elementStates.filter((elementState: any) =>
24
+ elementState?.viewerSettings?.column && app.dataFrame!.col(elementState.viewerSettings.column),
25
+ );
26
+ }
17
27
  }
18
28
 
19
- async render(): Promise<void> {
20
- return new Promise<void>((resolve) =>{
21
- // const filteredDf = DG.DataFrame.fromColumns(
22
- // this.app.dataFrame!.columns.toList().filter((col) => !col.name.startsWith('~')));
23
- // const _hiidenTv = DG.TableView.create(filteredDf, true);
24
- //const tv = DG.TableView.create(this.app.dataFrame!, false);
25
- this.app.dataFrame!.columns.names().forEach((name) => {
26
- if (name.startsWith('~'))
27
- this.app.dataFrame!.columns.remove(name);
28
- });
29
-
30
- const tylesViewereSketchStateString = this.app.campaign?.tilesViewerFormSketch;
31
- let sketchState: any | null = null;
32
- if (tylesViewereSketchStateString && tylesViewereSketchStateString.length > 0) {
33
- try {
34
- sketchState = JSON.parse(tylesViewereSketchStateString);
35
- } catch (e) {
36
- console.error('Failed to parse sketch state string', e);
37
- }
38
- }
39
- let isInitialized = true;
40
- if (!this.v || this.v.isDetached) {
41
- isInitialized = false;
42
- if (sketchState) {
43
- // after saving, some columns might be removed in the meantime, so we need to update the
44
- //sketch state and remove them so that the viewer can be initialized correctly.
45
- if (sketchState.elementStates && (sketchState.elementStates.length ?? 0) > 0) {
46
- sketchState.elementStates = sketchState.elementStates.filter((elementState: any) =>
47
- elementState?.viewerSettings?.column && this.app.dataFrame!.col(elementState.viewerSettings.column),
48
- );
49
- }
50
- }
51
- this.v = DG.Viewer.fromType(DG.VIEWER.TILE_VIEWER, this.app.dataFrame!,
52
- {lanesColumnName: TileCategoriesColName, lanes: this.app.template?.stages ?? [],
53
- ...((sketchState?.elementStates?.length ?? 0) > 0 ? {sketchState} : {})});
54
- const opts = this.v.getOptions();
55
- opts.look.sketchState = (sketchState?.elementStates?.length ?? 0) > 0 ? sketchState : null;
29
+ const tileOpts = {lanesColumnName: TileCategoriesColName, lanes: app.template?.stages ?? [],
30
+ ...((sketchState?.elementStates?.length ?? 0) > 0 ? {sketchState} : {})};
56
31
 
57
- this.v.setOptions(opts);
58
- this.v.copyViewersLook(this.v); // hacky way to apply sketch state
59
- }
60
- //this.root.appendChild(tv.root);
32
+ const tv = getTableView();
61
33
 
62
- if (!isInitialized) {
63
- ui.empty(this.root);
64
- this.root.appendChild(this.v.root);
65
- this.v.root.style.height = '100%';
66
- this.v.root.style.width = '100%';
67
- setTimeout(() => {
68
- this.v?.view?._onAdded();
69
- const ribbons = grok.shell.v?.getRibbonPanels();
34
+ if (!tv) {
35
+ grok.shell.error('Failed to create tiles viewer. table view is not available.');
36
+ return;
37
+ }
38
+ let v: DG.Viewer | null = null;
39
+ const modal = ui.dialog('Progress Tracker');
40
+ try {
41
+ v = tv.addViewer(DG.VIEWER.TILE_VIEWER, tileOpts);
70
42
 
71
- if (ribbons) {
72
- const hasSubmit = checkRibbonsHaveSubmit(ribbons);
73
- if (hasSubmit) {
74
- resolve();
75
- return;
76
- }
77
- const designVButton = ui.bigButton('Design view', () => {
78
- const v = grok.shell.view(this.app.designViewName);
79
- if (v)
80
- grok.shell.v = v;
81
- });
82
- const submitButton = ui.bigButton('Submit', () => {
83
- const dialogContent = this.app._submitView?.render();
84
- if (dialogContent) {
85
- const dlg = ui.dialog('Submit');
86
- dlg.add(dialogContent);
87
- dlg.addButton('Save', ()=>{this.app.saveCampaign(); dlg.close();});
88
- dlg.addButton('Submit', ()=>{this.app._submitView?.submit(); dlg.close();});
89
- dlg.show();
90
- }
91
- });
92
- submitButton.classList.add('hit-design-submit-button');
93
- ribbons.push([designVButton, submitButton]);
94
- grok.shell.v.setRibbonPanels(ribbons);
95
- }
96
- resolve();
97
- }, 5);
98
- } else
99
- resolve();
100
- });
43
+ const opts = v.getOptions();
44
+ opts.look.sketchState = (sketchState?.elementStates?.length ?? 0) > 0 ? sketchState : null;
101
45
 
102
- //const tv = DG.TableView.create(this.app.dataFrame!, false);
46
+ v.setOptions(opts);
47
+ v.copyViewersLook(v); // hacky way to apply sketch state
48
+ } catch (e) {
49
+ grok.shell.error('Failed to create tiles viewer with preset layout.\n Falling back to default layout.');
50
+ console.error('Failed to create tiles viewer', e);
51
+ if (v) {
52
+ v.close();
53
+ v.detach();
54
+ }
55
+ v = tv.addViewer(DG.VIEWER.TILE_VIEWER,
56
+ {lanesColumnName: TileCategoriesColName, lanes: app.template?.stages ?? []});
103
57
  }
104
58
 
105
- onActivated(): void {
106
- this.render();
59
+ if (!v) {
60
+ grok.shell.error('Failed to create tiles viewer. check the console for more details.');
61
+ return;
107
62
  }
63
+ modal.add(v.root);
108
64
 
109
- get sketchStateString(): string | null {
110
- if (!this.v)
111
- return null;
112
- const sketchState = this.v.props.sketchState;
113
- if (sketchState && typeof sketchState == 'object')
114
- return JSON.stringify(sketchState);
115
- return null;
116
- }
65
+ // from this modal, only way to go to another view is through edit form.
66
+ // when this happens, we should not destroy the viewer,
67
+ //but just hide it so that when we come back, we can show it again.
68
+ const hideModal = () => modal.root.style.setProperty('display', 'none', 'important');
69
+ const showModal = () => modal.root.style.display = 'flex';
70
+
71
+ const viewChangeSub = grok.events.onCurrentViewChanged.subscribe(() => {
72
+ if (grok.shell.v === tv)
73
+ showModal();
74
+ else
75
+ hideModal();
76
+ });
77
+
78
+
79
+ const closeSub = modal.onClose.subscribe(() => {
80
+ closeSub.unsubscribe();
81
+ viewChangeSub.unsubscribe();
82
+ // save the sketch state
83
+ try {
84
+ const sketchState = v.props.sketchState;
85
+ if (sketchState && typeof sketchState == 'object') {
86
+ const stringState = JSON.stringify(sketchState);
87
+ if (app.campaign)
88
+ app.campaign.tilesViewerFormSketch = stringState;
89
+ }
90
+ } catch (e) {
91
+ grok.shell.error('Failed to save sketch state. check the console for more details.');
92
+ console.error('Failed to save sketch state', e);
93
+ }
94
+ v.detach();
95
+ v.close();
96
+ });
97
+
98
+ modal.showModal(true);
99
+
100
+
101
+ // remove the modal background
102
+ document.querySelector('.d4-modal-background')?.remove();
117
103
  }