@opengis/admin 0.3.23 → 0.3.25
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 +97 -97
- package/config.js +4 -4
- package/dist/{add-page-2cPkdIAC.js → add-page-BI4K8Lzk.js} +1 -1
- package/dist/{admin-interface-D9Dx7QqK.js → admin-interface-DDP6KpGO.js} +226 -226
- package/dist/{admin-view-C_Ecdip-.js → admin-view-C--DkpIG.js} +3 -3
- package/dist/admin.js +1 -1
- package/dist/admin.umd.cjs +48 -48
- package/dist/assets/logo.svg +41 -41
- package/dist/{card-view-MuS2Gqq6.js → card-view-CPwz8aJg.js} +1 -1
- package/dist/{edit-page-Dr397YuE.js → edit-page-BsDJ8lKP.js} +1 -1
- package/dist/{import-file-CcRnsq1s.js → import-file-B8gDejaq.js} +5459 -5452
- package/dist/{profile-page-BrKTAsqO.js → profile-page-C5UftUwo.js} +1 -1
- package/dist/style.css +1 -1
- package/module/settings/card/admin.accounts.table/index.yml +7 -7
- package/module/settings/card/admin.accounts.table/rules.hbs +18 -18
- package/module/settings/card/admin.accounts.table/users.hbs +13 -13
- package/module/settings/card/admin.roles.table/access.hbs +11 -11
- package/module/settings/card/admin.roles.table/general_info.hbs +9 -9
- package/module/settings/card/admin.roles.table/index.yml +22 -22
- package/module/settings/card/admin.roles.table/users.hbs +12 -12
- package/module/settings/card/admin.routes.table/general_info.hbs +13 -13
- package/module/settings/card/admin.routes.table/groups.hbs +11 -11
- package/module/settings/card/admin.routes.table/index.yml +15 -15
- package/module/settings/card/admin.routes.table/users.hbs +16 -16
- package/module/settings/card/admin.table_properties.table/custom_columns.hbs +22 -22
- package/module/settings/card/admin.table_properties.table/index.yml +12 -12
- package/module/settings/card/admin.table_properties.table/info.hbs +17 -17
- package/module/settings/card/admin.users.table/general_info.hbs +18 -18
- package/module/settings/card/admin.users.table/index.yml +20 -20
- package/module/settings/card/admin.users.table/last_login.hbs +17 -17
- package/module/settings/card/admin.users.table/logs.hbs +16 -16
- package/module/settings/card/admin.users.table/routes.hbs +13 -13
- package/module/settings/card/admin.users.table/user_roles.hbs +35 -35
- package/module/settings/cls/change_type.json +13 -13
- package/module/settings/cls/core.actions.json +17 -17
- package/module/settings/cls/core.column_type.json +14 -14
- package/module/settings/cls/core.scope.json +13 -13
- package/module/settings/cls/properties.site_status.json +13 -13
- package/module/settings/cls/properties.widget_status.json +13 -13
- package/module/settings/cls/users.user_type.json +13 -13
- package/module/settings/cls/yes_no.json +11 -11
- package/module/settings/form/admin.accounts.form.json +13 -13
- package/module/settings/form/admin.custom_column.form.json +55 -55
- package/module/settings/form/admin.properties.form.json +15 -15
- package/module/settings/form/admin.roles.form.json +21 -21
- package/module/settings/form/admin.routes.form.json +25 -25
- package/module/settings/form/admin.rules.form.json +30 -30
- package/module/settings/form/admin.table_properties.form.json +19 -19
- package/module/settings/form/admin.user_properties.form.json +15 -15
- package/module/settings/form/admin.user_roles.form.json +24 -24
- package/module/settings/form/admin.user_roles_card.form.json +13 -13
- package/module/settings/form/admin.users.form.json +177 -177
- package/module/settings/form/admin.users_edit.form.json +145 -145
- package/module/settings/form/context.account_grants.form.json +24 -24
- package/module/settings/form/context.account_users.form.json +12 -12
- package/module/settings/form/user.user_roles.form.json +13 -13
- package/module/settings/interface/admin.properties.json +4 -4
- package/module/settings/interface/admin.roles.json +4 -4
- package/module/settings/interface/admin.routes.json +4 -4
- package/module/settings/interface/admin.users.json +4 -4
- package/module/settings/menu.json +72 -72
- package/module/settings/select/core.routes.sql +1 -1
- package/module/settings/select/core.user_mentioned.sql +1 -1
- package/module/settings/select/core.user_uid.sql +1 -1
- package/module/settings/table/admin.accounts.table.json +49 -49
- package/module/settings/table/admin.custom_column.table.json +100 -100
- package/module/settings/table/admin.properties.table.json +39 -39
- package/module/settings/table/admin.roles.table.json +77 -77
- package/module/settings/table/admin.routes.table.json +73 -73
- package/module/settings/table/admin.rules.table.json +77 -77
- package/module/settings/table/admin.table_properties.table.json +37 -37
- package/module/settings/table/admin.user_properties.table.json +34 -34
- package/module/settings/table/admin.user_roles.table.json +74 -74
- package/module/settings/table/admin.users.table.json +135 -135
- package/module/settings/table/context.account_grants.table.json +88 -88
- package/module/settings/table/context.account_users.table.json +53 -53
- package/module/settings/table/log.table_changes.table.json +100 -100
- package/package.json +102 -102
- package/plugin.js +30 -30
- package/server/helpers/core/badge.js +16 -16
- package/server/helpers/core/buttonHelper.js +21 -21
- package/server/helpers/core/coalesce.js +7 -7
- package/server/helpers/core/select.js +48 -48
- package/server/helpers/core/token.js +18 -18
- package/server/helpers/index.js +40 -40
- package/server/helpers/list/buttonHelper.js +21 -21
- package/server/helpers/list/descriptionList.js +45 -45
- package/server/helpers/list/tableList.js +82 -82
- package/server/helpers/list/utils/button.js +5 -5
- package/server/helpers/list/utils/buttonDel.js +12 -12
- package/server/helpers/list/utils/buttonEdit.js +14 -14
- package/server/helpers/temp/contentList.js +58 -58
- package/server/helpers/temp/ifCond.js +101 -101
- package/server/helpers/utils/button.js +5 -5
- package/server/helpers/utils/buttonAdd.js +6 -6
- package/server/helpers/utils/buttonDel.js +6 -6
- package/server/helpers/utils/buttonEdit.js +5 -5
- package/server/helpers/utils/mdToHTML.js +17 -17
- package/server/helpers/utils/paddingNumber.js +3 -3
- package/server/plugins/access/funcs/getAdminAccess.js +12 -12
- package/server/plugins/access/index.mjs +6 -6
- package/server/plugins/adminHook.js +81 -81
- package/server/plugins/cron.js +10 -10
- package/server/plugins/docs.js +28 -28
- package/server/plugins/hook.js +276 -276
- package/server/plugins/vite.js +77 -77
- package/server/routes/access/controllers/access.group.js +29 -29
- package/server/routes/access/controllers/access.group.post.js +54 -54
- package/server/routes/access/controllers/access.interface.js +33 -33
- package/server/routes/access/index.mjs +11 -11
- package/server/routes/access/schema.mjs +67 -67
- package/server/routes/calendar/controllers/calendar.data.js +125 -125
- package/server/routes/calendar/index.mjs +7 -7
- package/server/routes/calendar/schema.js +21 -21
- package/server/routes/data/controllers/cardData.js +127 -127
- package/server/routes/data/controllers/cardTabData.js +49 -49
- package/server/routes/data/controllers/funcs/getFilterSQL/index.js +92 -92
- package/server/routes/data/controllers/funcs/getFilterSQL/util/formatValue.js +170 -170
- package/server/routes/data/controllers/funcs/getFilterSQL/util/getCustomQuery.js +13 -13
- package/server/routes/data/controllers/funcs/getFilterSQL/util/getFilterQuery.js +64 -64
- package/server/routes/data/controllers/funcs/getFilterSQL/util/getOptimizedQuery.js +12 -12
- package/server/routes/data/controllers/funcs/getFilterSQL/util/getTableSql.js +34 -34
- package/server/routes/data/controllers/tableData.js +31 -31
- package/server/routes/data/controllers/tableDataId.js +27 -27
- package/server/routes/data/controllers/tableFilter.js +9 -9
- package/server/routes/data/controllers/tableInfo.js +112 -112
- package/server/routes/data/controllers/tokenInfo.js +9 -9
- package/server/routes/data/controllers/utils/assignTokens.js +30 -30
- package/server/routes/data/controllers/utils/conditions.js +20 -20
- package/server/routes/data/controllers/utils/getColumns.js +8 -8
- package/server/routes/data/index.mjs +20 -20
- package/server/routes/data/schema.js +54 -54
- package/server/routes/dblist/controllers/readItems.js +20 -20
- package/server/routes/dblist/controllers/setItem.js +22 -22
- package/server/routes/dblist/index.mjs +18 -18
- package/server/routes/dblist/utils/formatData.js +7 -7
- package/server/routes/menu/controllers/getMenu.js +77 -77
- package/server/routes/menu/controllers/interfaces.js +20 -20
- package/server/routes/menu/index.mjs +7 -7
- package/server/routes/notifications/controllers/readNotifications.js +27 -27
- package/server/routes/notifications/controllers/testEmail.js +35 -35
- package/server/routes/notifications/controllers/userNotifications.js +53 -53
- package/server/routes/notifications/funcs/addNotification.js +21 -21
- package/server/routes/notifications/funcs/sendNotification.js +92 -92
- package/server/routes/notifications/hook/onWidgetSet.js +56 -56
- package/server/routes/notifications/index.mjs +26 -26
- package/server/routes/notifications/schema.js +16 -16
- package/server/routes/print/controllers/cardPrint.js +135 -135
- package/server/routes/print/controllers/printTemplate.add.js +37 -37
- package/server/routes/print/controllers/printTemplate.delete.js +29 -29
- package/server/routes/print/controllers/printTemplate.edit.js +42 -42
- package/server/routes/print/controllers/printTemplate.js +67 -67
- package/server/routes/print/controllers/printTemplateList.js +19 -19
- package/server/routes/print/controllers/printTemplatePreview.js +87 -87
- package/server/routes/print/index.mjs +19 -19
- package/server/routes/properties/controllers/admin.properties.get.js +31 -31
- package/server/routes/properties/controllers/table.properties.get.js +120 -120
- package/server/routes/properties/controllers/table.properties.post.js +115 -115
- package/server/routes/properties/controllers/user.properties.get.js +19 -19
- package/server/routes/properties/controllers/user.properties.post.js +10 -10
- package/server/routes/properties/index.mjs +21 -21
- package/server/routes/properties/schema.js +10 -10
- package/server/routes/properties/utils/dataInsert.js +26 -26
- package/server/routes/properties/utils/getColumnMetaData.js +17 -17
- package/server/routes/properties/utils/refreshData.js +128 -128
- package/server/routes/report/controllers/data.js +76 -76
- package/server/routes/report/controllers/list.js +18 -18
- package/server/routes/report/index.mjs +7 -7
- package/server/routes/report/utils/formatValue.js +179 -179
- package/server/routes/report/utils/getFilterQuery.js +67 -67
- package/server/routes/root.mjs +3 -3
- package/server/routes/templates/controllers/getTemplate.js +44 -44
- package/server/routes/templates/index.mjs +16 -16
- package/server/routes/templates/schema.js +8 -8
- package/server/routes/user/controllers/user.cls.id.js +14 -14
- package/server/routes/user/controllers/user.cls.js +72 -72
- package/server/routes/user/controllers/user.cls.post.js +54 -54
- package/server/routes/user/controllers/user.info.js +17 -17
- package/server/routes/user/schema.js +14 -14
- package/server/routes/util/controllers/code.generator.js +89 -89
- package/server/routes/util/index.mjs +5 -5
- package/server/routes/widget/controllers/widget.del.js +63 -63
- package/server/routes/widget/controllers/widget.get.js +125 -125
- package/server/routes/widget/controllers/widget.set.js +84 -84
- package/server/routes/widget/hook/onWidgetSet.js +12 -12
- package/server/routes/widget/index.mjs +16 -16
- package/server/routes/widget/schema.js +12 -12
- package/server/templates/cls/itree.recrzone_category.json +73 -73
- package/server/templates/cls/test.json +9 -9
- package/server/templates/form/admin.profile.form.json +31 -31
- package/server/templates/form/admin.user_cls.data.form.json +49 -49
- package/server/templates/form/admin.user_group_rel.form.json +21 -21
- package/server/templates/form/cp_building.form.json +32 -32
- package/server/templates/form/form-user-pass.json +10 -10
- package/server/templates/form/form-user_group.json +39 -39
- package/server/templates/form/form-users.json +156 -156
- package/server/templates/form/user_group_access.form.json +22 -22
- package/server/templates/pt/card-print.pt.hbs +245 -245
- package/server/templates/select/account_id.json +2 -2
- package/server/templates/table/gis.dataset.table.json +43 -43
- package/server/templates/table/management.user_group.table.json +112 -112
- package/server/templates/table/management.users.table.json +126 -126
- package/utils.js +26 -26
@@ -1,48 +1,48 @@
|
|
1
|
-
import { getPG, getSelect } from "@opengis/fastify-table/utils.js";
|
2
|
-
const pg = getPG();
|
3
|
-
|
4
|
-
export default async function select(ids, options) {
|
5
|
-
if (!ids || (Array.isArray(ids) && ids.length === 0) || ids === '') {
|
6
|
-
return '';
|
7
|
-
}
|
8
|
-
|
9
|
-
const data = options.hash?.data;
|
10
|
-
if (!data && data !== false && data !== 0) return '';
|
11
|
-
try {
|
12
|
-
const idsArray = Array.isArray(ids) ? ids : [ids];
|
13
|
-
|
14
|
-
const classifier = await getSelect(data);
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
if (!classifier) return `Не знайдено класифікатор ${data}`;
|
19
|
-
|
20
|
-
const arr = classifier.arr || []
|
21
|
-
if (classifier.sql && typeof classifier.sql === 'string') {
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
const metaQuery = `SELECT * FROM (${classifier.sql})q LIMIT 0`;
|
26
|
-
const meta = await pg.query(metaQuery);
|
27
|
-
const idColumn = meta.fields[0].name;
|
28
|
-
const textColumn = meta.fields[1].name;
|
29
|
-
|
30
|
-
const sql = `SELECT "${idColumn}" AS id, "${textColumn}" AS text FROM (${classifier.sql}) q WHERE "${idColumn}" = ANY($1::text[])`;
|
31
|
-
const values = [idsArray.map(id => String(id))];
|
32
|
-
|
33
|
-
const { rows } = await pg.query(sql, values);
|
34
|
-
Object.assign(arr, rows)
|
35
|
-
|
36
|
-
}
|
37
|
-
if (!arr.length) return idsArray
|
38
|
-
|
39
|
-
const results = idsArray.map(id => {
|
40
|
-
const result = arr.find(el => String(el.id) == String(id));
|
41
|
-
return result ? result.text : '';
|
42
|
-
});
|
43
|
-
|
44
|
-
return results.filter(Boolean).join(', ');
|
45
|
-
} catch (error) {
|
46
|
-
return `Сталася помилка.<!-- err: ${error.toString()} -->`;
|
47
|
-
}
|
48
|
-
}
|
1
|
+
import { getPG, getSelect } from "@opengis/fastify-table/utils.js";
|
2
|
+
const pg = getPG();
|
3
|
+
|
4
|
+
export default async function select(ids, options) {
|
5
|
+
if (!ids || (Array.isArray(ids) && ids.length === 0) || ids === '') {
|
6
|
+
return '';
|
7
|
+
}
|
8
|
+
|
9
|
+
const data = options.hash?.data;
|
10
|
+
if (!data && data !== false && data !== 0) return '';
|
11
|
+
try {
|
12
|
+
const idsArray = Array.isArray(ids) ? ids : [ids];
|
13
|
+
|
14
|
+
const classifier = await getSelect(data);
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
if (!classifier) return `Не знайдено класифікатор ${data}`;
|
19
|
+
|
20
|
+
const arr = classifier.arr || []
|
21
|
+
if (classifier.sql && typeof classifier.sql === 'string') {
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
const metaQuery = `SELECT * FROM (${classifier.sql})q LIMIT 0`;
|
26
|
+
const meta = await pg.query(metaQuery);
|
27
|
+
const idColumn = meta.fields[0].name;
|
28
|
+
const textColumn = meta.fields[1].name;
|
29
|
+
|
30
|
+
const sql = `SELECT "${idColumn}" AS id, "${textColumn}" AS text FROM (${classifier.sql}) q WHERE "${idColumn}" = ANY($1::text[])`;
|
31
|
+
const values = [idsArray.map(id => String(id))];
|
32
|
+
|
33
|
+
const { rows } = await pg.query(sql, values);
|
34
|
+
Object.assign(arr, rows)
|
35
|
+
|
36
|
+
}
|
37
|
+
if (!arr.length) return idsArray
|
38
|
+
|
39
|
+
const results = idsArray.map(id => {
|
40
|
+
const result = arr.find(el => String(el.id) == String(id));
|
41
|
+
return result ? result.text : '';
|
42
|
+
});
|
43
|
+
|
44
|
+
return results.filter(Boolean).join(', ');
|
45
|
+
} catch (error) {
|
46
|
+
return `Сталася помилка.<!-- err: ${error.toString()} -->`;
|
47
|
+
}
|
48
|
+
}
|
@@ -1,19 +1,19 @@
|
|
1
|
-
import { setToken } from "@opengis/fastify-table/utils.js";
|
2
|
-
|
3
|
-
export default function token(params) {
|
4
|
-
|
5
|
-
const { data, hash } = params;
|
6
|
-
|
7
|
-
if (!data?.root?.user?.uid && !hash.uid) return '-';
|
8
|
-
if (!hash || typeof hash !== 'object') return '-';
|
9
|
-
|
10
|
-
// const id = hash?.edit ? hash?.id : data?.root?.id;
|
11
|
-
// console.log(hash)
|
12
|
-
const [token] = setToken({
|
13
|
-
ids: [JSON.stringify(hash)],
|
14
|
-
|
15
|
-
uid: data?.root?.user?.uid || hash.uid,
|
16
|
-
array: 1,
|
17
|
-
});
|
18
|
-
return token;
|
1
|
+
import { setToken } from "@opengis/fastify-table/utils.js";
|
2
|
+
|
3
|
+
export default function token(params) {
|
4
|
+
|
5
|
+
const { data, hash } = params;
|
6
|
+
|
7
|
+
if (!data?.root?.user?.uid && !hash.uid) return '-';
|
8
|
+
if (!hash || typeof hash !== 'object') return '-';
|
9
|
+
|
10
|
+
// const id = hash?.edit ? hash?.id : data?.root?.id;
|
11
|
+
// console.log(hash)
|
12
|
+
const [token] = setToken({
|
13
|
+
ids: [JSON.stringify(hash)],
|
14
|
+
|
15
|
+
uid: data?.root?.user?.uid || hash.uid,
|
16
|
+
array: 1,
|
17
|
+
});
|
18
|
+
return token;
|
19
19
|
}
|
package/server/helpers/index.js
CHANGED
@@ -1,40 +1,40 @@
|
|
1
|
-
|
2
|
-
import { handlebars, handlebarsSync } from "@opengis/fastify-table/utils.js";
|
3
|
-
|
4
|
-
import token from "./core/token.js";
|
5
|
-
import descriptionList from "./list/descriptionList.js";
|
6
|
-
import tableList from "./list/tableList.js";
|
7
|
-
import buttonHelper from "./core/buttonHelper.js";
|
8
|
-
import select from "./core/select.js";
|
9
|
-
import badge from "./core/badge.js";
|
10
|
-
import coalesce from "./core/coalesce.js";
|
11
|
-
import mdToHTML from "./utils/mdToHTML.js";
|
12
|
-
|
13
|
-
|
14
|
-
import ifCond from "./temp/ifCond.js";
|
15
|
-
import contentList from "./temp/contentList.js";
|
16
|
-
import paddingNumber from './utils/paddingNumber.js';
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
export default async function route() {
|
21
|
-
|
22
|
-
handlebars.registerHelper('token', token);
|
23
|
-
handlebars.registerHelper('mdToHTML', mdToHTML);
|
24
|
-
handlebars.registerHelper('descriptionList', descriptionList);
|
25
|
-
handlebars.registerHelper('tableList', tableList);
|
26
|
-
handlebars.registerHelper('button', buttonHelper);
|
27
|
-
handlebars.registerHelper('select', select);
|
28
|
-
handlebars.registerHelper('badge', badge);
|
29
|
-
handlebars.registerHelper('contentList', contentList);
|
30
|
-
handlebarsSync.registerHelper('ifCond', ifCond);
|
31
|
-
handlebarsSync.registerHelper('button', buttonHelper);
|
32
|
-
handlebars.registerHelper('ifCond', ifCond);
|
33
|
-
handlebars.registerHelper('empty', () => { });
|
34
|
-
handlebarsSync.registerHelper('empty', () => { });
|
35
|
-
handlebars.registerHelper('coalesce', coalesce);
|
36
|
-
handlebarsSync.registerHelper('coalesce', coalesce);
|
37
|
-
|
38
|
-
handlebarsSync.registerHelper('paddingNumber', paddingNumber);
|
39
|
-
handlebars.registerHelper('paddingNumber', paddingNumber);
|
40
|
-
}
|
1
|
+
|
2
|
+
import { handlebars, handlebarsSync } from "@opengis/fastify-table/utils.js";
|
3
|
+
|
4
|
+
import token from "./core/token.js";
|
5
|
+
import descriptionList from "./list/descriptionList.js";
|
6
|
+
import tableList from "./list/tableList.js";
|
7
|
+
import buttonHelper from "./core/buttonHelper.js";
|
8
|
+
import select from "./core/select.js";
|
9
|
+
import badge from "./core/badge.js";
|
10
|
+
import coalesce from "./core/coalesce.js";
|
11
|
+
import mdToHTML from "./utils/mdToHTML.js";
|
12
|
+
|
13
|
+
|
14
|
+
import ifCond from "./temp/ifCond.js";
|
15
|
+
import contentList from "./temp/contentList.js";
|
16
|
+
import paddingNumber from './utils/paddingNumber.js';
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
export default async function route() {
|
21
|
+
|
22
|
+
handlebars.registerHelper('token', token);
|
23
|
+
handlebars.registerHelper('mdToHTML', mdToHTML);
|
24
|
+
handlebars.registerHelper('descriptionList', descriptionList);
|
25
|
+
handlebars.registerHelper('tableList', tableList);
|
26
|
+
handlebars.registerHelper('button', buttonHelper);
|
27
|
+
handlebars.registerHelper('select', select);
|
28
|
+
handlebars.registerHelper('badge', badge);
|
29
|
+
handlebars.registerHelper('contentList', contentList);
|
30
|
+
handlebarsSync.registerHelper('ifCond', ifCond);
|
31
|
+
handlebarsSync.registerHelper('button', buttonHelper);
|
32
|
+
handlebars.registerHelper('ifCond', ifCond);
|
33
|
+
handlebars.registerHelper('empty', () => { });
|
34
|
+
handlebarsSync.registerHelper('empty', () => { });
|
35
|
+
handlebars.registerHelper('coalesce', coalesce);
|
36
|
+
handlebarsSync.registerHelper('coalesce', coalesce);
|
37
|
+
|
38
|
+
handlebarsSync.registerHelper('paddingNumber', paddingNumber);
|
39
|
+
handlebars.registerHelper('paddingNumber', paddingNumber);
|
40
|
+
}
|
@@ -1,21 +1,21 @@
|
|
1
|
-
import buttonAdd from "../utils/buttonAdd.js";
|
2
|
-
import buttonDel from "../utils/buttonDel.js";
|
3
|
-
import buttonEdit from "../utils/buttonEdit.js";
|
4
|
-
import button from "../utils/button.js";
|
5
|
-
export default function buttonHelper(data, opt) {
|
6
|
-
const { hash } = opt;
|
7
|
-
|
8
|
-
// console.log(params)
|
9
|
-
|
10
|
-
if (!hash.token) return "token empty";
|
11
|
-
if (hash.add) {
|
12
|
-
return buttonAdd(hash.token, hash.title);
|
13
|
-
}
|
14
|
-
if (hash.del) {
|
15
|
-
return buttonDel(hash.token, hash.title);
|
16
|
-
}
|
17
|
-
if (hash.edit) {
|
18
|
-
return buttonEdit(hash.token, hash.title);
|
19
|
-
}
|
20
|
-
return button(hash.token, hash.title);
|
21
|
-
}
|
1
|
+
import buttonAdd from "../utils/buttonAdd.js";
|
2
|
+
import buttonDel from "../utils/buttonDel.js";
|
3
|
+
import buttonEdit from "../utils/buttonEdit.js";
|
4
|
+
import button from "../utils/button.js";
|
5
|
+
export default function buttonHelper(data, opt) {
|
6
|
+
const { hash } = opt;
|
7
|
+
|
8
|
+
// console.log(params)
|
9
|
+
|
10
|
+
if (!hash.token) return "token empty";
|
11
|
+
if (hash.add) {
|
12
|
+
return buttonAdd(hash.token, hash.title);
|
13
|
+
}
|
14
|
+
if (hash.del) {
|
15
|
+
return buttonDel(hash.token, hash.title);
|
16
|
+
}
|
17
|
+
if (hash.edit) {
|
18
|
+
return buttonEdit(hash.token, hash.title);
|
19
|
+
}
|
20
|
+
return button(hash.token, hash.title);
|
21
|
+
}
|
@@ -1,46 +1,46 @@
|
|
1
|
-
import { config, handlebarsSync, handlebars } from '@opengis/fastify-table/utils.js'
|
2
|
-
|
3
|
-
async function format(d, key, data) {
|
4
|
-
|
5
|
-
if (!key?.includes) return '';
|
6
|
-
if (d === true) return 'Так';
|
7
|
-
if (d === false) return 'Ні';
|
8
|
-
|
9
|
-
if (key.includes('{{')) {
|
10
|
-
return await handlebars.compile(key)(data);
|
11
|
-
}
|
12
|
-
|
13
|
-
return d;
|
14
|
-
}
|
15
|
-
export default async function descriptionList(data, opt) {
|
16
|
-
const { hash } = opt;
|
17
|
-
|
18
|
-
// no data
|
19
|
-
if (hash.nodata && !data) {
|
20
|
-
const noDataText = typeof hash.nodata == 'string' ? hash.nodata : '<div class="bg-gray-200 text-center p-6 rounded-xl"><h3 class="text-lg font-semibold">Інформація відсутня</h3></div>';
|
21
|
-
return noDataText
|
22
|
-
}
|
23
|
-
if (!hash.columns) return 'columns empty'
|
24
|
-
const keys = hash.columns.split(hash.divider || ',').map(el => hash.comma ? el.trim().replace(new RegExp(hash.comma || '#', 'g'), ',') : el.trim());
|
25
|
-
|
26
|
-
const result = [];
|
27
|
-
|
28
|
-
for (let i = 0; i < keys.length; i += 2) {
|
29
|
-
const name = keys[i];
|
30
|
-
const nameHBS = name.includes('{{') ? await handlebars.compile(name)({ ...data, hash }) : false;
|
31
|
-
|
32
|
-
if (!nameHBS && name.includes('{{')) continue;
|
33
|
-
|
34
|
-
const key = keys[i + 1];
|
35
|
-
|
36
|
-
const d1 = await format(data[key], key, data) || '-';
|
37
|
-
|
38
|
-
result.push(`<div class="grid grid-cols-1 gap-1 py-3 sm:grid-cols-3 sm:gap-4 even:bg-gray-50">
|
39
|
-
<dt class="text-gray-900">${nameHBS || name}</dt>
|
40
|
-
<dd class="text-gray-700 sm:col-span-2">${d1}</dd>
|
41
|
-
</div>
|
42
|
-
`);
|
43
|
-
|
44
|
-
}
|
45
|
-
return '<dl class=" divide-y divide-gray-100 py-[5px]">' + result.join('') + '</dl>';
|
1
|
+
import { config, handlebarsSync, handlebars } from '@opengis/fastify-table/utils.js'
|
2
|
+
|
3
|
+
async function format(d, key, data) {
|
4
|
+
|
5
|
+
if (!key?.includes) return '';
|
6
|
+
if (d === true) return 'Так';
|
7
|
+
if (d === false) return 'Ні';
|
8
|
+
|
9
|
+
if (key.includes('{{')) {
|
10
|
+
return await handlebars.compile(key)(data);
|
11
|
+
}
|
12
|
+
|
13
|
+
return d;
|
14
|
+
}
|
15
|
+
export default async function descriptionList(data, opt) {
|
16
|
+
const { hash } = opt;
|
17
|
+
|
18
|
+
// no data
|
19
|
+
if (hash.nodata && !data) {
|
20
|
+
const noDataText = typeof hash.nodata == 'string' ? hash.nodata : '<div class="bg-gray-200 text-center p-6 rounded-xl"><h3 class="text-lg font-semibold">Інформація відсутня</h3></div>';
|
21
|
+
return noDataText
|
22
|
+
}
|
23
|
+
if (!hash.columns) return 'columns empty'
|
24
|
+
const keys = hash.columns.split(hash.divider || ',').map(el => hash.comma ? el.trim().replace(new RegExp(hash.comma || '#', 'g'), ',') : el.trim());
|
25
|
+
|
26
|
+
const result = [];
|
27
|
+
|
28
|
+
for (let i = 0; i < keys.length; i += 2) {
|
29
|
+
const name = keys[i];
|
30
|
+
const nameHBS = name.includes('{{') ? await handlebars.compile(name)({ ...data, hash }) : false;
|
31
|
+
|
32
|
+
if (!nameHBS && name.includes('{{')) continue;
|
33
|
+
|
34
|
+
const key = keys[i + 1];
|
35
|
+
|
36
|
+
const d1 = await format(data[key], key, data) || '-';
|
37
|
+
|
38
|
+
result.push(`<div class="grid grid-cols-1 gap-1 py-3 sm:grid-cols-3 sm:gap-4 even:bg-gray-50">
|
39
|
+
<dt class="text-gray-900">${nameHBS || name}</dt>
|
40
|
+
<dd class="text-gray-700 sm:col-span-2">${d1}</dd>
|
41
|
+
</div>
|
42
|
+
`);
|
43
|
+
|
44
|
+
}
|
45
|
+
return '<dl class=" divide-y divide-gray-100 py-[5px]">' + result.join('') + '</dl>';
|
46
46
|
}
|
@@ -1,83 +1,83 @@
|
|
1
|
-
import { handlebarsSync, setToken, handlebars } from '@opengis/fastify-table/utils.js'
|
2
|
-
|
3
|
-
import buttonEdit from './utils/buttonEdit.js';
|
4
|
-
import buttonDel from './utils/buttonDel.js';
|
5
|
-
|
6
|
-
function format(d, key, data, hash) {
|
7
|
-
if (!key?.includes) return '';
|
8
|
-
if (d === true) return 'Так';
|
9
|
-
if (d === false) return 'Ні';
|
10
|
-
if (key === 'actions') {
|
11
|
-
return `<div class="flex items-center gap-2">${(hash.form ? buttonEdit(d, 'Редагувати') : '') + buttonDel(d)}</div>`
|
12
|
-
}
|
13
|
-
if (key.startsWith('{{')) {
|
14
|
-
return handlebars.compile(key)(data);
|
15
|
-
} else if (key.startsWith('{{') && key.includes(' ') && !(key.match(/\{\{([^\s]+)/)?.[1] in handlebars.helpers)) {
|
16
|
-
return null;
|
17
|
-
}
|
18
|
-
if (!d) return '-';
|
19
|
-
return d;
|
20
|
-
}
|
21
|
-
export default async function tableList(data, opt) {
|
22
|
-
const { hash } = opt;
|
23
|
-
// no data
|
24
|
-
// const time = Date.now();
|
25
|
-
if (hash.nodata && !data?.length) {
|
26
|
-
const noDataText = typeof hash.nodata == 'string' ? hash.nodata : '<div class="bg-gray-200 text-center p-6 rounded-xl"><h3 class="text-lg font-semibold">Інформація відсутня</h3></div>';
|
27
|
-
return noDataText
|
28
|
-
}
|
29
|
-
if (!hash.columns) return 'columns empty'
|
30
|
-
const keys = hash.columns.split(hash.divider || ',').map(el => hash.comma ? el.trim().replace(new RegExp(hash.comma, 'g'), ',') : el.trim()).concat(hash.uid && hash.table && hash.id && !hash.noactions ? ['Дії', 'actions'] : []);
|
31
|
-
|
32
|
-
const result = [];
|
33
|
-
result.push('<thead class="text-left"> <tr>');
|
34
|
-
|
35
|
-
// thead
|
36
|
-
const skip = {}
|
37
|
-
for (let i = 0; i < keys.length; i += 2) {
|
38
|
-
const name = keys[i];
|
39
|
-
|
40
|
-
// check hbs
|
41
|
-
if (name.includes('{{')) {
|
42
|
-
console.log(hash)
|
43
|
-
}
|
44
|
-
const nameHBS = name.includes('{{') ? handlebarsSync.compile(name)({ ...data, hash }) : false;
|
45
|
-
// console.log(name, data, nameHBS)
|
46
|
-
skip[name] = name.includes('{{') && !nameHBS;
|
47
|
-
if (skip[name]) continue;
|
48
|
-
|
49
|
-
result.push(`<th class="whitespace-nowrap py-3 font-medium text-gray-900 ">
|
50
|
-
${nameHBS || name}
|
51
|
-
</th>`)
|
52
|
-
}
|
53
|
-
result.push('</tr></thead><tbody class="divide-y divide-gray-200">');
|
54
|
-
|
55
|
-
// body
|
56
|
-
for (let k = 0; k < data.length; k += 1) {
|
57
|
-
const row = data[k];
|
58
|
-
result.push('<tr>');
|
59
|
-
const obj = { form: hash.form, table: hash.table, id: row[hash.id] }
|
60
|
-
const token = hash.table ? setToken({ ids: [JSON.stringify(obj)], uid: hash.uid, array: 1 })[0] : null;
|
61
|
-
for (let i = 0; i < keys.length; i += 2) {
|
62
|
-
|
63
|
-
const name = keys[i];
|
64
|
-
const key = keys[i + 1];
|
65
|
-
if (!key) continue;
|
66
|
-
if (skip[name]) continue;
|
67
|
-
|
68
|
-
const tokenData = key == 'actions' ? token : null;
|
69
|
-
const d1 = key.includes('{{') ? await handlebars.compile(key)({ ...row, token, hash }) || '-' : null
|
70
|
-
result.push(`<td class="whitespace-nowrap py-2 text-gray-900">
|
71
|
-
${d1 || format(tokenData || row[key], key, row, hash)}
|
72
|
-
</td>`);
|
73
|
-
|
74
|
-
}
|
75
|
-
// action token
|
76
|
-
|
77
|
-
result.push('</tr>');
|
78
|
-
}
|
79
|
-
result.push('</tbody>');
|
80
|
-
|
81
|
-
// console.log(Date.now() - time)
|
82
|
-
return '<table class="min-w-full divide-y-2 divide-gray-200 bg-white min-w-full divide-y-2 divide-gray-200 bg-white "> ' + result.join('') + '</table>';
|
1
|
+
import { handlebarsSync, setToken, handlebars } from '@opengis/fastify-table/utils.js'
|
2
|
+
|
3
|
+
import buttonEdit from './utils/buttonEdit.js';
|
4
|
+
import buttonDel from './utils/buttonDel.js';
|
5
|
+
|
6
|
+
function format(d, key, data, hash) {
|
7
|
+
if (!key?.includes) return '';
|
8
|
+
if (d === true) return 'Так';
|
9
|
+
if (d === false) return 'Ні';
|
10
|
+
if (key === 'actions') {
|
11
|
+
return `<div class="flex items-center gap-2">${(hash.form ? buttonEdit(d, 'Редагувати') : '') + buttonDel(d)}</div>`
|
12
|
+
}
|
13
|
+
if (key.startsWith('{{')) {
|
14
|
+
return handlebars.compile(key)(data);
|
15
|
+
} else if (key.startsWith('{{') && key.includes(' ') && !(key.match(/\{\{([^\s]+)/)?.[1] in handlebars.helpers)) {
|
16
|
+
return null;
|
17
|
+
}
|
18
|
+
if (!d) return '-';
|
19
|
+
return d;
|
20
|
+
}
|
21
|
+
export default async function tableList(data, opt) {
|
22
|
+
const { hash } = opt;
|
23
|
+
// no data
|
24
|
+
// const time = Date.now();
|
25
|
+
if (hash.nodata && !data?.length) {
|
26
|
+
const noDataText = typeof hash.nodata == 'string' ? hash.nodata : '<div class="bg-gray-200 text-center p-6 rounded-xl"><h3 class="text-lg font-semibold">Інформація відсутня</h3></div>';
|
27
|
+
return noDataText
|
28
|
+
}
|
29
|
+
if (!hash.columns) return 'columns empty'
|
30
|
+
const keys = hash.columns.split(hash.divider || ',').map(el => hash.comma ? el.trim().replace(new RegExp(hash.comma, 'g'), ',') : el.trim()).concat(hash.uid && hash.table && hash.id && !hash.noactions ? ['Дії', 'actions'] : []);
|
31
|
+
|
32
|
+
const result = [];
|
33
|
+
result.push('<thead class="text-left"> <tr>');
|
34
|
+
|
35
|
+
// thead
|
36
|
+
const skip = {}
|
37
|
+
for (let i = 0; i < keys.length; i += 2) {
|
38
|
+
const name = keys[i];
|
39
|
+
|
40
|
+
// check hbs
|
41
|
+
if (name.includes('{{')) {
|
42
|
+
console.log(hash)
|
43
|
+
}
|
44
|
+
const nameHBS = name.includes('{{') ? handlebarsSync.compile(name)({ ...data, hash }) : false;
|
45
|
+
// console.log(name, data, nameHBS)
|
46
|
+
skip[name] = name.includes('{{') && !nameHBS;
|
47
|
+
if (skip[name]) continue;
|
48
|
+
|
49
|
+
result.push(`<th class="whitespace-nowrap py-3 font-medium text-gray-900 ">
|
50
|
+
${nameHBS || name}
|
51
|
+
</th>`)
|
52
|
+
}
|
53
|
+
result.push('</tr></thead><tbody class="divide-y divide-gray-200">');
|
54
|
+
|
55
|
+
// body
|
56
|
+
for (let k = 0; k < data.length; k += 1) {
|
57
|
+
const row = data[k];
|
58
|
+
result.push('<tr>');
|
59
|
+
const obj = { form: hash.form, table: hash.table, id: row[hash.id] }
|
60
|
+
const token = hash.table ? setToken({ ids: [JSON.stringify(obj)], uid: hash.uid, array: 1 })[0] : null;
|
61
|
+
for (let i = 0; i < keys.length; i += 2) {
|
62
|
+
|
63
|
+
const name = keys[i];
|
64
|
+
const key = keys[i + 1];
|
65
|
+
if (!key) continue;
|
66
|
+
if (skip[name]) continue;
|
67
|
+
|
68
|
+
const tokenData = key == 'actions' ? token : null;
|
69
|
+
const d1 = key.includes('{{') ? await handlebars.compile(key)({ ...row, token, hash }) || '-' : null
|
70
|
+
result.push(`<td class="whitespace-nowrap py-2 text-gray-900">
|
71
|
+
${d1 || format(tokenData || row[key], key, row, hash)}
|
72
|
+
</td>`);
|
73
|
+
|
74
|
+
}
|
75
|
+
// action token
|
76
|
+
|
77
|
+
result.push('</tr>');
|
78
|
+
}
|
79
|
+
result.push('</tbody>');
|
80
|
+
|
81
|
+
// console.log(Date.now() - time)
|
82
|
+
return '<table class="min-w-full divide-y-2 divide-gray-200 bg-white min-w-full divide-y-2 divide-gray-200 bg-white "> ' + result.join('') + '</table>';
|
83
83
|
}
|
@@ -1,6 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
export default function button(token, title) {
|
4
|
-
return `<button onclick="window.v3plugin.$form({ token: '${token}' })"
|
5
|
-
class="inline-flex items-center px-2 py-1 text-sm font-medium text-white duration-300 bg-blue-600 border border-transparent rounded-lg gap-x-2 hover:bg-blue-700 hover:text-white">${title || 'Додати'}</button>`;
|
1
|
+
|
2
|
+
|
3
|
+
export default function button(token, title) {
|
4
|
+
return `<button onclick="window.v3plugin.$form({ token: '${token}' })"
|
5
|
+
class="inline-flex items-center px-2 py-1 text-sm font-medium text-white duration-300 bg-blue-600 border border-transparent rounded-lg gap-x-2 hover:bg-blue-700 hover:text-white">${title || 'Додати'}</button>`;
|
6
6
|
}
|
@@ -1,13 +1,13 @@
|
|
1
|
-
// export default function button(token, title) {
|
2
|
-
// return `<button onclick="window.v3plugin.$api({ api: '/api/table/${token}', method:'delete',confirm: { title:'Підтвердити операцію', text: 'Ви впевнені що хочете вилучити запис?', cancel: 'Скасувати', confirm : 'Виконати'} })"
|
3
|
-
// class="inline-flex items-center px-2 py-1 text-sm font-medium text-white duration-300 bg-red-600 border border-transparent rounded-lg gap-x-2 hover:bg-red-700 hover:text-white">${title || 'Вилучити'}</button>`;
|
4
|
-
// }
|
5
|
-
|
6
|
-
|
7
|
-
const newColor = 'red'
|
8
|
-
export default function button(token, title) {
|
9
|
-
return `<button onclick="window.v3plugin.$api({ api: '/api/table/${token}', method:'delete',confirm: { title:'Підтвердити операцію', text: 'Ви впевнені що хочете вилучити запис?', cancel: 'Скасувати', confirm : 'Виконати'} })"
|
10
|
-
class="group px-2 py-1 inline-flex border-solid justify-center items-center gap-2 rounded-md font-semibold focus:outline-none text-sm transition-all border border-transparent hover:text-white ring-offset-white bg-${newColor}-100 text-${newColor}-100 hover:bg-${newColor}-500 focus:ring-${newColor}-500">
|
11
|
-
<svg class="group-hover:fill-white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" width="15" height="15" fill="#ef4444"><path d="M135.2 17.7L128 32 32 32C14.3 32 0 46.3 0 64S14.3 96 32 96l384 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-96 0-7.2-14.3C307.4 6.8 296.3 0 284.2 0L163.8 0c-12.1 0-23.2 6.8-28.6 17.7zM416 128L32 128 53.2 467c1.6 25.3 22.6 45 47.9 45l245.8 0c25.3 0 46.3-19.7 47.9-45L416 128z"/></svg>
|
12
|
-
</button>`;
|
1
|
+
// export default function button(token, title) {
|
2
|
+
// return `<button onclick="window.v3plugin.$api({ api: '/api/table/${token}', method:'delete',confirm: { title:'Підтвердити операцію', text: 'Ви впевнені що хочете вилучити запис?', cancel: 'Скасувати', confirm : 'Виконати'} })"
|
3
|
+
// class="inline-flex items-center px-2 py-1 text-sm font-medium text-white duration-300 bg-red-600 border border-transparent rounded-lg gap-x-2 hover:bg-red-700 hover:text-white">${title || 'Вилучити'}</button>`;
|
4
|
+
// }
|
5
|
+
|
6
|
+
|
7
|
+
const newColor = 'red'
|
8
|
+
export default function button(token, title) {
|
9
|
+
return `<button onclick="window.v3plugin.$api({ api: '/api/table/${token}', method:'delete',confirm: { title:'Підтвердити операцію', text: 'Ви впевнені що хочете вилучити запис?', cancel: 'Скасувати', confirm : 'Виконати'} })"
|
10
|
+
class="group px-2 py-1 inline-flex border-solid justify-center items-center gap-2 rounded-md font-semibold focus:outline-none text-sm transition-all border border-transparent hover:text-white ring-offset-white bg-${newColor}-100 text-${newColor}-100 hover:bg-${newColor}-500 focus:ring-${newColor}-500">
|
11
|
+
<svg class="group-hover:fill-white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" width="15" height="15" fill="#ef4444"><path d="M135.2 17.7L128 32 32 32C14.3 32 0 46.3 0 64S14.3 96 32 96l384 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-96 0-7.2-14.3C307.4 6.8 296.3 0 284.2 0L163.8 0c-12.1 0-23.2 6.8-28.6 17.7zM416 128L32 128 53.2 467c1.6 25.3 22.6 45 47.9 45l245.8 0c25.3 0 46.3-19.7 47.9-45L416 128z"/></svg>
|
12
|
+
</button>`;
|
13
13
|
}
|
@@ -1,15 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
// export default function button(token, title) {
|
4
|
-
// return `<button onclick="window.v3plugin.$form({ token: '${token}' })"
|
5
|
-
// class="inline-flex items-center px-2 py-1 text-sm font-medium text-white duration-300 bg-blue-600 border border-transparent rounded-lg gap-x-2 hover:bg-blue-700 hover:text-white">${title || 'Редагувати'}</button>`;
|
6
|
-
// }
|
7
|
-
|
8
|
-
|
9
|
-
const newColor = 'blue'
|
10
|
-
export default function button(token, title) {
|
11
|
-
return `<button onclick="window.v3plugin.$form({ token: '${token}' })"
|
12
|
-
class="group px-2 py-1 inline-flex border-solid justify-center items-center gap-2 rounded-md font-semibold focus:outline-none text-sm transition-all border border-transparent hover:text-white ring-offset-white bg-${newColor}-100 text-${newColor}-100 hover:bg-${newColor}-500 focus:ring-${newColor}-500">
|
13
|
-
<svg class="group-hover:fill-white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="15" height="15" fill="#3b82f6"><path d="M471.6 21.7c-21.9-21.9-57.3-21.9-79.2 0L362.3 51.7l97.9 97.9 30.1-30.1c21.9-21.9 21.9-57.3 0-79.2L471.6 21.7zm-299.2 220c-6.1 6.1-10.8 13.6-13.5 21.9l-29.6 88.8c-2.9 8.6-.6 18.1 5.8 24.6s15.9 8.7 24.6 5.8l88.8-29.6c8.2-2.7 15.7-7.4 21.9-13.5L437.7 172.3 339.7 74.3 172.4 241.7zM96 64C43 64 0 107 0 160L0 416c0 53 43 96 96 96l256 0c53 0 96-43 96-96l0-96c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 96c0 17.7-14.3 32-32 32L96 448c-17.7 0-32-14.3-32-32l0-256c0-17.7 14.3-32 32-32l96 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L96 64z"/></svg>
|
14
|
-
</button>`;
|
1
|
+
|
2
|
+
|
3
|
+
// export default function button(token, title) {
|
4
|
+
// return `<button onclick="window.v3plugin.$form({ token: '${token}' })"
|
5
|
+
// class="inline-flex items-center px-2 py-1 text-sm font-medium text-white duration-300 bg-blue-600 border border-transparent rounded-lg gap-x-2 hover:bg-blue-700 hover:text-white">${title || 'Редагувати'}</button>`;
|
6
|
+
// }
|
7
|
+
|
8
|
+
|
9
|
+
const newColor = 'blue'
|
10
|
+
export default function button(token, title) {
|
11
|
+
return `<button onclick="window.v3plugin.$form({ token: '${token}' })"
|
12
|
+
class="group px-2 py-1 inline-flex border-solid justify-center items-center gap-2 rounded-md font-semibold focus:outline-none text-sm transition-all border border-transparent hover:text-white ring-offset-white bg-${newColor}-100 text-${newColor}-100 hover:bg-${newColor}-500 focus:ring-${newColor}-500">
|
13
|
+
<svg class="group-hover:fill-white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="15" height="15" fill="#3b82f6"><path d="M471.6 21.7c-21.9-21.9-57.3-21.9-79.2 0L362.3 51.7l97.9 97.9 30.1-30.1c21.9-21.9 21.9-57.3 0-79.2L471.6 21.7zm-299.2 220c-6.1 6.1-10.8 13.6-13.5 21.9l-29.6 88.8c-2.9 8.6-.6 18.1 5.8 24.6s15.9 8.7 24.6 5.8l88.8-29.6c8.2-2.7 15.7-7.4 21.9-13.5L437.7 172.3 339.7 74.3 172.4 241.7zM96 64C43 64 0 107 0 160L0 416c0 53 43 96 96 96l256 0c53 0 96-43 96-96l0-96c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 96c0 17.7-14.3 32-32 32L96 448c-17.7 0-32-14.3-32-32l0-256c0-17.7 14.3-32 32-32l96 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L96 64z"/></svg>
|
14
|
+
</button>`;
|
15
15
|
}
|