flameresttable 1.0.22 → 1.0.24
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/.eslintrc +8 -1
- package/package.json +1 -1
- package/src/App.vue +1 -1
- package/src/Table/Columns.ts +38 -4
- package/src/Table/FlameTable.ts +18 -5
- package/src/Table/Table.vue +124 -9
- package/src/Table/TableFilters.vue +1 -1
- package/src/Table/TableFiltersSelector.vue +47 -0
- package/src/Table/TableOpts.ts +5 -0
- package/src/Table/TableRowParams.ts +1 -0
package/.eslintrc
CHANGED
|
@@ -16,7 +16,14 @@
|
|
|
16
16
|
"vue/no-multiple-template-root": "off",
|
|
17
17
|
"vue/no-duplicate-attributes": "off",
|
|
18
18
|
"linebreak-style": "off",
|
|
19
|
-
"vue/multiline-html-element-content-newline": "off"
|
|
19
|
+
"vue/multiline-html-element-content-newline": "off",
|
|
20
|
+
"vue/attributes-order": "off",
|
|
21
|
+
"vue/html-closing-bracket-newline": "off",
|
|
22
|
+
"vue/html-self-closing": "off",
|
|
23
|
+
"vue/max-attributes-per-line": "off",
|
|
24
|
+
"vue/first-attribute-linebreak": "off",
|
|
25
|
+
"vue/html-indent": "off",
|
|
26
|
+
"vue/no-v-html": "off"
|
|
20
27
|
},
|
|
21
28
|
"plugins": [
|
|
22
29
|
"@typescript-eslint"
|
package/package.json
CHANGED
package/src/App.vue
CHANGED
|
@@ -52,7 +52,7 @@ opts.LoadParams.sort = ['-dt1'];
|
|
|
52
52
|
<template lang="pug">
|
|
53
53
|
Table(:model="Model", :opts="opts")
|
|
54
54
|
template(v-slot:RowSubSlot="params")
|
|
55
|
-
| {{ params.row.name + '
|
|
55
|
+
| {{ params.row.name + ' LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG line' }}
|
|
56
56
|
</template>
|
|
57
57
|
|
|
58
58
|
<style>
|
package/src/Table/Columns.ts
CHANGED
|
@@ -33,6 +33,11 @@ export class Column implements IColumn {
|
|
|
33
33
|
*/
|
|
34
34
|
title: "",
|
|
35
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Выделена ли строка чекбоксом
|
|
38
|
+
*/
|
|
39
|
+
isSelected: false,
|
|
40
|
+
|
|
36
41
|
/**
|
|
37
42
|
* Возможность преобразовать вывод из любой колонки
|
|
38
43
|
* @param row строка
|
|
@@ -57,7 +62,22 @@ export class Column implements IColumn {
|
|
|
57
62
|
* @param column
|
|
58
63
|
* @returns
|
|
59
64
|
*/
|
|
60
|
-
click: (row: any, column: Column) => { }
|
|
65
|
+
click: (row: any, column: Column) => { },
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* CSS-классы колонки в таблице
|
|
69
|
+
*/
|
|
70
|
+
classes: '',
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* CSS-классы заголовка таблице
|
|
74
|
+
*/
|
|
75
|
+
classesHeader: '',
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Ширина таблицы
|
|
79
|
+
*/
|
|
80
|
+
width: null,
|
|
61
81
|
|
|
62
82
|
}
|
|
63
83
|
|
|
@@ -117,7 +137,12 @@ export class Column implements IColumn {
|
|
|
117
137
|
|
|
118
138
|
// Позиция фильтра по порядку
|
|
119
139
|
filterRow: 0,
|
|
120
|
-
filterColumn: 0
|
|
140
|
+
filterColumn: 0,
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* CSS-классы,
|
|
144
|
+
*/
|
|
145
|
+
classes: '',
|
|
121
146
|
|
|
122
147
|
}
|
|
123
148
|
|
|
@@ -251,7 +276,11 @@ export interface IColumn {
|
|
|
251
276
|
title?: string,
|
|
252
277
|
value?: (row: any, column: Column) => string,
|
|
253
278
|
isRawValue?: boolean,
|
|
254
|
-
click?: (row: any, column: Column) => void
|
|
279
|
+
click?: (row: any, column: Column) => void,
|
|
280
|
+
classes?: string,
|
|
281
|
+
classesHeader?: string,
|
|
282
|
+
width?: number | null,
|
|
283
|
+
isSelected?: boolean,
|
|
255
284
|
},
|
|
256
285
|
|
|
257
286
|
/**
|
|
@@ -274,7 +303,12 @@ export interface IColumn {
|
|
|
274
303
|
|
|
275
304
|
// Позиция фильтра по порядку
|
|
276
305
|
filterRow?: number,
|
|
277
|
-
filterColumn?: number
|
|
306
|
+
filterColumn?: number,
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* CSS-классы, применяемые к фильтру,
|
|
310
|
+
*/
|
|
311
|
+
classes?: string,
|
|
278
312
|
|
|
279
313
|
},
|
|
280
314
|
|
package/src/Table/FlameTable.ts
CHANGED
|
@@ -60,6 +60,11 @@ export default class FlameTable<T> {
|
|
|
60
60
|
*/
|
|
61
61
|
public OpenedRow: any = null;
|
|
62
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Выделенные галочками чекбоксы
|
|
65
|
+
*/
|
|
66
|
+
public RowsSelected: Array<T> = [];
|
|
67
|
+
|
|
63
68
|
/**
|
|
64
69
|
* Проинициализировать модели
|
|
65
70
|
*/
|
|
@@ -192,10 +197,10 @@ export default class FlameTable<T> {
|
|
|
192
197
|
case 'number':
|
|
193
198
|
case 'daterange':
|
|
194
199
|
|
|
195
|
-
if (el.valueRange.
|
|
196
|
-
customFilters.where[key] = ['>=', key, el.valueRange
|
|
197
|
-
|
|
198
|
-
|
|
200
|
+
if (el.valueRange.length > 0) {
|
|
201
|
+
customFilters.where[key] = ['>=', key, el.valueRange[0]];
|
|
202
|
+
customFilters.where[key] = ['<=', key, el.valueRange[1]];
|
|
203
|
+
}
|
|
199
204
|
|
|
200
205
|
break;
|
|
201
206
|
|
|
@@ -278,6 +283,14 @@ export default class FlameTable<T> {
|
|
|
278
283
|
return res;
|
|
279
284
|
}
|
|
280
285
|
|
|
281
|
-
|
|
286
|
+
public getSelectedRows() {
|
|
287
|
+
const result: Array<T> = [];
|
|
288
|
+
this.Rows.rows.forEach((r: any) => {
|
|
289
|
+
const param = this.RowsParams[r[(this.model as any).constructor.primaryKeys[0]]]
|
|
290
|
+
if (param.selected)
|
|
291
|
+
result.push(r)
|
|
292
|
+
})
|
|
293
|
+
return result;
|
|
294
|
+
}
|
|
282
295
|
|
|
283
296
|
}
|
package/src/Table/Table.vue
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<div class="flex items-center justify-between">
|
|
9
9
|
<slot name="defaultButtons">
|
|
10
10
|
<div v-show="$props.opts?.Add.can"
|
|
11
|
-
class="flex cursor-pointer justify-center items-center text-white
|
|
11
|
+
class="flex cursor-pointer justify-center items-center text-white bg-blue-600 font-medium rounded text-sm px-4 text-center hover:bg-blue-700 .focus:ring-4.focus:ring-blue-200.dark:focus:ring-blue-900"
|
|
12
12
|
@click="add()">
|
|
13
13
|
<div class="text-xl">
|
|
14
14
|
+
|
|
@@ -34,8 +34,18 @@
|
|
|
34
34
|
|
|
35
35
|
<!-- ЗАГОЛОВКИ СТОЛБЦОВ-->
|
|
36
36
|
<div class="table-header-group">
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
|
|
38
|
+
<!-- ЧЕКБОКСЫ -->
|
|
39
|
+
<div class="table-cell w-[65px] align-middle">
|
|
40
|
+
<label class="checkbox" v-if="Table.opts.rowSelectors">
|
|
41
|
+
<input type='checkbox' @change="CheckboxSelectionChanged($event, true)">
|
|
42
|
+
<span class='indicator'></span>
|
|
43
|
+
</label>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<div v-for="column in Table.columns" v-show="column.Table.isShow" :key="'cheader_' + column.name"
|
|
47
|
+
:class="' defaultHeader ' + column.Table.classesHeader"
|
|
48
|
+
class=" table-cell align-middle border-r border-r-slate-100 px-2">
|
|
39
49
|
<span>{{ column.title !== '' ? column.title :
|
|
40
50
|
column.name }}</span>
|
|
41
51
|
</div>
|
|
@@ -55,10 +65,23 @@
|
|
|
55
65
|
<div class="table-row-group">
|
|
56
66
|
|
|
57
67
|
<template v-for="(row) in (Table.Rows.rows)">
|
|
58
|
-
<div :key="'row_' + (row as any).id" class="table-row cursor-pointer hover:bg-slate-100" v-if="true">
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
68
|
+
<div :key="'row_' + (row as any).id" class="defaultRow table-row cursor-pointer hover:bg-slate-100" v-if="true">
|
|
69
|
+
|
|
70
|
+
<!-- ЧЕКБОКСЫ -->
|
|
71
|
+
<div class="table-cell align-middle">
|
|
72
|
+
<label class="checkbox" v-if="Table.opts.rowSelectors">
|
|
73
|
+
<input type='checkbox' v-model="Table.RowsParams[(row as any)[primaryKey]].selected"
|
|
74
|
+
@change="CheckboxSelectionChanged($event, false)">
|
|
75
|
+
<span class='indicator'></span>
|
|
76
|
+
</label>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<div v-for="column in Table.columns" v-show="column.Table.isShow" :key="'tc_' + column.name"
|
|
80
|
+
:class="' defaultCell ' + column.Table.classes"
|
|
81
|
+
class="table-cell align-middle border-r border-r-slate-100 px-2 last:border-r-0 last:pr-0"
|
|
82
|
+
@click="columnClick(row, column)"
|
|
83
|
+
:style="(column.Table.width === null ? '' : 'width:' + column.Table.width + 'px')">
|
|
84
|
+
|
|
62
85
|
<span v-if="!column.Table.isRawValue">{{
|
|
63
86
|
column.Table.value(row, column) }}</span>
|
|
64
87
|
<span v-else v-html="column.Table.value(row, column)"></span>
|
|
@@ -181,12 +204,12 @@
|
|
|
181
204
|
<!-- КНОПКИ СОХРАНЕНИЯ-->
|
|
182
205
|
<div class="flex w-full mt-3 mb-2 justify-between items-center">
|
|
183
206
|
<div v-show="$props.opts?.Add.can"
|
|
184
|
-
class="cursor-pointer ml-2 text-lg py-2 text-white block bg-gray-400 font-medium rounded
|
|
207
|
+
class="cursor-pointer ml-2 text-lg py-2 text-white block bg-gray-400 font-medium rounded px-4 text-center hover:bg-blue-700 focus:ring-4 focus:ring-blue-200 dark:focus:ring-blue-900"
|
|
185
208
|
@click="Table.OpenedRow = null; FlameTableModal?.close()">
|
|
186
209
|
Отмена
|
|
187
210
|
</div>
|
|
188
211
|
<div
|
|
189
|
-
class="cursor-pointer ml-2 text-lg py-2 mr-3 text-white block bg-blue-600 font-medium rounded
|
|
212
|
+
class="cursor-pointer ml-2 text-lg py-2 mr-3 text-white block bg-blue-600 font-medium rounded px-4 text-center hover:bg-blue-700 focus:ring-4 focus:ring-blue-200 dark:focus:ring-blue-900"
|
|
190
213
|
@click=" SaveTable()">
|
|
191
214
|
{{ Table.mode === 'add' ? 'Добавить' : 'Сохранить' }}
|
|
192
215
|
</div>
|
|
@@ -398,6 +421,14 @@ export default defineComponent({
|
|
|
398
421
|
}
|
|
399
422
|
}
|
|
400
423
|
},
|
|
424
|
+
|
|
425
|
+
CheckboxSelectionChanged(event: any, all: boolean = false) {
|
|
426
|
+
this.Table.getSelectedRows();
|
|
427
|
+
if (all === true)
|
|
428
|
+
for (const key in this.Table.RowsParams) {
|
|
429
|
+
this.Table.RowsParams[key].selected = event.target.checked
|
|
430
|
+
}
|
|
431
|
+
}
|
|
401
432
|
},
|
|
402
433
|
|
|
403
434
|
})
|
|
@@ -408,4 +439,88 @@ export default defineComponent({
|
|
|
408
439
|
.no-wrap-cell {
|
|
409
440
|
white-space: nowrap !important;
|
|
410
441
|
}
|
|
442
|
+
|
|
443
|
+
.defaultHeader {
|
|
444
|
+
color: rgba(55, 53, 47, 0.65);
|
|
445
|
+
font-size: 14px;
|
|
446
|
+
line-height: 16.8px;
|
|
447
|
+
font-family: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, "Apple Color Emoji", Arial, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol";
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
.defaultRow {
|
|
451
|
+
color: rgb(55, 53, 47);
|
|
452
|
+
font-size: 14px;
|
|
453
|
+
line-height: 16.8px;
|
|
454
|
+
font-family: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, "Apple Color Emoji", Arial, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol";
|
|
455
|
+
border: 1px solid rgb(233, 233, 231);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// ЧЕКБОКСЫ
|
|
459
|
+
$black: #2D3137;
|
|
460
|
+
$blue: #3785BC;
|
|
461
|
+
$green: #329E78;
|
|
462
|
+
$grey: #D6D6D6;
|
|
463
|
+
$red: #DD3C3A;
|
|
464
|
+
$white: #FFFFFF;
|
|
465
|
+
|
|
466
|
+
$border-radius: 3px;
|
|
467
|
+
|
|
468
|
+
@mixin checkbox($color) {
|
|
469
|
+
margin-right: 1rem;
|
|
470
|
+
padding-left: 1.75rem;
|
|
471
|
+
position: relative;
|
|
472
|
+
-webkit-user-select: none;
|
|
473
|
+
-moz-user-select: none;
|
|
474
|
+
-ms-user-select: none;
|
|
475
|
+
user-select: none;
|
|
476
|
+
|
|
477
|
+
input[type="checkbox"] {
|
|
478
|
+
position: absolute;
|
|
479
|
+
opacity: 0;
|
|
480
|
+
|
|
481
|
+
&:focus~span {
|
|
482
|
+
border: 2px solid lighten($black, 50%);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
&:focus:checked~span {
|
|
486
|
+
border: 2px solid darken($color, 15%);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
&:checked~span {
|
|
490
|
+
color: $white;
|
|
491
|
+
background: $color url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+DQo8c3ZnIHdpZHRoPSIxMiIgaGVpZ2h0PSI5IiB2aWV3Qm94PSIwIDAgMTIgOSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCiAgPHBhdGggZD0iTTQuNTc1IDguOTc3cy0uNDA0LS4wMDctLjUzNi0uMTY1TC4wNTcgNS42NGwuODI5LTEuMjI3TDQuNDcgNy4yNjggMTAuOTIxLjA4NmwuOTIzIDEuMTAzLTYuODYzIDcuNjRjLS4xMzQtLjAwMy0uNDA2LjE0OC0uNDA2LjE0OHoiIGZpbGw9IiNGRkYiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPg0KPC9zdmc+) 50% 40% no-repeat;
|
|
492
|
+
border: 2px solid $color;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
span {
|
|
498
|
+
border-radius: $border-radius;
|
|
499
|
+
position: absolute;
|
|
500
|
+
left: 50%;
|
|
501
|
+
top: 50%;
|
|
502
|
+
transform: translate(-50%, -50%);
|
|
503
|
+
width: 1.09rem;
|
|
504
|
+
height: 1.09rem;
|
|
505
|
+
background-color: lighten($black, 65%);
|
|
506
|
+
border: 1px solid lighten($black, 65%);
|
|
507
|
+
pointer-events: none;
|
|
508
|
+
-webkit-user-select: none;
|
|
509
|
+
-moz-user-select: none;
|
|
510
|
+
-ms-user-select: none;
|
|
511
|
+
user-select: none;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
label.checkbox {
|
|
516
|
+
@include checkbox($green);
|
|
517
|
+
|
|
518
|
+
&.blue {
|
|
519
|
+
@include checkbox($blue);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
&.red {
|
|
523
|
+
@include checkbox($red);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
411
526
|
</style>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="fc flex-wrap">
|
|
3
|
-
<div v-for="(col) in props.columns" :key="col.name" v-show="col.Filter.isShow">
|
|
3
|
+
<div v-for="(col) in props.columns" :key="col.name" v-show="col.Filter.isShow" :class="col.Filter.classes">
|
|
4
4
|
|
|
5
5
|
<!-- ТЕКСТ -->
|
|
6
6
|
<div class="fc flex-col">
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- Это селектор c мультивыбором -->
|
|
3
|
+
<div>
|
|
4
|
+
|
|
5
|
+
</div>
|
|
6
|
+
</template>
|
|
7
|
+
|
|
8
|
+
<script setup lang="ts" generic="T">
|
|
9
|
+
import { onMounted, reactive, ref, defineProps } from '@vue/runtime-core'; import type { Ref } from 'vue'; import { storeFile } from "@/store"; import { useRoute, useRouter } from 'vue-router'; import REST from "flamerest"
|
|
10
|
+
|
|
11
|
+
// Иконки
|
|
12
|
+
import { XCircleIcon } from '@icons/24/solid'
|
|
13
|
+
import TableOpts from './TableOpts';
|
|
14
|
+
import { Column } from './Columns';
|
|
15
|
+
//import { TableFilter } from './TableOpts.js';
|
|
16
|
+
import FlameTable from './FlameTable';
|
|
17
|
+
import Datepicker from '@vuepic/vue-datepicker';
|
|
18
|
+
|
|
19
|
+
// Глобальное хранилище и роуты
|
|
20
|
+
const store = storeFile(), router = useRouter(), route = useRoute();
|
|
21
|
+
|
|
22
|
+
// Локальное состояние компонента
|
|
23
|
+
const state = reactive({
|
|
24
|
+
data: {}
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
// Входящие данные компонента
|
|
28
|
+
const props = defineProps<{
|
|
29
|
+
columns: { [key: string]: Column; },
|
|
30
|
+
table: FlameTable<any>,
|
|
31
|
+
}>()
|
|
32
|
+
|
|
33
|
+
// Примонтировано
|
|
34
|
+
onMounted(async () => {
|
|
35
|
+
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
const update = () => {
|
|
40
|
+
|
|
41
|
+
props.table.update();
|
|
42
|
+
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<style scoped lang="scss"></style>
|
package/src/Table/TableOpts.ts
CHANGED