@ai-table/state 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. package/esm2022/public-api.mjs +2 -1
  2. package/esm2022/shared/to-table/array-event.mjs +45 -15
  3. package/esm2022/shared/to-table/index.mjs +8 -8
  4. package/esm2022/shared/to-yjs/add-node.mjs +21 -10
  5. package/esm2022/shared/to-yjs/index.mjs +3 -1
  6. package/esm2022/shared/to-yjs/remove-node.mjs +21 -10
  7. package/esm2022/types/view.mjs +28 -25
  8. package/esm2022/utils/build.mjs +16 -0
  9. package/esm2022/utils/common.mjs +11 -0
  10. package/esm2022/utils/field/date.mjs +56 -0
  11. package/esm2022/utils/field/field.mjs +32 -0
  12. package/esm2022/utils/field/index.mjs +22 -0
  13. package/esm2022/utils/field/number.mjs +28 -0
  14. package/esm2022/utils/field/rate.mjs +20 -0
  15. package/esm2022/utils/field/select.mjs +33 -0
  16. package/esm2022/utils/field/text.mjs +21 -0
  17. package/esm2022/utils/filter-records.mjs +52 -0
  18. package/esm2022/utils/index.mjs +6 -0
  19. package/esm2022/utils/view.mjs +69 -0
  20. package/esm2022/view/action/general.mjs +89 -5
  21. package/esm2022/view/action/index.mjs +2 -1
  22. package/esm2022/view/action/position.mjs +21 -0
  23. package/esm2022/view/action/view.mjs +4 -4
  24. package/esm2022/view/constants/view.mjs +3 -2
  25. package/esm2022/view/plugins/view.plugin.mjs +15 -6
  26. package/fesm2022/ai-table-state.mjs +565 -67
  27. package/fesm2022/ai-table-state.mjs.map +1 -1
  28. package/package.json +1 -1
  29. package/public-api.d.ts +1 -0
  30. package/public-api.d.ts.map +1 -1
  31. package/shared/to-table/array-event.d.ts +3 -2
  32. package/shared/to-table/array-event.d.ts.map +1 -1
  33. package/shared/to-table/index.d.ts +3 -3
  34. package/shared/to-table/index.d.ts.map +1 -1
  35. package/shared/to-yjs/add-node.d.ts +2 -2
  36. package/shared/to-yjs/add-node.d.ts.map +1 -1
  37. package/shared/to-yjs/index.d.ts.map +1 -1
  38. package/shared/to-yjs/remove-node.d.ts +2 -2
  39. package/shared/to-yjs/remove-node.d.ts.map +1 -1
  40. package/types/view.d.ts +32 -14
  41. package/types/view.d.ts.map +1 -1
  42. package/utils/build.d.ts +5 -0
  43. package/utils/build.d.ts.map +1 -0
  44. package/utils/common.d.ts +2 -0
  45. package/utils/common.d.ts.map +1 -0
  46. package/utils/field/date.d.ts +8 -0
  47. package/utils/field/date.d.ts.map +1 -0
  48. package/utils/field/field.d.ts +8 -0
  49. package/utils/field/field.d.ts.map +1 -0
  50. package/utils/field/index.d.ts +4 -0
  51. package/utils/field/index.d.ts.map +1 -0
  52. package/utils/field/number.d.ts +7 -0
  53. package/utils/field/number.d.ts.map +1 -0
  54. package/utils/field/rate.d.ts +7 -0
  55. package/utils/field/rate.d.ts.map +1 -0
  56. package/utils/field/select.d.ts +7 -0
  57. package/utils/field/select.d.ts.map +1 -0
  58. package/utils/field/text.d.ts +8 -0
  59. package/utils/field/text.d.ts.map +1 -0
  60. package/utils/filter-records.d.ts +5 -0
  61. package/utils/filter-records.d.ts.map +1 -0
  62. package/utils/index.d.ts +6 -0
  63. package/utils/index.d.ts.map +1 -0
  64. package/utils/view.d.ts +6 -0
  65. package/utils/view.d.ts.map +1 -0
  66. package/view/action/general.d.ts +9 -1
  67. package/view/action/general.d.ts.map +1 -1
  68. package/view/action/index.d.ts +1 -0
  69. package/view/action/index.d.ts.map +1 -1
  70. package/view/action/position.d.ts +8 -0
  71. package/view/action/position.d.ts.map +1 -0
  72. package/view/action/view.d.ts +4 -3
  73. package/view/action/view.d.ts.map +1 -1
  74. package/view/constants/view.d.ts +2 -1
  75. package/view/constants/view.d.ts.map +1 -1
  76. package/view/plugins/view.plugin.d.ts.map +1 -1
@@ -1,7 +1,8 @@
1
1
  import * as Y from 'yjs';
2
- import { ActionName, AITableQueries, getDefaultFieldValue, Actions, FLUSHING } from '@ai-table/grid';
3
- import { isArray } from 'ngx-tethys/util';
2
+ import { ActionName, AITableQueries, getDefaultFieldValue, idCreator, Actions, FLUSHING, AITableFieldType } from '@ai-table/grid';
3
+ import { isArray, isEmpty as isEmpty$1, isObject, isUndefinedOrNull, TinyDate } from 'ngx-tethys/util';
4
4
  import { createDraft, finishDraft } from 'immer';
