flameresttable 1.0.22 → 1.0.23

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 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flameresttable",
3
- "version": "1.0.22",
3
+ "version": "1.0.23",
4
4
  "main": "./src/plugin.ts",
5
5
  "repository": {
6
6
  "type": "git",
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 + ' dfg df dfg dfgdg dgdf gdfgd gdf gdgd fgdf gdf gdf gdfgdfg dfgdf gdg' }}
55
+ | {{ params.row.name + ' LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG line' }}
56
56
  </template>
57
57
 
58
58
  <style>
@@ -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
  /**
@@ -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.from.trim() !== '')
196
- customFilters.where[key] = ['>=', key, el.valueRange.from];
197
- if (el.valueRange.to.trim() !== '')
198
- customFilters.where[key] = ['<=', key, el.valueRange.to];
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
  }
@@ -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 block 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"
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
- <div v-for="column in Table.columns" v-show="column.Table.isShow" :key="'cheader_' + column"
38
- class="table-cell border-r border-r-slate-100 px-2">
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
- <div v-for="column in Table.columns" v-show="column.Table.isShow" :key="'tc_' + column"
60
- class="table-cell border-r border-r-slate-100 px-2 last:border-r-0 last:pr-0"
61
- @click="columnClick(row, column)">
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 text-sm px-4 text-center hover:bg-blue-700 focus:ring-4 focus:ring-blue-200 dark:focus:ring-blue-900"
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 text-sm px-4 text-center hover:bg-blue-700 focus:ring-4 focus:ring-blue-200 dark:focus:ring-blue-900"
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>
@@ -11,6 +11,11 @@ export default class TableOpts {
11
11
  */
12
12
  public autoload: boolean = true;
13
13
 
14
+ /**
15
+ * Добавить колонку выбора записей галочками
16
+ */
17
+ public rowSelectors: boolean = true;
18
+
14
19
  /**
15
20
  * Колонки
16
21
  */
@@ -1,5 +1,6 @@
1
1
  export default class TableRowParams {
2
2
 
3
3
  public collapsed: boolean = true;
4
+ public selected: boolean = false;
4
5
 
5
6
  }