flameresttable 1.0.0

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 ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "extends": [
3
+ "eslint:recommended",
4
+ "plugin:@typescript-eslint/recommended",
5
+ "plugin:vue/recommended"
6
+ ],
7
+ "rules": {
8
+ "no-unused-vars": "off",
9
+ "@typescript-eslint/no-unused-vars": "off",
10
+ "no-empty-function": "off",
11
+ "@typescript-eslint/no-empty-function": "off",
12
+ "@typescript-eslint/no-inferrable-types": "off",
13
+ "no-multiple-empty-lines": "off",
14
+ "@typescript-eslint/no-explicit-any": "off",
15
+ "vue/multi-word-component-names": "off",
16
+ "vue/no-multiple-template-root": "off",
17
+ "vue/no-duplicate-attributes": "off",
18
+ "linebreak-style": "off"
19
+ },
20
+ "plugins": [
21
+ "@typescript-eslint"
22
+ ],
23
+ "parser": "vue-eslint-parser",
24
+ "parserOptions": {
25
+ "parser": "@typescript-eslint/parser"
26
+ }
27
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "recommendations": ["Vue.volar", "Wscats.vue", "bradlc.vscode-tailwindcss", "afzalsayed96.heroicons", "ionutvmi.path-autocomplete", "bam.vscode-file-templates", "pmneo.tsimporter", "dbaeumer.vscode-eslint"],
3
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "type": "chrome",
6
+ "request": "launch",
7
+ "name": "Chrome",
8
+ "url": "http://localhost:3000",
9
+ "webRoot": "${workspaceFolder}/src",
10
+ "preLaunchTask": "start-dev-server",
11
+ "postDebugTask": "stop-dev-server",
12
+ "userDataDir": "${execPath}/../chrome-debug-default-profile/"
13
+ },
14
+ {
15
+ "type": "msedge",
16
+ "request": "launch",
17
+ "name": "VSCode Edge",
18
+ "url": "http://localhost:3000",
19
+ "webRoot": "${workspaceFolder}/src",
20
+ "preLaunchTask": "start-dev-server",
21
+ "runtimeExecutable": "stable",
22
+ "runtimeArgs": [
23
+ "--headless"
24
+ ],
25
+ "port": 9229
26
+ }
27
+ ]
28
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "volar.codeLens.pugTools": false,
3
+ "vetur.validation.script": false,
4
+ "vetur.validation.template": false,
5
+ "vetur.validation.style": false,
6
+ "tailwindCSS.includeLanguages": {
7
+ "plaintext": "html"
8
+ },
9
+ "tailwindCSS.emmetCompletions": true,
10
+ "css.lint.unknownAtRules": "ignore"
11
+ }
@@ -0,0 +1,36 @@
1
+ {
2
+ "version": "2.0.0",
3
+ "tasks": [
4
+ {
5
+ "label": "start-dev-server",
6
+ "type": "npm",
7
+ "script": "dev",
8
+ "isBackground": true,
9
+ "problemMatcher": {
10
+ "owner": "npm",
11
+ "background": {
12
+ "activeOnStart": true,
13
+ "beginsPattern": ".*",
14
+ "endsPattern": "ready in"
15
+ },
16
+ "pattern": {
17
+ "regexp": "",
18
+ }
19
+ }
20
+ },
21
+ {
22
+ "label": "stop-dev-server",
23
+ "command": "echo ${input:terminate}",
24
+ "type": "shell"
25
+ },
26
+ // OTHER
27
+ ],
28
+ "inputs": [
29
+ {
30
+ "id": "terminate",
31
+ "type": "command",
32
+ "command": "workbench.action.tasks.terminate",
33
+ "args": "terminateAll"
34
+ }
35
+ ]
36
+ }
package/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # Vue 3 + Vite + Pinia + Router + Tailwind + Pug + Typescript template
2
+
3
+ Hello, world!
4
+
5
+ That starter for rapid prototyping a services. Start with
6
+
7
+ git clone https://github.com/FlameArt/vuestarter.git ./projectName
8
+
9
+ ## Under the hood
10
+
11
+ * Vite
12
+ * Vue 3 [via composition api]
13
+ * Typescript
14
+ * Pinia as state manager
15
+ * Vue Router 4
16
+ * Tailwind as css framework
17
+ * Pug as html framework
18
+ * ESLint
19
+ * Capacitor as converter to Android and iOS apps
20
+ * VSCode ready with Volar
21
+ * [FlameREST](https://github.com/FlameArt/auto-rest-template-yii2) attached
22
+ * Precreated Signup, Auth and Password Reset pages
23
+
24
+ # VSCode improvements
25
+
26
+ Pug-lexer in Volar doesn`t support all tailwind functions currently. So you need to apply fix https://github.com/pugjs/pug/pull/3373
27
+
28
+ OR just fix the `Volar` extension directly in `%USERNAME%/.vscode/extensions/vue.volar-VERSION/dist/node/server.js` that
29
+
30
+ (/^\.([_a-z0-9\-]*[_a-z][_a-z0-9\-]*)/i, 'class');
31
+
32
+ to that
33
+
34
+ (/^\.([_a-z0-9\-]*[_a-z]([_a-z0-9\-\[\]]|:(?! ))*)/i, 'class');
35
+
36
+ Compilation works fine without any fixes
37
+
38
+ # Licenses
39
+ MIT
@@ -0,0 +1,6 @@
1
+ {
2
+ "appId": "com.app.name",
3
+ "appName": "appname",
4
+ "webDir": "dist",
5
+ "bundledWebRuntime": false
6
+ }
package/index.html ADDED
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <link rel="icon" href="/favicon.ico" />
7
+ <meta name="description" content="Vite App">
8
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
9
+ <title>Vite App</title>
10
+ </head>
11
+
12
+ <body>
13
+ <div id="app"></div>
14
+ <div id="my-modals"></div>
15
+ <script type="module" src="/src/main.ts"></script>
16
+ </body>
17
+
18
+ </html>
package/jsconfig.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "compilerOptions": {
3
+ "baseUrl": "./",
4
+ "paths": {
5
+ "@/*": [
6
+ "src/*"
7
+ ],
8
+ "@icons/*": [
9
+ "node_modules/@heroicons/vue/*"
10
+ ],
11
+ "@models/*": [
12
+ "./models/*"
13
+ ]
14
+ },
15
+ "jsx": "preserve",
16
+ "include": [
17
+ "src/**/*.js",
18
+ "node_modules/@heroicons/vue/*",
19
+ "./models/*"
20
+ ]
21
+ },
22
+ "vueCompilerOptions": {
23
+ "plugins": [
24
+ "@volar/vue-language-plugin-pug"
25
+ ]
26
+ }
27
+ }
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "flameresttable",
3
+ "version": "1.0.0",
4
+ "main": "./src/plugin.ts",
5
+ "scripts": {
6
+ "dev": "vite",
7
+ "build": "vue-tsc --noEmit && vite build",
8
+ "preview": "npm run build && vite preview",
9
+ "install/update": "npm i && npm update --save",
10
+ "push and publish": "git push && npm --no-git-tag-version version patch && npm publish",
11
+ "android": "npm run build && npx cap add android && npx cap sync && npx cap open android"
12
+ },
13
+ "dependencies": {
14
+ "@vuepic/vue-datepicker": "^3.6.8",
15
+ "flamerest": "^1.0.63",
16
+ "pinia": "^2.0.32",
17
+ "pug": "github:FlameArt/pug-tailwind-only",
18
+ "pug-lexer": "github:FlameArt/pug-lexer-only",
19
+ "sass": "^1.58.3",
20
+ "vue": "^3.2.45",
21
+ "vue-router": "^4.1.6"
22
+ },
23
+ "devDependencies": {
24
+ "@capacitor/android": "^3.9.0",
25
+ "@capacitor/cli": "^3.9.0",
26
+ "@capacitor/core": "^3.9.0",
27
+ "@heroicons/vue": "^2.0.16",
28
+ "@types/lodash.merge": "^4.6.7",
29
+ "@types/node": "18.8.0",
30
+ "@typescript-eslint/eslint-plugin": "^5.53.0",
31
+ "@typescript-eslint/parser": "^5.53.0",
32
+ "@vitejs/plugin-vue": "^4.0.0",
33
+ "@volar/vue-language-plugin-pug": "^1.1.7",
34
+ "@vue/compiler-sfc": "^3.2.45",
35
+ "autoprefixer": "^10.4.13",
36
+ "eslint": "^8.34.0",
37
+ "eslint-plugin-vue": "^8.7.1",
38
+ "lodash.merge": "^4.6.2",
39
+ "postcss": "^8.4.21",
40
+ "postcss-import": "^14.1.0",
41
+ "tailwindcss": "^3.2.7",
42
+ "typescript": "^4.9.5",
43
+ "vite": "^4.1.4",
44
+ "vue-tsc": "^1.1.7",
45
+ "vue-universal-modal": "^1.1.4"
46
+ },
47
+ "rules": {}
48
+ }
@@ -0,0 +1,7 @@
1
+ module.exports = {
2
+ plugins: {
3
+ 'postcss-import': {},
4
+ tailwindcss: {},
5
+ autoprefixer: {},
6
+ },
7
+ }
Binary file
@@ -0,0 +1,2 @@
1
+ User-agent: *
2
+ Allow: /
package/src/App.vue ADDED
@@ -0,0 +1,44 @@
1
+ <script setup lang="ts">
2
+ import { onMounted, reactive, defineProps } from '@vue/runtime-core'; import { storeFile } from "@/store"; import { useRoute, useRouter } from 'vue-router'; import REST from "flamerest"
3
+ import Table from './Table/Table.vue';
4
+ const store = storeFile(), router = useRouter(), route = useRoute();
5
+
6
+ let notRedirectOnAuthList = [
7
+ "Auth",
8
+ "Signup",
9
+ "ResetPasswordRequest",
10
+ "ResetPassword",
11
+ ];
12
+
13
+ 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
+ });
26
+ });
27
+ </script>
28
+
29
+ <template lang="pug">
30
+ Table
31
+ </template>
32
+
33
+ <style>
34
+ #app {
35
+ font-family: Avenir, Helvetica, Arial, sans-serif;
36
+ -webkit-font-smoothing: antialiased;
37
+ -moz-osx-font-smoothing: grayscale;
38
+ }
39
+
40
+ /* Цвет стандартного фона модального окна */
41
+ .vue-universal-modal {
42
+ background-color: rgba(0, 0, 0, 0.15) !important;
43
+ }
44
+ </style>
@@ -0,0 +1,328 @@
1
+ export class Column implements IColumn {
2
+
3
+ /**
4
+ * Текстовое название поля [колонки], как оно есть в базе
5
+ */
6
+ public name: string = "";
7
+
8
+ /**
9
+ * Общее отображаемое имя
10
+ * Если не установлены более детализированные имена для заголовков таблицы или в попапе - используется оно
11
+ */
12
+ public title: string = "";
13
+
14
+ /**
15
+ * Параметры таблицы
16
+ */
17
+ public Table = {
18
+ /**
19
+ * Показывать ли поле в таблице
20
+ */
21
+ isShow: true,
22
+
23
+ /**
24
+ * Заголовок столбца в таблице
25
+ */
26
+ title: "",
27
+
28
+ /**
29
+ * Возможность преобразовать вывод из любой колонки
30
+ * @param row строка
31
+ * @param column колонка
32
+ * @returns преобразованное значение
33
+ */
34
+ value: (row: any, column: Column) => {
35
+ return row[column.name]
36
+ },
37
+
38
+ /**
39
+ * Выводить ли значение из функции value() в чистом html-виде
40
+ * При значении false любые спецсимволы интерпретируются как строковые символы
41
+ * При значении true - результат из value() будет напрямую подставлен в HTML
42
+ * ОСТОРОЖНО С XSS: если подставлять при true чистый пользовательский ввод, он сможет выполнить любой код
43
+ */
44
+ isRawValue: false,
45
+
46
+ /**
47
+ * Клик
48
+ * @param row
49
+ * @param column
50
+ * @returns
51
+ */
52
+ click: (row: any, column: Column) => { }
53
+
54
+ }
55
+
56
+ /**
57
+ * Настройки фильтра
58
+ */
59
+ public Filter = {
60
+
61
+ // Показываем ли фильтр
62
+ isShow: true,
63
+
64
+ // Значение
65
+ valueString: "",
66
+ valueRange: { from: '', to: '' },
67
+
68
+ // Минимальное число символов в строке фильтра, после которого будет произведён запрос
69
+ filterMinSymbolsRequest: 0,
70
+
71
+ // Позиция фильтра по порядку
72
+ filterRow: 0,
73
+ filterColumn: 0
74
+
75
+ }
76
+
77
+ public Popup = {
78
+
79
+ // Тут привязка к реальным данным
80
+ model: "",
81
+
82
+ // Заголовок поля в попапе
83
+ title: "",
84
+
85
+ // Подсказка
86
+ desc: "",
87
+
88
+ // Текст плейсхолдера
89
+ placeholder: "",
90
+
91
+ isShow: true,
92
+ isEnabled: true,
93
+
94
+ // Отправлять ли поле на бекенд при сохранении записи: добавлении и удалении
95
+ isSendFromAdd: true,
96
+ isSendFromEdit: true,
97
+
98
+ // Количество строк текстового поля
99
+ popupTextRows: 6,
100
+
101
+ // Настройка загрузчика картинок
102
+ popupImage: {
103
+ buttons: false,
104
+ convertTo: 'image/jpeg'
105
+ },
106
+
107
+ // Тип элемента в попапе
108
+ // string - обычная строка или селектор строк
109
+ // text - text area
110
+ // button - кнопка
111
+ popupType: 'string' as "string" | "text" | "button" | "date" | "selector",
112
+
113
+ // Текст ошибки добавления/обновления
114
+ errorMessage: '',
115
+
116
+ // Настройки селектора, если он включён в popupType
117
+ Selector: {
118
+
119
+ // Значения селектора - готовые
120
+ values: [],
121
+
122
+ // Загрузчик значений - используется всегда и перекрывает values
123
+ loader: (column: Column) => null
124
+
125
+ },
126
+
127
+ }
128
+
129
+ // Ленивая загрузка полей базы или вообще их не загрузка для экономии траффика
130
+ public isLoadToTable = true;
131
+ public isLoadToPopup = true;
132
+
133
+ // Порядок колонки в сортировке вывода
134
+ SortOrder: number | null = null;
135
+
136
+
137
+ // Функция кнопки
138
+ public buttonFunction = (row: any) => { return true; };
139
+
140
+
141
+
142
+ /**
143
+ * Релативная таблица
144
+ */
145
+ public linkedto: any = {};
146
+ public selectResults: Array<any> = [];
147
+
148
+ /**
149
+ * Загружать ли данные от foreign keys, т.к. данных может быть много, по-умолчанию выключено
150
+ */
151
+ public isLoadKeys = false;
152
+
153
+ // Какие параметры при загрузке ключа
154
+ public loadKeysParams = {
155
+ where: null,
156
+ expand: null,
157
+ fields: null,
158
+ sortfields: null,
159
+ page: 1,
160
+ perPage: 9999
161
+ }
162
+
163
+ public selectRepresentAs = function (item: any) { return item };
164
+
165
+ public Edit = {
166
+ name: "",
167
+ desc: "",
168
+ can: true,
169
+ }
170
+ public Add = {
171
+ name: "",
172
+ desc: "",
173
+ can: true,
174
+ default: undefined
175
+ }
176
+
177
+
178
+
179
+
180
+ }
181
+
182
+
183
+ export interface IColumn {
184
+ /**
185
+ * Текстовое название поля, как оно есть в базе
186
+ */
187
+ name?: string,
188
+
189
+ /**
190
+ * Отображаемое имя
191
+ */
192
+ title?: string,
193
+
194
+
195
+ /**
196
+ * Параметры таблицы
197
+ */
198
+ Table?: {
199
+ isShow?: boolean,
200
+ title?: string,
201
+ value?: (row: any, column: Column) => string,
202
+ isRawValue?: boolean,
203
+ click?: (row: any, column: Column) => void
204
+ },
205
+
206
+ /**
207
+ * Настройки фильтра
208
+ */
209
+ Filter?: {
210
+
211
+ // Показываем ли фильтр
212
+ isShow?: boolean,
213
+
214
+ // Значение
215
+ valueString?: string,
216
+ valueRange?: { from: string, to: string },
217
+
218
+ // Минимальное число символов в строке фильтра, после которого будет произведён запрос
219
+ filterMinSymbolsRequest?: number,
220
+
221
+ // Позиция фильтра по порядку
222
+ filterRow?: number,
223
+ filterColumn?: number
224
+
225
+ },
226
+
227
+ Popup?: {
228
+
229
+ // Тут привязка к реальным данным
230
+ model?: string,
231
+
232
+ // Заголовок поля в попапе
233
+ title?: string,
234
+
235
+ // Подсказка
236
+ desc?: string,
237
+
238
+ // Текст плейсхолдера
239
+ placeholder?: string,
240
+
241
+
242
+ isShow?: boolean,
243
+ isEnabled?: boolean,
244
+
245
+ // Отправлять ли поле на бекенд при сохранении записи: добавлении и удалении
246
+ isSendFromAdd?: boolean,
247
+ isSendFromEdit?: boolean,
248
+
249
+ // Количество строк текстового поля
250
+ popupTextRows?: number,
251
+
252
+ // Настройка загрузчика картинок
253
+ popupImage?: {
254
+ buttons?: boolean,
255
+ convertTo?: string
256
+ },
257
+
258
+ // Тип элемента в попапе
259
+ // string - обычная строка или селектор строк
260
+ // text - text area
261
+ // button - кнопка
262
+ popupType?: "string" | "text" | "button" | "date" | "selector",
263
+
264
+ // Текст ошибки добавления/обновления
265
+ errorMessage?: string,
266
+
267
+
268
+ // Настройки селектора, если он включён в popupType
269
+ Selector?: {
270
+
271
+ // Значения селектора - готовые
272
+ values?: Array<any>,
273
+
274
+ // Загрузчик значений - используется всегда и перекрывает values
275
+ loader?: (column: Column) => Array<any> | null
276
+
277
+ },
278
+
279
+ },
280
+
281
+ // Ленивая загрузка полей базы или вообще их не загрузка для экономии траффика
282
+ isLoadToTable?: boolean,
283
+ isLoadToPopup?: boolean,
284
+
285
+
286
+ // Функция кнопки
287
+ buttonFunction?: any,
288
+
289
+
290
+ // Порядок колонки
291
+ SortOrder?: number | null,
292
+
293
+ /**
294
+ * Релативная таблица
295
+ */
296
+ linkedto?: any,
297
+ selectResults?: Array<any>,
298
+
299
+ /**
300
+ * Загружать ли данные от foreign keys, т.к. данных может быть много, по-умолчанию выключено
301
+ */
302
+ isLoadKeys?: boolean,
303
+
304
+ // Какие параметры при загрузке ключа
305
+ loadKeysParams?: {
306
+ where?: any,
307
+ expand?: any,
308
+ fields?: any,
309
+ sortfields?: any,
310
+ page?: number,
311
+ perPage?: number
312
+ },
313
+
314
+ selectRepresentAs?: any,
315
+
316
+ Edit?: {
317
+ name?: string,
318
+ desc?: string,
319
+ can?: boolean,
320
+ },
321
+ Add?: {
322
+ name?: string,
323
+ desc?: string,
324
+ can?: boolean,
325
+ default?: any
326
+ }
327
+
328
+ }