@followupus/common 0.0.2 → 0.2.0
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/README.md +15 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -1
- package/dist/shared/index.d.ts +2 -0
- package/dist/shared/index.js +2 -0
- package/dist/shared/shared.d.ts +51 -0
- package/dist/shared/shared.js +392 -0
- package/dist/shared/types.d.ts +96 -0
- package/dist/shared/types.js +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/validator.d.ts +3 -0
- package/dist/utils/validator.js +36 -0
- package/package.json +22 -15
package/README.md
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { IBaseCustomColumn, IBaseGroup, IFilter, IFilterCondition, IPureBoard } from "./types";
|
|
2
|
+
export declare const COLUMN_TYPES: {
|
|
3
|
+
NUMBER: string;
|
|
4
|
+
TEXT: string;
|
|
5
|
+
DROPDOWN: string;
|
|
6
|
+
DATE: string;
|
|
7
|
+
STATUS: string;
|
|
8
|
+
PRIORITY: string;
|
|
9
|
+
LINK: string;
|
|
10
|
+
TAGS: string;
|
|
11
|
+
EMAIL: string;
|
|
12
|
+
PEOPLE: string;
|
|
13
|
+
LINKED_COLUMN: string;
|
|
14
|
+
REF_LINED_COLUMN: string;
|
|
15
|
+
FILES: string;
|
|
16
|
+
HOURS: string;
|
|
17
|
+
TIMELINE: string;
|
|
18
|
+
PHONE: string;
|
|
19
|
+
CURRENCY: string;
|
|
20
|
+
};
|
|
21
|
+
export declare const OP_TYPES: {
|
|
22
|
+
CONTAINS: string;
|
|
23
|
+
NOT_CONTAINS: string;
|
|
24
|
+
IS: string;
|
|
25
|
+
IS_NOT: string;
|
|
26
|
+
EMPTY: string;
|
|
27
|
+
NOT_EMPTY: string;
|
|
28
|
+
EQUAL: string;
|
|
29
|
+
GREATER: string;
|
|
30
|
+
GREATER_EQUAL: string;
|
|
31
|
+
NOT_EQUAL: string;
|
|
32
|
+
LESS_EQUAL: string;
|
|
33
|
+
LESS: string;
|
|
34
|
+
};
|
|
35
|
+
export declare const COLUMN_OP_TYPES: {
|
|
36
|
+
[x: string]: string[];
|
|
37
|
+
};
|
|
38
|
+
export declare const DATE_GROUPS: {
|
|
39
|
+
OVERDUE: string;
|
|
40
|
+
TODAY: string;
|
|
41
|
+
TOMORROW: string;
|
|
42
|
+
THIS_WEEK: string;
|
|
43
|
+
NEXT_WEEK: string;
|
|
44
|
+
THIS_MONTH: string;
|
|
45
|
+
FUTURE: string;
|
|
46
|
+
};
|
|
47
|
+
export declare const getColumnValueType: (columnType: string) => "string" | "number" | "object" | "stringArray" | "objectArray";
|
|
48
|
+
export declare const getDateGroupKey: (dateStr: string) => string | null;
|
|
49
|
+
export declare const getValidConditions: (filter: IFilter, headers?: IBaseCustomColumn[]) => IFilterCondition[];
|
|
50
|
+
export declare const filterItemsByConditions: (groups: IBaseGroup[], filter: IFilter, headers?: IBaseCustomColumn[]) => IBaseGroup[];
|
|
51
|
+
export declare const filterBoardTree: (board: IPureBoard, filter: IFilter) => IPureBoard;
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import { isEqual } from "lodash";
|
|
2
|
+
import dayjs from "dayjs";
|
|
3
|
+
export const COLUMN_TYPES = {
|
|
4
|
+
NUMBER: "number",
|
|
5
|
+
TEXT: "string",
|
|
6
|
+
DROPDOWN: "dropdown",
|
|
7
|
+
DATE: "date",
|
|
8
|
+
STATUS: "status",
|
|
9
|
+
PRIORITY: "priority",
|
|
10
|
+
LINK: "link",
|
|
11
|
+
TAGS: "tags",
|
|
12
|
+
EMAIL: "email",
|
|
13
|
+
PEOPLE: "people",
|
|
14
|
+
LINKED_COLUMN: "linked_column",
|
|
15
|
+
REF_LINED_COLUMN: "ref_linked_column",
|
|
16
|
+
FILES: "files",
|
|
17
|
+
HOURS: "hours",
|
|
18
|
+
TIMELINE: "timeline",
|
|
19
|
+
PHONE: "phone",
|
|
20
|
+
CURRENCY: "currency",
|
|
21
|
+
};
|
|
22
|
+
export const OP_TYPES = {
|
|
23
|
+
CONTAINS: "like",
|
|
24
|
+
NOT_CONTAINS: "not_like",
|
|
25
|
+
IS: "in",
|
|
26
|
+
IS_NOT: "not_in",
|
|
27
|
+
EMPTY: "empty",
|
|
28
|
+
NOT_EMPTY: "not_empty",
|
|
29
|
+
EQUAL: "eq",
|
|
30
|
+
GREATER: "gt",
|
|
31
|
+
GREATER_EQUAL: "gte",
|
|
32
|
+
NOT_EQUAL: "neq",
|
|
33
|
+
LESS_EQUAL: "lte",
|
|
34
|
+
LESS: "lt",
|
|
35
|
+
};
|
|
36
|
+
export const COLUMN_OP_TYPES = {
|
|
37
|
+
[COLUMN_TYPES.TEXT]: [
|
|
38
|
+
OP_TYPES.CONTAINS,
|
|
39
|
+
OP_TYPES.NOT_CONTAINS,
|
|
40
|
+
OP_TYPES.IS,
|
|
41
|
+
OP_TYPES.IS_NOT,
|
|
42
|
+
],
|
|
43
|
+
[COLUMN_TYPES.DATE]: [
|
|
44
|
+
OP_TYPES.IS,
|
|
45
|
+
OP_TYPES.IS_NOT,
|
|
46
|
+
OP_TYPES.EMPTY,
|
|
47
|
+
OP_TYPES.NOT_EMPTY,
|
|
48
|
+
],
|
|
49
|
+
[COLUMN_TYPES.NUMBER]: [
|
|
50
|
+
OP_TYPES.EQUAL,
|
|
51
|
+
OP_TYPES.NOT_EQUAL,
|
|
52
|
+
OP_TYPES.GREATER,
|
|
53
|
+
OP_TYPES.GREATER_EQUAL,
|
|
54
|
+
OP_TYPES.LESS,
|
|
55
|
+
OP_TYPES.LESS_EQUAL,
|
|
56
|
+
OP_TYPES.EMPTY,
|
|
57
|
+
OP_TYPES.NOT_EMPTY,
|
|
58
|
+
],
|
|
59
|
+
[COLUMN_TYPES.DROPDOWN]: [
|
|
60
|
+
OP_TYPES.IS,
|
|
61
|
+
OP_TYPES.IS_NOT,
|
|
62
|
+
OP_TYPES.EMPTY,
|
|
63
|
+
OP_TYPES.NOT_EMPTY,
|
|
64
|
+
],
|
|
65
|
+
[COLUMN_TYPES.STATUS]: [
|
|
66
|
+
OP_TYPES.IS,
|
|
67
|
+
OP_TYPES.IS_NOT,
|
|
68
|
+
OP_TYPES.EMPTY,
|
|
69
|
+
OP_TYPES.NOT_EMPTY,
|
|
70
|
+
],
|
|
71
|
+
[COLUMN_TYPES.PRIORITY]: [
|
|
72
|
+
OP_TYPES.IS,
|
|
73
|
+
OP_TYPES.IS_NOT,
|
|
74
|
+
OP_TYPES.EMPTY,
|
|
75
|
+
OP_TYPES.NOT_EMPTY,
|
|
76
|
+
],
|
|
77
|
+
[COLUMN_TYPES.PEOPLE]: [
|
|
78
|
+
OP_TYPES.IS,
|
|
79
|
+
OP_TYPES.IS_NOT,
|
|
80
|
+
OP_TYPES.EMPTY,
|
|
81
|
+
OP_TYPES.NOT_EMPTY,
|
|
82
|
+
],
|
|
83
|
+
};
|
|
84
|
+
export const DATE_GROUPS = {
|
|
85
|
+
OVERDUE: "overdue",
|
|
86
|
+
TODAY: "today",
|
|
87
|
+
TOMORROW: "tomorrow",
|
|
88
|
+
THIS_WEEK: "thisWeek",
|
|
89
|
+
NEXT_WEEK: "nextWeek",
|
|
90
|
+
THIS_MONTH: "thisMonth",
|
|
91
|
+
FUTURE: "future",
|
|
92
|
+
};
|
|
93
|
+
export const getColumnValueType = (columnType) => {
|
|
94
|
+
switch (columnType) {
|
|
95
|
+
case COLUMN_TYPES.PEOPLE:
|
|
96
|
+
case COLUMN_TYPES.FILES:
|
|
97
|
+
case COLUMN_TYPES.TAGS:
|
|
98
|
+
return "stringArray";
|
|
99
|
+
case COLUMN_TYPES.TIMELINE:
|
|
100
|
+
return "object";
|
|
101
|
+
case COLUMN_TYPES.NUMBER:
|
|
102
|
+
case COLUMN_TYPES.HOURS:
|
|
103
|
+
case COLUMN_TYPES.CURRENCY:
|
|
104
|
+
return "number";
|
|
105
|
+
case COLUMN_TYPES.LINKED_COLUMN:
|
|
106
|
+
case COLUMN_TYPES.REF_LINED_COLUMN:
|
|
107
|
+
return "objectArray";
|
|
108
|
+
default:
|
|
109
|
+
return "string";
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
export const getDateGroupKey = (dateStr) => {
|
|
113
|
+
if (!dateStr)
|
|
114
|
+
return null;
|
|
115
|
+
const current = dayjs();
|
|
116
|
+
const day = dayjs(dateStr);
|
|
117
|
+
if (day.isBefore(current, "date")) {
|
|
118
|
+
return DATE_GROUPS.OVERDUE;
|
|
119
|
+
}
|
|
120
|
+
if (current.isSame(day, "date")) {
|
|
121
|
+
return DATE_GROUPS.TODAY;
|
|
122
|
+
}
|
|
123
|
+
const tomorrow = current.add(1, "day");
|
|
124
|
+
if (tomorrow.isSame(day, "date")) {
|
|
125
|
+
return DATE_GROUPS.TOMORROW;
|
|
126
|
+
}
|
|
127
|
+
const endDayOfThisWeek = current.set("day", 6);
|
|
128
|
+
if (day.isBefore(endDayOfThisWeek, "date") ||
|
|
129
|
+
day.isSame(endDayOfThisWeek, "date")) {
|
|
130
|
+
return DATE_GROUPS.THIS_WEEK;
|
|
131
|
+
}
|
|
132
|
+
const endDayOfNextWeek = endDayOfThisWeek.add(7, "day");
|
|
133
|
+
if (day.isAfter(endDayOfThisWeek, "date") &&
|
|
134
|
+
(day.isBefore(endDayOfNextWeek, "date") ||
|
|
135
|
+
day.isSame(endDayOfNextWeek, "date"))) {
|
|
136
|
+
return DATE_GROUPS.THIS_WEEK;
|
|
137
|
+
}
|
|
138
|
+
const endDayOfThisMonth = current.set("date", current.daysInMonth());
|
|
139
|
+
if (day.isBefore(endDayOfThisMonth, "date") ||
|
|
140
|
+
day.isSame(endDayOfThisMonth, "date")) {
|
|
141
|
+
return DATE_GROUPS.THIS_MONTH;
|
|
142
|
+
}
|
|
143
|
+
return DATE_GROUPS.FUTURE;
|
|
144
|
+
};
|
|
145
|
+
export const getValidConditions = (filter, headers) => {
|
|
146
|
+
if (!filter.criteria?.length || !headers?.length) {
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
// 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
|
|
150
|
+
return filter.criteria.filter((c) => {
|
|
151
|
+
const validHeader = headers.find((h) => h.columnId === c.columnId);
|
|
152
|
+
if (!validHeader)
|
|
153
|
+
return false;
|
|
154
|
+
const validOperate = COLUMN_OP_TYPES[validHeader.type].includes(c.op);
|
|
155
|
+
if (!validOperate)
|
|
156
|
+
return false;
|
|
157
|
+
const isDropdown = [
|
|
158
|
+
COLUMN_TYPES.DROPDOWN,
|
|
159
|
+
COLUMN_TYPES.STATUS,
|
|
160
|
+
COLUMN_TYPES.PRIORITY,
|
|
161
|
+
].includes(validHeader.type);
|
|
162
|
+
switch (c.op) {
|
|
163
|
+
case OP_TYPES.IS:
|
|
164
|
+
case OP_TYPES.IS_NOT:
|
|
165
|
+
return (c.blank ||
|
|
166
|
+
(!!c.value?.filter((v) => !!v || v === 0)?.length &&
|
|
167
|
+
(!isDropdown ||
|
|
168
|
+
c.value.some((v) => validHeader.dropdowns?.find((d) => d.key === v)))));
|
|
169
|
+
case OP_TYPES.EMPTY:
|
|
170
|
+
case OP_TYPES.NOT_EMPTY:
|
|
171
|
+
return true;
|
|
172
|
+
case OP_TYPES.CONTAINS:
|
|
173
|
+
case OP_TYPES.NOT_CONTAINS:
|
|
174
|
+
return !!c.value?.length;
|
|
175
|
+
case OP_TYPES.EQUAL:
|
|
176
|
+
case OP_TYPES.NOT_EQUAL:
|
|
177
|
+
case OP_TYPES.GREATER:
|
|
178
|
+
case OP_TYPES.GREATER_EQUAL:
|
|
179
|
+
case OP_TYPES.LESS:
|
|
180
|
+
case OP_TYPES.LESS_EQUAL:
|
|
181
|
+
return !!c.value?.length;
|
|
182
|
+
default:
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
};
|
|
187
|
+
const isInConditionValues = (itemVal, valueType, condition) => {
|
|
188
|
+
switch (valueType) {
|
|
189
|
+
case "number":
|
|
190
|
+
case "string":
|
|
191
|
+
return ((condition.blank && !itemVal) ||
|
|
192
|
+
!!condition.value.find((val) => val === itemVal));
|
|
193
|
+
case "stringArray":
|
|
194
|
+
return ((condition.blank && !itemVal?.length) ||
|
|
195
|
+
condition.value.some((val) => Array.isArray(itemVal) && itemVal?.includes(val)));
|
|
196
|
+
case "object":
|
|
197
|
+
return ((condition.blank && !itemVal) ||
|
|
198
|
+
!!condition.value.find((val) => isEqual(val, itemVal)));
|
|
199
|
+
case "objectArray":
|
|
200
|
+
return ((condition.blank && !itemVal?.length) ||
|
|
201
|
+
condition.value.some((val) => Array.isArray(itemVal) &&
|
|
202
|
+
itemVal.find((existVal) => isEqual(val, existVal))));
|
|
203
|
+
default:
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
return false;
|
|
207
|
+
};
|
|
208
|
+
const isDateInConditionValues = (itemVal, condition) => {
|
|
209
|
+
if (condition.blank && !itemVal)
|
|
210
|
+
return true;
|
|
211
|
+
const groupKey = getDateGroupKey(itemVal);
|
|
212
|
+
if (!groupKey)
|
|
213
|
+
return !!condition.blank;
|
|
214
|
+
return !!condition.value?.find((dateGroup) => dateGroup === groupKey);
|
|
215
|
+
};
|
|
216
|
+
const isEmpty = (itemVal, valueType) => {
|
|
217
|
+
switch (valueType) {
|
|
218
|
+
case "number":
|
|
219
|
+
case "string":
|
|
220
|
+
return !itemVal;
|
|
221
|
+
case "stringArray":
|
|
222
|
+
return !itemVal?.length;
|
|
223
|
+
case "object":
|
|
224
|
+
return !itemVal || !Object.keys(itemVal).length;
|
|
225
|
+
case "objectArray":
|
|
226
|
+
return !itemVal?.length;
|
|
227
|
+
default:
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
return true;
|
|
231
|
+
};
|
|
232
|
+
const isContains = (itemVal, valueType, condition) => {
|
|
233
|
+
const checkVal = condition.value?.length
|
|
234
|
+
? condition.value[0]
|
|
235
|
+
: "";
|
|
236
|
+
switch (valueType) {
|
|
237
|
+
case "number":
|
|
238
|
+
return itemVal || itemVal === 0
|
|
239
|
+
? itemVal.toString().includes(checkVal)
|
|
240
|
+
: false;
|
|
241
|
+
case "string":
|
|
242
|
+
return !!itemVal && itemVal.includes(checkVal);
|
|
243
|
+
case "stringArray":
|
|
244
|
+
return itemVal?.length
|
|
245
|
+
? itemVal.some((val) => val.includes(checkVal))
|
|
246
|
+
: false;
|
|
247
|
+
default:
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
return false;
|
|
251
|
+
};
|
|
252
|
+
const isEquals = (itemVal, valueType, condition) => {
|
|
253
|
+
const checkVal = condition.value?.length ? condition.value[0] : "";
|
|
254
|
+
switch (valueType) {
|
|
255
|
+
case "number":
|
|
256
|
+
return typeof checkVal === "number"
|
|
257
|
+
? checkVal === itemVal
|
|
258
|
+
: parseInt(checkVal, 10) === itemVal;
|
|
259
|
+
case "string":
|
|
260
|
+
return !!itemVal && checkVal === itemVal;
|
|
261
|
+
case "object":
|
|
262
|
+
return isEqual(itemVal, checkVal);
|
|
263
|
+
default:
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
return false;
|
|
267
|
+
};
|
|
268
|
+
const isGreater = (itemVal, condition) => {
|
|
269
|
+
const checkVal = condition.value?.length ? condition.value[0] : "";
|
|
270
|
+
if (typeof checkVal === "number") {
|
|
271
|
+
return itemVal > checkVal;
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
const parseVal = parseInt(checkVal, 10);
|
|
275
|
+
return parseVal ? itemVal > parseVal : false;
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
const isGreaterEqual = (itemVal, condition) => {
|
|
279
|
+
const checkVal = condition.value?.length ? condition.value[0] : "";
|
|
280
|
+
if (typeof checkVal === "number") {
|
|
281
|
+
return itemVal >= checkVal;
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
const parseVal = parseInt(checkVal, 10);
|
|
285
|
+
return parseVal ? itemVal >= parseVal : false;
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
const isLess = (itemVal, condition) => {
|
|
289
|
+
const checkVal = condition.value?.length ? condition.value[0] : "";
|
|
290
|
+
if (typeof checkVal === "number") {
|
|
291
|
+
return itemVal < checkVal;
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
const parseVal = parseInt(checkVal, 10);
|
|
295
|
+
return parseVal ? itemVal < parseVal : false;
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
const isLessEqual = (itemVal, condition) => {
|
|
299
|
+
const checkVal = condition.value?.length ? condition.value[0] : "";
|
|
300
|
+
if (typeof checkVal === "number") {
|
|
301
|
+
return itemVal <= checkVal;
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
const parseVal = parseInt(checkVal, 10);
|
|
305
|
+
return parseVal ? itemVal <= parseVal : false;
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
export const filterItemsByConditions = (groups, filter, headers) => {
|
|
309
|
+
if (!headers?.length)
|
|
310
|
+
return groups;
|
|
311
|
+
const validConditions = getValidConditions(filter, headers);
|
|
312
|
+
if (!validConditions?.length) {
|
|
313
|
+
return groups;
|
|
314
|
+
}
|
|
315
|
+
groups.forEach((g) => {
|
|
316
|
+
g.items = g.items?.filter((item) => {
|
|
317
|
+
let match = false;
|
|
318
|
+
for (const condition of validConditions) {
|
|
319
|
+
const header = headers?.find((h) => h.columnId === condition.columnId);
|
|
320
|
+
const valueType = getColumnValueType(header?.type ?? "");
|
|
321
|
+
const itemVal = item.data?.[condition.columnId]?.value;
|
|
322
|
+
const isDate = header?.type === COLUMN_TYPES.DATE;
|
|
323
|
+
switch (condition.op) {
|
|
324
|
+
case OP_TYPES.IS:
|
|
325
|
+
match = isDate
|
|
326
|
+
? isDateInConditionValues(itemVal, condition)
|
|
327
|
+
: isInConditionValues(itemVal, valueType, condition);
|
|
328
|
+
break;
|
|
329
|
+
case OP_TYPES.IS_NOT:
|
|
330
|
+
match = isDate
|
|
331
|
+
? !isDateInConditionValues(itemVal, condition)
|
|
332
|
+
: !isInConditionValues(itemVal, valueType, condition);
|
|
333
|
+
break;
|
|
334
|
+
case OP_TYPES.EMPTY:
|
|
335
|
+
match = isEmpty(itemVal, valueType);
|
|
336
|
+
break;
|
|
337
|
+
case OP_TYPES.NOT_EMPTY:
|
|
338
|
+
match = !isEmpty(itemVal, valueType);
|
|
339
|
+
break;
|
|
340
|
+
case OP_TYPES.CONTAINS:
|
|
341
|
+
match = isContains(itemVal, valueType, condition);
|
|
342
|
+
break;
|
|
343
|
+
case OP_TYPES.NOT_CONTAINS:
|
|
344
|
+
match = !isContains(itemVal, valueType, condition);
|
|
345
|
+
break;
|
|
346
|
+
case OP_TYPES.EQUAL:
|
|
347
|
+
match = isEquals(itemVal, valueType, condition);
|
|
348
|
+
break;
|
|
349
|
+
case OP_TYPES.NOT_EQUAL:
|
|
350
|
+
match = !isEquals(itemVal, valueType, condition);
|
|
351
|
+
break;
|
|
352
|
+
case OP_TYPES.GREATER:
|
|
353
|
+
match =
|
|
354
|
+
typeof itemVal === "number"
|
|
355
|
+
? isGreater(itemVal, condition)
|
|
356
|
+
: false;
|
|
357
|
+
break;
|
|
358
|
+
case OP_TYPES.GREATER_EQUAL:
|
|
359
|
+
match =
|
|
360
|
+
typeof itemVal === "number"
|
|
361
|
+
? isGreaterEqual(itemVal, condition)
|
|
362
|
+
: false;
|
|
363
|
+
break;
|
|
364
|
+
case OP_TYPES.LESS_EQUAL:
|
|
365
|
+
match =
|
|
366
|
+
typeof itemVal === "number"
|
|
367
|
+
? isLessEqual(itemVal, condition)
|
|
368
|
+
: false;
|
|
369
|
+
break;
|
|
370
|
+
case OP_TYPES.LESS:
|
|
371
|
+
match =
|
|
372
|
+
typeof itemVal === "number" ? isLess(itemVal, condition) : false;
|
|
373
|
+
break;
|
|
374
|
+
default:
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
377
|
+
if (!match)
|
|
378
|
+
return false;
|
|
379
|
+
}
|
|
380
|
+
return match;
|
|
381
|
+
});
|
|
382
|
+
});
|
|
383
|
+
return groups;
|
|
384
|
+
};
|
|
385
|
+
export const filterBoardTree = (board, filter) => {
|
|
386
|
+
if (!board.groups?.length || !board.headers?.length)
|
|
387
|
+
return board;
|
|
388
|
+
return {
|
|
389
|
+
...board,
|
|
390
|
+
groups: filterItemsByConditions(board.groups, filter, board.headers),
|
|
391
|
+
};
|
|
392
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
export interface IBaseUser {
|
|
2
|
+
userId: string;
|
|
3
|
+
username: string;
|
|
4
|
+
email: string;
|
|
5
|
+
firstname: string;
|
|
6
|
+
lastname: string;
|
|
7
|
+
}
|
|
8
|
+
export interface ILinkedSource {
|
|
9
|
+
boardId: string;
|
|
10
|
+
boardName?: string;
|
|
11
|
+
columnId: string;
|
|
12
|
+
deleted?: number;
|
|
13
|
+
type: string;
|
|
14
|
+
name: string;
|
|
15
|
+
dropdowns?: {
|
|
16
|
+
key: string;
|
|
17
|
+
value: string;
|
|
18
|
+
}[];
|
|
19
|
+
setting?: IColumnSetting;
|
|
20
|
+
}
|
|
21
|
+
export interface IBaseItem {
|
|
22
|
+
itemId: string;
|
|
23
|
+
groupId?: string;
|
|
24
|
+
boardId?: string;
|
|
25
|
+
parentId?: string;
|
|
26
|
+
data?: Record<string, any>;
|
|
27
|
+
subs?: IBaseItem[];
|
|
28
|
+
index?: number;
|
|
29
|
+
deleted?: boolean;
|
|
30
|
+
}
|
|
31
|
+
export interface IColumnSetting {
|
|
32
|
+
currency?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface IBaseCustomColumn {
|
|
35
|
+
columnId: string;
|
|
36
|
+
type: string;
|
|
37
|
+
name: string;
|
|
38
|
+
description?: string;
|
|
39
|
+
dropdowns?: {
|
|
40
|
+
key: string;
|
|
41
|
+
value: string;
|
|
42
|
+
}[];
|
|
43
|
+
linkedGroup?: string;
|
|
44
|
+
linked?: ILinkedSource;
|
|
45
|
+
index?: number;
|
|
46
|
+
deleted?: boolean;
|
|
47
|
+
}
|
|
48
|
+
export interface IBaseGroup {
|
|
49
|
+
groupId: string;
|
|
50
|
+
name: string;
|
|
51
|
+
description?: string;
|
|
52
|
+
items?: IBaseItem[];
|
|
53
|
+
deleted?: boolean;
|
|
54
|
+
}
|
|
55
|
+
export interface IBaseBoard {
|
|
56
|
+
name: string;
|
|
57
|
+
boardId: string;
|
|
58
|
+
type?: "board";
|
|
59
|
+
folderId?: string;
|
|
60
|
+
policyId?: string;
|
|
61
|
+
shareType?: number;
|
|
62
|
+
terminology?: string;
|
|
63
|
+
activeStatus?: number;
|
|
64
|
+
orgId?: string;
|
|
65
|
+
description?: string;
|
|
66
|
+
workspaceId?: string;
|
|
67
|
+
createdBy?: string;
|
|
68
|
+
updatedBy?: string;
|
|
69
|
+
createdAt?: string;
|
|
70
|
+
updatedAt?: string;
|
|
71
|
+
}
|
|
72
|
+
export interface IPureBoard extends IBaseBoard {
|
|
73
|
+
headers?: IBaseCustomColumn[];
|
|
74
|
+
groups?: IBaseGroup[];
|
|
75
|
+
people?: IBaseUser[];
|
|
76
|
+
}
|
|
77
|
+
export interface IFilterCondition {
|
|
78
|
+
conditionId?: string;
|
|
79
|
+
columnId: string;
|
|
80
|
+
op: string;
|
|
81
|
+
value: string[] | number[];
|
|
82
|
+
blank?: boolean;
|
|
83
|
+
}
|
|
84
|
+
export interface IFilter {
|
|
85
|
+
andOr: "and" | "or";
|
|
86
|
+
criteria?: IFilterCondition[];
|
|
87
|
+
}
|
|
88
|
+
export interface IDynamicView {
|
|
89
|
+
filter?: IFilter;
|
|
90
|
+
viewId?: string;
|
|
91
|
+
displayColumns?: string[];
|
|
92
|
+
editScope: "all" | "own" | "notAllow";
|
|
93
|
+
allowNewItem?: boolean;
|
|
94
|
+
allowComment?: boolean;
|
|
95
|
+
step: "itemsSetting" | "customizeView" | "itemDetail" | "customizeForm" | "shareSetting";
|
|
96
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./validator";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./validator";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import Schema from "async-validator";
|
|
2
|
+
const descriptor = {
|
|
3
|
+
email: {
|
|
4
|
+
type: "email",
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
validator: Schema.validators.email,
|
|
7
|
+
},
|
|
8
|
+
url: {
|
|
9
|
+
type: "url",
|
|
10
|
+
// @ts-ignore
|
|
11
|
+
validator: Schema.validators.url,
|
|
12
|
+
},
|
|
13
|
+
phone: {
|
|
14
|
+
type: "string", //+1 (408) 888-8888
|
|
15
|
+
pattern: /^(\+?1)?\(?[2-9]\d{2}\)?\s?\d{3}-?\d{4}$/,
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
const validator = new Schema(descriptor);
|
|
19
|
+
export const isValidEmail = async (email) => {
|
|
20
|
+
await validator.validate({ email }).catch(err => {
|
|
21
|
+
throw err;
|
|
22
|
+
});
|
|
23
|
+
return true;
|
|
24
|
+
};
|
|
25
|
+
export const isValidUrl = async (url) => {
|
|
26
|
+
await validator.validate({ url }).catch(err => {
|
|
27
|
+
throw err;
|
|
28
|
+
});
|
|
29
|
+
return true;
|
|
30
|
+
};
|
|
31
|
+
export const isValidPhone = async (phone) => {
|
|
32
|
+
await validator.validate({ phone }).catch(err => {
|
|
33
|
+
throw err;
|
|
34
|
+
});
|
|
35
|
+
return true;
|
|
36
|
+
};
|
package/package.json
CHANGED
|
@@ -1,26 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@followupus/common",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "followup common utils npm package with TypeScript and VSCode",
|
|
5
|
+
"main": "./dist/index.js",
|
|
5
6
|
"module": "./dist/index.js",
|
|
6
7
|
"types": "./dist/index.d.ts",
|
|
7
8
|
"files": [
|
|
8
9
|
"dist"
|
|
9
10
|
],
|
|
10
11
|
"type": "module",
|
|
11
|
-
"scripts": {
|
|
12
|
-
"dev": "tsc --watch",
|
|
13
|
-
"build": "tsc --project tsconfig.build.json",
|
|
14
|
-
"clean": "rm -rf ./dist",
|
|
15
|
-
"lint:staged": "lint-staged",
|
|
16
|
-
"format": "prettier --write \"**/*.{ts,tsx}\"",
|
|
17
|
-
"changeset": "changeset",
|
|
18
|
-
"version": "changeset version",
|
|
19
|
-
"release": "pnpm build && changeset publish --access public --registry=https://registry.npmjs.com/",
|
|
20
|
-
"lint": "eslint ./src/ --fix",
|
|
21
|
-
"test": "tsc && node --test build/test/**/*.spec.js",
|
|
22
|
-
"typecheck": "tsc --noEmit"
|
|
23
|
-
},
|
|
24
12
|
"repository": {
|
|
25
13
|
"type": "git",
|
|
26
14
|
"url": "git+https://github.com/followup/common.git"
|
|
@@ -51,6 +39,7 @@
|
|
|
51
39
|
"@changesets/cli": "^2.27.1",
|
|
52
40
|
"@commitlint/cli": "^19.1.0",
|
|
53
41
|
"@commitlint/config-conventional": "^19.1.0",
|
|
42
|
+
"@types/lodash": "^4.17.0",
|
|
54
43
|
"@types/node": "^20.11.26",
|
|
55
44
|
"@typescript-eslint/eslint-plugin": "^7.2.0",
|
|
56
45
|
"@typescript-eslint/parser": "^7.2.0",
|
|
@@ -74,5 +63,23 @@
|
|
|
74
63
|
"simple-git-hooks": {
|
|
75
64
|
"pre-commit": "pnpm lint-staged",
|
|
76
65
|
"commit-msg": "pnpm commitlint -e \"$@\""
|
|
66
|
+
},
|
|
67
|
+
"dependencies": {
|
|
68
|
+
"async-validator": "^4.2.5",
|
|
69
|
+
"dayjs": "^1.11.10",
|
|
70
|
+
"lodash": "^4.17.21"
|
|
71
|
+
},
|
|
72
|
+
"scripts": {
|
|
73
|
+
"dev": "tsc --watch",
|
|
74
|
+
"build": "tsc --project tsconfig.build.json",
|
|
75
|
+
"clean": "rm -rf ./dist",
|
|
76
|
+
"lint:staged": "lint-staged",
|
|
77
|
+
"format": "prettier --write \"**/*.{ts,tsx}\"",
|
|
78
|
+
"changeset": "changeset",
|
|
79
|
+
"version": "changeset version",
|
|
80
|
+
"release": "pnpm build && changeset publish --access public --registry=https://registry.npmjs.com/",
|
|
81
|
+
"lint": "eslint ./src/ --fix",
|
|
82
|
+
"test": "tsc && node --test build/test/**/*.spec.js",
|
|
83
|
+
"typecheck": "tsc --noEmit"
|
|
77
84
|
}
|
|
78
|
-
}
|
|
85
|
+
}
|