@dative-gpi/foundation-shared-components 1.0.50 → 1.0.52

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.
Files changed (34) hide show
  1. package/components/FSCard.vue +6 -2
  2. package/components/FSClickable.vue +6 -9
  3. package/components/FSDialogRemove.vue +1 -0
  4. package/components/agenda/FSAgenda.vue +210 -0
  5. package/components/agenda/FSAgendaDialogCalendar.vue +76 -0
  6. package/components/agenda/FSAgendaHeader.vue +190 -0
  7. package/components/agenda/FSAgendaHorizontalEvent.vue +162 -0
  8. package/components/agenda/FSAgendaHorizontalTimeLineMarker.vue +46 -0
  9. package/components/agenda/FSAgendaHoursCol.vue +103 -0
  10. package/components/agenda/FSAgendaHoursRow.vue +124 -0
  11. package/components/agenda/FSAgendaVerticalEvent.vue +160 -0
  12. package/components/agenda/FSAgendaVerticalTimeLineMarker.vue +46 -0
  13. package/components/agenda/FSDayAgenda.vue +200 -0
  14. package/components/agenda/FSMonthAgenda.vue +258 -0
  15. package/components/agenda/FSSelectAgendaMode.vue +54 -0
  16. package/components/agenda/FSWeekAgenda.vue +329 -0
  17. package/components/fields/FSCommentField.vue +93 -0
  18. package/components/tiles/FSChartTileUI.vue +116 -0
  19. package/components/tiles/FSCommentTileUI.vue +149 -0
  20. package/components/tiles/FSModelTileUI.vue +59 -0
  21. package/models/agenda.ts +9 -0
  22. package/models/index.ts +1 -0
  23. package/package.json +4 -4
  24. package/styles/components/fs_agenda.scss +32 -0
  25. package/styles/components/fs_agenda_event.scss +41 -0
  26. package/styles/components/fs_agenda_hours_col.scss +4 -0
  27. package/styles/components/fs_agenda_hours_row.scss +13 -0
  28. package/styles/components/fs_agenda_time_line_marker.scss +19 -0
  29. package/styles/components/fs_clickable.scss +4 -2
  30. package/styles/components/fs_dialog.scss +11 -15
  31. package/styles/components/index.scss +5 -0
  32. package/tools/alertsTools.ts +54 -0
  33. package/tools/chartsTools.ts +300 -0
  34. package/tools/index.ts +2 -0
