flameresttable 1.0.12 → 1.0.13

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.
@@ -5,7 +5,7 @@
5
5
  "type": "chrome",
6
6
  "request": "launch",
7
7
  "name": "Chrome",
8
- "url": "http://localhost:3000",
8
+ "url": "http://testrest/",
9
9
  "webRoot": "${workspaceFolder}/src",
10
10
  "preLaunchTask": "start-dev-server",
11
11
  "postDebugTask": "stop-dev-server",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flameresttable",
3
- "version": "1.0.12",
3
+ "version": "1.0.13",
4
4
  "main": "./src/plugin.ts",
5
5
  "repository": {
6
6
  "type": "git",
@@ -15,38 +15,35 @@
15
15
  "android": "npm run build && npx cap add android && npx cap sync && npx cap open android"
16
16
  },
17
17
  "dependencies": {
18
- "@vuepic/vue-datepicker": "^3.6.8",
19
- "flamerest": "^1.0.80",
18
+ "@vuepic/vue-datepicker": "^7.2.0",
19
+ "flamerest": "^1.0.92",
20
20
  "lodash-es": "^4.17.21",
21
- "pinia": "^2.0.34",
21
+ "pinia": "^2.1.7",
22
22
  "pug": "github:FlameArt/pug-tailwind-only",
23
23
  "pug-lexer": "github:FlameArt/pug-lexer-only",
24
- "sass": "^1.62.0",
25
- "vue": "^3.2.45",
26
- "vue-router": "^4.1.6"
24
+ "sass": "^1.69.5",
25
+ "vue": "^3.3.7",
26
+ "vue-router": "^4.2.5"
27
27
  },
28
28
  "devDependencies": {
29
- "@capacitor/android": "^3.9.0",
30
- "@capacitor/cli": "^3.9.0",
31
- "@capacitor/core": "^3.9.0",
32
- "@heroicons/vue": "^2.0.17",
33
- "@types/lodash-es": "^4.17.7",
34
- "@types/lodash.merge": "^4.6.7",
35
- "@types/node": "18.8.0",
36
- "@typescript-eslint/eslint-plugin": "^5.59.0",
37
- "@typescript-eslint/parser": "^5.59.0",
38
- "@vitejs/plugin-vue": "^4.1.0",
39
- "@volar/vue-language-plugin-pug": "^1.2.0",
40
- "@vue/compiler-sfc": "^3.2.45",
41
- "autoprefixer": "^10.4.14",
42
- "eslint": "^8.38.0",
29
+ "@heroicons/vue": "^2.0.18",
30
+ "@types/lodash-es": "^4.17.10",
31
+ "@types/lodash.merge": "^4.6.8",
32
+ "@types/node": "20.8.9",
33
+ "@typescript-eslint/eslint-plugin": "^6.9.0",
34
+ "@typescript-eslint/parser": "^6.9.0",
35
+ "@vitejs/plugin-vue": "^4.4.0",
36
+ "@volar/vue-language-plugin-pug": "^1.6.5",
37
+ "@vue/compiler-sfc": "^3.3.7",
38
+ "autoprefixer": "^10.4.16",
39
+ "eslint": "^8.52.0",
43
40
  "eslint-plugin-vue": "^8.7.1",
44
- "postcss": "^8.4.23",
41
+ "postcss": "^8.4.31",
45
42
  "postcss-import": "^14.1.0",
46
- "tailwindcss": "^3.3.1",
47
- "typescript": "^4.9.5",
48
- "vite": "^4.2.2",
49
- "vue-tsc": "^1.2.0",
43
+ "tailwindcss": "^3.3.5",
44
+ "typescript": "^5.2.2",
45
+ "vite": "^4.5.0",
46
+ "vue-tsc": "^1.8.22",
50
47
  "vue-universal-modal": "^1.1.4"
51
48
  },
52
49
  "rules": {}
package/src/App.vue CHANGED
@@ -1,6 +1,10 @@
1
1
  <script setup lang="ts">
2
2
  import { onMounted, reactive, defineProps } from '@vue/runtime-core'; import { storeFile } from "@/store"; import { useRoute, useRouter } from 'vue-router'; import REST from "flamerest"
3
3
  import Table from './Table/Table.vue';
4
+ import { ref } from 'vue';
5
+ import Model from '@models/Testtable';
6
+ import TableOpts from './Table/TableOpts';
7
+
4
8
  const store = storeFile(), router = useRouter(), route = useRoute();
5
9
 