5
+ import { fromUnixTime, subDays } from 'date-fns';
5
6
 
6
7
  class Positions {
7
8
  }
@@ -11,36 +12,39 @@ var Direction;
11
12
  Direction[Direction["ascending"] = 1] = "ascending";
12
13
  Direction[Direction["descending"] = -1] = "descending";
13
14
  })(Direction || (Direction = {}));
14
- var LogicalOperator;
15
- (function (LogicalOperator) {
16
- LogicalOperator["and"] = "and";
17
- LogicalOperator["or"] = "or";
18
- })(LogicalOperator || (LogicalOperator = {}));
19
- var FilterOperationSymbol;
20
- (function (FilterOperationSymbol) {
21
- FilterOperationSymbol["eq"] = "eq";
22
- FilterOperationSymbol["gte"] = "gte";
23
- FilterOperationSymbol["lte"] = "lte";
24
- FilterOperationSymbol["gt"] = "gt";
25
- FilterOperationSymbol["lt"] = "lt";
26
- FilterOperationSymbol["in"] = "in";
27
- FilterOperationSymbol["contain"] = "contain";
28
- FilterOperationSymbol["ne"] = "ne";
29
- FilterOperationSymbol["nin"] = "nin";
30
- FilterOperationSymbol["between"] = "between";
31
- FilterOperationSymbol["besides"] = "besides";
32
- FilterOperationSymbol["empty"] = "empty";
33
- FilterOperationSymbol["exists"] = "exists";
34
- FilterOperationSymbol["notContain"] = "not_contain";
35
- })(FilterOperationSymbol || (FilterOperationSymbol = {}));
36
- class GridSettings {
37
- }
15
+ var AITableFilterLogical;
16
+ (function (AITableFilterLogical) {
17
+ AITableFilterLogical["and"] = "and";
18
+ AITableFilterLogical["or"] = "or";
19
+ })(AITableFilterLogical || (AITableFilterLogical = {}));
20
+ var AITableFilterOperation;
21
+ (function (AITableFilterOperation) {
22
+ AITableFilterOperation["eq"] = "eq";
23
+ AITableFilterOperation["gte"] = "gte";
24
+ AITableFilterOperation["lte"] = "lte";
25
+ AITableFilterOperation["gt"] = "gt";
26
+ AITableFilterOperation["lt"] = "lt";
27
+ AITableFilterOperation["in"] = "in";
28
+ AITableFilterOperation["contain"] = "contain";
29
+ AITableFilterOperation["ne"] = "ne";
30
+ AITableFilterOperation["nin"] = "nin";
31
+ AITableFilterOperation["between"] = "between";
32
+ AITableFilterOperation["besides"] = "besides";
33
+ AITableFilterOperation["empty"] = "empty";
34
+ AITableFilterOperation["exists"] = "exists";
35
+ AITableFilterOperation["notContain"] = "not_contain";
36
+ })(AITableFilterOperation || (AITableFilterOperation = {}));
38
37
  var ViewActionName;
39
38
  (function (ViewActionName) {
40
39
  ViewActionName["SetView"] = "set_view";
41
40
  ViewActionName["AddView"] = "add_view";
42
41
  ViewActionName["RemoveView"] = "remove_view";
43
42
  })(ViewActionName || (ViewActionName = {}));
43
+ var PositionActionName;
44
+ (function (PositionActionName) {
45
+ PositionActionName["AddRecordPosition"] = "add_record_position";
46
+ PositionActionName["RemoveRecordPosition"] = "remove_record_position";
47
+ })(PositionActionName || (PositionActionName = {}));
44
48
 
45
49
  const createSharedType = () => {
46
50
  const doc = new Y.Doc();
@@ -163,13 +167,14 @@ const initTable = (sharedType) => {
163
167
  };
164
168
  };
165
169
 