@@ -0,0 +1,329 @@
1
+ <template>
2
+ <FSCol
3
+ class="fs-agenda-month-container"
4
+ height="100%"
5
+ width="100%"
6
+ gap="0"
7
+ >
8
+ <FSRow
9
+ gap="0"
10
+ :wrap="false"
11
+ >
12
+ <FSCol
13
+ height="100%"
14
+ :width="$props.firstColumnWidth"
15
+ >
16
+ </FSCol>
17
+
18
+ <FSAgendaHoursRow
19
+ :displayNow="$props.nowIsInSelectedRange"
20
+ :modelValue="nowHour"
21
+ />
22
+ </FSRow>
23
+ <FSRow
24
+ class="fs-agenda-month"
25
+ height="100%"
26
+ :style="style"
27
+ :wrap="false"
28
+ gap="0px"
29
+ >
30
+ <FSCol
31
+ class="fs-agenda-label-day-container"
32
+ height="100%"
33
+ gap="0"
34
+ :width="$props.firstColumnWidth"
35
+ >
36
+ <FSCol
37
+ class="fs-agenda-label-day"
38
+ v-for="day in weekDays"
39
+ :style="getDayLabelStyle(day.isNowDay)"
40
+ :key="day.dayNumber"
41
+ height="100%"
42
+ width="100%"
43
+ >
44
+ <FSCard
45
+ height="100%"
46
+ width="100%"
47
+ :borderRadius="0"
48
+ :border="false"
49
+ variant="standard"
50
+ :color="day.isNowDay ? 'primary' : 'background'"
51
+ >
52
+ <FSCol
53
+ padding="6px"
54
+ height="100%"
55
+ width="100%"
56
+ gap="2px"
57
+ align="center-left"
58
+ >
59
+ <FSCol
60
+ gap="0px"
61
+ >
62
+ <FSSpan
63
+ font="text-overline"
64
+ >
65
+ {{ day.dayName }}
66
+ </FSSpan>
67
+ <FSSpan
68
+ font="text-h3"
69
+ >
70
+ {{ to2Digits(day.dayNumber) }}
71
+ </FSSpan>
72
+ </FSCol>
73
+ <FSText
74
+ font="text-overline"
75
+ class="fs-agenda-week-number-label"
76
+ :color="weekTextColor"
77
+ >
78
+ {{ $tr('ui.common.agenda.week-short', 'W{0}',day.weekNumber) }}
79
+ </FSText>
80
+ </FSCol>
81
+ </FSCard>
82
+ </FSCol>
83
+
84
+ </FSCol>
85
+ <FSCol
86
+ class="fs-agenda-body"
87
+ gap="0"
88
+ height="100%"
89
+ width="100%"
90
+ >
91
+ <slot />
92
+ <template
93
+ v-if="loading"
94
+ >
95
+ <FSLoader
96
+ height="100%"
97
+ width="100%"
98
+ padding="2px"
99
+ />
100
+ </template>
101
+ <template
102
+ v-else
103
+ >
104
+ <FSRow
105
+ v-for="day in weekDays"
106
+ :key="day.dayNumber"
107
+ class="fs-agenda-row-day"
108
+ height="100%"
109
+ width="fill"
110
+ align="center-left"
111
+ >
112
+ <FSAgendaHorizontalEvent
113
+ v-for="event in getDayEvents(day.dayStartEpoch)"
114
+ :key="event.id"
115
+ :variant="event.end < now ? 'past' : event.start > now ? 'future' : 'current'"
116
+ :now="now"
117
+ :dayStart="day.dayStartEpoch"
118
+ :label="event.label"
119
+ :start="event.start"
120
+ :end="event.end"
121
+ :icon="event.icon"
122
+ :iconBis="event.iconBis"
123
+ :id="event.id"
124
+ :color="event.color"
125
+ @click="() => $emit('click:eventId', event.id)"
126
+ >
127
+ <template
128
+ #default="{ label, icon, timeStart, timeEnd, iconBis, variant }"
129
+ >
130
+ <FSRow
131
+ align="center-left"
132
+ gap="4px"
133
+ :wrap="false"
134
+ >
135
+ <FSCol
136
+ height="100%"
137
+ width="fill"
138
+ align="center-left"
139
+ padding="8px 0 8px 8px"
140
+ >
141
+ <FSSpan>
142
+ {{ `${timeStart} - ${timeEnd}` }}
143
+ </FSSpan>
144
+ <FSRow
145
+ align="center-left"
146
+ :wrap="false"
147
+ >
148
+ <FSIcon
149
+ v-if="icon"
150
+ :icon="icon"
151
+ size="24px"
152
+ />
153
+ <FSSpan
154
+ font="text-button"
155
+ >
156
+ {{ label }}
157
+ </FSSpan>
158
+ </FSRow>
159
+ </FSCol>
160
+ <FSCol
161
+ v-if="iconBis && variant !== 'current'"
162
+ align="center-right"
163
+ padding="8px 8px 8px 0"
164
+ width="hug"
165
+ >
166
+ <FSIcon
167
+ :icon="iconBis"
168
+ size="20px"
169
+ />
170
+ </FSCol>
171
+ </FSRow>
172
+ </template>
173
+ </FSAgendaHorizontalEvent>
174
+ </FSRow>
175
+ </template>
176
+ </FSCol>
177
+ </FSRow>
178
+ </FSCol>
179
+ </template>
180
+
181
+ <script lang="ts">
182
+ import { defineComponent, computed, type PropType, type StyleValue } from 'vue';
183
+
184
+ import { useTranslations as useTranslationsProvider } from "@dative-gpi/bones-ui";
185
+ import { useDateFormat } from "@dative-gpi/foundation-shared-services/composables";
186
+
187
+ import { useColors } from "@dative-gpi/foundation-shared-components/composables";
188
+ import { ColorEnum, type FSAgendaEvent } from "@dative-gpi/foundation-shared-components/models";
189
+
190
+ import FSAgendaHorizontalEvent from './FSAgendaHorizontalEvent.vue';
191
+ import FSAgendaHoursRow from './FSAgendaHoursRow.vue';
192
+ import FSCard from '../FSCard.vue';
193
+ import FSCol from '../FSCol.vue';
194
+ import FSRow from '../FSRow.vue';
195
+ import FSLoader from '../FSLoader.vue';
196
+ import FSSpan from '../FSSpan.vue';
197
+ import FSIcon from '../FSIcon.vue';
198
+ import FSText from '../FSText.vue';
199
+
200
+ export default defineComponent({
201
+ name: 'FSWeekAgenda',
202
+ components: {
203
+ FSAgendaHorizontalEvent,
204
+ FSAgendaHoursRow,
205
+ FSCard,
206
+ FSCol,
207
+ FSIcon,
208
+ FSLoader,
209
+ FSRow,
210
+ FSSpan,
211
+ FSText
212
+ },
213
+ props: {
214
+ now: {
215
+ type: Number,
216
+ required: true
217
+ },
218
+ start: {
219
+ type: Number,
220
+ required: true
221
+ },
222
+ end: {
223
+ type: Number,
224
+ required: true
225
+ },
226
+ nowIsInSelectedRange: {
227
+ type: Boolean,
228
+ required: true
229
+ },
230
+ firstColumnWidth: {
231
+ type: String,
232
+ required: true
233
+ },
234
+ loading: {
235
+ type: Boolean,
236
+ default: false
237
+ },
238
+ events: {
239
+ type: Array as PropType<FSAgendaEvent[]>,
240
+ default: () => []
241
+ }
242
+ },
243
+ emits: ['click:eventId'],
244
+ setup(props) {
245
+ const { $tr } = useTranslationsProvider();
246
+ const { getColors } = useColors();
247
+ const { epochToWeekNumber } = useDateFormat();
248
+
249
+ const primaryColors = getColors(ColorEnum.Primary);
250
+ const lightColors = getColors(ColorEnum.Light);
251
+
252
+ const weekTextColor = lightColors.dark;
253
+
254
+ const nowHour = computed(() => new Date(props.now).getHours());
255
+
256
+ const weekDays = computed(() => {
257
+ const daysOfWeek = [
258
+ $tr('ui.common.sunday-short', 'SUN'),
259
+ $tr('ui.common.monday-short', 'MON'),
260
+ $tr('ui.common.tuesday-short', 'TUE'),
261
+ $tr('ui.common.wednesday-short', 'WED'),
262
+ $tr('uui.common.thursday-short', 'THU'),
263
+ $tr('ui.common.friday-short', 'FRI'),
264
+ $tr('ui.common.saturday-short', 'SAT')
265
+ ];
266
+ const weekDaysArray = [];
267
+ const nowDate = new Date(props.now);
268
+
269
+ let currentDay = new Date(props.start);
270
+ const endDate = new Date(props.end);
271
+
272
+ while (currentDay <= endDate) {
273
+ weekDaysArray.push({
274
+ dayNumber: currentDay.getDate(),
275
+ dayName: daysOfWeek[currentDay.getDay()],
276
+ dayStartEpoch: currentDay.getTime(),
277
+ weekNumber: epochToWeekNumber(currentDay.getTime()),
278
+ isNowDay: currentDay.toDateString() === nowDate.toDateString(),
279
+ });
280
+
281
+ currentDay.setDate(currentDay.getDate() + 1);
282
+ }
283
+
284
+ return weekDaysArray;
285
+ });
286
+
287
+ const style = computed((): StyleValue => {
288
+ return {
289
+ '--fs-agenda-row-day-border-bottom-color': lightColors.base,
290
+ };
291
+ });
292
+
293
+ const to2Digits = (value: number | string) => {
294
+ return value.toString().padStart(2, '0');
295
+ };
296
+
297
+ const getDayLabelStyle = (isNowDay: boolean = false) => {
298
+ if (isNowDay) {
299
+ return {
300
+ '--fs-agenda-label-day-border-bottom-color': primaryColors.base,
301
+ '--fs-agenda-label-day-border-right-color': lightColors.base,
302
+ };
303
+ }
304
+ return {
305
+ '--fs-agenda-label-day-border-bottom-color': lightColors.base,
306
+ '--fs-agenda-label-day-border-right-color': lightColors.base,
307
+ };
308
+ };
309
+
310
+ const getDayEvents = (dayStartEpoch: number) => {
311
+ return props.events.filter((event) => {
312
+ const isStartingInDay = event.start >= dayStartEpoch && event.start < (dayStartEpoch + 1000 * 60 * 60 * 24);
313
+ const isEndingInDay = event.end >= dayStartEpoch && event.end < (dayStartEpoch + 1000 * 60 * 60 * 24);
314
+ return isStartingInDay || isEndingInDay;
315
+ });
316
+ };
317
+
318
+ return {
319
+ style,
320
+ nowHour,
321
+ weekDays,
322
+ weekTextColor,
323
+ getDayEvents,
324
+ getDayLabelStyle,
325
+ to2Digits
326
+ };
327
+ },
328
+ });
329
+ </script>
@@ -0,0 +1,93 @@
1
+ <template>
2
+ <FSCol>
3
+ <FSRow
4
+ align="top-left"
5
+ >
6
+ <FSImage
7
+ :imageId="userImageId"
8
+ :width="32"
9
+ :height="32"
10
+ rounded="circle"
11
+ />
12
+ <FSTextArea
13
+ :rows="5"
14
+ :hideHeader="true"
15
+ :placeholder="$tr('ui.common.write-comment', 'Write a comment...')"
16
+ v-model="innertext"
17
+ />
18
+ </FSRow>
19
+ <FSRow>
20
+ <v-spacer></v-spacer>
21
+ <FSButtonCancel
22
+ v-if="showCancelButton"
23
+ @click="$emit('cancel')"
24
+ />
25
+ <FSButton
26
+ :color="ColorEnum.Primary"
27
+ :loading="creating"
28
+ prependIcon="mdi-send-outline"
29
+ :label="buttonLabel ?? $tr('ui.common.publish','Publish')"
30
+ @click="() => $emit('submit', innertext)"
31
+ />
32
+ </FSRow>
33
+ </FSCol>
34
+ </template>
35
+
36
+ <script lang="ts">
37
+ import type { PropType} from "vue";
38
+ import { defineComponent, ref } from "vue";
39
+
40
+ import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
41
+
42
+ import FSButtonCancel from "../buttons/FSButtonCancel.vue";
43
+ import FSTextArea from "./FSTextArea.vue";
44
+ import FSButton from "../FSButton.vue";
45
+ import FSImage from "../FSImage.vue";
46
+ import FSRow from "../FSRow.vue";
47
+ import FSCol from "../FSCol.vue";
48
+
49
+ export default defineComponent({
50
+ name: "FSCommentField",
51
+ components: {
52
+ FSButton,
53
+ FSButtonCancel,
54
+ FSImage,
55
+ FSTextArea,
56
+ FSRow,
57
+ FSCol,
58
+ },
59
+ props: {
60
+ buttonLabel: {
61
+ type: String,
62
+ required: false,
63
+ },
64
+ creating: {
65
+ type: Boolean,
66
+ required: false,
67
+ },
68
+ userImageId: {
69
+ type: String as PropType<string | null>,
70
+ required: false,
71
+ },
72
+ text: {
73
+ type: String,
74
+ required: false,
75
+ },
76
+ showCancelButton: {
77
+ type: Boolean,
78
+ required: false,
79
+ default: false,
80
+ },
81
+ },
82
+ emits: ["submit","cancel"],
83
+ setup(props) {
84
+
85
+ const innertext = ref<string | undefined>(props.text);
86
+
87
+ return {
88
+ innertext,
89
+ ColorEnum
90
+ };
91
+ },
92
+ })
93
+ </script>
@@ -0,0 +1,116 @@
1
+ <template>
2
+ <FSClickable
3
+ padding="16px"
4
+ height="124px"
5
+ width="275px"
6
+ v-bind="$attrs"
7
+ >
8
+ <template
9
+ #default
10
+ >
11
+ <FSRow
12
+ align="center-left"
13
+ :wrap="false"
14
+ >
15
+ <FSCol
16
+ align="center-left"
17
+ >
18
+ <FSSpan
19
+ font="text-button"
20
+ :lineClamp="2"
21
+ >
22
+ {{ $props.label }}
23
+ </FSSpan>
24
+ <FSIcon
25
+ :color="ColorEnum.Error"
26
+ >
27
+ {{ chartIcon(type) }}
28
+ </FSIcon>
29
+ <FSSpan
30
+ font="text-overline"
31
+ >
32
+ {{ $props.categoryLabel }}
33
+ </FSSpan>
34
+ </FSCol>
35
+ <FSCol
36
+ align="center-right"
37
+ width="hug"
38
+ >
39
+ <FSImage
40
+ v-if="$props.imageId"
41
+ height="92px"
42
+ width="92px"
43
+ :imageId="$props.imageId"
44
+ />
45
+ <FSIcon
46
+ v-else-if="$props.icon"
47
+ size="92px"
48
+ :icon="$props.icon"
49
+ />
50
+ </FSCol>
51
+ </FSRow>
52
+ </template>
53
+ </FSClickable>
54
+ </template>
55
+
56
+ <script lang="ts">
57
+ import { defineComponent } from "vue";
58
+ import type { PropType } from "vue";
59
+
60
+ import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
61
+ import type { ChartType } from "@dative-gpi/foundation-shared-domain/enums";
62
+
63
+ import { chartIcon } from "@dative-gpi/foundation-shared-components/tools";
64
+
65
+ import FSClickable from "../FSClickable.vue";
66
+ import FSImage from "../FSImage.vue";
67
+ import FSSpan from "../FSSpan.vue";
68
+ import FSIcon from "../FSIcon.vue";
69
+ import FSRow from "../FSRow.vue";
70
+ import FSCol from "../FSCol.vue";
71
+
72
+ export default defineComponent({
73
+ name: "FSChartTileUI",
74
+ components: {
75
+ FSIcon,
76
+ FSImage,
77
+ FSRow,
78
+ FSCol,
79
+ FSSpan,
80
+ FSClickable
81
+ },
82
+ props: {
83
+ label: {
84
+ type: String as PropType<string | null>,
85
+ required: false,
86
+ default: null
87
+ },
88
+ imageId: {
89
+ type: String as PropType<string | null>,
90
+ required: false,
91
+ default: null
92
+ },
93
+ categoryLabel: {
94
+ type: String as PropType<string | null>,
95
+ required: false,
96
+ default: null
97
+ },
98
+ icon: {
99
+ type: String as PropType<string | null>,
100
+ required: false,
101
+ default: null
102
+ },
103
+ type: {
104
+ type: Number as PropType<ChartType>,
105
+ required: false,
106
+ default: null
107
+ }
108
+ },
109
+ setup() {
110
+ return {
111
+ ColorEnum,
112
+ chartIcon
113
+ };
114
+ }
115
+ });
116
+ </script>
@@ -0,0 +1,149 @@
1
+ <template>
2
+ <FSCol
3
+ align="center-center"
4
+ >
5
+ <FSCard
6
+ padding="8px"
7
+ width="500px"
8
+ >
9
+ <template
10
+ #header
11
+ >
12
+ <FSRow
13
+ align="center-center"
14
+ gap="12px"
15
+ >
16
+ <FSImage
17
+ :imageId="userImageId"
18
+ width="24px"
19
+ height="24px"
20
+ rounded="circle"
21
+ />
22
+ <FSText
23
+ font="text-overline"
24
+ >
25
+ {{ userName }}
26
+ -
27
+ {{ timestamp }}
28
+ </FSText>
29
+ <v-spacer />
30
+ <FSButtonEditIcon
31
+ v-if="canEditRemove"
32
+ @click="showEditComment = true"
33
+ />
34
+ <FSButtonRemoveIcon
35
+ v-if="canEditRemove"
36
+ @click="$emit('remove')"
37
+ />
38
+ </FSRow>
39
+ </template>
40
+ <template
41
+ #body
42
+ >
43
+ <FSText
44
+ class="text-wrap"
45
+ >
46
+ {{ comment }}
47
+ </FSText>
48
+ </template>
49
+ <template
50
+ #footer
51
+ >
52
+ </template>
53
+ </FSCard>
54
+ <FSCol
55
+ width="500px"
56
+ v-if="showEditComment"
57
+ >
58
+ <FSCommentField
59
+ :userImageId="userImageId"
60
+ :showCancelButton="true"
61
+ :text="comment"
62
+ @cancel="showEditComment = false"
63
+ @submit="updateComment"
64
+ />
65
+ </FSCol>
66
+ </FSCol>
67
+ </template>
68
+
69
+ <script lang="ts">
70
+ import type { PropType} from "vue";
71
+ import { defineComponent, ref } from "vue";
72
+
73
+ import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
74
+
75
+ import FSButtonRemoveIcon from "../buttons/FSButtonRemoveIcon.vue";
76
+ import FSCommentField from "../fields/FSCommentField.vue";
77
+ import FSButtonEditIcon from "../buttons/FSButtonEditIcon.vue";
78
+ import FSImage from "../FSImage.vue";
79
+ import FSCard from "../FSCard.vue";
80
+ import FSText from "../FSText.vue";
81
+ import FSCol from "../FSCol.vue";
82
+ import FSRow from "../FSRow.vue";
83
+
84
+ export default defineComponent({
85
+ name: "FSCommentTileUI",
86
+ components: {
87
+ FSButtonRemoveIcon,
88
+ FSCommentField,
89
+ FSButtonEditIcon,
90
+ FSImage,
91
+ FSCard,
92
+ FSText,
93
+ FSCol,
94
+ FSRow,
95
+ },
96
+ props: {
97
+ id: {
98
+ type: String as PropType<string | null>,
99
+ required: false,
100
+ default: null
101
+ },
102
+ userName: {
103
+ type: String as PropType<string | null>,
104
+ required: false,
105
+ default: null
106
+ },
107
+ userImageId: {
108
+ type: String as PropType<string | null>,
109
+ required: false,
110
+ default: null
111
+ },
112
+ canEditRemove: {
113
+ type: Boolean,
114
+ required: false,
115
+ default: false
116
+ },
117
+ timestamp: {
118
+ type: String as PropType<string | null>,
119
+ required: false,
120
+ default: null
121
+ },
122
+ comment: {
123
+ type: String as PropType<string | undefined>,
124
+ required: false,
125
+ default: undefined
126
+ },
127
+ edited: {
128
+ type: Boolean,
129
+ required: false,
130
+ default: false
131
+ }
132
+ },
133
+ emits: ["edit", "remove"],
134
+ setup(props, { emit }) {
135
+ const showEditComment = ref(false);
136
+
137
+ const updateComment = (comment: string) => {
138
+ emit('edit',{commentId : props.id, comment : comment})
139
+ showEditComment.value = false;
140
+ };
141
+
142
+ return {
143
+ ColorEnum,
144
+ showEditComment,
145
+ updateComment
146
+ };
147
+ }
148
+ });
149
+ </script>