@followupus/common 0.9.9 → 0.9.11

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.
@@ -32,15 +32,17 @@ export declare const OP_TYPES: {
32
32
  NOT_EQUAL: string;
33
33
  LESS_EQUAL: string;
34
34
  LESS: string;
35
+ BEFORE: string;
36
+ AFTER: string;
35
37
  };
36
38
  export declare const COLUMN_OP_TYPES: {
37
- [x: string]: string[];
39
+ readonly [x: string]: readonly [string, string, string, string, string, string] | readonly [string, string, string, string] | readonly [string, string, string, string, string, string, string, string];
38
40
  };
39
41
  export declare const AUTOMATION_OP_TYPES: {
40
- [x: string]: string[];
42
+ [x: string]: string[] | readonly [string, string, string, string, string, string] | readonly [string, string, string, string] | readonly [string, string, string, string, string, string, string, string];
41
43
  };
42
44
  export declare const DYNAMIC_VIEW_OP_TYPES: {
43
- [x: string]: string[];
45
+ [x: string]: string[] | readonly [string, string, string, string, string, string] | readonly [string, string, string, string] | readonly [string, string, string, string, string, string, string, string];
44
46
  };
45
47
  export declare const THEMSELVES = "self";
46
48
  export declare const DATE_GROUPS: {
@@ -52,9 +54,20 @@ export declare const DATE_GROUPS: {
52
54
  THIS_MONTH: string;
53
55
  FUTURE: string;
54
56
  };
57
+ export declare const FILTER_DATE_GROUPS: {
58
+ TODAY: string;
59
+ THIS_WEEK: string;
60
+ THIS_MONTH: string;
61
+ };
62
+ export declare const DATE_VALUE_FORMAT = "YYYY-MM-DD";
63
+ export declare enum SpecialKeyInDateFilter {
64
+ SelectDate = "selectDate",
65
+ SelectRange = "selectRange"
66
+ }
55
67
  export declare const isLinkedColumns: (columnType?: string) => boolean;
56
68
  export declare const getColumnTypeFromId: (columnId: string) => string | undefined;
57
69
  export declare const getColumnValueType: (columnType: string) => "string" | "number" | "object" | "stringArray" | "objectArray";
70
+ export declare const getFilterDateGroupKeys: (dateStr: string) => string[] | null;
58
71
  export declare const getDateGroupKey: (dateStr: string) => string | null;
59
72
  export declare const getValidConditions: (filter: IFilter, headers?: IBaseCustomColumn[], currentUserId?: string, escapeHeaderCheck?: boolean) => IFilterCondition[];
60
73
  export declare const filterItemsByConditions: (groups: IBaseGroup[], filter: IFilter, headers?: IBaseCustomColumn[], currentUserId?: string) => IBaseGroup[];
@@ -33,6 +33,8 @@ export const OP_TYPES = {
33
33
  NOT_EQUAL: "neq",
34
34
  LESS_EQUAL: "lte",
35
35
  LESS: "lt",
36
+ BEFORE: "before",
37
+ AFTER: "after",
36
38
  };
37
39
  export const COLUMN_OP_TYPES = {
38
40
  [COLUMN_TYPES.TEXT]: [
@@ -46,8 +48,8 @@ export const COLUMN_OP_TYPES = {
46
48
  [COLUMN_TYPES.DATE]: [
47
49
  OP_TYPES.IS,
48
50
  OP_TYPES.IS_NOT,
49
- OP_TYPES.EMPTY,
50
- OP_TYPES.NOT_EMPTY,
51
+ OP_TYPES.BEFORE,
52
+ OP_TYPES.AFTER,
51
53
  ],
52
54
  [COLUMN_TYPES.NUMBER]: [
53
55
  OP_TYPES.EQUAL,
@@ -123,6 +125,17 @@ export const DATE_GROUPS = {
123
125
  THIS_MONTH: "thisMonth",
124
126
  FUTURE: "future",
125
127
  };
128
+ export const FILTER_DATE_GROUPS = {
129
+ TODAY: "today",
130
+ THIS_WEEK: "thisWeek",
131
+ THIS_MONTH: "thisMonth",
132
+ };
133
+ export const DATE_VALUE_FORMAT = "YYYY-MM-DD";
134
+ export var SpecialKeyInDateFilter;
135
+ (function (SpecialKeyInDateFilter) {
136
+ SpecialKeyInDateFilter["SelectDate"] = "selectDate";
137
+ SpecialKeyInDateFilter["SelectRange"] = "selectRange";
138
+ })(SpecialKeyInDateFilter || (SpecialKeyInDateFilter = {}));
126
139
  export const isLinkedColumns = (columnType) => {
127
140
  if (!columnType)
128
141
  return false;
@@ -151,6 +164,36 @@ export const getColumnValueType = (columnType) => {
151
164
  return "string";
152
165
  }
153
166
  };
167
+ export const getFilterDateGroupKeys = (dateStr) => {
168
+ const keys = [];
169
+ if (!dateStr)
170
+ return null;
171
+ const current = dayjs();
172
+ const day = dayjs(dateStr);
173
+ if (current.isSame(day, "date")) {
174
+ keys.push(FILTER_DATE_GROUPS.TODAY);
175
+ keys.push(FILTER_DATE_GROUPS.THIS_WEEK);
176
+ keys.push(FILTER_DATE_GROUPS.THIS_MONTH);
177
+ return keys;
178
+ }
179
+ const startDayOfThisWeek = current.set("day", 0);
180
+ const endDayOfThisWeek = current.set("day", 6);
181
+ const startDayOfThisMonth = current.set("date", 1);
182
+ const endDayOfThisMonth = current.set("date", current.daysInMonth());
183
+ if ((day.isAfter(startDayOfThisWeek, "date") ||
184
+ day.isSame(startDayOfThisWeek, "date")) &&
185
+ (day.isBefore(endDayOfThisWeek, "date") ||
186
+ day.isSame(endDayOfThisWeek, "date"))) {
187
+ keys.push(FILTER_DATE_GROUPS.THIS_WEEK);
188
+ }
189
+ if ((day.isAfter(startDayOfThisMonth, "date") ||
190
+ day.isSame(startDayOfThisMonth, "date")) &&
191
+ (day.isBefore(endDayOfThisMonth, "date") ||
192
+ day.isSame(endDayOfThisMonth, "date"))) {
193
+ keys.push(FILTER_DATE_GROUPS.THIS_MONTH);
194
+ }
195
+ return keys;
196
+ };
154
197
  export const getDateGroupKey = (dateStr) => {
155
198
  if (!dateStr)
156
199
  return null;
@@ -205,6 +248,9 @@ export const getValidConditions = (filter, headers, currentUserId, escapeHeaderC
205
248
  c.value.splice(idx, 1, currentUserId);
206
249
  }
207
250
  }
251
+ if (checkHeader?.type === COLUMN_TYPES.DATE) {
252
+ _.remove(c.value, v => v === Object.values(SpecialKeyInDateFilter).includes(v));
253
+ }
208
254
  });
209
255
  // for dropdown, if set the option is in filter condition, and user delete the option. should ignore it or make the option can't be deleted
210
256
  return newFilter.criteria.filter(c => {
@@ -229,6 +275,7 @@ export const getValidConditions = (filter, headers, currentUserId, escapeHeaderC
229
275
  COLUMN_TYPES.PRIORITY,
230
276
  COLUMN_TYPES.TAGS,
231
277
  ].includes(columnType);
278
+ const isDate = columnType === COLUMN_TYPES.DATE;
232
279
  switch (c.op) {
233
280
  case OP_TYPES.IS:
234
281
  case OP_TYPES.IS_NOT:
@@ -250,6 +297,10 @@ export const getValidConditions = (filter, headers, currentUserId, escapeHeaderC
250
297
  case OP_TYPES.LESS:
251
298
  case OP_TYPES.LESS_EQUAL:
252
299
  return !!c.value?.length;
300
+ case OP_TYPES.BEFORE:
301
+ case OP_TYPES.AFTER:
302
+ return (isDate &&
303
+ !!c.value?.filter(v => v === FILTER_DATE_GROUPS.TODAY || dayjs(v).isValid())?.length);
253
304
  default:
254
305
  return false;
255
306
  }
@@ -277,12 +328,56 @@ const isInConditionValues = (itemVal, valueType, condition) => {
277
328
  return false;
278
329
  };
279
330
  const isDateInConditionValues = (itemVal, condition) => {
280
- if (condition.blank && !itemVal)
331
+ if (condition.blank && (!itemVal || !dayjs(itemVal).isValid()))
281
332
  return true;
282
- const groupKey = getDateGroupKey(itemVal);
283
- if (!groupKey)
284
- return !!condition.blank;
285
- return !!condition.value?.find(dateGroup => dateGroup === groupKey);
333
+ const itemDate = dayjs(itemVal);
334
+ return !!condition.value?.some(c => {
335
+ if (c && typeof c === "object") {
336
+ // range
337
+ const startDt = dayjs(c.start);
338
+ const endDt = dayjs(c.end);
339
+ return (startDt.isValid() &&
340
+ endDt.isValid() &&
341
+ (itemDate.isAfter(startDt, "date") ||
342
+ itemDate.isSame(startDt, "date")) &&
343
+ (itemDate.isBefore(endDt, "date") || itemDate.isSame(endDt, "date")));
344
+ }
345
+ else if (dayjs(c).isValid()) {
346
+ return itemDate.isSame(dayjs(c), "date");
347
+ }
348
+ else {
349
+ const groupKeys = getFilterDateGroupKeys(itemVal);
350
+ return !!groupKeys?.includes(c);
351
+ }
352
+ });
353
+ // if (!groupKey) return !!condition.blank;
354
+ // return !!condition.value?.find((dateGroup) => dateGroup === groupKey);
355
+ };
356
+ const isDateBeforeConditionValues = (itemVal, condition) => {
357
+ if (!itemVal || !dayjs(itemVal).isValid())
358
+ return false;
359
+ const itemDate = dayjs(itemVal);
360
+ return !!condition.value?.some(c => {
361
+ if (dayjs(c).isValid()) {
362
+ return itemDate.isBefore(dayjs(c));
363
+ }
364
+ else if (c === FILTER_DATE_GROUPS.TODAY) {
365
+ return itemDate.isBefore(dayjs(), "date");
366
+ }
367
+ });
368
+ };
369
+ const isDateAfterConditionValues = (itemVal, condition) => {
370
+ if (!itemVal || !dayjs(itemVal).isValid())
371
+ return false;
372
+ const itemDate = dayjs(itemVal);
373
+ return !!condition.value?.some(c => {
374
+ if (dayjs(c).isValid()) {
375
+ return itemDate.isAfter(dayjs(c));
376
+ }
377
+ else if (c === FILTER_DATE_GROUPS.TODAY) {
378
+ return itemDate.isAfter(dayjs(), "date");
379
+ }
380
+ });
286
381
  };
287
382
  const isEmpty = (itemVal, valueType) => {
288
383
  switch (valueType) {
@@ -388,6 +483,7 @@ const checkItemMatched = (item, validConditions, headers) => {
388
483
  if (isLinkedColumn) {
389
484
  checkHeader = header?.linked;
390
485
  }
486
+ const isPeople = checkHeader?.type === COLUMN_TYPES.PEOPLE;
391
487
  const valueType = getColumnValueType(checkHeader?.type ?? "");
392
488
  const checkConditionFn = (itemVal) => {
393
489
  let match = false;
@@ -403,6 +499,12 @@ const checkItemMatched = (item, validConditions, headers) => {
403
499
  ? !isDateInConditionValues(itemVal, condition)
404
500
  : !isInConditionValues(itemVal, valueType, condition);
405
501
  break;
502
+ case OP_TYPES.BEFORE: // only for date type
503
+ match = isDate && isDateBeforeConditionValues(itemVal, condition);
504
+ break;
505
+ case OP_TYPES.AFTER:
506
+ match = isDate && isDateAfterConditionValues(itemVal, condition);
507
+ break;
406
508
  case OP_TYPES.EMPTY:
407
509
  match = isEmpty(itemVal, valueType);
408
510
  break;
@@ -450,13 +552,28 @@ const checkItemMatched = (item, validConditions, headers) => {
450
552
  ? item.data?.[condition.columnId]
451
553
  : item.data?.[condition.columnId]?.value;
452
554
  if (isLinkedColumn) {
453
- isItemMatched = !!itemValue?.some((item) => {
454
- const val = item.value;
455
- return checkConditionFn(val);
456
- });
555
+ isItemMatched =
556
+ !!itemValue?.some((item) => {
557
+ const val = item.value;
558
+ return checkConditionFn(val);
559
+ }) ||
560
+ (isPeople &&
561
+ !!item.subs?.some(sub => {
562
+ const subValue = sub.data?.[condition.columnId];
563
+ return !!subValue?.some((item) => {
564
+ const val = item.value;
565
+ return checkConditionFn(val);
566
+ });
567
+ }));
457
568
  }
458
569
  else {
459
- isItemMatched = checkConditionFn(itemValue);
570
+ isItemMatched =
571
+ checkConditionFn(itemValue) ||
572
+ (isPeople &&
573
+ !!item.subs?.some(sub => {
574
+ const subValue = sub.data?.[condition.columnId]?.value;
575
+ return checkConditionFn(subValue);
576
+ }));
460
577
  }
461
578
  if (!isItemMatched)
462
579
  return false;
@@ -472,8 +589,7 @@ export const filterItemsByConditions = (groups, filter, headers, currentUserId)
472
589
  }
473
590
  groups.forEach(g => {
474
591
  g.items = g.items?.filter(item => {
475
- return (checkItemMatched(item, validConditions, headers) ||
476
- item.subs?.some(sub => checkItemMatched(sub, validConditions, headers)));
592
+ return checkItemMatched(item, validConditions, headers);
477
593
  });
478
594
  });
479
595
  return groups;
@@ -4,6 +4,7 @@ export interface IBaseUser {
4
4
  email: string;
5
5
  firstname: string;
6
6
  lastname: string;
7
+ displayName: string;
7
8
  }
8
9
  export interface ILinkedSource {
9
10
  boardId: string;
@@ -15,8 +16,12 @@ export interface ILinkedSource {
15
16
  dropdowns?: {
16
17
  key: string;
17
18
  value: string;
19
+ attr?: {
20
+ color?: string;
21
+ };
18
22
  }[];
19
23
  setting?: IColumnSetting;
24
+ linkedGroup?: string;
20
25
  }
21
26
  export interface IBaseItem {
22
27
  itemId: string;
@@ -31,16 +36,20 @@ export interface IBaseItem {
31
36
  export interface IColumnSetting {
32
37
  currency?: string;
33
38
  }
39
+ export interface IDropdownOption {
40
+ key: string;
41
+ value?: string;
42
+ index?: number;
43
+ attr?: {
44
+ color?: string;
45
+ };
46
+ }
34
47
  export interface IBaseCustomColumn {
35
48
  columnId: string;
36
49
  type: string;
37
50
  name: string;
38
51
  description?: string;
39
- dropdowns?: {
40
- key: string;
41
- value: string;
42
- }[];
43
- linkedGroup?: string;
52
+ dropdowns?: IDropdownOption[];
44
53
  linked?: ILinkedSource;
45
54
  index?: number;
46
55
  deleted?: boolean;
@@ -51,10 +60,12 @@ export interface IBaseGroup {
51
60
  description?: string;
52
61
  items?: IBaseItem[];
53
62
  deleted?: boolean;
63
+ index?: number;
54
64
  }
55
65
  export interface IBaseBoard {
56
66
  name: string;
57
67
  boardId: string;
68
+ viewId?: string;
58
69
  type?: "board";
59
70
  folderId?: string;
60
71
  policyId?: string;
@@ -78,7 +89,7 @@ export interface IFilterCondition {
78
89
  conditionId?: string;
79
90
  columnId: string;
80
91
  op: string;
81
- value: string[] | number[];
92
+ value: any[];
82
93
  blank?: boolean;
83
94
  }
84
95
  export interface IFilter {
@@ -94,3 +105,7 @@ export interface IDynamicView {
94
105
  allowComment?: boolean;
95
106
  step: "itemsSetting" | "customizeView" | "itemDetail" | "customizeForm" | "shareSetting";
96
107
  }
108
+ export interface ActionEvent {
109
+ actionBy: "user" | "ai";
110
+ actionId?: string;
111
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@followupus/common",
3
- "version": "0.9.9",
3
+ "version": "0.9.11",
4
4
  "description": "followup common utils npm package with TypeScript and VSCode",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",