166
- function translateArrayEvent(aiTable, activeViewId, sharedType, event) {
170
+ function translateArrayEvent(aiTable, sharedType, event) {
167
171
  let offset = 0;
168
172
  let targetPath = getShareTypeNumberPath(event.path);
169
173
  const isRecordsTranslate = event.path.includes('records');
170
174
  const isFieldsTranslate = event.path.includes('fields');
171
175
  const isViewsTranslate = event.path.includes('views');
172
176
  const actions = [];
177
+ const activeViewId = aiTable.activeViewId();
173
178
  event.changes.delta.forEach((delta) => {
174
179
  if ('retain' in delta) {
175
180
  offset += delta.retain ?? 0;
@@ -220,21 +225,47 @@ function translateArrayEvent(aiTable, activeViewId, sharedType, event) {
220
225
  }
221
226
  else {
222
227
  try {
228
+ const sharedRecords = sharedType.get('records');
229
+ const sharedFields = sharedType.get('fields');
223
230
  delta.insert?.map((item) => {
224
231
  const recordIndex = targetPath[0];
225
232
  const fieldIndex = offset;
226
- const recordId = getSharedRecordId(sharedType.get('records'), recordIndex);
227
- const fieldId = getSharedMapValueId(sharedType.get('fields'), fieldIndex);
228
- const path = [recordId, fieldId];
229
- const fieldValue = AITableQueries.getFieldValue(aiTable, path);
230
- // To exclude insert triggered by field inserts.
231
- if (fieldValue !== item) {
232
- actions.push({
233
- type: ActionName.UpdateFieldValue,
234
- path,
235
- fieldValue,
236
- newFieldValue: item
237
- });
233
+ const record = aiTable.records()[recordIndex];
234
+ if (isPositionOperation(fieldIndex, sharedFields)) {
235
+ for (const key in item) {
236
+ if (!record.positions[key] && record.positions[key] !== 0) {
237
+ actions.push({
238
+ type: PositionActionName.AddRecordPosition,
239
+ path: [record._id],
240
+ position: {
241
+ [key]: item[key]
242
+ }
243
+ });
244
+ }
245
+ }
246
+ for (const key in record.positions) {
247
+ if (!item[key] && item[key] !== 0) {
248
+ actions.push({
249
+ type: PositionActionName.RemoveRecordPosition,
250
+ path: [key, record._id]
251
+ });
252
+ }
253
+ }
254
+ }
255
+ else {
256
+ const recordId = getSharedRecordId(sharedRecords, recordIndex);
257
+ const fieldId = getSharedMapValueId(sharedFields, fieldIndex);
258
+ const path = [recordId, fieldId];
259
+ const fieldValue = AITableQueries.getFieldValue(aiTable, path);
260
+ // To exclude insert triggered by field inserts.
261
+ if (fieldValue !== item) {
262
+ actions.push({
263
+ type: ActionName.UpdateFieldValue,
264
+ path,
265
+ fieldValue,
266
+ newFieldValue: item
267
+ });
268
+ }
238
269
  }
239
270
  });
240
271
  }
@@ -270,6 +301,9 @@ function translateArrayEvent(aiTable, activeViewId, sharedType, event) {
270
301
  function isAddOrRemove(targetPath) {
271
302
  return targetPath.length === 0;
272
303
  }
304
+ function isPositionOperation(fieldIndex, sharedFields) {
305
+ return fieldIndex === sharedFields.length;
306
+ }
273
307
  function getRemoveIds(event, type) {
274
308
  const ids = [];
275
309
  if (!type) {
@@ -378,27 +412,27 @@ const YjsAITable = {
378
412
  }
379
413
  };
380
414
 
381
- function translateYjsEvent(aiTable, activeViewId, sharedType, event) {
415
+ function translateYjsEvent(aiTable, sharedType, event) {
382
416
  if (event instanceof Y.YArrayEvent) {
383
- return translateArrayEvent(aiTable, activeViewId, sharedType, event);
417
+ return translateArrayEvent(aiTable, sharedType, event);
384
418
  }
385
419
  if (event instanceof Y.YMapEvent) {
386
420
  return translateMapEvent(aiTable, sharedType, event);
387
421
  }
388
422
  return [];
389
423
  }
390
- function applyEvents(aiTable, activeViewId, sharedType, events) {
391
- events.forEach((event) => translateYjsEvent(aiTable, activeViewId, sharedType, event).forEach((item) => {
424
+ function applyEvents(aiTable, sharedType, events) {
425
+ events.forEach((event) => translateYjsEvent(aiTable, sharedType, event).forEach((item) => {
392
426
  aiTable.apply(item);
393
427
  }));
394
428
  }
395
- function applyYjsEvents(aiTable, activeViewId, sharedType, events) {
429
+ function applyYjsEvents(aiTable, sharedType, events) {
396
430
  if (YjsAITable.isUndo(aiTable)) {
397
- applyEvents(aiTable, activeViewId, sharedType, events);
431
+ applyEvents(aiTable, sharedType, events);
398
432
  }
399
433
  else {
400
434
  YjsAITable.asRemote(aiTable, () => {
401
- applyEvents(aiTable, activeViewId, sharedType, events);
435
+ applyEvents(aiTable, sharedType, events);
402
436
  });
403
437
  }
404
438
  }
@@ -450,22 +484,33 @@ function setNode(sharedType, action) {
450
484
  }
451
485
 
452
486
  function addNode(sharedType, action) {
487
+ const records = sharedType.get('records');
488
+ const views = sharedType.get('views');
489
+ const fields = sharedType.get('fields');
453
490
  switch (action.type) {
454
491
  case ActionName.AddRecord:
455
- const records = sharedType.get('records');
456
492
  records && records.push([toRecordSyncElement(action.record)]);
457
493
  break;
458
494
  case ViewActionName.AddView:
459
- const views = sharedType.get('views');
460
495
  views && views.push([toSyncElement(action.view)]);
461
496
  break;
497
+ case PositionActionName.AddRecordPosition:
498
+ if (records) {
499
+ const recordIndex = getSharedRecordIndex(records, action.path[0]);
500
+ const record = records.get(recordIndex);
501
+ const customField = record.get(1);
502
+ const positionsIndex = customField.length - 1;
503
+ const positions = customField.get(positionsIndex);
504
+ const newPositions = { ...positions, ...action.position };
505
+ customField.delete(positionsIndex);
506
+ customField.insert(positionsIndex, [newPositions]);
507
+ }
508
+ break;
462
509
  case ActionName.AddField:
463
- const sharedFields = sharedType.get('fields');
464
- const sharedRecords = sharedType.get('records');
465
- if (sharedFields && sharedRecords) {
466
- sharedFields.push([toSyncElement(action.field)]);
510
+ if (fields && records) {
511
+ fields.push([toSyncElement(action.field)]);
467
512
  const path = action.path[0];
468
- for (let value of sharedRecords) {
513
+ for (let value of records) {
469
514
  const newRecord = getDefaultFieldValue(action.field);
470
515
  const customField = value.get(1);
471
516
  customField.insert(path, [newRecord]);
@@ -477,9 +522,11 @@ function addNode(sharedType, action) {
477
522
  }
478
523
 
479
524
  function removeNode(sharedType, action) {
525
+ const fields = sharedType.get('fields');
526
+ const records = sharedType.get('records');
527
+ const views = sharedType.get('views');
480
528
  switch (action.type) {
481
529
  case ActionName.RemoveRecord:
482
- const records = sharedType.get('records');
483
530
  if (records) {
484
531
  const recordIndex = getSharedRecordIndex(records, action.path[0]);
485
532
  if (recordIndex > -1) {
@@ -488,7 +535,6 @@ function removeNode(sharedType, action) {
488
535
  }
489
536
  break;
490
537
  case ViewActionName.RemoveView:
491
- const views = sharedType.get('views');
492
538
  if (views) {
493
539
  const viewIndex = getSharedMapValueIndex(views, action.path[0]);
494
540
  if (viewIndex > -1) {
@@ -496,14 +542,24 @@ function removeNode(sharedType, action) {
496
542
  }
497
543
  }
498
544
  break;
545
+ case PositionActionName.RemoveRecordPosition:
546
+ if (records) {
547
+ const recordIndex = getSharedRecordIndex(records, action.path[1]);
548
+ const record = records.get(recordIndex);
549
+ const customField = record.get(1);
550
+ const positionsIndex = customField.length - 1;
551
+ const positions = customField.get(positionsIndex);
552
+ delete positions[action.path[0]];
553
+ customField.delete(positionsIndex);
554
+ customField.insert(positionsIndex, [positions]);
555
+ }
556
+ break;
499
557
  case ActionName.RemoveField:
500
- const sharedFields = sharedType.get('fields');
501
- const sharedRecords = sharedType.get('records');
502
- if (sharedFields && sharedRecords) {
503
- const fieldIndex = getSharedMapValueIndex(sharedFields, action.path[0]);
558
+ if (fields && records) {
559
+ const fieldIndex = getSharedMapValueIndex(fields, action.path[0]);
504
560
  if (fieldIndex > -1) {
505
- sharedFields.delete(fieldIndex);
506
- for (let value of sharedRecords) {
561
+ fields.delete(fieldIndex);
562
+ for (let value of records) {
507
563
  value.get(1).delete(fieldIndex);
508
564
  }
509
565
  }
@@ -523,6 +579,8 @@ const actionMappers = {
523
579
  set_view: setNode,
524
580
  add_view: addNode,
525
581
  remove_view: removeNode,
582
+ add_record_position: addNode,
583
+ remove_record_position: removeNode
526
584
  };
527
585
  function applyActionOps(sharedType, actions, aiTable) {
528
586
  if (actions.length > 0) {
@@ -539,13 +597,78 @@ function applyActionOps(sharedType, actions, aiTable) {
539
597
  return sharedType;
540
598
  }
541
599
 
600
+ function createDefaultPositions(views, activeId, data, index) {
601
+ const positions = {};
602
+ const position = getPosition(data, activeId, index);
603
+ const maxPosition = data[data.length - 1].positions[activeId];
604
+ views.forEach((element) => {
605
+ positions[element._id] = element._id === activeId ? position : maxPosition + 1;
606
+ });
607
+ return positions;
608
+ }
609
+ function getPosition(data, activeViewId, index) {
610
+ let position = data.length - 1;
611
+ if (index !== 0 && index !== data.length) {
612
+ const previousViewPosition = data[index - 1].positions[activeViewId];
613
+ const nextViewPosition = data[index].positions[activeViewId];
614
+ position = (previousViewPosition + nextViewPosition) / 2;
615
+ }
616
+ else {
617
+ position = index;
618
+ }
619
+ return position;
620
+ }
621
+ function addView$1(aiTable, type) {
622
+ let index = aiTable.views().length;
623
+ const newId = idCreator();
624
+ let newView = {
625
+ _id: newId,
626
+ name: '表格视图 ' + index
627
+ };
628
+ let originViewId = aiTable.views()[aiTable.views().length - 1]._id;
629
+ if (type === 'copy') {
630
+ originViewId = aiTable.activeViewId();
631
+ const copyView = aiTable.views().find((item) => item._id === aiTable.activeViewId());
632
+ newView = {
633
+ ...copyView,
634
+ _id: newId,
635
+ name: copyView.name + '-副本'
636
+ };
637
+ index = aiTable.views().indexOf(copyView) + 1;
638
+ }
639
+ ViewActions.addView(aiTable, newView, [index]);
640
+ aiTable.records().forEach((record) => {
641
+ PositionActions.addRecordPosition(aiTable, { [newId]: record.positions[originViewId] }, [record._id]);
642
+ });
643
+ aiTable.fields().forEach((field) => {
644
+ Actions.setField(aiTable, {
645
+ positions: {
646
+ ...field.positions,
647
+ [newId]: field.positions[originViewId]
648
+ }
649
+ }, [field._id]);
650
+ });
651
+ return newView;
652
+ }
653
+ function removeView$1(aiTable, records, fields, activeViewId) {
654
+ records.forEach((record) => {
655
+ PositionActions.removeRecordPosition(aiTable, [activeViewId, record._id]);
656
+ });
657
+ fields.forEach((field) => {
658
+ const positions = { ...field.positions };
659
+ delete positions[activeViewId];
660
+ Actions.setField(aiTable, {
661
+ positions
662
+ }, [field._id]);
663
+ });
664
+ ViewActions.removeView(aiTable, [activeViewId]);
665
+ }
666
+
542
667
  const GeneralViewActions = {
543
668
  transform(aiTable, action) {
544
669
  const views = createDraft(aiTable.views());
545
670
  applyView(aiTable, views, action);
546
- aiTable.views.update(() => {
547
- return finishDraft(views);
548
- });
671
+ aiTable.views.set(finishDraft(views));
549
672
  }
550
673
  };
551
674
  const applyView = (aiTable, views, action) => {
@@ -589,6 +712,90 @@ const applyView = (aiTable, views, action) => {
589
712
  }
590
713
  }
591
714
  };
715
+ const GeneralActions = {
716
+ transform(aiTable, action) {
717
+ const records = createDraft(aiTable.records());
718
+ const fields = createDraft(aiTable.fields());
719
+ apply(aiTable, records, fields, action);
720
+ if (action.type === ActionName.AddRecord) {
721
+ aiTable.records.set(finishDraft(records));
722
+ }
723
+ if (action.type === ActionName.AddField) {
724
+ aiTable.fields.set(finishDraft(fields));
725
+ }
726
+ }
727
+ };
728
+ const apply = (aiTable, records, fields, action) => {
729
+ switch (action.type) {
730
+ case ActionName.AddRecord: {
731
+ const [recordIndex] = action.path;
732
+ if (recordIndex > -1) {
733
+ if (!action.record.positions) {
734
+ const activeView = aiTable.views().find((item) => item._id === aiTable.activeViewId());
735
+ let index = recordIndex;
736
+ if (activeView?.settings?.conditions) {
737
+ index = records.length;
738
+ }
739
+ action.record.positions = createDefaultPositions(aiTable.views(), aiTable.activeViewId(), aiTable.records(), index);
740
+ }
741
+ records.splice(recordIndex, 0, action.record);
742
+ }
743
+ break;
744
+ }
745
+ case ActionName.AddField: {
746
+ const [fieldIndex] = action.path;
747
+ if (fieldIndex > -1) {
748
+ const newField = action.field;
749
+ newField.positions = createDefaultPositions(aiTable.views(), aiTable.activeViewId(), aiTable.fields(), action.path[0]);
750
+ fields.splice(fieldIndex, 0, newField);
751
+ const newRecord = {
752
+ [newField._id]: getDefaultFieldValue(action.field)
753
+ };
754
+ records.forEach((item) => {
755
+ item.values = {
756
+ ...item.values,
757
+ ...newRecord
758
+ };
759
+ });
760
+ }
761
+ break;
762
+ }
763
+ }
764
+ };
765
+ const GeneralPositionActions = {
766
+ transform(aiTable, action) {
767
+ const records = createDraft(aiTable.records());
768
+ const fields = createDraft(aiTable.fields());
769
+ applyPosition(aiTable, records, action);
770
+ aiTable.records.update(() => {
771
+ return finishDraft(records);
772
+ });
773
+ aiTable.fields.update(() => {
774
+ return finishDraft(fields);
775
+ });
776
+ }
777
+ };
778
+ const applyPosition = (aiTable, records, action) => {
779
+ switch (action.type) {
780
+ case PositionActionName.AddRecordPosition: {
781
+ const { position, path } = action;
782
+ const record = records.find((item) => item._id === path[0]);
783
+ if (record) {
784
+ record.positions = {
785
+ ...record.positions,
786
+ ...position
787
+ };
788
+ }
789
+ break;
790
+ }
791
+ case PositionActionName.RemoveRecordPosition: {
792
+ const { path } = action;
793
+ const record = records.find((item) => item._id === path[1]);
794
+ delete record?.positions[path[0]];
795
+ break;
796
+ }
797
+ }
798
+ };
592
799
 
593
800
  function setView(aiTable, value, path) {
594
801
  const view = aiTable.views().find((item) => item._id === path[0]);
@@ -636,17 +843,47 @@ const ViewActions = {
636
843
  removeView
637
844
  };
638
845
 
846
+ function addRecordPosition(aiTable, position, path) {
847
+ const operation = {
848
+ type: PositionActionName.AddRecordPosition,
849
+ position,
850
+ path
851
+ };
852
+ aiTable.apply(operation);
853
+ }
854
+ function removeRecordPosition(aiTable, path) {
855
+ const operation = {
856
+ type: PositionActionName.RemoveRecordPosition,
857
+ path
858
+ };
859
+ aiTable.apply(operation);
860
+ }
861
+ const PositionActions = {
862
+ addRecordPosition,
863
+ removeRecordPosition
864
+ };
865
+
639
866
  const VIEW_ACTIONS = [ViewActionName.SetView, ViewActionName.AddView, ViewActionName.RemoveView];
867
+ const POSITION_ACTIONS = [PositionActionName.AddRecordPosition, PositionActionName.RemoveRecordPosition];
640
868
 
641
869
  const withView = (aiTable) => {
642
870
  const viewTable = aiTable;
643
871
  viewTable.apply = (action) => {
644
- aiTable.actions.push(action);
872
+ const sharedActions = viewTable.actions;
873
+ sharedActions.push(action);
645
874
  if (VIEW_ACTIONS.includes(action.type)) {
646
875
  GeneralViewActions.transform(viewTable, action);
647
876
  }
877
+ else if (POSITION_ACTIONS.includes(action.type)) {
878
+ GeneralPositionActions.transform(viewTable, action);
879
+ }
648
880
  else {
649
- Actions.transform(aiTable, action);
881
+ if (action.type === ActionName.AddField || action.type === ActionName.AddRecord) {
882
+ GeneralActions.transform(viewTable, action);
883
+ }
884
+ else {
885
+ Actions.transform(aiTable, action);
886
+ }
650
887
  }
651
888
  if (!FLUSHING.get(aiTable)) {
652
889
  FLUSHING.set(aiTable, true);
@@ -660,9 +897,270 @@ const withView = (aiTable) => {
660
897
  return aiTable;
661
898
  };
662
899
 
900
+ function isEmpty(value) {
901
+ if (isArray(value)) {
902
+ return isEmpty$1(value);
903
+ }
904
+ if (isObject(value)) {
905
+ return Reflect.ownKeys(value).length === 0;
906
+ }
907
+ return isUndefinedOrNull(value) || value == '';
908
+ }
909
+
910
+ class Field {
911
+ stringInclude(str, searchStr) {
912
+ return str.toLowerCase().includes(searchStr.trim().toLowerCase());
913
+ }
914
+ isMeetFilter(condition, cellValue) {
915
+ switch (condition.operation) {
916
+ case AITableFilterOperation.empty:
917
+ case AITableFilterOperation.exists: {
918
+ return this.isEmptyOrNot(condition.operation, cellValue);
919
+ }
920
+ default: {
921
+ return true;
922
+ }
923
+ }
924
+ }
925
+ isEmptyOrNot(operation, cellValue) {
926
+ switch (operation) {
927
+ case AITableFilterOperation.empty: {
928
+ return isEmpty(cellValue);
929
+ }
930
+ case AITableFilterOperation.exists: {
931
+ return !isEmpty(cellValue);
932
+ }
933
+ default: {
934
+ throw new Error('compare operator type error');
935
+ }
936
+ }
937
+ }
938
+ }
939
+
940
+ class TextField extends Field {
941
+ isMeetFilter(condition, cellValue) {
942
+ switch (condition.operation) {
943
+ case AITableFilterOperation.empty:
944
+ return isEmpty(cellValue);
945
+ case AITableFilterOperation.exists:
946
+ return !isEmpty(cellValue);
947
+ case AITableFilterOperation.contain:
948
+ return !isEmpty(cellValue) && this.stringInclude(cellValue, condition.value);
949
+ default:
950
+ return super.isMeetFilter(condition, cellValue);
951
+ }
952
+ }
953
+ static stringInclude(str, searchStr) {
954
+ return str.toLowerCase().includes(searchStr.trim().toLowerCase());
955
+ }
956
+ }
957
+
958
+ class SelectField extends Field {
959
+ isMeetFilter(condition, cellValue) {
960
+ switch (condition.operation) {
961
+ case AITableFilterOperation.empty:
962
+ return isEmpty(cellValue);
963
+ case AITableFilterOperation.exists:
964
+ return !isEmpty(cellValue);
965
+ case AITableFilterOperation.in:
966
+ return Array.isArray(condition.value) && hasIntersect(cellValue, condition.value);
967
+ case AITableFilterOperation.nin:
968
+ return Array.isArray(condition.value) && !hasIntersect(cellValue, condition.value);
969
+ default:
970
+ return super.isMeetFilter(condition, cellValue);
971
+ }
972
+ }
973
+ }
974
+ function hasIntersect(array1, array2) {
975
+ if (!Array.isArray(array1) || !Array.isArray(array2)) {
976
+ return false;
977
+ }
978
+ const set1 = new Set(array1);
979
+ const set2 = new Set(array2);
980
+ for (const ele of set1) {
981
+ if (set2.has(ele)) {
982
+ return true;
983
+ }
984
+ }
985
+ return false;
986
+ }
987
+
988
+ class DateField extends Field {
989
+ isMeetFilter(condition, cellValue) {
990
+ const [left, right] = this.getTimeRange(condition.value);
991
+ switch (condition.operation) {
992
+ case AITableFilterOperation.empty:
993
+ return isEmpty(cellValue.timestamp) || cellValue.timestamp === 0;
994
+ case AITableFilterOperation.exists:
995
+ return !isEmpty(cellValue.timestamp) && cellValue.timestamp !== 0;
996
+ case AITableFilterOperation.eq:
997
+ return left <= cellValue.timestamp && cellValue.timestamp < right;
998
+ case AITableFilterOperation.gt:
999
+ return cellValue.timestamp > right;
1000
+ case AITableFilterOperation.lt:
1001
+ return cellValue.timestamp < left;
1002
+ case AITableFilterOperation.between:
1003
+ return left <= cellValue.timestamp && cellValue.timestamp < right;
1004
+ default:
1005
+ return super.isMeetFilter(condition, cellValue);
1006
+ }
1007
+ }
1008
+ getTimeRange(value) {
1009
+ switch (value) {
1010
+ case 'today':
1011
+ return [new TinyDate(new Date()).startOfDay().getUnixTime(), new TinyDate(new Date()).endOfDay().getUnixTime()];
1012
+ case 'current_week':
1013
+ return [
1014
+ new TinyDate().startOfWeek({ weekStartsOn: 1 }).getUnixTime(),
1015
+ new TinyDate().endOfWeek({ weekStartsOn: 1 }).getUnixTime()
1016
+ ];
1017
+ case 'yesterday':
1018
+ return [
1019
+ new TinyDate(subDays(new Date(), 1)).startOfDay().getUnixTime(),
1020
+ new TinyDate(subDays(new Date(), 1)).endOfDay().getUnixTime()
1021
+ ];
1022
+ case 'current_month':
1023
+ return [new TinyDate().startOfMonth().getUnixTime(), new TinyDate().endOfMonth().getUnixTime()];
1024
+ default:
1025
+ if (isArray(value)) {
1026
+ return [
1027
+ new TinyDate(fromUnixTime(value[0])).startOfDay().getUnixTime(),
1028
+ new TinyDate(fromUnixTime(value[1])).endOfDay().getUnixTime()
1029
+ ];
1030
+ }
1031
+ return [
1032
+ new TinyDate(fromUnixTime(value)).startOfDay().getUnixTime(),
1033
+ new TinyDate(fromUnixTime(value)).endOfDay().getUnixTime()
1034
+ ];
1035
+ }
1036
+ }
1037
+ }
1038
+
1039
+ class NumberField extends Field {
1040
+ isMeetFilter(condition, cellValue) {
1041
+ switch (condition.operation) {
1042
+ case AITableFilterOperation.empty:
1043
+ return isEmpty(cellValue);
1044
+ case AITableFilterOperation.exists:
1045
+ return !isEmpty(cellValue);
1046
+ case AITableFilterOperation.eq:
1047
+ return !Number.isNaN(condition.value) && cellValue != null && cellValue !== '' && condition.value === cellValue;
1048
+ case AITableFilterOperation.gte:
1049
+ return cellValue != null && cellValue !== '' && cellValue >= condition.value;
1050
+ case AITableFilterOperation.lte:
1051
+ return cellValue != null && cellValue !== '' && cellValue <= condition.value;
1052
+ case AITableFilterOperation.gt:
1053
+ return cellValue != null && cellValue !== '' && cellValue > condition.value;
1054
+ case AITableFilterOperation.lt:
1055
+ return cellValue != null && cellValue !== '' && cellValue < condition.value;
1056
+ case AITableFilterOperation.ne:
1057
+ return cellValue == null || cellValue == '' || Number.isNaN(condition.value) || cellValue !== condition.value;
1058
+ default:
1059
+ return super.isMeetFilter(condition, cellValue);
1060
+ }
1061
+ }
1062
+ }
1063
+
1064
+ class RateField extends Field {
1065
+ isMeetFilter(condition, cellValue) {
1066
+ switch (condition.operation) {
1067
+ case AITableFilterOperation.empty:
1068
+ return isEmpty(cellValue);
1069
+ case AITableFilterOperation.exists:
1070
+ return !isEmpty(cellValue);
1071
+ case AITableFilterOperation.in:
1072
+ return !isEmpty(cellValue) && condition.value.includes(cellValue.toString());
1073
+ case AITableFilterOperation.nin:
1074
+ return isEmpty(cellValue) || !condition.value.includes(cellValue.toString());
1075
+ default:
1076
+ return super.isMeetFilter(condition, cellValue);
1077
+ }
1078
+ }
1079
+ }
1080
+
1081
+ const ViewOperationMap = {
1082
+ [AITableFieldType.text]: new TextField(),
1083
+ [AITableFieldType.richText]: new TextField(),
1084
+ [AITableFieldType.select]: new SelectField(),
1085
+ [AITableFieldType.date]: new DateField(),
1086
+ [AITableFieldType.createdAt]: new DateField(),
1087
+ [AITableFieldType.updatedAt]: new DateField(),
1088
+ [AITableFieldType.number]: new NumberField(),
1089
+ [AITableFieldType.rate]: new RateField(),
1090
+ [AITableFieldType.link]: new TextField(),
1091
+ [AITableFieldType.member]: new SelectField(),
1092
+ [AITableFieldType.progress]: new NumberField(),
1093
+ [AITableFieldType.createdBy]: new SelectField(),
1094
+ [AITableFieldType.updatedBy]: new SelectField()
1095
+ };
1096
+
1097
+ function getFilteredRecords(records, fields, activeView) {
1098
+ const { conditions, condition_logical } = activeView.settings || {};
1099
+ if (!conditions) {
1100
+ return records;
1101
+ }
1102
+ const illegalConditions = conditions.filter((item) => item.operation) || [];
1103
+ if (!illegalConditions.length) {
1104
+ return records;
1105
+ }
1106
+ return records.filter((record) => {
1107
+ return checkConditions(fields, record, { conditions: illegalConditions, condition_logical });
1108
+ });
1109
+ }
1110
+ function checkConditions(fields, record, filterConditions) {
1111
+ if (!record) {
1112
+ return false;
1113
+ }
1114
+ if (!filterConditions?.conditions) {
1115
+ return true;
1116
+ }
1117
+ const { condition_logical, conditions } = filterConditions;
1118
+ if (condition_logical === AITableFilterLogical.and) {
1119
+ return conditions.every((condition) => doFilterOperations(fields, record, condition));
1120
+ }
1121
+ if (!condition_logical || condition_logical === AITableFilterLogical.or) {
1122
+ return conditions.some((condition) => doFilterOperations(fields, record, condition));
1123
+ }
1124
+ return false;
1125
+ }
1126
+ function doFilterOperations(fields, record, condition) {
1127
+ const field = fields.find((item) => item._id === condition.field_id);
1128
+ const cellValue = record.values[condition.field_id];
1129
+ try {
1130
+ return field && doFilter(condition, field, cellValue);
1131
+ }
1132
+ catch (error) {
1133
+ return false;
1134
+ }
1135
+ }
1136
+ function doFilter(condition, field, cellValue) {
1137
+ if (condition.operation === AITableFilterOperation.empty) {
1138
+ return isEmpty(cellValue);
1139
+ }
1140
+ if (condition.operation === AITableFilterOperation.exists) {
1141
+ return !isEmpty(cellValue);
1142
+ }
1143
+ return ViewOperationMap[field.type].isMeetFilter(condition, cellValue);
1144
+ }
1145
+
1146
+ function sortByView(data, activeViewId) {
1147
+ const hasPositions = data.every((item) => item.positions && item.positions);
1148
+ if (hasPositions) {
1149
+ return [...data].sort((a, b) => a.positions[activeViewId] - b.positions[activeViewId]);
1150
+ }
1151
+ return data;
1152
+ }
1153
+ function buildRecordsByView(records, fields, activeView) {
1154
+ const filteredRecords = getFilteredRecords(records, fields, activeView);
1155
+ return sortByView(filteredRecords, activeView._id);
1156
+ }
1157
+ function buildFieldsByView(fields, activeView) {
1158
+ return sortByView(fields, activeView._id);
1159
+ }
1160
+
663
1161
  /**
664
1162
  * Generated bundle index. Do not edit.
665
1163
  */
666
1164
 
667
- export { Direction, FilterOperationSymbol, GeneralViewActions, GridSettings, LogicalOperator, Positions, VIEW_ACTIONS, ViewActionName, ViewActions, YjsAITable, actionMappers, addView, applyActionOps, applyEvents, applyView, applyYjsEvents, createSharedType, getShareTypeNumberPath, getSharedMapValueId, getSharedMapValueIndex, getSharedRecordId, getSharedRecordIndex, initSharedType, initTable, removeView, setView, toRecordSyncElement, toSharedType, toSyncElement, translatePositionToPath, translateToRecordValues, translateToRecords, translateYjsEvent, withView };
1165
+ export { AITableFilterLogical, AITableFilterOperation, Direction, GeneralActions, GeneralPositionActions, GeneralViewActions, POSITION_ACTIONS, PositionActionName, PositionActions, Positions, VIEW_ACTIONS, ViewActionName, ViewActions, ViewOperationMap, YjsAITable, actionMappers, addRecordPosition, addView$1 as addView, apply, applyActionOps, applyEvents, applyPosition, applyView, applyYjsEvents, buildFieldsByView, buildRecordsByView, createDefaultPositions, createSharedType, doFilter, getFilteredRecords, getPosition, getShareTypeNumberPath, getSharedMapValueId, getSharedMapValueIndex, getSharedRecordId, getSharedRecordIndex, initSharedType, initTable, isEmpty, removeRecordPosition, removeView$1 as removeView, sortByView, toRecordSyncElement, toSharedType, toSyncElement, translatePositionToPath, translateToRecordValues, translateToRecords, translateYjsEvent, withView };
668
1166
  //# sourceMappingURL=ai-table-state.mjs.map