@bagelink/vue 0.0.32 → 0.0.35
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/package.json +4 -2
- package/src/components/Comments.vue +30 -11
- package/src/components/ContactArray.vue +21 -6
- package/src/components/ContactSubmissions.vue +6 -3
- package/src/components/DataPreview.vue +22 -9
- package/src/components/FileUploader.vue +17 -8
- package/src/components/FormKitTable.vue +120 -71
- package/src/components/FormSchema.vue +20 -6
- package/src/components/LangText.vue +3 -1
- package/src/components/ListItem.vue +5 -1
- package/src/components/ListView.vue +25 -10
- package/src/components/MaterialIcon.vue +4 -1
- package/src/components/Modal.vue +17 -5
- package/src/components/ModalForm.vue +23 -8
- package/src/components/NavBar.vue +15 -5
- package/src/components/PersonPreview.vue +5 -7
- package/src/components/PersonPreviewFormkit.vue +5 -5
- package/src/components/RTXEditor.vue +4 -0
- package/src/components/RouterWrapper.vue +10 -2
- package/src/components/TabbedLayout.vue +8 -5
- package/src/components/TableSchema.vue +49 -14
- package/src/components/charts/BarChart.vue +35 -9
- package/src/components/dashboard/Lineart.vue +47 -15
- package/src/components/form/ItemRef.vue +10 -3
- package/src/components/form/MaterialIcon.vue +3 -3
- package/src/components/form/PlainInputField.vue +2 -3
- package/src/components/form/inputs/CheckInput.vue +3 -3
- package/src/components/form/inputs/Checkbox.vue +10 -2
- package/src/components/form/inputs/ColorPicker.vue +13 -3
- package/src/components/form/inputs/CurrencyInput.vue +7 -3
- package/src/components/form/inputs/DateInput.vue +8 -2
- package/src/components/form/inputs/DatetimeInput.vue +8 -4
- package/src/components/form/inputs/DurationInput.vue +8 -4
- package/src/components/form/inputs/DynamicLinkField.vue +9 -7
- package/src/components/form/inputs/EmailInput.vue +7 -3
- package/src/components/form/inputs/FloatInput.vue +7 -3
- package/src/components/form/inputs/IntInput.vue +8 -4
- package/src/components/form/inputs/JSONInput.vue +7 -3
- package/src/components/form/inputs/LinkField.vue +26 -19
- package/src/components/form/inputs/Password.vue +2 -0
- package/src/components/form/inputs/PasswordInput.vue +13 -10
- package/src/components/form/inputs/PlainText.vue +14 -3
- package/src/components/form/inputs/ReadOnlyInput.vue +5 -1
- package/src/components/form/inputs/RichTextEditor.vue +9 -7
- package/src/components/form/inputs/SelectField.vue +10 -5
- package/src/components/form/inputs/TableField.vue +1 -3
- package/src/components/form/inputs/TextArea.vue +11 -2
- package/src/components/form/inputs/TextInput.vue +13 -3
- package/src/components/form/inputs/index.ts +0 -1
- package/src/components/formkit/AddressArray.vue +1 -1
- package/src/components/formkit/BankDetailsArray.vue +10 -10
- package/src/components/formkit/ContactArrayFormKit.vue +58 -17
- package/src/components/formkit/FileUploader.vue +7 -7
- package/src/components/formkit/MiscFields.vue +6 -1
- package/src/components/formkit/Toggle.vue +8 -4
- package/src/components/whatsapp/form/MsgTemplate.vue +15 -8
- package/src/components/whatsapp/form/TextVariableExamples.vue +8 -3
- package/src/utils/index.ts +9 -4
- package/src/utils/modal.ts +7 -1
- package/src/utils/strings.ts +8 -1
|
@@ -1,11 +1,26 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="card list-view grid thin">
|
|
3
3
|
<div class="list-header flex gap-3 align-items-top">
|
|
4
|
-
<div
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
<div
|
|
5
|
+
v-if="enableSearch"
|
|
6
|
+
class="bagel-input search-wrap"
|
|
7
|
+
>
|
|
8
|
+
<input
|
|
9
|
+
:placeholder="searchPlaceholder"
|
|
10
|
+
v-model="searchTerm"
|
|
11
|
+
@input="search()"
|
|
12
|
+
>
|
|
13
|
+
<MaterialIcon
|
|
14
|
+
class="txtgray"
|
|
15
|
+
icon="search"
|
|
16
|
+
/>
|
|
7
17
|
</div>
|
|
8
|
-
<Btn
|
|
18
|
+
<Btn
|
|
19
|
+
color="blue"
|
|
20
|
+
v-if="enableAdd"
|
|
21
|
+
icon="add"
|
|
22
|
+
@click="emit('add')"
|
|
23
|
+
/>
|
|
9
24
|
</div>
|
|
10
25
|
<div class="list-content grid auto-flow-rows align-items-start">
|
|
11
26
|
<slot />
|
|
@@ -18,12 +33,12 @@ import { MaterialIcon, Btn } from '@/components';
|
|
|
18
33
|
import { debounce } from '@/utils';
|
|
19
34
|
|
|
20
35
|
defineProps<{
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
>()
|
|
36
|
+
enableAdd: boolean;
|
|
37
|
+
enableSearch: boolean;
|
|
38
|
+
open: boolean;
|
|
39
|
+
searchPlaceholder: string;
|
|
40
|
+
}
|
|
41
|
+
>();
|
|
27
42
|
const emit = defineEmits(['search', 'add', 'debounce']);
|
|
28
43
|
const searchTerm = $ref('');
|
|
29
44
|
const search = () => {
|
package/src/components/Modal.vue
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
<div
|
|
3
|
+
class="bg-dark"
|
|
4
|
+
:class="{ 'is-side': side, 'is-active': isActive }"
|
|
5
|
+
@click="() => (dismissable ? closeModal() : '')"
|
|
6
|
+
@keydown.esc="closeModal"
|
|
7
|
+
>
|
|
8
|
+
<div
|
|
9
|
+
class="card modal"
|
|
10
|
+
@click.stop
|
|
11
|
+
>
|
|
5
12
|
<header class="tool-bar">
|
|
6
13
|
<slot name="toolbar" />
|
|
7
14
|
</header>
|
|
@@ -10,7 +17,13 @@
|
|
|
10
17
|
</h3>
|
|
11
18
|
<slot />
|
|
12
19
|
<footer class="modal-footer mt-3">
|
|
13
|
-
<Btn
|
|
20
|
+
<Btn
|
|
21
|
+
v-for="(action, i) in actions"
|
|
22
|
+
:key="i"
|
|
23
|
+
@click="closeModal"
|
|
24
|
+
color="gray"
|
|
25
|
+
v-bind="action"
|
|
26
|
+
/>
|
|
14
27
|
<slot name="footer" />
|
|
15
28
|
</footer>
|
|
16
29
|
</div>
|
|
@@ -47,4 +60,3 @@ const closeModal = () => {
|
|
|
47
60
|
}, 200);
|
|
48
61
|
};
|
|
49
62
|
</script>
|
|
50
|
-
|
|
@@ -1,19 +1,32 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
|
-
class="bg-dark"
|
|
4
|
-
|
|
3
|
+
class="bg-dark"
|
|
4
|
+
:class="{ 'is-side': side, 'is-active': isActive }"
|
|
5
|
+
@click="() => (dismissable ? closeModal() : '')"
|
|
6
|
+
@keydown.esc="closeModal"
|
|
5
7
|
>
|
|
6
|
-
<div
|
|
8
|
+
<div
|
|
9
|
+
class="card modal"
|
|
10
|
+
@click.stop
|
|
11
|
+
>
|
|
7
12
|
<header class="tool-bar">
|
|
8
13
|
<slot name="toolbar" />
|
|
9
|
-
<Btn
|
|
14
|
+
<Btn
|
|
15
|
+
:style="{ float: side ? 'left' : 'right' }"
|
|
16
|
+
flat
|
|
17
|
+
icon="close"
|
|
18
|
+
@click="closeModal"
|
|
19
|
+
/>
|
|
10
20
|
<h3 class="modal-title">
|
|
11
21
|
{{ title }}
|
|
12
22
|
</h3>
|
|
13
23
|
</header>
|
|
14
24
|
<FormSchema
|
|
15
|
-
:onDelete="onDelete?runDelete
|
|
16
|
-
|
|
25
|
+
:onDelete="onDelete ? runDelete : null"
|
|
26
|
+
:modelValue="modelValue"
|
|
27
|
+
@update:modelValue="handleEmit"
|
|
28
|
+
@submit="runSubmit"
|
|
29
|
+
:schema="computedFormSchema"
|
|
17
30
|
/>
|
|
18
31
|
</div>
|
|
19
32
|
</div>
|
|
@@ -33,9 +46,11 @@ const props = defineProps<{
|
|
|
33
46
|
title?: string;
|
|
34
47
|
dismissable?: boolean;
|
|
35
48
|
actions?: BtnOptions[];
|
|
36
|
-
schema:FormKitSchemaDefinition |(() => FormKitSchemaDefinition);
|
|
49
|
+
schema: FormKitSchemaDefinition | (() => FormKitSchemaDefinition);
|
|
37
50
|
modelValue?: Record<string, any>;
|
|
38
|
-
|
|
51
|
+
// eslint-disable-next-line no-unused-vars
|
|
52
|
+
onSubmit?: ((formData: any) => Promise<void>);
|
|
53
|
+
// eslint-disable-next-line no-unused-vars
|
|
39
54
|
onDelete?: ((id: string) => void);
|
|
40
55
|
}>();
|
|
41
56
|
|
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
<div :class="{ open: isOpen, closed: !isOpen }">
|
|
3
3
|
<slot name="top" />
|
|
4
4
|
<div
|
|
5
|
-
class="nav-expend"
|
|
6
|
-
|
|
5
|
+
class="nav-expend"
|
|
6
|
+
@click="isOpen = !isOpen"
|
|
7
|
+
@keypress.enter="isOpen = !isOpen"
|
|
8
|
+
role="button"
|
|
9
|
+
aria-label="Toggle Navigation"
|
|
10
|
+
tabindex="0"
|
|
7
11
|
>
|
|
8
12
|
<div class="icon-font top-arrow">
|
|
9
13
|
chevron_right
|
|
@@ -13,7 +17,12 @@
|
|
|
13
17
|
<div class="full-nav">
|
|
14
18
|
<div class="nav-scroll">
|
|
15
19
|
<div class="nav-links-wrapper">
|
|
16
|
-
<RouterLink
|
|
20
|
+
<RouterLink
|
|
21
|
+
v-for="link in links"
|
|
22
|
+
class="nav-button"
|
|
23
|
+
:to="link.to"
|
|
24
|
+
:key="link.label"
|
|
25
|
+
>
|
|
17
26
|
<div class="icon-font">
|
|
18
27
|
{{ link.materialIcon }}
|
|
19
28
|
</div>
|
|
@@ -32,7 +41,6 @@
|
|
|
32
41
|
</template>
|
|
33
42
|
|
|
34
43
|
<script lang="ts" setup>
|
|
35
|
-
|
|
36
44
|
// import LangText from "../translation/LangText.vue"
|
|
37
45
|
import type { MaterialIcons } from '@/types/materialIcons';
|
|
38
46
|
|
|
@@ -79,9 +87,11 @@ withDefaults(
|
|
|
79
87
|
transition: all 0.4s cubic-bezier(0.36, 0.02, 0.23, 1);
|
|
80
88
|
}
|
|
81
89
|
|
|
90
|
+
/*
|
|
82
91
|
.nav-home-wrapper {
|
|
83
|
-
|
|
92
|
+
margin-bottom: 30px;
|
|
84
93
|
}
|
|
94
|
+
*/
|
|
85
95
|
|
|
86
96
|
.nav-expend {
|
|
87
97
|
background: white;
|
|
@@ -75,28 +75,26 @@
|
|
|
75
75
|
</template>
|
|
76
76
|
|
|
77
77
|
<script lang="ts" setup>
|
|
78
|
+
import { useBagel } from 'src/plugins/bagel';
|
|
79
|
+
import type { FormKitSchemaDefinition } from '@formkit/core';
|
|
78
80
|
import type { Person } from '@/types';
|
|
79
81
|
import {
|
|
80
82
|
initials, useModal,
|
|
81
83
|
} from '@/utils';
|
|
82
84
|
import { Btn, MaterialIcon } from '@/components';
|
|
83
|
-
import { useBagel } from 'src/plugins/bagel';
|
|
84
|
-
import type { FormKitSchemaDefinition } from '@formkit/core';
|
|
85
|
-
|
|
86
85
|
|
|
87
86
|
// const toast = useToast(); // TODO: use toast
|
|
88
87
|
const bagel = useBagel();
|
|
89
88
|
const { modalForm } = useModal();
|
|
90
89
|
|
|
91
|
-
|
|
92
90
|
const props = defineProps<{
|
|
93
91
|
person: Person;
|
|
94
|
-
|
|
92
|
+
// eslint-disable-next-line no-unused-vars
|
|
93
|
+
onClick?: ((event: MouseEvent) => void);
|
|
95
94
|
personSchema: () => FormKitSchemaDefinition;
|
|
96
95
|
}>();
|
|
97
96
|
|
|
98
97
|
const showEditForm = async () => {
|
|
99
|
-
|
|
100
98
|
const { first_name, last_name } = props.person;
|
|
101
99
|
modalForm({
|
|
102
100
|
side: true,
|
|
@@ -104,7 +102,7 @@ const showEditForm = async () => {
|
|
|
104
102
|
schema: props.personSchema,
|
|
105
103
|
modelValue: props.person,
|
|
106
104
|
onSubmit: (newPerson) => bagel
|
|
107
|
-
.put('/person', newPerson)
|
|
105
|
+
.put('/person', newPerson),
|
|
108
106
|
// .then(() => toast.success($t('updatedSuccessfully'))),
|
|
109
107
|
});
|
|
110
108
|
};
|
|
@@ -76,14 +76,13 @@
|
|
|
76
76
|
</template>
|
|
77
77
|
|
|
78
78
|
<script lang="ts" setup>
|
|
79
|
-
|
|
79
|
+
import { useBagel } from 'src/plugins/bagel';
|
|
80
|
+
import type { FormKitSchemaDefinition } from '@formkit/core';
|
|
80
81
|
import type { Person } from '@/types';
|
|
81
82
|
import {
|
|
82
83
|
useModal, initials,
|
|
83
84
|
} from '@/utils';
|
|
84
85
|
import { Btn, MaterialIcon } from '@/components';
|
|
85
|
-
import { useBagel } from 'src/plugins/bagel';
|
|
86
|
-
import type { FormKitSchemaDefinition } from '@formkit/core';
|
|
87
86
|
|
|
88
87
|
// const toast = useToast(); // TODO: use toast
|
|
89
88
|
const bagel = useBagel();
|
|
@@ -91,7 +90,8 @@ const { modalForm, hideModal } = useModal();
|
|
|
91
90
|
|
|
92
91
|
const props = defineProps<{
|
|
93
92
|
context: Record<string, any>;
|
|
94
|
-
|
|
93
|
+
// eslint-disable-next-line no-unused-vars
|
|
94
|
+
onClick?: ((event: MouseEvent) => void);
|
|
95
95
|
personSchema: () => FormKitSchemaDefinition;
|
|
96
96
|
}>();
|
|
97
97
|
|
|
@@ -104,7 +104,7 @@ const showEditForm = async () => {
|
|
|
104
104
|
title: `${first_name} ${last_name}`,
|
|
105
105
|
schema: props.personSchema,
|
|
106
106
|
modelValue: person,
|
|
107
|
-
onSubmit: (newPerson) => bagel.put('/person', newPerson)
|
|
107
|
+
onSubmit: (newPerson) => bagel.put('/person', newPerson),
|
|
108
108
|
// .then(() => toast.success($t('updatedSuccessfully'))), // TODO: use toast
|
|
109
109
|
});
|
|
110
110
|
};
|
|
@@ -111,9 +111,11 @@ function focusEditor() {
|
|
|
111
111
|
padding: 0.55rem;
|
|
112
112
|
min-height: 40px;
|
|
113
113
|
}
|
|
114
|
+
|
|
114
115
|
.new-comment .ProseMirror p {
|
|
115
116
|
margin: 0;
|
|
116
117
|
}
|
|
118
|
+
|
|
117
119
|
.comment-input .ProseMirror {
|
|
118
120
|
background-color: var(--bgl-bg);
|
|
119
121
|
margin-inline-start: 0;
|
|
@@ -128,6 +130,7 @@ function focusEditor() {
|
|
|
128
130
|
border: none;
|
|
129
131
|
box-shadow: inset 0 0 10px #00000012;
|
|
130
132
|
}
|
|
133
|
+
|
|
131
134
|
.ProseMirror,
|
|
132
135
|
.editor-wrapper {
|
|
133
136
|
height: 100%;
|
|
@@ -136,6 +139,7 @@ function focusEditor() {
|
|
|
136
139
|
border-radius: var(--btn-border-radius);
|
|
137
140
|
margin-inline-start: 1rem;
|
|
138
141
|
}
|
|
142
|
+
|
|
139
143
|
.ProseMirror p,
|
|
140
144
|
.editor-wrapper p {
|
|
141
145
|
margin: 0;
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<router-view v-slot="{ Component, route }">
|
|
3
|
-
<transition
|
|
4
|
-
|
|
3
|
+
<transition
|
|
4
|
+
:duration="300"
|
|
5
|
+
name="slide-fade"
|
|
6
|
+
mode="out-in"
|
|
7
|
+
appear
|
|
8
|
+
>
|
|
9
|
+
<component
|
|
10
|
+
:is="Component"
|
|
11
|
+
:key="route?.params.itemID"
|
|
12
|
+
/>
|
|
5
13
|
</transition>
|
|
6
14
|
</router-view>
|
|
7
15
|
</template>
|
|
@@ -24,7 +24,10 @@
|
|
|
24
24
|
v-for="tab in tabs.filter((item) => item === activeTab)"
|
|
25
25
|
:key="tab"
|
|
26
26
|
>
|
|
27
|
-
<slot
|
|
27
|
+
<slot
|
|
28
|
+
:name="tab"
|
|
29
|
+
:key="tab"
|
|
30
|
+
/>
|
|
28
31
|
</div>
|
|
29
32
|
</div>
|
|
30
33
|
</template>
|
|
@@ -44,9 +47,9 @@ const props = defineProps<{
|
|
|
44
47
|
}>();
|
|
45
48
|
|
|
46
49
|
function changeTab(tab: string) {
|
|
47
|
-
const router = props
|
|
50
|
+
const { router } = props;
|
|
48
51
|
activeTab = tab;
|
|
49
|
-
router.push({
|
|
52
|
+
void router.push({
|
|
50
53
|
path: router.currentRoute.value.path,
|
|
51
54
|
query: { ...router.currentRoute.value.query, t: tab },
|
|
52
55
|
hash: router.currentRoute.value.hash,
|
|
@@ -55,7 +58,7 @@ function changeTab(tab: string) {
|
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
onMounted(() => {
|
|
58
|
-
const firstTab =
|
|
61
|
+
const firstTab = props.modelValue || props.router.currentRoute.value.query.t || props.tabs[0];
|
|
59
62
|
activeTab = firstTab as string;
|
|
60
63
|
});
|
|
61
64
|
</script>
|
|
@@ -73,7 +76,7 @@ onMounted(() => {
|
|
|
73
76
|
.detail-section {
|
|
74
77
|
grid-area: detail-section;
|
|
75
78
|
} */
|
|
76
|
-
.card.tabs-top{
|
|
79
|
+
.card.tabs-top {
|
|
77
80
|
width: 99%;
|
|
78
81
|
|
|
79
82
|
}
|
|
@@ -3,19 +3,48 @@
|
|
|
3
3
|
<!-- <div v-for="field in schema" :key="field.id">{{ parseLocale(field.label) }}</div> -->
|
|
4
4
|
<table class="infinite-wrapper">
|
|
5
5
|
<thead class="row first-row">
|
|
6
|
-
<th
|
|
6
|
+
<th
|
|
7
|
+
class="col"
|
|
8
|
+
v-for="field in columns"
|
|
9
|
+
:key="field.id"
|
|
10
|
+
@click="sort(field.id)"
|
|
11
|
+
>
|
|
7
12
|
<div class="flex">
|
|
8
13
|
{{ parseLocale(field.label || field.id) }}
|
|
9
|
-
<div
|
|
10
|
-
|
|
14
|
+
<div
|
|
15
|
+
class="list-arrows"
|
|
16
|
+
:class="{ sorted: sortField === field.id }"
|
|
17
|
+
>
|
|
18
|
+
<MaterialIcon
|
|
19
|
+
:class="{ desc: sortDirection === 'DESC' }"
|
|
20
|
+
icon="keyboard_arrow_up"
|
|
21
|
+
/>
|
|
11
22
|
</div>
|
|
12
23
|
</div>
|
|
13
24
|
</th>
|
|
14
25
|
</thead>
|
|
15
|
-
<tbody
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
26
|
+
<tbody
|
|
27
|
+
ref="infinite"
|
|
28
|
+
class="rows infinite"
|
|
29
|
+
:class="{ loading }"
|
|
30
|
+
>
|
|
31
|
+
<tr
|
|
32
|
+
@click="selectElement(row)"
|
|
33
|
+
class="row row-item position-relative"
|
|
34
|
+
v-for="row in data"
|
|
35
|
+
:key="row.id"
|
|
36
|
+
>
|
|
37
|
+
<td
|
|
38
|
+
class="col"
|
|
39
|
+
v-for="field in columns"
|
|
40
|
+
:key="`${field.id}-${row.id}`"
|
|
41
|
+
>
|
|
42
|
+
<slot
|
|
43
|
+
v-if="slots[field.id]"
|
|
44
|
+
:name="field.id"
|
|
45
|
+
:row="row"
|
|
46
|
+
:field="field"
|
|
47
|
+
/>
|
|
19
48
|
<div v-else>
|
|
20
49
|
<component
|
|
21
50
|
:is="field.$el || field.$cmp || 'div'"
|
|
@@ -39,7 +68,6 @@ import { useSlots } from 'vue';
|
|
|
39
68
|
import { MaterialIcon } from '@/components';
|
|
40
69
|
import { parseLocale } from '@/utils';
|
|
41
70
|
|
|
42
|
-
|
|
43
71
|
const slots = useSlots();
|
|
44
72
|
const loading = $ref(true);
|
|
45
73
|
|
|
@@ -48,15 +76,21 @@ const props = defineProps<{
|
|
|
48
76
|
schema?: any[];
|
|
49
77
|
}>();
|
|
50
78
|
|
|
51
|
-
|
|
52
79
|
const emit = defineEmits(['select']);
|
|
53
80
|
|
|
54
81
|
const selectElement = (data: Record<string, any>) => {
|
|
55
82
|
emit('select', data);
|
|
56
83
|
};
|
|
57
84
|
|
|
58
|
-
const bindAttrs = (attrs: Record<string,
|
|
59
|
-
const arr = Object.entries(
|
|
85
|
+
const bindAttrs = (attrs: Record<string, any>, field: any, row: any) => {
|
|
86
|
+
const arr = Object.entries(
|
|
87
|
+
attrs || {},
|
|
88
|
+
)
|
|
89
|
+
.map(
|
|
90
|
+
([key, value]) => [
|
|
91
|
+
key, typeof value === 'function' ? value(field, row) : value,
|
|
92
|
+
],
|
|
93
|
+
);
|
|
60
94
|
const resolvedAttrs = Object.fromEntries(arr);
|
|
61
95
|
return resolvedAttrs;
|
|
62
96
|
};
|
|
@@ -76,11 +110,12 @@ const sort = (fieldname: string) => {
|
|
|
76
110
|
};
|
|
77
111
|
|
|
78
112
|
const columns = $computed(
|
|
79
|
-
() =>
|
|
80
|
-
|
|
113
|
+
() => (
|
|
114
|
+
props.schema ||
|
|
115
|
+
Object.keys(props.data[0]).map((k: string) => ({
|
|
81
116
|
id: k,
|
|
82
117
|
inputType: 'PlainText',
|
|
83
|
-
})),
|
|
118
|
+
}))),
|
|
84
119
|
);
|
|
85
120
|
</script>
|
|
86
121
|
|
|
@@ -1,24 +1,47 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="bar-chart">
|
|
3
|
-
<div
|
|
4
|
-
|
|
3
|
+
<div
|
|
4
|
+
class="graph-wrap"
|
|
5
|
+
v-for="(item, i) in dataArray"
|
|
6
|
+
:key="i"
|
|
7
|
+
>
|
|
8
|
+
<div
|
|
9
|
+
class="group-wrap"
|
|
10
|
+
v-if="item.group"
|
|
11
|
+
>
|
|
5
12
|
<p class="group-title">
|
|
6
13
|
{{ item.group }}
|
|
7
14
|
</p>
|
|
8
|
-
<div
|
|
9
|
-
|
|
15
|
+
<div
|
|
16
|
+
v-for="(nested, i) in item?.data || []"
|
|
17
|
+
:key="i"
|
|
18
|
+
class="bar-wrap"
|
|
19
|
+
>
|
|
20
|
+
<div
|
|
21
|
+
class="bar"
|
|
22
|
+
:style="{ height: loaded ? `${percent(nested.value)}%` : '0' }"
|
|
23
|
+
/>
|
|
10
24
|
<div
|
|
11
|
-
class="bar compare"
|
|
25
|
+
class="bar compare"
|
|
26
|
+
v-if="nested.compareValue"
|
|
27
|
+
:style="{
|
|
12
28
|
height: loaded ? `${percent(nested.compareValue)}%` : '0',
|
|
13
29
|
}"
|
|
14
30
|
/>
|
|
15
31
|
<!-- <p class="bar-txt">{{ nested.title }}</p> -->
|
|
16
32
|
</div>
|
|
17
33
|
</div>
|
|
18
|
-
<div
|
|
19
|
-
|
|
34
|
+
<div
|
|
35
|
+
v-else
|
|
36
|
+
class="bar-wrap"
|
|
37
|
+
>
|
|
38
|
+
<div
|
|
39
|
+
class="bar"
|
|
40
|
+
:style="{ height: loaded ? `${percent(item.value)}%` : '0' }"
|
|
41
|
+
/>
|
|
20
42
|
<div
|
|
21
|
-
class="bar compare"
|
|
43
|
+
class="bar compare"
|
|
44
|
+
v-if="item?.compareValue"
|
|
22
45
|
:style="{ height: loaded ? `${percent(item.compareValue)}%` : '0' }"
|
|
23
46
|
/>
|
|
24
47
|
<p class="bar-txt">
|
|
@@ -31,7 +54,10 @@
|
|
|
31
54
|
</p>
|
|
32
55
|
<div class="red-bar" />
|
|
33
56
|
<div class="bar-lines">
|
|
34
|
-
<p
|
|
57
|
+
<p
|
|
58
|
+
v-for="mark in marks"
|
|
59
|
+
:key="mark"
|
|
60
|
+
>
|
|
35
61
|
{{ mark.toLocaleString() }}
|
|
36
62
|
</p>
|
|
37
63
|
</div>
|
|
@@ -1,29 +1,64 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
|
|
2
|
+
<div
|
|
3
|
+
ref="chartContainer"
|
|
4
|
+
class="chart-line"
|
|
5
|
+
>
|
|
6
|
+
<Chart
|
|
7
|
+
v-if="chartSize"
|
|
8
|
+
:size="chartSize"
|
|
9
|
+
:data="data"
|
|
10
|
+
:margin="chartMargin"
|
|
11
|
+
:axis="axisConfig"
|
|
12
|
+
>
|
|
4
13
|
<template #layers>
|
|
5
|
-
<Grid
|
|
14
|
+
<Grid
|
|
15
|
+
:center="true"
|
|
16
|
+
strokeDasharray="2,2"
|
|
17
|
+
:hideY="true"
|
|
18
|
+
/>
|
|
6
19
|
<Area
|
|
7
|
-
aria-label="Profit/Loss"
|
|
20
|
+
aria-label="Profit/Loss"
|
|
21
|
+
:dataKeys="['date', 'total_value']"
|
|
22
|
+
type="monotone"
|
|
8
23
|
:areaStyle="{ fill: 'url(#grad)' }"
|
|
9
24
|
/>
|
|
10
25
|
<Line
|
|
11
|
-
:dataKeys="['date', 'total_value']"
|
|
26
|
+
:dataKeys="['date', 'total_value']"
|
|
27
|
+
type="monotone"
|
|
28
|
+
:dotStyle="dotStyling"
|
|
12
29
|
:lineStyle="{ stroke: BRAND_COLOR, r: 2 }"
|
|
13
30
|
/>
|
|
14
31
|
<Marker
|
|
15
|
-
v-if="displayMarker"
|
|
32
|
+
v-if="displayMarker"
|
|
33
|
+
:value="meanValue"
|
|
34
|
+
label="ממוצע"
|
|
35
|
+
:color="BRAND_COLOR"
|
|
36
|
+
:strokeWidth="2"
|
|
16
37
|
strokeDasharray="6 6"
|
|
17
38
|
/>
|
|
18
39
|
<defs>
|
|
19
|
-
<linearGradient
|
|
20
|
-
|
|
21
|
-
|
|
40
|
+
<linearGradient
|
|
41
|
+
id="grad"
|
|
42
|
+
gradientTransform="rotate(90)"
|
|
43
|
+
>
|
|
44
|
+
<stop
|
|
45
|
+
offset="0%"
|
|
46
|
+
:stop-color="BRAND_COLOR"
|
|
47
|
+
stop-opacity="1"
|
|
48
|
+
/>
|
|
49
|
+
<stop
|
|
50
|
+
offset="100%"
|
|
51
|
+
stop-color="white"
|
|
52
|
+
stop-opacity="0.4"
|
|
53
|
+
/>
|
|
22
54
|
</linearGradient>
|
|
23
55
|
</defs>
|
|
24
56
|
</template>
|
|
25
57
|
<template #widgets>
|
|
26
|
-
<Tooltip
|
|
58
|
+
<Tooltip
|
|
59
|
+
color="white"
|
|
60
|
+
:config="tooltipConfiguration"
|
|
61
|
+
/>
|
|
27
62
|
</template>
|
|
28
63
|
</Chart>
|
|
29
64
|
</div>
|
|
@@ -31,17 +66,14 @@
|
|
|
31
66
|
|
|
32
67
|
<script lang="ts" setup>
|
|
33
68
|
import { onMounted, onUnmounted } from 'vue';
|
|
34
|
-
import { useI18n } from 'vue-i18n';
|
|
35
69
|
import {
|
|
36
70
|
Chart, Grid, Line, Area, Tooltip, Marker,
|
|
37
71
|
} from 'vue3-charts';
|
|
38
72
|
import type { ChartAxis, Data } from 'vue3-charts/dist/types';
|
|
39
73
|
|
|
40
|
-
const props = defineProps<{ data: Data[] }>();
|
|
41
|
-
|
|
42
|
-
const { locale } = useI18n();
|
|
74
|
+
const props = defineProps<{ data: Data[], locale: string }>();
|
|
43
75
|
|
|
44
|
-
const data = $computed(() => (locale
|
|
76
|
+
const data = $computed(() => (props.locale === 'he' ? [...props.data].reverse() : props.data));
|
|
45
77
|
|
|
46
78
|
interface Size {
|
|
47
79
|
width: number;
|
|
@@ -2,11 +2,18 @@
|
|
|
2
2
|
<div>
|
|
3
3
|
{{ field.label || field.id }}
|
|
4
4
|
|
|
5
|
-
<Btn
|
|
5
|
+
<Btn
|
|
6
|
+
color="gray"
|
|
7
|
+
@click="openModal()"
|
|
8
|
+
v-if="field.refCollection"
|
|
9
|
+
>
|
|
6
10
|
{{ content }}
|
|
7
11
|
<MaterialIcon icon="arrow_forward" />
|
|
8
12
|
</Btn>
|
|
9
|
-
<span
|
|
13
|
+
<span
|
|
14
|
+
v-else
|
|
15
|
+
class="pill"
|
|
16
|
+
>
|
|
10
17
|
{{ content }}
|
|
11
18
|
</span>
|
|
12
19
|
</div>
|
|
@@ -33,6 +40,6 @@ const content = computed(() => props.field.refFields?.map((k) => props.modelValu
|
|
|
33
40
|
const openModal = () => {
|
|
34
41
|
console.log(`openning ${props.modelValue?.id}`);
|
|
35
42
|
openRef.value = true;
|
|
36
|
-
router.push(`/${props.field.refCollection}/${props.modelValue?.id}`);
|
|
43
|
+
void router.push(`/${props.field.refCollection}/${props.modelValue?.id}`);
|
|
37
44
|
};
|
|
38
45
|
</script>
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
</template>
|
|
9
9
|
|
|
10
10
|
<script setup lang="ts">
|
|
11
|
-
import { MaterialIcons } from '
|
|
11
|
+
import { MaterialIcons } from '@/types/materialIcons';
|
|
12
12
|
|
|
13
13
|
defineProps<{
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
icon: MaterialIcons
|
|
15
|
+
size?: number
|
|
16
16
|
}>();
|
|
17
17
|
</script>
|
|
18
18
|
|