6
10
  let notRedirectOnAuthList = [
@@ -11,23 +15,23 @@ let notRedirectOnAuthList = [
11
15
  ];
12
16
 
13
17
  onMounted(() => {
14
- REST.auth().then((res) => {
15
- store.authUser(res);
16
- store.User.isLoaded = true;
17
- if (res.isAuthorized === false) {
18
- if (!notRedirectOnAuthList.includes(route.name?.toString() ?? "")) {
19
- router.push({ name: "Auth" });
20
- }
21
- } else {
22
- // Load state
23
- // store.projects = REST.get("projects");
24
- }
25
- });
18
+
26
19
  });
20
+
21
+ const TableComponent = ref<InstanceType<typeof Table>>();
22
+ const opts = new TableOpts;
23
+ opts.Add.can = true;
24
+ opts.Remove.can = true;
25
+
26
+ // Загружаем первичные данные
27
+ Model.all({ sort: ['id'] }).then(r =>
28
+ TableComponent.value?.Table.load(r)
29
+ )
30
+
27
31
  </script>
28
32
 
29
33
  <template lang="pug">
30
- Table
34
+ Table(:model="Model", :opts="opts")
31
35
  </template>
32
36
 
33
37
  <style>
@@ -53,6 +53,32 @@ export class Column implements IColumn {
53
53
 
54
54
  }
55
55
 
56
+ /**
57
+ * Это related данные для всех селекторов и внутри таблицы
58
+ */
59
+ public Selector = {
60
+
61
+ /**
62
+ * Загрузчик значений
63
+ * @returns Array
64
+ */
65
+ loader: () => [],
66
+
67
+ /**
68
+ * Здесь список готовых значений
69
+ */
70
+ values: [],
71
+
72
+ /**
73
+ * Здесь можно определить кастомный лоадер при поиске
74
+ * @param row
75
+ * @param col
76
+ * @returns
77
+ */
78
+ value: (row: any, col: string) => row[col]
79
+
80
+ };
81
+
56
82
  /**
57
83
  * Настройки фильтра
58
84
  */
@@ -65,6 +91,14 @@ export class Column implements IColumn {
65
91
  valueString: "",
66
92
  valueRange: { from: '', to: '' },
67
93
 
94
+ // Тип фильтра
95
+ type: 'text' as "text" | "fixed" | "fulltext" | "number" | "date" | "daterange" | "selector",
96
+
97
+ /**
98
+ * Список значений под выбор
99
+ */
100
+ select: [],
101
+
68
102
  // Минимальное число символов в строке фильтра, после которого будет произведён запрос
69
103
  filterMinSymbolsRequest: 0,
70
104
 
@@ -211,6 +245,9 @@ export interface IColumn {
211
245
  // Показываем ли фильтр
212
246
  isShow?: boolean,
213
247
 
248
+ // Тип фильтра
249
+ type: "text" | "fixed" | "fulltext" | "number" | "date" | "daterange" | "selector",
250
+
214
251
  // Значение
215
252
  valueString?: string,
216
253
  valueRange?: { from: string, to: string },
@@ -3,6 +3,7 @@ import { Rows, SavedObject } from 'flamerest';
3
3
  import TableOpts from "./TableOpts";
4
4
  import { reactive, UnwrapRef } from 'vue';
5
5
  import merge from 'lodash-es/merge'
6
+ import ITableLoadParams from './TableLoadParams';
6
7
 
7
8
  // Подгрузчик типа класса
8
9
  type Class<T> = new (...args: any[]) => T
@@ -121,12 +122,64 @@ export default class FlameTable<T> {
121
122
 
122
123
  if (SaveLoadParams !== null) this.opts.LoadParams = SaveLoadParams;
123
124
 
124
- const rows: Rows<T> = await (this.model as any).constructor.all(Object.assign(this.opts.LoadParams, { page: this.Pager.page, perPage: this.Pager.perPage }));
125
+ // Дополняем загрузочные параметры фильтрами
126
+ const filters = this.applyFiltersParams();
127
+
128
+ const rows: Rows<T> = await (this.model as any).constructor.all(merge({}, this.opts.LoadParams, filters, { page: this.Pager.page, perPage: this.Pager.perPage }));
125
129
 
126
130
  this.load(rows);
127
131
 
128
132
  }
129
133
 
134
+ public applyFiltersParams() {
135
+ const customFilters: ITableLoadParams = {
136
+ where: {}
137
+ };
138
+ for (const key in this.columns) {
139
+ const el = this.columns[key].Filter;
140
+ switch (el.type) {
141
+
142
+ // Частичное совпадение
143
+ case 'text':
144
+
145
+ if (el.valueString.trim() === '') continue;
146
+ customFilters.where[key] = ['LIKE', key, el.valueString];
147
+ break;
148
+
149
+ // Фуллтекстовый поиск
150
+ case 'fulltext':
151
+
152
+ if (el.valueString.trim() === '') continue;
153
+ customFilters.where[key] = ['FULLTEXT', key, el.valueString];
154
+ break;
155
+
156
+ // Точное совпадение
157
+ case 'fixed':
158
+ case 'date':
159
+ case 'selector':
160
+
161
+ if (el.valueString.trim() === '') continue;
162
+ customFilters.where[key] = el.valueString;
163
+
164
+ break;
165
+
166
+ // ДИАПАЗОН
167
+ case 'number':
168
+ case 'daterange':
169
+
170
+ if (el.valueRange.from.trim() !== '')
171
+ customFilters.where[key] = ['>=', key, el.valueRange.from];
172
+ if (el.valueRange.to.trim() !== '')
173
+ customFilters.where[key] = ['<=', key, el.valueRange.to];
174
+
175
+ break;
176
+
177
+ default:
178
+ alert('Unknown table filter type');
179
+ }
180
+ }
181
+ return customFilters;
182
+ }
130
183
 
131
184
 
132
185
  public async add(): Promise<SavedObject<T> | null> {
@@ -1,12 +1,12 @@
1
1
  <template lang="pug">
2
- nav.relative.z-0.w-full.fc.rounded-md.-space-x-px(aria-label='Pagination' @click="")
2
+ nav.relative.z-0.w-full.fc.flex-wrap.rounded-md.-space-x-px(aria-label='Pagination' @click="")
3
3
  a.relative.inline-flex.items-center.px-2.py-2.rounded-l-md.border.border-gray-300.bg-white.text-sm.font-medium.text-gray-500(href='#' class='hover:bg-gray-50')
4
4
  span.sr-only Previous
5
5
  // Heroicon name: solid/chevron-left
6
6
  svg.h-5.w-5(xmlns='http://www.w3.org/2000/svg' viewbox='0 0 20 20' fill='currentColor' aria-hidden='true')
7
7
  path(fill-rule='evenodd' d='M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z' clip-rule='evenodd')
8
8
  // Current: "z-10 bg-indigo-50 border-indigo-500 text-indigo-600", Default: "bg-white border-gray-300 text-gray-500 hover:bg-gray-50"
9
- a.bg-white.border-gray-300.text-gray-500.relative.inline-flex.items-center.px-4.py-2.border.text-sm.font-medium(v-for="page in props.table.Pager.count" class="hover:bg-gray-50" :class="props.table.Pager.page === page ? 'z-10 bg-indigo-50 border-indigo-500 text-indigo-600' : ''" @click="goPage(page)")
9
+ a.cursor-pointer.bg-white.border-gray-300.text-gray-500.relative.inline-flex.items-center.px-4.py-2.border.text-sm.font-medium(v-for="page in props.table.Pager.count" class="hover:bg-gray-50" :class="props.table.Pager.page === page ? 'z-10 bg-indigo-50 border-indigo-500 text-indigo-600' : ''" @click="goPage(page)")
10
10
  | {{ page }}
11
11
  //span.relative.inline-flex.items-center.px-4.py-2.border.border-gray-300.bg-white.text-sm.font-medium.text-gray-700 ...
12
12
  a.relative.inline-flex.items-center.px-2.py-2.rounded-r-md.border.border-gray-300.bg-white.text-sm.font-medium.text-gray-500(href='#' class='hover:bg-gray-50')
@@ -1,6 +1,9 @@
1
1
  <template>
2
2
  <div class="mt-0 overflow-x-scroll">
3
3
 
4
+ <!-- ФИЛЬТРЫ -->
5
+ <TableFilters :columns="Table.columns" :table="Table"></TableFilters>
6
+
4
7
  <!-- "ДОБАВИТЬ" И ЧИСЛО ЗАПИСЕЙ-->
5
8
  <div class="flex items-center justify-between">
6
9
  <slot name="defaultButtons">
@@ -176,7 +179,7 @@
176
179
  </div>
177
180
  <div
178
181
  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"
179
- @click=" SaveTable() ">
182
+ @click=" SaveTable()">
180
183
  {{ Table.mode === 'add' ? 'Добавить' : 'Сохранить' }}
181
184
  </div>
182
185
  </div>
@@ -197,6 +200,7 @@ import TableOpts from './TableOpts';
197
200
  import FlameTable from './FlameTable';
198
201
  import ModalVue from './../components/default/Modal.vue';
199
202
  import Paginator from './Paginator.vue';
203
+ import TableFilters from './TableFilters.vue';
200
204
  type Class<T> = new (...args: any[]) => T;
201
205
 
202
206
  import Datepicker from '@vuepic/vue-datepicker';
@@ -205,7 +209,7 @@ import { isNumber } from 'lodash';
205
209
 
206
210
 
207
211
  export default defineComponent({
208
- components: { ModalVue, Paginator, Datepicker },
212
+ components: { ModalVue, Paginator, Datepicker, TableFilters },
209
213
  props: {
210
214
  rows: {
211
215
  default: [] as Array<any>,
@@ -1,13 +1,25 @@
1
- <template lang="pug">
2
- .flex
1
+ <template>
2
+ <div class="fc flex-wrap">
3
+ <div v-for="(col) in props.columns" :key="col.name">
4
+ {{ col.name }}
5
+ <!-- ТЕКСТ -->
6
+ <div v-if="col.Filter.type === 'text'">
7
+ <input type="text" @keyup="update()" v-model="col.Filter.valueString" />
8
+ </div>
9
+
10
+ </div>
11
+ </div>
3
12
  </template>
4
13
 
5
- <script setup lang="ts">
14
+ <script setup lang="ts" generic="T">
6
15
  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"
7
16
 
8
17
  // Иконки
9
18
  import { XCircleIcon } from '@icons/24/solid'
10
- import { TableFilter } from './TableOpts.js';
19
+ import TableOpts from './TableOpts';
20
+ import { Column } from './Columns';
21
+ //import { TableFilter } from './TableOpts.js';
22
+ import FlameTable from './FlameTable';
11
23
 
12
24
  // Глобальное хранилище и роуты
13
25
  const store = storeFile(), router = useRouter(), route = useRoute();
@@ -19,7 +31,8 @@ const state = reactive({
19
31
 
20
32
  // Входящие данные компонента
21
33
  const props = defineProps<{
22
- filters: Array<TableFilter>
34
+ columns: { [key: string]: Column; },
35
+ table: FlameTable<any>,
23
36
  }>()
24
37
 
25
38
  // Примонтировано
@@ -27,6 +40,13 @@ onMounted(async () => {
27
40
 
28
41
  })
29
42
 
43
+
44
+ const update = () => {
45
+
46
+ props.table.update();
47
+
48
+ }
49
+
30
50
  </script>
31
51
 
32
52
  <style scoped lang="scss"></style>
@@ -0,0 +1,10 @@
1
+ export default interface ITableLoadParams {
2
+
3
+ where?: any
4
+ fields?: any,
5
+ expand?: any,
6
+ sortfields?: Array<string>,
7
+ page?: number,
8
+ perPage?: number
9
+
10
+ }
@@ -2,6 +2,7 @@ import { Column, IColumn } from './Columns';
2
2
 
3
3
  import merge from 'lodash-es/merge'
4
4
  import FlameTable from './FlameTable';
5
+ import ITableLoadParams from './TableLoadParams';
5
6
 
6
7
  export default class TableOpts {
7
8
 
@@ -18,7 +19,7 @@ export default class TableOpts {
18
19
  /**
19
20
  * Параметры прогрузки
20
21
  */
21
- public LoadParams = {} as any;
22
+ public LoadParams: ITableLoadParams = {};
22
23
 
23
24
 
24
25
  public set(ColumnName: string, mergingOpts: IColumn) {
package/src/main.ts CHANGED
@@ -6,12 +6,14 @@ import router from "./router";
6
6
 
7
7
  import 'vue-universal-modal/dist/index.css'
8
8
  import VueUniversalModal from 'vue-universal-modal'
9
+ import REST from 'flamerest';
9
10
 
10
11
 
12
+ REST.SERVER = 'http://testrest';
11
13
 
12
14
 
13
15
  createApp(App)
14
- .use(createPinia())
15
- .use(router)
16
- .use(VueUniversalModal, {teleportTarget: '#my-modals',modalComponent: 'CustomModal'})
17
- .mount('#app')
16
+ .use(createPinia())
17
+ .use(router)
18
+ .use(VueUniversalModal, { teleportTarget: '#my-modals', modalComponent: 'CustomModal' })
19
+ .mount('#app')
package/src/router.ts CHANGED
@@ -3,34 +3,8 @@ const routes = [
3
3
  {
4
4
  path: '/',
5
5
  name: 'Home',
6
- component: ()=> import('./pages/Home.vue'),
6
+ component: () => import('./pages/Home.vue'),
7
7
  },
8
- {
9
- path: '/in',
10
- name: 'Auth',
11
- component: ()=> import('./pages/user/Auth.vue'),
12
- },
13
- {
14
- path: '/signup',
15
- name: 'Signup',
16
- component: ()=> import('./pages/user/Signup.vue'),
17
- },
18
- {
19
- path: '/resetpasswordrequest',
20
- name: 'ResetPasswordRequest',
21
- component: ()=> import('./pages/user/ResetPasswordRequest.vue'),
22
- },
23
- {
24
- path: '/resetpassword',
25
- name: 'ResetPassword',
26
- component: ()=> import('./pages/user/ResetPassword.vue'),
27
- },
28
- {
29
- path: '/mysettings',
30
- name: 'MySettings',
31
- component: ()=> import('./pages/user/UserSettings.vue'),
32
- },
33
-
34
8
 
35
9
  ]
36
10
  const router = createRouter({