@ai-table/grid 0.0.3 → 0.0.4
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/components/cell-editors/select/select-editor.component.d.ts +15 -0
- package/components/cell-editors/select/select-editor.component.d.ts.map +1 -0
- package/components/field-menu/field-menu.component.d.ts +6 -6
- package/components/field-menu/field-menu.component.d.ts.map +1 -1
- package/components/field-property-editor/field-property-editor.component.d.ts +2 -1
- package/components/field-property-editor/field-property-editor.component.d.ts.map +1 -1
- package/constants/editor.d.ts +1 -1
- package/constants/editor.d.ts.map +1 -1
- package/constants/field.d.ts +10 -4
- package/constants/field.d.ts.map +1 -1
- package/core/action/field.d.ts +6 -0
- package/core/action/field.d.ts.map +1 -1
- package/core/action/general.d.ts.map +1 -1
- package/core/action/index.d.ts +5 -0
- package/core/action/index.d.ts.map +1 -1
- package/core/action/record.d.ts +4 -0
- package/core/action/record.d.ts.map +1 -1
- package/core/constants/field.d.ts +2 -0
- package/core/constants/field.d.ts.map +1 -1
- package/core/types/action.d.ts +31 -2
- package/core/types/action.d.ts.map +1 -1
- package/core/types/core.d.ts +31 -10
- package/core/types/core.d.ts.map +1 -1
- package/core/utils/common.d.ts +2 -1
- package/core/utils/common.d.ts.map +1 -1
- package/core/utils/queries.d.ts +3 -1
- package/core/utils/queries.d.ts.map +1 -1
- package/esm2022/components/cell-editors/select/select-editor.component.mjs +46 -0
- package/esm2022/components/field-menu/field-menu.component.mjs +6 -5
- package/esm2022/components/field-property-editor/field-property-editor.component.mjs +8 -5
- package/esm2022/constants/editor.mjs +8 -8
- package/esm2022/constants/field.mjs +15 -3
- package/esm2022/constants/grid.mjs +5 -5
- package/esm2022/core/action/field.mjs +43 -2
- package/esm2022/core/action/general.mjs +68 -14
- package/esm2022/core/action/record.mjs +22 -5
- package/esm2022/core/constants/field.mjs +19 -13
- package/esm2022/core/types/action.mjs +6 -1
- package/esm2022/core/types/core.mjs +11 -14
- package/esm2022/core/types/index.mjs +1 -1
- package/esm2022/core/utils/common.mjs +10 -1
- package/esm2022/core/utils/field.mjs +3 -3
- package/esm2022/core/utils/queries.mjs +36 -6
- package/esm2022/core/utils/record.mjs +3 -3
- package/esm2022/grid.component.mjs +40 -11
- package/esm2022/pipes/grid.mjs +1 -2
- package/esm2022/services/event.service.mjs +10 -3
- package/esm2022/services/selection.servive.mjs +64 -0
- package/esm2022/types/field.mjs +1 -1
- package/esm2022/types/grid.mjs +1 -1
- package/esm2022/utils/build.mjs +13 -5
- package/fesm2022/ai-table-grid.mjs +454 -182
- package/fesm2022/ai-table-grid.mjs.map +1 -1
- package/grid.component.d.ts +13 -6
- package/grid.component.d.ts.map +1 -1
- package/package.json +1 -1
- package/pipes/grid.d.ts.map +1 -1
- package/services/event.service.d.ts +2 -0
- package/services/event.service.d.ts.map +1 -1
- package/services/selection.servive.d.ts +16 -0
- package/services/selection.servive.d.ts.map +1 -0
- package/styles/styles.scss +70 -3
- package/types/field.d.ts +3 -3
- package/types/field.d.ts.map +1 -1
- package/types/grid.d.ts +7 -2
- package/types/grid.d.ts.map +1 -1
- package/utils/build.d.ts +2 -2
- package/utils/build.d.ts.map +1 -1
- package/components/cell-editors/single-select/single-select-editor.component.d.ts +0 -14
- package/components/cell-editors/single-select/single-select-editor.component.d.ts.map +0 -1
- package/esm2022/components/cell-editors/single-select/single-select-editor.component.mjs +0 -44
@@ -1,14 +1,15 @@
|
|
1
1
|
import * as i0 from '@angular/core';
|
2
|
-
import { Pipe, computed, model, inject, booleanAttribute, Component, ChangeDetectionStrategy, Input, Injectable, input,
|
3
|
-
import
|
2
|
+
import { Pipe, signal, computed, model, inject, booleanAttribute, Component, ChangeDetectionStrategy, Input, Injectable, input, output } from '@angular/core';
|
3
|
+
import * as i4 from '@angular/common';
|
4
|
+
import { NgIf, NgTemplateOutlet, NgForOf, NgClass, CommonModule, NgComponentOutlet } from '@angular/common';
|
4
5
|
import { ThyTag } from 'ngx-tethys/tag';
|
5
6
|
import * as i1$1 from 'ngx-tethys/popover';
|
6
7
|
import { ThyPopoverRef, ThyPopoverModule } from 'ngx-tethys/popover';
|
7
8
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
8
|
-
import { createDraft, finishDraft } from 'immer';
|
9
9
|
import { helpers, isUndefinedOrNull } from 'ngx-tethys/util';
|
10
|
+
import { createDraft, finishDraft } from 'immer';
|
10
11
|
import { ThyIcon } from 'ngx-tethys/icon';
|
11
|
-
import { of, fromEvent } from 'rxjs';
|
12
|
+
import { of, Subject, fromEvent } from 'rxjs';
|
12
13
|
import * as i1 from '@angular/forms';
|
13
14
|
import { FormsModule } from '@angular/forms';
|
14
15
|
import { ThyInputGroup, ThyInputCount, ThyInputDirective, ThyInput } from 'ngx-tethys/input';
|
@@ -17,18 +18,19 @@ import { ThyUniqueCheckValidator, ThyFormModule, ThyConfirmValidatorDirective }
|
|
17
18
|
import { ThyDropdownDirective, ThyDropdownMenuComponent, ThyDropdownMenuItemDirective, ThyDropdownMenuItemNameDirective, ThyDropdownMenuItemIconDirective } from 'ngx-tethys/dropdown';
|
18
19
|
import { ThyButton } from 'ngx-tethys/button';
|
19
20
|
import { ThyListItem } from 'ngx-tethys/list';
|
20
|
-
import {
|
21
|
-
import { ThyOption, ThyAutofocusDirective, ThyEnterDirective, ThyStopPropagationDirective } from 'ngx-tethys/shared';
|
21
|
+
import { ThyAutofocusDirective, ThyEnterDirective, ThyOption, ThyStopPropagationDirective } from 'ngx-tethys/shared';
|
22
22
|
import { ThyInputNumber } from 'ngx-tethys/input-number';
|
23
23
|
import { ThyDatePicker, ThyDatePickerFormatPipe } from 'ngx-tethys/date-picker';
|
24
24
|
import { ThyTimePickerModule } from 'ngx-tethys/time-picker';
|
25
25
|
import { ThyRate } from 'ngx-tethys/rate';
|
26
26
|
import { ThyTooltipModule, ThyTooltipService } from 'ngx-tethys/tooltip';
|
27
|
+
import { ThySelect } from 'ngx-tethys/select';
|
27
28
|
import { ThyFlexibleText } from 'ngx-tethys/flexible-text';
|
29
|
+
import * as i6 from 'ngx-tethys/checkbox';
|
30
|
+
import { ThyCheckboxModule } from 'ngx-tethys/checkbox';
|
28
31
|
import { ThyDivider } from 'ngx-tethys/divider';
|
29
32
|
import { ThyAction } from 'ngx-tethys/action';
|
30
33
|
|
31
|
-
;
|
32
34
|
class SelectOptionPipe {
|
33
35
|
transform(id, options) {
|
34
36
|
return options.find((item) => item.id === id);
|
@@ -44,36 +46,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.2", ngImpor
|
|
44
46
|
}]
|
45
47
|
}] });
|
46
48
|
|
47
|
-
;
|
48
|
-
const buildGridData = (recordValue, fieldsValue) => {
|
49
|
-
return {
|
50
|
-
type: 'grid',
|
51
|
-
fields: fieldsValue,
|
52
|
-
records: recordValue
|
53
|
-
};
|
54
|
-
};
|
55
|
-
|
56
|
-
function getRecordOrField(value, id) {
|
57
|
-
return computed(() => {
|
58
|
-
return value().find((item) => item.id === id);
|
59
|
-
});
|
60
|
-
}
|
61
|
-
|
62
49
|
var AITableFieldType;
|
63
50
|
(function (AITableFieldType) {
|
64
|
-
|
65
|
-
AITableFieldType[
|
66
|
-
AITableFieldType[
|
67
|
-
AITableFieldType[
|
68
|
-
|
69
|
-
AITableFieldType[
|
70
|
-
//
|
71
|
-
AITableFieldType[
|
72
|
-
|
73
|
-
|
74
|
-
// Checkbox = 11,
|
75
|
-
AITableFieldType[AITableFieldType["Rating"] = 12] = "Rating";
|
76
|
-
// Member = 13
|
51
|
+
AITableFieldType["text"] = "text";
|
52
|
+
AITableFieldType["richText"] = "rich_text";
|
53
|
+
AITableFieldType["select"] = "select";
|
54
|
+
AITableFieldType["number"] = "number";
|
55
|
+
AITableFieldType["date"] = "date";
|
56
|
+
AITableFieldType["member"] = "member";
|
57
|
+
// cascadeSelect = "cascade_select", // 包含单选和多选,参数复杂后续再进行设计
|
58
|
+
AITableFieldType["progress"] = "progress";
|
59
|
+
AITableFieldType["rate"] = "rate";
|
60
|
+
AITableFieldType["link"] = "link";
|
77
61
|
})(AITableFieldType || (AITableFieldType = {}));
|
78
62
|
var AITableStatType;
|
79
63
|
(function (AITableStatType) {
|
@@ -102,6 +86,11 @@ var ActionName;
|
|
102
86
|
ActionName["UpdateFieldValue"] = "update_field_value";
|
103
87
|
ActionName["AddRecord"] = "add_record";
|
104
88
|
ActionName["AddField"] = "add_field";
|
89
|
+
ActionName["MoveField"] = "move_field";
|
90
|
+
ActionName["MoveRecord"] = "move_record";
|
91
|
+
ActionName["RemoveField"] = "remove_field";
|
92
|
+
ActionName["RemoveRecord"] = "remove_record";
|
93
|
+
ActionName["SetField"] = "set_field";
|
105
94
|
})(ActionName || (ActionName = {}));
|
106
95
|
var ExecuteType;
|
107
96
|
(function (ExecuteType) {
|
@@ -110,65 +99,6 @@ var ExecuteType;
|
|
110
99
|
ExecuteType[ExecuteType["Redo"] = 2] = "Redo";
|
111
100
|
})(ExecuteType || (ExecuteType = {}));
|
112
101
|
|
113
|
-
function addField(aiTable, field, path) {
|
114
|
-
const operation = {
|
115
|
-
type: ActionName.AddField,
|
116
|
-
field,
|
117
|
-
path
|
118
|
-
};
|
119
|
-
aiTable.apply(operation);
|
120
|
-
}
|
121
|
-
const FieldActions = {
|
122
|
-
addField
|
123
|
-
};
|
124
|
-
|
125
|
-
const apply = (aiTable, records, fields, options) => {
|
126
|
-
switch (options.type) {
|
127
|
-
case ActionName.UpdateFieldValue: {
|
128
|
-
const [recordIndex, fieldIndex] = options.path;
|
129
|
-
const fieldId = aiTable.fields()[fieldIndex].id;
|
130
|
-
records[recordIndex].value[fieldId] = options.newFieldValue;
|
131
|
-
break;
|
132
|
-
}
|
133
|
-
case ActionName.AddRecord: {
|
134
|
-
const [recordIndex] = options.path;
|
135
|
-
records.splice(recordIndex, 0, options.record);
|
136
|
-
break;
|
137
|
-
}
|
138
|
-
case ActionName.AddField: {
|
139
|
-
const [fieldIndex] = options.path;
|
140
|
-
const newField = options.field;
|
141
|
-
fields.splice(fieldIndex, 0, newField);
|
142
|
-
const newRecord = {
|
143
|
-
[newField.id]: ''
|
144
|
-
};
|
145
|
-
records.forEach((item) => {
|
146
|
-
item.value = {
|
147
|
-
...item.value,
|
148
|
-
...newRecord
|
149
|
-
};
|
150
|
-
});
|
151
|
-
}
|
152
|
-
}
|
153
|
-
return {
|
154
|
-
records,
|
155
|
-
fields
|
156
|
-
};
|
157
|
-
};
|
158
|
-
const GeneralActions = {
|
159
|
-
transform(aiTable, op) {
|
160
|
-
const records = createDraft(aiTable.records());
|
161
|
-
const fields = createDraft(aiTable.fields());
|
162
|
-
apply(aiTable, records, fields, op);
|
163
|
-
aiTable.fields.update(() => {
|
164
|
-
return finishDraft(fields);
|
165
|
-
});
|
166
|
-
aiTable.records.update(() => {
|
167
|
-
return finishDraft(records);
|
168
|
-
});
|
169
|
-
}
|
170
|
-
};
|
171
|
-
|
172
102
|
function idCreator(length = 5) {
|
173
103
|
// remove numeral
|
174
104
|
const $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz'; /**** Easily confusing characters are removed by default oOLl,9gq,Vv,Uu,I1****/
|
@@ -182,34 +112,40 @@ function idCreator(length = 5) {
|
|
182
112
|
|
183
113
|
const BasicFields = [
|
184
114
|
{
|
185
|
-
type: AITableFieldType.
|
115
|
+
type: AITableFieldType.text,
|
186
116
|
name: '文本',
|
187
|
-
icon: 'font'
|
117
|
+
icon: 'font',
|
118
|
+
width: 300
|
188
119
|
},
|
189
120
|
{
|
190
|
-
type: AITableFieldType.
|
121
|
+
type: AITableFieldType.select,
|
191
122
|
name: '单选',
|
192
|
-
icon: 'check-circle'
|
123
|
+
icon: 'check-circle',
|
124
|
+
width: 200
|
193
125
|
},
|
194
126
|
{
|
195
|
-
type: AITableFieldType.
|
127
|
+
type: AITableFieldType.number,
|
196
128
|
name: '数字',
|
197
|
-
icon: 'hashtag'
|
129
|
+
icon: 'hashtag',
|
130
|
+
width: 200
|
198
131
|
},
|
199
132
|
{
|
200
|
-
type: AITableFieldType.
|
133
|
+
type: AITableFieldType.date,
|
201
134
|
name: '日期',
|
202
|
-
icon: 'calendar'
|
135
|
+
icon: 'calendar',
|
136
|
+
width: 200
|
203
137
|
},
|
204
138
|
{
|
205
|
-
type: AITableFieldType.
|
139
|
+
type: AITableFieldType.rate,
|
206
140
|
name: '评分',
|
207
|
-
icon: 'star-circle'
|
141
|
+
icon: 'star-circle',
|
142
|
+
width: 200
|
208
143
|
},
|
209
144
|
{
|
210
|
-
type: AITableFieldType.
|
145
|
+
type: AITableFieldType.link,
|
211
146
|
name: '链接',
|
212
|
-
icon: 'link-insert'
|
147
|
+
icon: 'link-insert',
|
148
|
+
width: 300
|
213
149
|
}
|
214
150
|
];
|
215
151
|
const Fields = [...BasicFields];
|
@@ -218,12 +154,12 @@ const FieldsMap = helpers.keyBy([...BasicFields], 'type');
|
|
218
154
|
function getDefaultFieldValue(type) {
|
219
155
|
return '';
|
220
156
|
}
|
221
|
-
function createDefaultFieldName(aiTable, type = AITableFieldType.
|
157
|
+
function createDefaultFieldName(aiTable, type = AITableFieldType.text) {
|
222
158
|
const fields = aiTable.fields();
|
223
159
|
const count = fields.filter((item) => item.type === type).length;
|
224
160
|
return count === 0 ? FieldsMap[type].name : FieldsMap[type].name + count;
|
225
161
|
}
|
226
|
-
function createDefaultField(aiTable, type = AITableFieldType.
|
162
|
+
function createDefaultField(aiTable, type = AITableFieldType.text) {
|
227
163
|
return { id: idCreator(), type, name: createDefaultFieldName(aiTable, type) };
|
228
164
|
}
|
229
165
|
|
@@ -234,6 +170,11 @@ function createAITable(records, fields) {
|
|
234
170
|
records,
|
235
171
|
fields,
|
236
172
|
actions: [],
|
173
|
+
selection: signal({
|
174
|
+
selectedRecords: new Map(),
|
175
|
+
selectedFields: new Map(),
|
176
|
+
selectedCells: new Map()
|
177
|
+
}),
|
237
178
|
onChange: () => { },
|
238
179
|
apply: (action) => {
|
239
180
|
aiTable.actions.push(action);
|
@@ -250,14 +191,17 @@ function createAITable(records, fields) {
|
|
250
191
|
};
|
251
192
|
return aiTable;
|
252
193
|
}
|
194
|
+
function isPathEqual(path, another) {
|
195
|
+
return path.length === another.length && path.every((n, i) => n === another[i]);
|
196
|
+
}
|
253
197
|
|
254
198
|
function getDefaultRecord(fields) {
|
255
199
|
const newRow = {
|
256
200
|
id: idCreator(),
|
257
|
-
|
201
|
+
values: {}
|
258
202
|
};
|
259
203
|
fields.map((item) => {
|
260
|
-
newRow.
|
204
|
+
newRow.values[item.id] = getDefaultFieldValue(item.type);
|
261
205
|
});
|
262
206
|
return newRow;
|
263
207
|
}
|
@@ -275,23 +219,205 @@ const AITableQueries = {
|
|
275
219
|
if (!isUndefinedOrNull(fieldIndex) && fieldIndex > -1) {
|
276
220
|
return [fieldIndex];
|
277
221
|
}
|
278
|
-
throw new Error(`
|
222
|
+
throw new Error(`can not find the path: ${JSON.stringify({ ...(field || {}), ...(record || {}) })}`);
|
279
223
|
},
|
280
224
|
getFieldValue(aiTable, path) {
|
281
|
-
if (!aiTable
|
282
|
-
throw new Error(`
|
225
|
+
if (!aiTable) {
|
226
|
+
throw new Error(`aiTable does not exist`);
|
227
|
+
}
|
228
|
+
if (!aiTable.records()) {
|
229
|
+
throw new Error(`aiTable has no records`);
|
230
|
+
}
|
231
|
+
if (!aiTable.fields()) {
|
232
|
+
throw new Error(`aiTable has no fields`);
|
233
|
+
}
|
234
|
+
if (!path) {
|
235
|
+
throw new Error(`path does not exist as path [${path}]`);
|
236
|
+
}
|
237
|
+
const field = aiTable.fields()[path[1]];
|
238
|
+
if (!field) {
|
239
|
+
throw new Error(`can not find field at path [${path}]`);
|
240
|
+
}
|
241
|
+
return aiTable.records()[path[0]].values[field.id];
|
242
|
+
},
|
243
|
+
getField(aiTable, path) {
|
244
|
+
if (!aiTable) {
|
245
|
+
throw new Error(`aiTable does not exist`);
|
246
|
+
}
|
247
|
+
if (!path) {
|
248
|
+
throw new Error(`path does not exist as path [${path}]`);
|
283
249
|
}
|
284
|
-
|
285
|
-
|
250
|
+
return aiTable.fields()[path[0]];
|
251
|
+
},
|
252
|
+
getRecord(aiTable, path) {
|
253
|
+
if (!aiTable) {
|
254
|
+
throw new Error(`aiTable does not exist`);
|
255
|
+
}
|
256
|
+
if (!path) {
|
257
|
+
throw new Error(`path does not exist as path [${path}]`);
|
258
|
+
}
|
259
|
+
return aiTable.records()[path[0]];
|
260
|
+
}
|
261
|
+
};
|
262
|
+
|
263
|
+
function addField(aiTable, field, path) {
|
264
|
+
const operation = {
|
265
|
+
type: ActionName.AddField,
|
266
|
+
field,
|
267
|
+
path
|
268
|
+
};
|
269
|
+
aiTable.apply(operation);
|
270
|
+
}
|
271
|
+
function moveField(aiTable, path, newPath) {
|
272
|
+
const operation = {
|
273
|
+
type: ActionName.MoveField,
|
274
|
+
path,
|
275
|
+
newPath
|
276
|
+
};
|
277
|
+
aiTable.apply(operation);
|
278
|
+
}
|
279
|
+
function removeField(aiTable, path) {
|
280
|
+
const operation = {
|
281
|
+
type: ActionName.RemoveField,
|
282
|
+
path
|
283
|
+
};
|
284
|
+
aiTable.apply(operation);
|
285
|
+
}
|
286
|
+
function setField(aiTable, value, path) {
|
287
|
+
const field = AITableQueries.getField(aiTable, path);
|
288
|
+
if (field) {
|
289
|
+
const oldField = {};
|
290
|
+
const newField = {};
|
291
|
+
for (const k in value) {
|
292
|
+
if (field[k] !== value[k]) {
|
293
|
+
if (field.hasOwnProperty(k)) {
|
294
|
+
oldField[k] = field[k];
|
295
|
+
}
|
296
|
+
newField[k] = value[k];
|
297
|
+
}
|
298
|
+
}
|
299
|
+
const operation = {
|
300
|
+
type: ActionName.SetField,
|
301
|
+
field: oldField,
|
302
|
+
newField,
|
303
|
+
path
|
304
|
+
};
|
305
|
+
aiTable.apply(operation);
|
306
|
+
}
|
307
|
+
}
|
308
|
+
const FieldActions = {
|
309
|
+
addField,
|
310
|
+
moveField,
|
311
|
+
removeField,
|
312
|
+
setField
|
313
|
+
};
|
314
|
+
|
315
|
+
const apply = (aiTable, records, fields, options) => {
|
316
|
+
switch (options.type) {
|
317
|
+
case ActionName.UpdateFieldValue: {
|
318
|
+
const [recordIndex, fieldIndex] = options.path;
|
319
|
+
if (fieldIndex > -1 && recordIndex > -1) {
|
320
|
+
const fieldId = aiTable.fields()[fieldIndex].id;
|
321
|
+
records[recordIndex].values[fieldId] = options.newFieldValue;
|
322
|
+
}
|
323
|
+
break;
|
324
|
+
}
|
325
|
+
case ActionName.AddRecord: {
|
326
|
+
const [recordIndex] = options.path;
|
327
|
+
if (recordIndex > -1) {
|
328
|
+
records.splice(recordIndex, 0, options.record);
|
329
|
+
}
|
330
|
+
break;
|
331
|
+
}
|
332
|
+
case ActionName.AddField: {
|
333
|
+
const [fieldIndex] = options.path;
|
334
|
+
if (fieldIndex > -1) {
|
335
|
+
const newField = options.field;
|
336
|
+
fields.splice(fieldIndex, 0, newField);
|
337
|
+
const newRecord = {
|
338
|
+
[newField.id]: ''
|
339
|
+
};
|
340
|
+
records.forEach((item) => {
|
341
|
+
item.values = {
|
342
|
+
...item.values,
|
343
|
+
...newRecord
|
344
|
+
};
|
345
|
+
});
|
346
|
+
}
|
347
|
+
break;
|
348
|
+
}
|
349
|
+
case ActionName.MoveRecord: {
|
350
|
+
if (isPathEqual(options.path, options.newPath)) {
|
351
|
+
return;
|
352
|
+
}
|
353
|
+
const record = records[options.path[0]];
|
354
|
+
records.splice(options.path[0], 1);
|
355
|
+
records.splice(options.newPath[0], 0, record);
|
356
|
+
break;
|
357
|
+
}
|
358
|
+
case ActionName.MoveField: {
|
359
|
+
if (isPathEqual(options.path, options.newPath)) {
|
360
|
+
return;
|
361
|
+
}
|
362
|
+
const field = fields[options.path[0]];
|
363
|
+
fields.splice(options.path[0], 1);
|
364
|
+
fields.splice(options.newPath[0], 0, field);
|
365
|
+
break;
|
366
|
+
}
|
367
|
+
case ActionName.RemoveField: {
|
368
|
+
const [fieldIndex] = options.path;
|
369
|
+
if (fieldIndex > -1) {
|
370
|
+
const fieldId = aiTable.fields()[fieldIndex].id;
|
371
|
+
fields.splice(fieldIndex, 1);
|
372
|
+
records.forEach((item) => {
|
373
|
+
delete item.values[fieldId];
|
374
|
+
});
|
375
|
+
}
|
376
|
+
break;
|
377
|
+
}
|
378
|
+
case ActionName.RemoveRecord: {
|
379
|
+
const [recordIndex] = options.path;
|
380
|
+
if (recordIndex > -1) {
|
381
|
+
records.splice(recordIndex, 1);
|
382
|
+
}
|
383
|
+
break;
|
384
|
+
}
|
385
|
+
case ActionName.SetField: {
|
386
|
+
const [fieldIndex] = options.path;
|
387
|
+
if (fieldIndex > -1) {
|
388
|
+
fields.splice(fieldIndex, 1, {
|
389
|
+
...fields[fieldIndex],
|
390
|
+
...options.newField
|
391
|
+
});
|
392
|
+
}
|
393
|
+
break;
|
394
|
+
}
|
395
|
+
}
|
396
|
+
return {
|
397
|
+
records,
|
398
|
+
fields
|
399
|
+
};
|
400
|
+
};
|
401
|
+
const GeneralActions = {
|
402
|
+
transform(aiTable, op) {
|
403
|
+
const records = createDraft(aiTable.records());
|
404
|
+
const fields = createDraft(aiTable.fields());
|
405
|
+
apply(aiTable, records, fields, op);
|
406
|
+
aiTable.fields.update(() => {
|
407
|
+
return finishDraft(fields);
|
408
|
+
});
|
409
|
+
aiTable.records.update(() => {
|
410
|
+
return finishDraft(records);
|
411
|
+
});
|
286
412
|
}
|
287
413
|
};
|
288
414
|
|
289
415
|
function updateFieldValue(aiTable, value, path) {
|
290
|
-
const
|
291
|
-
if (
|
416
|
+
const field = AITableQueries.getFieldValue(aiTable, path);
|
417
|
+
if (field !== value) {
|
292
418
|
const operation = {
|
293
419
|
type: ActionName.UpdateFieldValue,
|
294
|
-
fieldValue:
|
420
|
+
fieldValue: field,
|
295
421
|
newFieldValue: value,
|
296
422
|
path
|
297
423
|
};
|
@@ -306,9 +432,26 @@ function addRecord(aiTable, record, path) {
|
|
306
432
|
};
|
307
433
|
aiTable.apply(operation);
|
308
434
|
}
|
435
|
+
function moveRecord(aiTable, path, newPath) {
|
436
|
+
const operation = {
|
437
|
+
type: ActionName.MoveRecord,
|
438
|
+
path,
|
439
|
+
newPath
|
440
|
+
};
|
441
|
+
aiTable.apply(operation);
|
442
|
+
}
|
443
|
+
function removeRecord(aiTable, path) {
|
444
|
+
const operation = {
|
445
|
+
type: ActionName.RemoveRecord,
|
446
|
+
path
|
447
|
+
};
|
448
|
+
aiTable.apply(operation);
|
449
|
+
}
|
309
450
|
const RecordActions = {
|
310
451
|
addRecord,
|
311
|
-
updateFieldValue
|
452
|
+
updateFieldValue,
|
453
|
+
moveRecord,
|
454
|
+
removeRecord
|
312
455
|
};
|
313
456
|
|
314
457
|
const Actions = {
|
@@ -317,13 +460,35 @@ const Actions = {
|
|
317
460
|
...FieldActions
|
318
461
|
};
|
319
462
|
|
463
|
+
const buildGridData = (recordValue, fieldsValue, selection) => {
|
464
|
+
return {
|
465
|
+
type: 'grid',
|
466
|
+
fields: fieldsValue.map(item => {
|
467
|
+
return {
|
468
|
+
...item,
|
469
|
+
icon: item.icon || FieldsMap[item.type].icon,
|
470
|
+
width: item.width || FieldsMap[item.type].width
|
471
|
+
};
|
472
|
+
}),
|
473
|
+
records: recordValue.map((item) => {
|
474
|
+
return { ...item, checked: selection.selectedRecords.has(item.id) };
|
475
|
+
})
|
476
|
+
};
|
477
|
+
};
|
478
|
+
|
479
|
+
function getRecordOrField(value, id) {
|
480
|
+
return computed(() => {
|
481
|
+
return value().find((item) => item.id === id);
|
482
|
+
});
|
483
|
+
}
|
484
|
+
|
320
485
|
const DEFAULT_COLUMN_WIDTH = 200;
|
321
486
|
const MIN_COLUMN_WIDTH = 80;
|
322
487
|
const DBL_CLICK_EDIT_TYPE = [
|
323
|
-
AITableFieldType.
|
324
|
-
AITableFieldType.
|
325
|
-
AITableFieldType.
|
326
|
-
AITableFieldType.
|
488
|
+
AITableFieldType.text,
|
489
|
+
AITableFieldType.number,
|
490
|
+
AITableFieldType.select,
|
491
|
+
AITableFieldType.date
|
327
492
|
];
|
328
493
|
const RowHeight = {
|
329
494
|
Short: 32,
|
@@ -360,7 +525,8 @@ class AITableFieldPropertyEditor {
|
|
360
525
|
}
|
361
526
|
editFieldProperty() {
|
362
527
|
if (this.isUpdate) {
|
363
|
-
|
528
|
+
const path = this.aiTable.fields().findIndex((item) => item.id === this.aiField().id);
|
529
|
+
Actions.setField(this.aiTable, this.aiField(), [path]);
|
364
530
|
}
|
365
531
|
else {
|
366
532
|
Actions.addField(this.aiTable, this.aiField(), [this.aiTable.fields().length]);
|
@@ -371,7 +537,7 @@ class AITableFieldPropertyEditor {
|
|
371
537
|
this.thyPopoverRef.close();
|
372
538
|
}
|
373
539
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.2", ngImport: i0, type: AITableFieldPropertyEditor, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
374
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.2", type: AITableFieldPropertyEditor, isStandalone: true, selector: "ai-table-field-property-editor", inputs: { aiField: { classPropertyName: "aiField", publicName: "aiField", isSignal: true, isRequired: true, transformFunction: null }, aiTable: { classPropertyName: "aiTable", publicName: "aiTable", isSignal: false, isRequired: true, transformFunction: null }, aiExternalTemplate: { classPropertyName: "aiExternalTemplate", publicName: "aiExternalTemplate", isSignal: false, isRequired: false, transformFunction: null }, isUpdate: { classPropertyName: "isUpdate", publicName: "isUpdate", isSignal: false, isRequired: false, transformFunction: booleanAttribute } }, outputs: { aiField: "aiFieldChange" }, host: { classAttribute: "field-property-editor d-block pl-5 pr-5 pb-5 pt-4" }, ngImport: i0, template: "<form thyForm name=\"createPropertyForm\" [thyFormValidatorConfig]=\"validatorConfig\" thyLayout=\"vertical\">\n <thy-form-group thyLabelRequired thyLabelText=\"\u8868\u683C\u5217\u540D\">\n <thy-input-group>\n <input\n thyInput\n thyAutofocus\n name=\"fieldName\"\n [maxlength]=\"fieldMaxLength\"\n [(ngModel)]=\"aiField().name\"\n required\n placeholder=\"\u8F93\u5165\u5217\u540D\u79F0\"\n [thyUniqueCheck]=\"checkUniqueName\"\n />\n <ng-template #suffix>\n <thy-input-count></thy-input-count>\n </ng-template>\n </thy-input-group>\n </thy-form-group>\n <thy-form-group thyLabelText=\"\u5217\u7C7B\u578B\">\n <div class=\"ml-n5 mr-n5\">\n <thy-list-item [thyDropdown]=\"menu\" thyTrigger=\"hover\" thyPlacement=\"right\" class=\"justify-content-between\">\n <span>\n <thy-icon [thyIconName]=\"fieldType().icon\" class=\"text-desc mr-2\"></thy-icon>\n <span>{{ fieldType().name }}</span>\n </span>\n <thy-icon thyIconName=\"angle-right\" class=\"text-desc\"></thy-icon>\n </thy-list-item>\n </div>\n </thy-form-group>\n <ng-container *ngIf=\"aiExternalTemplate; else defaultTemplate\">\n <ng-container *ngTemplateOutlet=\"aiExternalTemplate\"></ng-container>\n </ng-container>\n <ng-template #defaultTemplate>\n <!-- TODO: \u5185\u90E8\u5C5E\u6027\u6E32\u67D3 -->\n </ng-template>\n <thy-form-group-footer thyAlign=\"right\">\n <button thyButton=\"link-secondary\" (click)=\"cancel()\" thySize=\"sm\">\u53D6\u6D88</button>\n <button thyButton=\"primary\" (thyFormSubmit)=\"editFieldProperty()\" thySize=\"sm\">\u786E\u5B9A</button>\n </thy-form-group-footer>\n</form>\n\n<thy-dropdown-menu #menu>\n @for (item of selectableFields; track item.type) {\n <a thyDropdownMenuItem href=\"javascript:;\" (click)=\"selectFieldType(item.type)\">\n <thy-icon [thyIconName]=\"item.icon\"></thy-icon>\n <span thyDropdownMenuItemName>{{ item.name }}</span>\n </a>\n }\n</thy-dropdown-menu>\n", styles: [":host{width:350px}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ThyIcon, selector: "thy-icon, [thy-icon]", inputs: ["thyIconType", "thyTwotoneColor", "thyIconName", "thyIconRotate", "thyIconSet", "thyIconLegging", "thyIconLinearGradient"] }, { kind: "component", type: ThyInputGroup, selector: "thy-input-group", inputs: ["thyAppendText", "thyAppendTextTranslateKey", "thyPrependText", "thyPrependTextTranslateKey", "thySize"] }, { kind: "component", type: ThyInputCount, selector: "thy-input-count", inputs: ["thyInput"] }, { kind: "directive", type: ThyInputDirective, selector: "input[thyInput], select[thyInput], textarea[thyInput]", inputs: ["thySize"], exportAs: ["thyInput"] }, { kind: "directive", type: ThyUniqueCheckValidator, selector: "[thyUniqueCheck]", inputs: ["thyUniqueCheck"] }, { kind: "directive", type: ThyDropdownDirective, selector: "[thyDropdown]", inputs: ["thyDropdownMenu", "thyDropdown", "thyTrigger", "thyShowDelay", "thyHideDelay", "thyActiveClass", "thyPopoverOptions", "thyPlacement", "thyMenuInsideClosable", "thyPanelClass"], outputs: ["thyActiveChange"] }, { kind: "component", type: ThyDropdownMenuComponent, selector: "thy-dropdown-menu", inputs: ["thyWidth", "thyImmediateRender"] }, { kind: "directive", type: ThyDropdownMenuItemDirective, selector: "[thyDropdownMenuItem]", inputs: ["thyType", "thyDisabled"] }, { kind: "directive", type: ThyDropdownMenuItemNameDirective, selector: "[thyDropdownMenuItemName]" }, { kind: "component", type: ThyButton, selector: "thy-button,[thy-button],[thyButton]", inputs: ["thyButton", "thyType", "thyLoading", "thyLoadingText", "thySize", "thyIcon", "thyBlock"] }, { kind: "ngmodule", type: ThyFormModule }, { kind: "directive", type: i2.ThyFormDirective, selector: "[thyForm],[thy-form]", inputs: ["thyLayout", "thyEnterKeyMode", "thyFormValidatorConfig"], exportAs: ["thyForm"] }, { kind: "component", type: i2.ThyFormGroup, selector: "thy-form-group", inputs: ["thyLabelText", "thyLabelTextTranslateKey", "thyLabelRequired", "thyLabelPaddingTopClear", "thyFeedbackIcon", "thyTipsMode", "thyTips", "thyTipsTranslateKey", "thyRowFill"] }, { kind: "directive", type: i2.ThyFormSubmitDirective, selector: "[thyFormSubmit],[thy-form-submit]", outputs: ["thyFormSubmit"] }, { kind: "component", type: i2.ThyFormGroupFooter, selector: "thy-form-group-footer", inputs: ["thyAlign"] }, { kind: "component", type: ThyListItem, selector: "thy-list-item,[thy-list-item]" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
540
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.2", type: AITableFieldPropertyEditor, isStandalone: true, selector: "ai-table-field-property-editor", inputs: { aiField: { classPropertyName: "aiField", publicName: "aiField", isSignal: true, isRequired: true, transformFunction: null }, aiTable: { classPropertyName: "aiTable", publicName: "aiTable", isSignal: false, isRequired: true, transformFunction: null }, aiExternalTemplate: { classPropertyName: "aiExternalTemplate", publicName: "aiExternalTemplate", isSignal: false, isRequired: false, transformFunction: null }, isUpdate: { classPropertyName: "isUpdate", publicName: "isUpdate", isSignal: false, isRequired: false, transformFunction: booleanAttribute } }, outputs: { aiField: "aiFieldChange" }, host: { classAttribute: "field-property-editor d-block pl-5 pr-5 pb-5 pt-4" }, ngImport: i0, template: "<form thyForm name=\"createPropertyForm\" [thyFormValidatorConfig]=\"validatorConfig\" thyLayout=\"vertical\">\n <thy-form-group thyLabelRequired thyLabelText=\"\u8868\u683C\u5217\u540D\">\n <thy-input-group>\n <input\n thyInput\n [thyAutofocus]=\"true\"\n name=\"fieldName\"\n [maxlength]=\"fieldMaxLength\"\n [(ngModel)]=\"aiField().name\"\n required\n placeholder=\"\u8F93\u5165\u5217\u540D\u79F0\"\n [thyUniqueCheck]=\"checkUniqueName\"\n />\n <ng-template #suffix>\n <thy-input-count></thy-input-count>\n </ng-template>\n </thy-input-group>\n </thy-form-group>\n <thy-form-group thyLabelText=\"\u5217\u7C7B\u578B\">\n <div class=\"ml-n5 mr-n5\">\n <thy-list-item [thyDropdown]=\"menu\" thyTrigger=\"hover\" thyPlacement=\"right\" class=\"justify-content-between\">\n <span>\n <thy-icon [thyIconName]=\"fieldType().icon\" class=\"text-desc mr-2\"></thy-icon>\n <span>{{ fieldType().name }}</span>\n </span>\n <thy-icon thyIconName=\"angle-right\" class=\"text-desc\"></thy-icon>\n </thy-list-item>\n </div>\n </thy-form-group>\n <ng-container *ngIf=\"aiExternalTemplate; else defaultTemplate\">\n <ng-container *ngTemplateOutlet=\"aiExternalTemplate\"></ng-container>\n </ng-container>\n <ng-template #defaultTemplate>\n <!-- TODO: \u5185\u90E8\u5C5E\u6027\u6E32\u67D3 -->\n </ng-template>\n <thy-form-group-footer thyAlign=\"right\">\n <button thyButton=\"link-secondary\" (click)=\"cancel()\" thySize=\"sm\">\u53D6\u6D88</button>\n <button thyButton=\"primary\" (thyFormSubmit)=\"editFieldProperty()\" thySize=\"sm\">\u786E\u5B9A</button>\n </thy-form-group-footer>\n</form>\n\n<thy-dropdown-menu #menu>\n @for (item of selectableFields; track item.type) {\n <a thyDropdownMenuItem href=\"javascript:;\" (click)=\"selectFieldType(item.type)\">\n <thy-icon [thyIconName]=\"item.icon\"></thy-icon>\n <span thyDropdownMenuItemName>{{ item.name }}</span>\n </a>\n }\n</thy-dropdown-menu>\n", styles: [":host{width:350px}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ThyIcon, selector: "thy-icon, [thy-icon]", inputs: ["thyIconType", "thyTwotoneColor", "thyIconName", "thyIconRotate", "thyIconSet", "thyIconLegging", "thyIconLinearGradient"] }, { kind: "component", type: ThyInputGroup, selector: "thy-input-group", inputs: ["thyAppendText", "thyAppendTextTranslateKey", "thyPrependText", "thyPrependTextTranslateKey", "thySize"] }, { kind: "component", type: ThyInputCount, selector: "thy-input-count", inputs: ["thyInput"] }, { kind: "directive", type: ThyInputDirective, selector: "input[thyInput], select[thyInput], textarea[thyInput]", inputs: ["thySize"], exportAs: ["thyInput"] }, { kind: "directive", type: ThyUniqueCheckValidator, selector: "[thyUniqueCheck]", inputs: ["thyUniqueCheck"] }, { kind: "directive", type: ThyDropdownDirective, selector: "[thyDropdown]", inputs: ["thyDropdownMenu", "thyDropdown", "thyTrigger", "thyShowDelay", "thyHideDelay", "thyActiveClass", "thyPopoverOptions", "thyPlacement", "thyMenuInsideClosable", "thyPanelClass"], outputs: ["thyActiveChange"] }, { kind: "component", type: ThyDropdownMenuComponent, selector: "thy-dropdown-menu", inputs: ["thyWidth", "thyImmediateRender"] }, { kind: "directive", type: ThyDropdownMenuItemDirective, selector: "[thyDropdownMenuItem]", inputs: ["thyType", "thyDisabled"] }, { kind: "directive", type: ThyDropdownMenuItemNameDirective, selector: "[thyDropdownMenuItemName]" }, { kind: "component", type: ThyButton, selector: "thy-button,[thy-button],[thyButton]", inputs: ["thyButton", "thyType", "thyLoading", "thyLoadingText", "thySize", "thyIcon", "thyBlock"] }, { kind: "ngmodule", type: ThyFormModule }, { kind: "directive", type: i2.ThyFormDirective, selector: "[thyForm],[thy-form]", inputs: ["thyLayout", "thyEnterKeyMode", "thyFormValidatorConfig"], exportAs: ["thyForm"] }, { kind: "component", type: i2.ThyFormGroup, selector: "thy-form-group", inputs: ["thyLabelText", "thyLabelTextTranslateKey", "thyLabelRequired", "thyLabelPaddingTopClear", "thyFeedbackIcon", "thyTipsMode", "thyTips", "thyTipsTranslateKey", "thyRowFill"] }, { kind: "directive", type: i2.ThyFormSubmitDirective, selector: "[thyFormSubmit],[thy-form-submit]", outputs: ["thyFormSubmit"] }, { kind: "component", type: i2.ThyFormGroupFooter, selector: "thy-form-group-footer", inputs: ["thyAlign"] }, { kind: "component", type: ThyListItem, selector: "thy-list-item,[thy-list-item]" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: ThyAutofocusDirective, selector: "input[thyAutofocus],textarea[thyAutofocus]", inputs: ["thyAutofocus", "thyAutoSelect"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
375
541
|
}
|
376
542
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.2", ngImport: i0, type: AITableFieldPropertyEditor, decorators: [{
|
377
543
|
type: Component,
|
@@ -394,10 +560,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.2", ngImpor
|
|
394
560
|
ThyButton,
|
395
561
|
ThyFormModule,
|
396
562
|
ThyListItem,
|
397
|
-
NgTemplateOutlet
|
563
|
+
NgTemplateOutlet,
|
564
|
+
ThyAutofocusDirective
|
398
565
|
], host: {
|
399
566
|
class: 'field-property-editor d-block pl-5 pr-5 pb-5 pt-4'
|
400
|
-
}, template: "<form thyForm name=\"createPropertyForm\" [thyFormValidatorConfig]=\"validatorConfig\" thyLayout=\"vertical\">\n <thy-form-group thyLabelRequired thyLabelText=\"\u8868\u683C\u5217\u540D\">\n <thy-input-group>\n <input\n thyInput\n thyAutofocus\n name=\"fieldName\"\n [maxlength]=\"fieldMaxLength\"\n [(ngModel)]=\"aiField().name\"\n required\n placeholder=\"\u8F93\u5165\u5217\u540D\u79F0\"\n [thyUniqueCheck]=\"checkUniqueName\"\n />\n <ng-template #suffix>\n <thy-input-count></thy-input-count>\n </ng-template>\n </thy-input-group>\n </thy-form-group>\n <thy-form-group thyLabelText=\"\u5217\u7C7B\u578B\">\n <div class=\"ml-n5 mr-n5\">\n <thy-list-item [thyDropdown]=\"menu\" thyTrigger=\"hover\" thyPlacement=\"right\" class=\"justify-content-between\">\n <span>\n <thy-icon [thyIconName]=\"fieldType().icon\" class=\"text-desc mr-2\"></thy-icon>\n <span>{{ fieldType().name }}</span>\n </span>\n <thy-icon thyIconName=\"angle-right\" class=\"text-desc\"></thy-icon>\n </thy-list-item>\n </div>\n </thy-form-group>\n <ng-container *ngIf=\"aiExternalTemplate; else defaultTemplate\">\n <ng-container *ngTemplateOutlet=\"aiExternalTemplate\"></ng-container>\n </ng-container>\n <ng-template #defaultTemplate>\n <!-- TODO: \u5185\u90E8\u5C5E\u6027\u6E32\u67D3 -->\n </ng-template>\n <thy-form-group-footer thyAlign=\"right\">\n <button thyButton=\"link-secondary\" (click)=\"cancel()\" thySize=\"sm\">\u53D6\u6D88</button>\n <button thyButton=\"primary\" (thyFormSubmit)=\"editFieldProperty()\" thySize=\"sm\">\u786E\u5B9A</button>\n </thy-form-group-footer>\n</form>\n\n<thy-dropdown-menu #menu>\n @for (item of selectableFields; track item.type) {\n <a thyDropdownMenuItem href=\"javascript:;\" (click)=\"selectFieldType(item.type)\">\n <thy-icon [thyIconName]=\"item.icon\"></thy-icon>\n <span thyDropdownMenuItemName>{{ item.name }}</span>\n </a>\n }\n</thy-dropdown-menu>\n", styles: [":host{width:350px}\n"] }]
|
567
|
+
}, template: "<form thyForm name=\"createPropertyForm\" [thyFormValidatorConfig]=\"validatorConfig\" thyLayout=\"vertical\">\n <thy-form-group thyLabelRequired thyLabelText=\"\u8868\u683C\u5217\u540D\">\n <thy-input-group>\n <input\n thyInput\n [thyAutofocus]=\"true\"\n name=\"fieldName\"\n [maxlength]=\"fieldMaxLength\"\n [(ngModel)]=\"aiField().name\"\n required\n placeholder=\"\u8F93\u5165\u5217\u540D\u79F0\"\n [thyUniqueCheck]=\"checkUniqueName\"\n />\n <ng-template #suffix>\n <thy-input-count></thy-input-count>\n </ng-template>\n </thy-input-group>\n </thy-form-group>\n <thy-form-group thyLabelText=\"\u5217\u7C7B\u578B\">\n <div class=\"ml-n5 mr-n5\">\n <thy-list-item [thyDropdown]=\"menu\" thyTrigger=\"hover\" thyPlacement=\"right\" class=\"justify-content-between\">\n <span>\n <thy-icon [thyIconName]=\"fieldType().icon\" class=\"text-desc mr-2\"></thy-icon>\n <span>{{ fieldType().name }}</span>\n </span>\n <thy-icon thyIconName=\"angle-right\" class=\"text-desc\"></thy-icon>\n </thy-list-item>\n </div>\n </thy-form-group>\n <ng-container *ngIf=\"aiExternalTemplate; else defaultTemplate\">\n <ng-container *ngTemplateOutlet=\"aiExternalTemplate\"></ng-container>\n </ng-container>\n <ng-template #defaultTemplate>\n <!-- TODO: \u5185\u90E8\u5C5E\u6027\u6E32\u67D3 -->\n </ng-template>\n <thy-form-group-footer thyAlign=\"right\">\n <button thyButton=\"link-secondary\" (click)=\"cancel()\" thySize=\"sm\">\u53D6\u6D88</button>\n <button thyButton=\"primary\" (thyFormSubmit)=\"editFieldProperty()\" thySize=\"sm\">\u786E\u5B9A</button>\n </thy-form-group-footer>\n</form>\n\n<thy-dropdown-menu #menu>\n @for (item of selectableFields; track item.type) {\n <a thyDropdownMenuItem href=\"javascript:;\" (click)=\"selectFieldType(item.type)\">\n <thy-icon [thyIconName]=\"item.icon\"></thy-icon>\n <span thyDropdownMenuItemName>{{ item.name }}</span>\n </a>\n }\n</thy-dropdown-menu>\n", styles: [":host{width:350px}\n"] }]
|
401
568
|
}], ctorParameters: () => [], propDecorators: { aiTable: [{
|
402
569
|
type: Input,
|
403
570
|
args: [{ required: true }]
|
@@ -445,10 +612,20 @@ const EditFieldPropertyItem = {
|
|
445
612
|
icon: 'edit',
|
446
613
|
exec: (aiTable, field, origin) => {
|
447
614
|
const fieldService = AI_TABLE_GRID_FIELD_SERVICE_MAP.get(aiTable);
|
448
|
-
|
615
|
+
const copyField = signal(JSON.parse(JSON.stringify(field())));
|
616
|
+
origin && fieldService?.editFieldProperty(origin, aiTable, copyField, true);
|
449
617
|
}
|
450
618
|
};
|
451
|
-
const
|
619
|
+
const RemoveFieldItem = {
|
620
|
+
id: 'removeField',
|
621
|
+
name: '删除列',
|
622
|
+
icon: 'trash',
|
623
|
+
exec: (aiTable, field) => {
|
624
|
+
const path = AITableQueries.findPath(aiTable, field());
|
625
|
+
Actions.removeField(aiTable, path);
|
626
|
+
}
|
627
|
+
};
|
628
|
+
const DefaultFieldMenus = [EditFieldPropertyItem, RemoveFieldItem];
|
452
629
|
|
453
630
|
class AbstractEditCellEditor {
|
454
631
|
constructor() {
|
@@ -485,40 +662,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.2", ngImpor
|
|
485
662
|
args: [{ required: true }]
|
486
663
|
}] } });
|
487
664
|
|
488
|
-
class SingleSelectCellEditorComponent extends AbstractEditCellEditor {
|
489
|
-
constructor() {
|
490
|
-
super();
|
491
|
-
this.selectOptions = computed(() => {
|
492
|
-
return this.field().options;
|
493
|
-
});
|
494
|
-
}
|
495
|
-
updateValue(value) {
|
496
|
-
if (!value) {
|
497
|
-
this.updateFieldValue();
|
498
|
-
this.closePopover();
|
499
|
-
}
|
500
|
-
}
|
501
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.2", ngImport: i0, type: SingleSelectCellEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
502
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.0.2", type: SingleSelectCellEditorComponent, isStandalone: true, selector: "single-select-cell-editor", host: { classAttribute: "d-block h-100" }, usesInheritance: true, ngImport: i0, template: `<thy-select [(ngModel)]="modelValue" [thyAutoExpand]="true" (thyOnExpandStatusChange)="updateValue($event)">
|
503
|
-
<thy-option *ngFor="let option of selectOptions()" [thyValue]="option.id" [thyLabelText]="option.name"> </thy-option>
|
504
|
-
</thy-select> `, isInline: true, dependencies: [{ kind: "directive", type: NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ThySelect, selector: "thy-select,thy-custom-select", inputs: ["thyDropdownWidthMode", "thyShowSearch", "thyPlaceHolder", "thyServerSearch", "thyLoadState", "thyAutoActiveFirstItem", "thyMode", "thySize", "thyEmptyStateText", "thyEmptySearchMessageText", "thyEnableScrollLoad", "thyAllowClear", "thyDisabled", "thySortComparator", "thyFooterTemplate", "thyPlacement", "thyOrigin", "thyFooterClass", "thyAutoExpand", "thyHasBackdrop", "thyMaxTagCount", "thyBorderless", "thyOptions", "thyPreset"], outputs: ["thyOnSearch", "thyOnScrollToBottom", "thyOnExpandStatusChange"], exportAs: ["thySelect"] }, { kind: "component", type: ThyOption, selector: "thy-option", inputs: ["thyValue", "thyRawValue", "thyLabelText", "thyShowOptionCustom", "thySearchKey", "thyDisabled"], outputs: ["selectionChange", "visibleChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
505
|
-
}
|
506
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.2", ngImport: i0, type: SingleSelectCellEditorComponent, decorators: [{
|
507
|
-
type: Component,
|
508
|
-
args: [{
|
509
|
-
selector: 'single-select-cell-editor',
|
510
|
-
template: `<thy-select [(ngModel)]="modelValue" [thyAutoExpand]="true" (thyOnExpandStatusChange)="updateValue($event)">
|
511
|
-
<thy-option *ngFor="let option of selectOptions()" [thyValue]="option.id" [thyLabelText]="option.name"> </thy-option>
|
512
|
-
</thy-select> `,
|
513
|
-
standalone: true,
|
514
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
515
|
-
host: {
|
516
|
-
class: 'd-block h-100'
|
517
|
-
},
|
518
|
-
imports: [NgIf, NgForOf, FormsModule, ThySelect, ThyOption, ThyTag, ThyIcon]
|
519
|
-
}]
|
520
|
-
}], ctorParameters: () => [] });
|
521
|
-
|
522
665
|
class TextCellEditorComponent extends AbstractEditCellEditor {
|
523
666
|
updateValue() {
|
524
667
|
this.updateFieldValue();
|
@@ -698,19 +841,56 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.2", ngImpor
|
|
698
841
|
}]
|
699
842
|
}] });
|
700
843
|
|
844
|
+
class SelectCellEditorComponent extends AbstractEditCellEditor {
|
845
|
+
constructor() {
|
846
|
+
super();
|
847
|
+
this.selectOptions = computed(() => {
|
848
|
+
return this.field().options;
|
849
|
+
});
|
850
|
+
}
|
851
|
+
updateValue(value) {
|
852
|
+
if (!value) {
|
853
|
+
this.updateFieldValue();
|
854
|
+
this.closePopover();
|
855
|
+
}
|
856
|
+
}
|
857
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.2", ngImport: i0, type: SelectCellEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
858
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.0.2", type: SelectCellEditorComponent, isStandalone: true, selector: "single-select-cell-editor", inputs: { isMultiple: "isMultiple" }, host: { classAttribute: "d-block h-100" }, usesInheritance: true, ngImport: i0, template: `<thy-select [(ngModel)]="modelValue" [thyAutoExpand]="true" (thyOnExpandStatusChange)="updateValue($event)">
|
859
|
+
<thy-option *ngFor="let option of selectOptions()" [thyValue]="option.id" [thyLabelText]="option.name"> </thy-option>
|
860
|
+
</thy-select> `, isInline: true, dependencies: [{ kind: "directive", type: NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ThySelect, selector: "thy-select,thy-custom-select", inputs: ["thyDropdownWidthMode", "thyShowSearch", "thyPlaceHolder", "thyServerSearch", "thyLoadState", "thyAutoActiveFirstItem", "thyMode", "thySize", "thyEmptyStateText", "thyEmptySearchMessageText", "thyEnableScrollLoad", "thyAllowClear", "thyDisabled", "thySortComparator", "thyFooterTemplate", "thyPlacement", "thyOrigin", "thyFooterClass", "thyAutoExpand", "thyHasBackdrop", "thyMaxTagCount", "thyBorderless", "thyOptions", "thyPreset"], outputs: ["thyOnSearch", "thyOnScrollToBottom", "thyOnExpandStatusChange"], exportAs: ["thySelect"] }, { kind: "component", type: ThyOption, selector: "thy-option", inputs: ["thyValue", "thyRawValue", "thyLabelText", "thyShowOptionCustom", "thySearchKey", "thyDisabled"], outputs: ["selectionChange", "visibleChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
861
|
+
}
|
862
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.2", ngImport: i0, type: SelectCellEditorComponent, decorators: [{
|
863
|
+
type: Component,
|
864
|
+
args: [{
|
865
|
+
selector: 'single-select-cell-editor',
|
866
|
+
template: `<thy-select [(ngModel)]="modelValue" [thyAutoExpand]="true" (thyOnExpandStatusChange)="updateValue($event)">
|
867
|
+
<thy-option *ngFor="let option of selectOptions()" [thyValue]="option.id" [thyLabelText]="option.name"> </thy-option>
|
868
|
+
</thy-select> `,
|
869
|
+
standalone: true,
|
870
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
871
|
+
host: {
|
872
|
+
class: 'd-block h-100'
|
873
|
+
},
|
874
|
+
imports: [NgIf, NgForOf, FormsModule, ThySelect, ThyOption, ThyTag, ThyIcon]
|
875
|
+
}]
|
876
|
+
}], ctorParameters: () => [], propDecorators: { isMultiple: [{
|
877
|
+
type: Input
|
878
|
+
}] } });
|
879
|
+
|
701
880
|
const GRID_CELL_EDITOR_MAP = {
|
702
|
-
[AITableFieldType.
|
703
|
-
[AITableFieldType.
|
704
|
-
[AITableFieldType.
|
705
|
-
[AITableFieldType.
|
706
|
-
[AITableFieldType.
|
707
|
-
[AITableFieldType.
|
881
|
+
[AITableFieldType.text]: TextCellEditorComponent,
|
882
|
+
[AITableFieldType.select]: SelectCellEditorComponent,
|
883
|
+
[AITableFieldType.number]: NumberCellEditorComponent,
|
884
|
+
[AITableFieldType.date]: DateTimeCellEditorComponent,
|
885
|
+
[AITableFieldType.rate]: RatingCellEditorComponent,
|
886
|
+
[AITableFieldType.link]: LinkCellEditorComponent
|
708
887
|
};
|
709
888
|
|
710
889
|
class AITableGridEventService {
|
711
890
|
constructor(thyPopover) {
|
712
891
|
this.thyPopover = thyPopover;
|
713
892
|
this.takeUntilDestroyed = takeUntilDestroyed();
|
893
|
+
this.mousedownEvent$ = new Subject();
|
714
894
|
}
|
715
895
|
initialize(aiTable, aiFieldRenderers) {
|
716
896
|
this.aiTable = aiTable;
|
@@ -722,11 +902,16 @@ class AITableGridEventService {
|
|
722
902
|
.subscribe((event) => {
|
723
903
|
this.dblClick(event);
|
724
904
|
});
|
905
|
+
fromEvent(element, 'mousedown')
|
906
|
+
.pipe(this.takeUntilDestroyed)
|
907
|
+
.subscribe((event) => {
|
908
|
+
this.mousedownEvent$.next(event);
|
909
|
+
});
|
725
910
|
}
|
726
911
|
dblClick(event) {
|
727
912
|
const cellDom = event.target.closest('.grid-cell');
|
728
913
|
const type = cellDom && cellDom.getAttribute('type');
|
729
|
-
if (type && DBL_CLICK_EDIT_TYPE.includes(
|
914
|
+
if (type && DBL_CLICK_EDIT_TYPE.includes(type)) {
|
730
915
|
this.openEdit(cellDom);
|
731
916
|
}
|
732
917
|
}
|
@@ -755,6 +940,7 @@ class AITableGridEventService {
|
|
755
940
|
height: height + 2 + 'px',
|
756
941
|
placement: 'top',
|
757
942
|
offset: -(height + 4),
|
943
|
+
minWidth: width,
|
758
944
|
initialState: {
|
759
945
|
field: field,
|
760
946
|
record: record,
|
@@ -776,11 +962,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.2", ngImpor
|
|
776
962
|
|
777
963
|
class FieldMenu {
|
778
964
|
execute(menu) {
|
779
|
-
const field =
|
965
|
+
const field = getRecordOrField(this.aiTable.fields, this.fieldId);
|
780
966
|
menu.exec && menu.exec(this.aiTable, field, this.origin);
|
781
967
|
}
|
782
968
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.2", ngImport: i0, type: FieldMenu, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
783
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.2", type: FieldMenu, isStandalone: true, selector: "field-menu", inputs: {
|
969
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.2", type: FieldMenu, isStandalone: true, selector: "field-menu", inputs: { fieldId: "fieldId", aiTable: "aiTable", fieldMenus: "fieldMenus", origin: "origin" }, ngImport: i0, template: "@for (menu of fieldMenus; track index; let index = $index) {\n @if (menu.id === 'divider') {\n <thy-divider [thyStyle]=\"'solid'\"></thy-divider>\n } @else {\n <a thyDropdownMenuItem href=\"javascript:;\" (click)=\"execute(menu)\">\n <thy-icon [thyIconName]=\"menu.icon!\"></thy-icon>\n <span>{{ menu.name! }}</span>\n </a>\n }\n}\n", dependencies: [{ kind: "component", type: ThyIcon, selector: "thy-icon, [thy-icon]", inputs: ["thyIconType", "thyTwotoneColor", "thyIconName", "thyIconRotate", "thyIconSet", "thyIconLegging", "thyIconLinearGradient"] }, { kind: "component", type: ThyDivider, selector: "thy-divider", inputs: ["thyVertical", "thyStyle", "thyColor", "thyText", "thyTextDirection", "thyDeeper"] }, { kind: "directive", type: ThyDropdownMenuItemDirective, selector: "[thyDropdownMenuItem]", inputs: ["thyType", "thyDisabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
784
970
|
}
|
785
971
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.2", ngImport: i0, type: FieldMenu, decorators: [{
|
786
972
|
type: Component,
|
@@ -792,7 +978,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.2", ngImpor
|
|
792
978
|
ThyDropdownMenuItemNameDirective,
|
793
979
|
ThyDropdownMenuItemIconDirective
|
794
980
|
], template: "@for (menu of fieldMenus; track index; let index = $index) {\n @if (menu.id === 'divider') {\n <thy-divider [thyStyle]=\"'solid'\"></thy-divider>\n } @else {\n <a thyDropdownMenuItem href=\"javascript:;\" (click)=\"execute(menu)\">\n <thy-icon [thyIconName]=\"menu.icon!\"></thy-icon>\n <span>{{ menu.name! }}</span>\n </a>\n }\n}\n" }]
|
795
|
-
}], propDecorators: {
|
981
|
+
}], propDecorators: { fieldId: [{
|
796
982
|
type: Input,
|
797
983
|
args: [{ required: true }]
|
798
984
|
}], aiTable: [{
|
@@ -805,31 +991,109 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.2", ngImpor
|
|
805
991
|
type: Input
|
806
992
|
}] } });
|
807
993
|
|
994
|
+
class AITableGridSelectionService {
|
995
|
+
constructor() { }
|
996
|
+
initialize(aiTable) {
|
997
|
+
this.aiTable = aiTable;
|
998
|
+
}
|
999
|
+
clearSelection() {
|
1000
|
+
this.aiTable.selection.set({
|
1001
|
+
selectedRecords: new Map(),
|
1002
|
+
selectedFields: new Map(),
|
1003
|
+
selectedCells: new Map()
|
1004
|
+
});
|
1005
|
+
}
|
1006
|
+
selectCell(recordId, fieldId) {
|
1007
|
+
this.clearSelection();
|
1008
|
+
this.aiTable.selection().selectedCells.set(recordId, { [fieldId]: true });
|
1009
|
+
}
|
1010
|
+
selectField(fieldId) {
|
1011
|
+
this.clearSelection();
|
1012
|
+
this.aiTable.selection().selectedFields.set(fieldId, true);
|
1013
|
+
}
|
1014
|
+
selectRecord(recordId) {
|
1015
|
+
if (this.aiTable.selection().selectedRecords.has(recordId)) {
|
1016
|
+
this.aiTable.selection().selectedRecords.delete(recordId);
|
1017
|
+
}
|
1018
|
+
else {
|
1019
|
+
this.aiTable.selection().selectedRecords.set(recordId, true);
|
1020
|
+
}
|
1021
|
+
this.aiTable.selection.set({
|
1022
|
+
selectedRecords: this.aiTable.selection().selectedRecords,
|
1023
|
+
selectedFields: new Map(),
|
1024
|
+
selectedCells: new Map()
|
1025
|
+
});
|
1026
|
+
}
|
1027
|
+
toggleSelectAll(checked) {
|
1028
|
+
this.clearSelection();
|
1029
|
+
if (checked) {
|
1030
|
+
this.aiTable.records().forEach((item) => {
|
1031
|
+
this.selectRecord(item.id);
|
1032
|
+
});
|
1033
|
+
}
|
1034
|
+
}
|
1035
|
+
updateSelect(event) {
|
1036
|
+
const target = event.target;
|
1037
|
+
const cellDom = target.closest('.grid-cell');
|
1038
|
+
const colDom = target.closest('.grid-field');
|
1039
|
+
if (cellDom) {
|
1040
|
+
const fieldId = cellDom.getAttribute('fieldId');
|
1041
|
+
const recordId = cellDom.getAttribute('recordId');
|
1042
|
+
fieldId && recordId && this.selectCell(recordId, fieldId);
|
1043
|
+
}
|
1044
|
+
if (colDom) {
|
1045
|
+
const fieldId = colDom.getAttribute('fieldId');
|
1046
|
+
fieldId && this.selectField(fieldId);
|
1047
|
+
}
|
1048
|
+
}
|
1049
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.2", ngImport: i0, type: AITableGridSelectionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
1050
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.2", ngImport: i0, type: AITableGridSelectionService }); }
|
1051
|
+
}
|
1052
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.2", ngImport: i0, type: AITableGridSelectionService, decorators: [{
|
1053
|
+
type: Injectable
|
1054
|
+
}], ctorParameters: () => [] });
|
1055
|
+
|
808
1056
|
class AITableGrid {
|
809
|
-
|
1057
|
+
get isSelectedAll() {
|
1058
|
+
return this.aiTable.selection().selectedRecords.size === this.aiRecords().length;
|
1059
|
+
}
|
1060
|
+
constructor(elementRef, aiTableGridEventService, aiTableGridSelectionService, aiTableGridFieldService, ngZone) {
|
810
1061
|
this.elementRef = elementRef;
|
811
1062
|
this.aiTableGridEventService = aiTableGridEventService;
|
1063
|
+
this.aiTableGridSelectionService = aiTableGridSelectionService;
|
812
1064
|
this.aiTableGridFieldService = aiTableGridFieldService;
|
1065
|
+
this.ngZone = ngZone;
|
813
1066
|
this.aiRecords = model.required();
|
814
1067
|
this.aiFields = model.required();
|
815
1068
|
this.aiRowHeight = input();
|
816
1069
|
this.aiFieldConfig = input();
|
817
1070
|
this.aiReadonly = input();
|
1071
|
+
this.aiPlugins = input();
|
818
1072
|
this.AITableFieldType = AITableFieldType;
|
819
1073
|
this.takeUntilDestroyed = takeUntilDestroyed();
|
820
1074
|
this.onChange = output();
|
821
1075
|
this.aiTableInitialized = output();
|
822
1076
|
this.gridData = computed(() => {
|
823
|
-
return buildGridData(this.aiRecords(), this.aiFields());
|
1077
|
+
return buildGridData(this.aiRecords(), this.aiFields(), this.aiTable.selection());
|
824
1078
|
});
|
825
1079
|
}
|
826
1080
|
ngOnInit() {
|
827
1081
|
this.initAITable();
|
828
1082
|
this.initService();
|
829
1083
|
this.buildFieldMenus();
|
1084
|
+
this.ngZone.runOutsideAngular(() => {
|
1085
|
+
this.aiTableGridEventService.mousedownEvent$.pipe(this.takeUntilDestroyed).subscribe((event) => {
|
1086
|
+
if (event?.target) {
|
1087
|
+
this.aiTableGridSelectionService.updateSelect(event);
|
1088
|
+
}
|
1089
|
+
});
|
1090
|
+
});
|
830
1091
|
}
|
831
1092
|
initAITable() {
|
832
1093
|
this.aiTable = createAITable(this.aiRecords, this.aiFields);
|
1094
|
+
this.aiPlugins()?.forEach((plugin) => {
|
1095
|
+
this.aiTable = plugin(this.aiTable);
|
1096
|
+
});
|
833
1097
|
this.aiTableInitialized.emit(this.aiTable);
|
834
1098
|
this.aiTable.onChange = () => {
|
835
1099
|
this.onChange.emit({
|
@@ -841,6 +1105,7 @@ class AITableGrid {
|
|
841
1105
|
}
|
842
1106
|
initService() {
|
843
1107
|
this.aiTableGridEventService.initialize(this.aiTable, this.aiFieldConfig()?.fieldPropertyEditor);
|
1108
|
+
this.aiTableGridSelectionService.initialize(this.aiTable);
|
844
1109
|
this.aiTableGridEventService.registerEvents(this.elementRef.nativeElement);
|
845
1110
|
this.aiTableGridFieldService.initAIFieldConfig(this.aiFieldConfig());
|
846
1111
|
AI_TABLE_GRID_FIELD_SERVICE_MAP.set(this.aiTable, this.aiTableGridFieldService);
|
@@ -851,12 +1116,18 @@ class AITableGrid {
|
|
851
1116
|
addRecord() {
|
852
1117
|
Actions.addRecord(this.aiTable, getDefaultRecord(this.aiFields()), [this.aiRecords().length]);
|
853
1118
|
}
|
1119
|
+
selectRecord(recordId) {
|
1120
|
+
this.aiTableGridSelectionService.selectRecord(recordId);
|
1121
|
+
}
|
1122
|
+
toggleSelectAll(checked) {
|
1123
|
+
this.aiTableGridSelectionService.toggleSelectAll(checked);
|
1124
|
+
}
|
854
1125
|
addField(gridColumnBlank) {
|
855
|
-
const field = signal(createDefaultField(this.aiTable, AITableFieldType.
|
1126
|
+
const field = signal(createDefaultField(this.aiTable, AITableFieldType.text));
|
856
1127
|
this.aiTableGridFieldService.editFieldProperty(gridColumnBlank, this.aiTable, field, false);
|
857
1128
|
}
|
858
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.2", ngImport: i0, type: AITableGrid, deps: [{ token: i0.ElementRef }, { token: AITableGridEventService }, { token: AITableGridFieldService }], target: i0.ɵɵFactoryTarget.Component }); }
|
859
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.2", type: AITableGrid, isStandalone: true, selector: "ai-table-grid", inputs: { aiRecords: { classPropertyName: "aiRecords", publicName: "aiRecords", isSignal: true, isRequired: true, transformFunction: null }, aiFields: { classPropertyName: "aiFields", publicName: "aiFields", isSignal: true, isRequired: true, transformFunction: null }, aiRowHeight: { classPropertyName: "aiRowHeight", publicName: "aiRowHeight", isSignal: true, isRequired: false, transformFunction: null }, aiFieldConfig: { classPropertyName: "aiFieldConfig", publicName: "aiFieldConfig", isSignal: true, isRequired: false, transformFunction: null }, aiReadonly: { classPropertyName: "aiReadonly", publicName: "aiReadonly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { aiRecords: "aiRecordsChange", aiFields: "aiFieldsChange", onChange: "onChange", aiTableInitialized: "aiTableInitialized" }, host: { classAttribute: "ai-table-grid" }, providers: [ThyTooltipService, AITableGridEventService, AITableGridFieldService], ngImport: i0, template: "<div class=\"grid-header d-flex\">\n <div class=\"grid-column-checkbox grid-cell\">\n <
|
1129
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.2", ngImport: i0, type: AITableGrid, deps: [{ token: i0.ElementRef }, { token: AITableGridEventService }, { token: AITableGridSelectionService }, { token: AITableGridFieldService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
|
1130
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.2", type: AITableGrid, isStandalone: true, selector: "ai-table-grid", inputs: { aiRecords: { classPropertyName: "aiRecords", publicName: "aiRecords", isSignal: true, isRequired: true, transformFunction: null }, aiFields: { classPropertyName: "aiFields", publicName: "aiFields", isSignal: true, isRequired: true, transformFunction: null }, aiRowHeight: { classPropertyName: "aiRowHeight", publicName: "aiRowHeight", isSignal: true, isRequired: false, transformFunction: null }, aiFieldConfig: { classPropertyName: "aiFieldConfig", publicName: "aiFieldConfig", isSignal: true, isRequired: false, transformFunction: null }, aiReadonly: { classPropertyName: "aiReadonly", publicName: "aiReadonly", isSignal: true, isRequired: false, transformFunction: null }, aiPlugins: { classPropertyName: "aiPlugins", publicName: "aiPlugins", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { aiRecords: "aiRecordsChange", aiFields: "aiFieldsChange", onChange: "onChange", aiTableInitialized: "aiTableInitialized" }, host: { classAttribute: "ai-table-grid" }, providers: [ThyTooltipService, AITableGridEventService, AITableGridFieldService, AITableGridSelectionService], ngImport: i0, template: "<div class=\"grid-header d-flex\">\n <div class=\"grid-column-checkbox grid-cell\">\n <label thyCheckbox thyLabelText=\"\" [ngModel]=\"isSelectedAll\" (ngModelChange)=\"toggleSelectAll($event)\"></label>\n </div>\n @for (field of gridData().fields; track field.id) {\n <div\n class=\"grid-cell grid-field\"\n #fieldAction\n [attr.fieldId]=\"field.id\"\n [ngClass]=\"{ highlight: aiTable.selection().selectedFields.has(field.id) }\"\n [ngStyle]=\"{ width: field.width + 'px' }\"\n >\n <span class=\"text-truncate\">\n <thy-icon [thyIconName]=\"field.icon!\" class=\"mr-2 text-muted\"></thy-icon>\n <span>{{ field.name }}</span>\n </span>\n <a\n class=\"grid-field-action\"\n thyAction\n thyActiveClass=\"active\"\n thyIcon=\"more-vertical\"\n [thyDropdown]=\"fieldMenu\"\n href=\"javascript:;\"\n >\n <thy-dropdown-menu #fieldMenu>\n <field-menu [origin]=\"fieldAction\" [fieldId]=\"field.id\" [aiTable]=\"aiTable\" [fieldMenus]=\"fieldMenus\"></field-menu>\n </thy-dropdown-menu>\n </a>\n </div>\n }\n <div class=\"grid-column-blank cursor-pointer\" #gridColumnBlank (click)=\"addField(gridColumnBlank)\">\n <thy-icon thyIconName=\"plus\"></thy-icon>\n </div>\n</div>\n<div class=\"grid-body d-flex\">\n @for (record of gridData().records; track record.id; let index = $index) {\n <div class=\"grid-row d-flex\" [ngClass]=\"{ highlight: aiTable.selection().selectedRecords.has(record.id) }\">\n <div class=\"grid-row-index\">\n <label\n [ngClass]=\"record.checked ? 'checked-box' : 'unchecked-box'\"\n thyCheckbox\n thyLabelText=\"\"\n [ngModel]=\"record.checked\"\n (ngModelChange)=\"selectRecord(record.id)\"\n ></label>\n <span [ngClass]=\"record.checked ? 'grid-row-no-number' : 'grid-row-number'\"> {{ index + 1 }} </span>\n </div>\n @for (field of gridData().fields; track $index) {\n <div\n class=\"grid-cell\"\n [ngClass]=\"{\n highlight: aiTable.selection().selectedCells.has(record.id) || aiTable.selection().selectedFields.has(field.id),\n selected: aiTable.selection().selectedCells.get(record.id)?.hasOwnProperty(field.id)\n }\"\n [attr.type]=\"[field.type]\"\n [attr.fieldId]=\"[field.id]\"\n [attr.recordId]=\"[record.id]\"\n [ngStyle]=\"{ width: field.width + 'px' }\"\n #cell\n >\n @switch (field.type) {\n @case (AITableFieldType.select) {\n @if (!field.isMultiple && record.values[field.id] | selectOption: field['options']; as selectedOption) {\n <thy-tag [thyColor]=\"selectedOption!.color!\">{{ selectedOption.name }}</thy-tag>\n }\n }\n @case (AITableFieldType.date) {\n {{ record.values[field.id] | thyDatePickerFormat }}\n }\n @case (AITableFieldType.rate) {\n <thy-rate [(ngModel)]=\"record.values[field.id]\"></thy-rate>\n }\n @case (AITableFieldType.link) {\n <a\n class=\"d-block\"\n thyStopPropagation\n thyFlexibleText\n [thyTooltipContent]=\"record.values[field.id]?.text\"\n [href]=\"record.values[field.id]?.url\"\n target=\"_blank\"\n >{{ record.values[field.id]?.text }}</a\n >\n }\n @default {\n <span class=\"text-truncate\"> {{ record.values[field.id] }}</span>\n }\n }\n <div class=\"autofill-container\"></div>\n </div>\n }\n <div class=\"grid-column-blank\"></div>\n </div>\n }\n <div class=\"grid-row-insert grid-row cursor-pointer\" (click)=\"addRecord()\">\n <thy-icon thyIconName=\"plus\"></thy-icon>\n </div>\n</div>\n\n<div #activeBorder class=\"active-border\"></div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: SelectOptionPipe, name: "selectOption" }, { kind: "component", type: ThyTag, selector: "thy-tag,[thyTag]", inputs: ["thyTag", "thyShape", "thyColor", "thyTheme", "thySize", "thyHoverable"] }, { kind: "ngmodule", type: ThyPopoverModule }, { kind: "component", type: ThyIcon, selector: "thy-icon, [thy-icon]", inputs: ["thyIconType", "thyTwotoneColor", "thyIconName", "thyIconRotate", "thyIconSet", "thyIconLegging", "thyIconLinearGradient"] }, { kind: "component", type: ThyRate, selector: "thy-rate", inputs: ["thyCount", "thyDisabled", "thyAllowHalf", "thyAllowClear", "thyTooltips", "thyIconTemplate"], outputs: ["thyItemHoverChange"] }, { kind: "pipe", type: ThyDatePickerFormatPipe, name: "thyDatePickerFormat" }, { kind: "ngmodule", type: ThyTooltipModule }, { kind: "component", type: ThyFlexibleText, selector: "thy-flexible-text,[thyFlexibleText]", inputs: ["thyTooltipTrigger", "thyContainerClass", "thyTooltipContent", "thyTooltipPlacement", "thyTooltipOffset"], exportAs: ["thyFlexibleText"] }, { kind: "directive", type: ThyStopPropagationDirective, selector: "[thyStopPropagation]", inputs: ["thyStopPropagation"] }, { kind: "component", type: FieldMenu, selector: "field-menu", inputs: ["fieldId", "aiTable", "fieldMenus", "origin"] }, { kind: "component", type: ThyAction, selector: "thy-action, [thyAction]", inputs: ["thyType", "thyIcon", "thyActionIcon", "thyActive", "thyActionActive", "thyTheme", "thyHoverIcon", "thyDisabled"] }, { kind: "directive", type: ThyDropdownDirective, selector: "[thyDropdown]", inputs: ["thyDropdownMenu", "thyDropdown", "thyTrigger", "thyShowDelay", "thyHideDelay", "thyActiveClass", "thyPopoverOptions", "thyPlacement", "thyMenuInsideClosable", "thyPanelClass"], outputs: ["thyActiveChange"] }, { kind: "component", type: ThyDropdownMenuComponent, selector: "thy-dropdown-menu", inputs: ["thyWidth", "thyImmediateRender"] }, { kind: "ngmodule", type: ThyCheckboxModule }, { kind: "component", type: i6.ThyCheckbox, selector: "thy-checkbox,[thy-checkbox],[thyCheckbox]", inputs: ["thyIndeterminate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
860
1131
|
}
|
861
1132
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.2", ngImport: i0, type: AITableGrid, decorators: [{
|
862
1133
|
type: Component,
|
@@ -881,9 +1152,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.2", ngImpor
|
|
881
1152
|
FieldMenu,
|
882
1153
|
ThyAction,
|
883
1154
|
ThyDropdownDirective,
|
884
|
-
ThyDropdownMenuComponent
|
885
|
-
|
886
|
-
}]
|
1155
|
+
ThyDropdownMenuComponent,
|
1156
|
+
ThyCheckboxModule
|
1157
|
+
], providers: [ThyTooltipService, AITableGridEventService, AITableGridFieldService, AITableGridSelectionService], template: "<div class=\"grid-header d-flex\">\n <div class=\"grid-column-checkbox grid-cell\">\n <label thyCheckbox thyLabelText=\"\" [ngModel]=\"isSelectedAll\" (ngModelChange)=\"toggleSelectAll($event)\"></label>\n </div>\n @for (field of gridData().fields; track field.id) {\n <div\n class=\"grid-cell grid-field\"\n #fieldAction\n [attr.fieldId]=\"field.id\"\n [ngClass]=\"{ highlight: aiTable.selection().selectedFields.has(field.id) }\"\n [ngStyle]=\"{ width: field.width + 'px' }\"\n >\n <span class=\"text-truncate\">\n <thy-icon [thyIconName]=\"field.icon!\" class=\"mr-2 text-muted\"></thy-icon>\n <span>{{ field.name }}</span>\n </span>\n <a\n class=\"grid-field-action\"\n thyAction\n thyActiveClass=\"active\"\n thyIcon=\"more-vertical\"\n [thyDropdown]=\"fieldMenu\"\n href=\"javascript:;\"\n >\n <thy-dropdown-menu #fieldMenu>\n <field-menu [origin]=\"fieldAction\" [fieldId]=\"field.id\" [aiTable]=\"aiTable\" [fieldMenus]=\"fieldMenus\"></field-menu>\n </thy-dropdown-menu>\n </a>\n </div>\n }\n <div class=\"grid-column-blank cursor-pointer\" #gridColumnBlank (click)=\"addField(gridColumnBlank)\">\n <thy-icon thyIconName=\"plus\"></thy-icon>\n </div>\n</div>\n<div class=\"grid-body d-flex\">\n @for (record of gridData().records; track record.id; let index = $index) {\n <div class=\"grid-row d-flex\" [ngClass]=\"{ highlight: aiTable.selection().selectedRecords.has(record.id) }\">\n <div class=\"grid-row-index\">\n <label\n [ngClass]=\"record.checked ? 'checked-box' : 'unchecked-box'\"\n thyCheckbox\n thyLabelText=\"\"\n [ngModel]=\"record.checked\"\n (ngModelChange)=\"selectRecord(record.id)\"\n ></label>\n <span [ngClass]=\"record.checked ? 'grid-row-no-number' : 'grid-row-number'\"> {{ index + 1 }} </span>\n </div>\n @for (field of gridData().fields; track $index) {\n <div\n class=\"grid-cell\"\n [ngClass]=\"{\n highlight: aiTable.selection().selectedCells.has(record.id) || aiTable.selection().selectedFields.has(field.id),\n selected: aiTable.selection().selectedCells.get(record.id)?.hasOwnProperty(field.id)\n }\"\n [attr.type]=\"[field.type]\"\n [attr.fieldId]=\"[field.id]\"\n [attr.recordId]=\"[record.id]\"\n [ngStyle]=\"{ width: field.width + 'px' }\"\n #cell\n >\n @switch (field.type) {\n @case (AITableFieldType.select) {\n @if (!field.isMultiple && record.values[field.id] | selectOption: field['options']; as selectedOption) {\n <thy-tag [thyColor]=\"selectedOption!.color!\">{{ selectedOption.name }}</thy-tag>\n }\n }\n @case (AITableFieldType.date) {\n {{ record.values[field.id] | thyDatePickerFormat }}\n }\n @case (AITableFieldType.rate) {\n <thy-rate [(ngModel)]=\"record.values[field.id]\"></thy-rate>\n }\n @case (AITableFieldType.link) {\n <a\n class=\"d-block\"\n thyStopPropagation\n thyFlexibleText\n [thyTooltipContent]=\"record.values[field.id]?.text\"\n [href]=\"record.values[field.id]?.url\"\n target=\"_blank\"\n >{{ record.values[field.id]?.text }}</a\n >\n }\n @default {\n <span class=\"text-truncate\"> {{ record.values[field.id] }}</span>\n }\n }\n <div class=\"autofill-container\"></div>\n </div>\n }\n <div class=\"grid-column-blank\"></div>\n </div>\n }\n <div class=\"grid-row-insert grid-row cursor-pointer\" (click)=\"addRecord()\">\n <thy-icon thyIconName=\"plus\"></thy-icon>\n </div>\n</div>\n\n<div #activeBorder class=\"active-border\"></div>\n" }]
|
1158
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: AITableGridEventService }, { type: AITableGridSelectionService }, { type: AITableGridFieldService }, { type: i0.NgZone }] });
|
887
1159
|
|
888
1160
|
var AITableRowHeight;
|
889
1161
|
(function (AITableRowHeight) {
|
@@ -897,5 +1169,5 @@ var AITableRowHeight;
|
|
897
1169
|
* Generated bundle index. Do not edit.
|
898
1170
|
*/
|
899
1171
|
|
900
|
-
export { AITableFieldPropertyEditor, AITableFieldType, AITableGrid, AITableQueries, AITableRowHeight, AITableStatType, ActionName, Actions, BasicFields, DBL_CLICK_EDIT_TYPE, DEFAULT_COLUMN_WIDTH, DefaultFieldMenus, DividerMenuItem, EditFieldPropertyItem, ExecuteType, FLUSHING, Fields, FieldsMap, MIN_COLUMN_WIDTH, RowHeight, SelectOptionPipe, buildGridData, createAITable, createDefaultField, createDefaultFieldName, getDefaultFieldValue, getDefaultRecord, getRecordOrField, idCreator };
|
1172
|
+
export { AITableFieldPropertyEditor, AITableFieldType, AITableGrid, AITableQueries, AITableRowHeight, AITableStatType, ActionName, Actions, BasicFields, DBL_CLICK_EDIT_TYPE, DEFAULT_COLUMN_WIDTH, DefaultFieldMenus, DividerMenuItem, EditFieldPropertyItem, ExecuteType, FLUSHING, Fields, FieldsMap, MIN_COLUMN_WIDTH, RemoveFieldItem, RowHeight, SelectOptionPipe, buildGridData, createAITable, createDefaultField, createDefaultFieldName, getDefaultFieldValue, getDefaultRecord, getRecordOrField, idCreator, isPathEqual };
|
901
1173
|
//# sourceMappingURL=ai-table-grid.mjs.map
|