flameresttable 1.0.13 → 1.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,5 +9,8 @@
9
9
  opts.Popup.beforeEdit = async (row: any, table: typeof FlameTable.prototype): Promise<boolean> => {
10
10
  }
11
11
 
12
+ ### RowSubSlot
13
+ Это слот для клика по строке таблицы, если включён параметр `opts.onRowClickOpenSlot`
14
+
12
15
  # Licenses
13
16
  MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flameresttable",
3
- "version": "1.0.13",
3
+ "version": "1.0.15",
4
4
  "main": "./src/plugin.ts",
5
5
  "repository": {
6
6
  "type": "git",
package/src/App.vue CHANGED
@@ -20,9 +20,26 @@ onMounted(() => {
20
20
 
21
21
  const TableComponent = ref<InstanceType<typeof Table>>();
22
22
  const opts = new TableOpts;
23
+
24
+ opts.set('name', { title: 'Название' });
25
+ opts.set('dt1', { title: 'Дата 1' });
26
+ opts.set('dt2', { title: 'Дата 2' });
27
+ opts.set('id', { title: 'Дата 2', Filter: { isShow: false } });
28
+ opts.set('file', { title: 'файл', Filter: { isShow: false } });
29
+ opts.set("name", {
30
+ title: 'Название', Table:
31
+ {
32
+ isRawValue: true,
33
+ isShow: true,
34
+ value: (row, column) => '<a href="https://4h.notion.site/' + row[column.name].replace('-', '') + '">Notion</a>'
35
+ },
36
+ Popup: { isShow: true }
37
+ });
23
38
  opts.Add.can = true;
24
39
  opts.Remove.can = true;
25
40
 
41
+ opts.onRowClickOpenSlot = true;
42
+
26
43
  // Загружаем первичные данные
27
44
  Model.all({ sort: ['id'] }).then(r =>
28
45
  TableComponent.value?.Table.load(r)
@@ -32,6 +49,8 @@ Model.all({ sort: ['id'] }).then(r =>
32
49
 
33
50
  <template lang="pug">
34
51
  Table(:model="Model", :opts="opts")
52
+ template(v-slot:RowSubSlot="params")
53
+ | {{ params.row.name }}
35
54
  </template>
36
55
 
37
56
  <style>
@@ -246,7 +246,7 @@ export interface IColumn {
246
246
  isShow?: boolean,
247
247
 
248
248
  // Тип фильтра
249
- type: "text" | "fixed" | "fulltext" | "number" | "date" | "daterange" | "selector",
249
+ type?: "text" | "fixed" | "fulltext" | "number" | "date" | "daterange" | "selector",
250
250
 
251
251
  // Значение
252
252
  valueString?: string,
@@ -4,6 +4,7 @@ import TableOpts from "./TableOpts";
4
4
  import { reactive, UnwrapRef } from 'vue';
5
5
  import merge from 'lodash-es/merge'
6
6
  import ITableLoadParams from './TableLoadParams';
7
+ import TableRowParams from './TableRowParams';
7
8
 
8
9
  // Подгрузчик типа класса
9
10
  type Class<T> = new (...args: any[]) => T
@@ -39,6 +40,11 @@ export default class FlameTable<T> {
39
40
  */
40
41
  public Rows = reactive({ rows: [] as Array<T> });
41
42
 
43
+ /**
44
+ * Динамические параметры строк
45
+ */
46
+ public RowsParams: { [key: string]: TableRowParams } = reactive({});
47
+
42
48
  /**
43
49
  * Параметры паджинации
44
50
  */
@@ -110,6 +116,16 @@ export default class FlameTable<T> {
110
116
  if (rows.data) {
111
117
  this.Rows.rows = (rows.data ?? []) as any;
112
118
  Object.keys(this.Pager).forEach((key) => (this.Pager as any)[key] = (rows.pages as any)[key])
119
+
120
+ // удаляем чтобы при перезагрузке не сохранялось состояние пред. строк
121
+ // производительность: если не стирать параметры строк, то при долгом пользовании таблицей и больших её объёмах в памяти накопится куча позиций, это утечка
122
+ for (const key in this.RowsParams) delete this.RowsParams[key];
123
+
124
+ // Заполняем параметры каждой строки
125
+ this.Rows.rows.forEach(row => {
126
+ // @ts-expect-error okay
127
+ this.RowsParams[row[this.model.constructor.primaryKeys[0]]] = new TableRowParams
128
+ })
113
129
  }
114
130
 
115
131
  }
@@ -53,25 +53,30 @@
53
53
  <!-- СТРОКИ-->
54
54
  <div class="table-row-group">
55
55
 
56
- <div v-for="row in (Table.Rows.rows)" :key="'row_' + (row as any).id"
57
- class="table-row cursor-pointer hover:bg-slate-100">
58
- <div v-for="column in Table.columns" v-show="column.Table.isShow" :key="'tc_' + column"
59
- class="table-cell border-r border-r-slate-100 px-2 last:border-r-0 last:pr-0"
60
- @click="column.Table.click(row, column)">
61
- <span>{{
62
- column.Table.value(row, column) }}</span>
63
- </div>
64
- <div v-if="opts.Edit.can" class="table-cell border-r border-r-slate-100 px-2 text-center">
65
- <button class="px-2 py-1 bg-green-600 text-white my-1" @click="edit(row)">
66
- Изменить
67
- </button>
56
+ <template v-for="(row) in (Table.Rows.rows)">
57
+ <div :key="'row_' + (row as any).id" class="table-row cursor-pointer hover:bg-slate-100" v-if="true">
58
+ <div v-for="column in Table.columns" v-show="column.Table.isShow" :key="'tc_' + column"
59
+ class="table-cell border-r border-r-slate-100 px-2 last:border-r-0 last:pr-0"
60
+ @click="columnClick(row, column)">
61
+ <span v-if="!column.Table.isRawValue">{{
62
+ column.Table.value(row, column) }}</span>
63
+ <span v-else v-html="column.Table.value(row, column)"></span>
64
+ </div>
65
+ <div v-if="opts.Edit.can" class="table-cell border-r border-r-slate-100 px-2 text-center">
66
+ <button class="px-2 py-1 bg-green-600 text-white my-1" @click="edit(row)">
67
+ Изменить
68
+ </button>
69
+ </div>
70
+ <div v-if="opts.Remove.can" class="table-cell border-r border-r-slate-100 px-2 text-center">
71
+ <button class="px-2 py-1 bg-gray-600 opacity-30 text-white my-1" @click="deleteRow(row)">
72
+ Удалить
73
+ </button>
74
+ </div>
68
75
  </div>
69
- <div v-if="opts.Remove.can" class="table-cell border-r border-r-slate-100 px-2 text-center">
70
- <button class="px-2 py-1 bg-gray-600 opacity-30 text-white my-1" @click="deleteRow(row)">
71
- Удалить
72
- </button>
76
+ <div :key="'row_slot_' + (row as any).id" v-if="opts.onRowClickOpenSlot && !isRowCollapsed(row)">
77
+ <slot name="RowSubSlot" :row="row" />
73
78
  </div>
74
- </div>
79
+ </template>
75
80
  </div>
76
81
 
77
82
  </div>
@@ -194,7 +199,7 @@ import { onMounted, reactive, ref, defineProps } from '@vue/runtime-core'; impor
194
199
  // Иконки
195
200
  import { XCircleIcon } from '@icons/24/solid'
196
201
  import { computed } from '@vue/reactivity';
197
- import { Column } from './Columns';
202
+ import { Column, IColumn } from './Columns';
198
203
  import { defineComponent } from 'vue';
199
204
  import TableOpts from './TableOpts';
200
205
  import FlameTable from './FlameTable';
@@ -322,6 +327,22 @@ export default defineComponent({
322
327
  })
323
328
  }
324
329
 
330
+ const primaryKey = (Table.model as any).constructor.primaryKeys[0];
331
+
332
+ const columnClick = (row: any, column: Column) => {
333
+ if (Table.opts.onRowClickOpenSlot) {
334
+ Table.RowsParams[row[primaryKey]].collapsed = !Table.RowsParams[row[primaryKey]].collapsed
335
+ }
336
+ else {
337
+ if (column?.Table?.click !== undefined)
338
+ column.Table.click(row, column);
339
+ }
340
+ }
341
+ const isRowCollapsed = (row: any) => {
342
+ return Table.RowsParams[row[primaryKey]].collapsed
343
+ }
344
+
345
+
325
346
  return {
326
347
  Table,
327
348
  FlameTableModal,
@@ -331,7 +352,10 @@ export default defineComponent({
331
352
  SaveTable,
332
353
  deleteRow,
333
354
  fileUpdated,
334
- getSelector
355
+ getSelector,
356
+ primaryKey,
357
+ columnClick,
358
+ isRowCollapsed
335
359
  }
336
360
 
337
361
  },
@@ -368,7 +392,7 @@ export default defineComponent({
368
392
  }
369
393
  }
370
394
  }
371
- }
395
+ },
372
396
  },
373
397
 
374
398
  })
@@ -1,10 +1,14 @@
1
1
  <template>
2
2
  <div class="fc flex-wrap">
3
- <div v-for="(col) in props.columns" :key="col.name">
4
- {{ col.name }}
3
+ <div v-for="(col) in props.columns" :key="col.name" v-show="col.Filter.isShow">
4
+
5
5
  <!-- ТЕКСТ -->
6
- <div v-if="col.Filter.type === 'text'">
7
- <input type="text" @keyup="update()" v-model="col.Filter.valueString" />
6
+ <div class="fc flex-col">
7
+ <div class="text-xs text-slate-400">{{ col.title.toUpperCase() ?? col.name }}</div>
8
+ <div v-if="col.Filter.type === 'text' || col.Filter.type === 'fixed' || col.Filter.type === 'fulltext'">
9
+ <input class="outline-none border border-slate-500 px-2 py-1 mx-2" :placeholder="col.title ?? col.name"
10
+ type="text" @keyup="update()" v-model="col.Filter.valueString" />
11
+ </div>
8
12
  </div>
9
13
 
10
14
  </div>
@@ -21,6 +21,10 @@ export default class TableOpts {
21
21
  */
22
22
  public LoadParams: ITableLoadParams = {};
23
23
 
24
+ /**
25
+ * Открывать субслот в таблице при клике
26
+ */
27
+ public onRowClickOpenSlot: boolean = false;
24
28
 
25
29
  public set(ColumnName: string, mergingOpts: IColumn) {
26
30
  // TODO: ЕСТЬ ОШИБКА???
@@ -0,0 +1,5 @@
1
+ export default class TableRowParams {
2
+
3
+ public collapsed: boolean = true;
4
+
5
+ }