@dative-gpi/foundation-shared-components 1.0.51 → 1.0.53

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 (36) 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/FSLocationTileUI.vue +138 -0
  21. package/components/tiles/FSModelTileUI.vue +59 -0
  22. package/models/agenda.ts +9 -0
  23. package/models/index.ts +1 -0
  24. package/package.json +4 -4
  25. package/styles/components/fs_agenda.scss +32 -0
  26. package/styles/components/fs_agenda_event.scss +41 -0
  27. package/styles/components/fs_agenda_hours_col.scss +4 -0
  28. package/styles/components/fs_agenda_hours_row.scss +13 -0
  29. package/styles/components/fs_agenda_time_line_marker.scss +19 -0
  30. package/styles/components/fs_clickable.scss +4 -2
  31. package/styles/components/fs_dialog.scss +11 -15
  32. package/styles/components/fs_tile.scss +4 -0
  33. package/styles/components/index.scss +5 -0
  34. package/tools/alertsTools.ts +54 -0
  35. package/tools/chartsTools.ts +300 -0
  36. package/tools/index.ts +2 -0
@@ -165,12 +165,16 @@ export default defineComponent({
165
165
  });
166
166
 
167
167
  const classes = computed((): string[] => {
168
- const classNames = ["fs-card", "fs-background"];
168
+ const classNames = ["fs-card"];
169
169
  switch(props.variant) {
170
170
  case "gradient":
171
171
  classNames.push("fs-card-gradient");
172
172
  break;
173
- default:
173
+ case "background":
174
+ classNames.push("fs-card-background");
175
+ classNames.push("fs-card-clickable");
176
+ break;
177
+ default:
174
178
  classNames.push("fs-card-background");
175
179
  break;
176
180
  }
@@ -10,13 +10,12 @@
10
10
  @mouseup="active = false"
11
11
  >
12
12
  <FSCard
13
+ height="100%"
14
+ width="100%"
13
15
  :borderRadius="$props.borderRadius"
14
16
  :borderStyle="$props.borderStyle"
15
17
  :padding="$props.padding"
16
- :height="$props.height"
17
- :width="$props.width"
18
18
  :class="classes"
19
- :style="style"
20
19
  v-bind="$attrs"
21
20
  >
22
21
  <template
@@ -52,13 +51,12 @@
52
51
  @mouseup="active = false"
53
52
  >
54
53
  <FSCard
54
+ height="100%"
55
+ width="100%"
55
56
  :borderRadius="$props.borderRadius"
56
57
  :borderStyle="$props.borderStyle"
57
58
  :padding="$props.padding"
58
- :height="$props.height"
59
- :width="$props.width"
60
59
  :class="classes"
61
- :style="style"
62
60
  v-bind="$attrs"
63
61
  >
64
62
  <template
@@ -95,13 +93,12 @@
95
93
  @mouseup="active = false"
96
94
  >
97
95
  <FSCard
96
+ height="100%"
97
+ width="100%"
98
98
  :borderRadius="$props.borderRadius"
99
99
  :borderStyle="$props.borderStyle"
100
100
  :padding="$props.padding"
101
- :height="$props.height"
102
- :width="$props.width"
103
101
  :class="classes"
104
- :style="style"
105
102
  v-bind="$attrs"
106
103
  >
107
104
  <template
@@ -1,5 +1,6 @@
1
1
  <template>
2
2
  <FSDialogSubmit
3
+ width="460px"
3
4
  :title="title"
4
5
  :submitButtonLabel="$tr('ui.button.remove', 'Remove')"
5
6
  :submitButtonColor="ColorEnum.Error"
@@ -0,0 +1,210 @@
1
+ <template>
2
+ <FSCol
3
+ :height="$props.height"
4
+ :width="$props.width"
5
+ gap="24px"
6
+ >
7
+ <FSAgendaHeader
8
+ :mode="$props.mode!"
9
+ :start="start"
10
+ :end="end"
11
+ :now="now"
12
+ @update:start="($event) => $emit('update:start', $event)"
13
+ @update:end="($event) => $emit('update:end', $event)"
14
+ @update:mode="($event) => $emit('update:mode', $event)"
15
+ />
16
+ <FSCol
17
+ class="fs-agenda-view"
18
+ height="100%"
19
+ gap="0"
20
+ >
21
+ <FSWindow
22
+ v-if="$props.mode"
23
+ :modelValue="$props.mode"
24
+ width="100%"
25
+ height="100%"
26
+ >
27
+ <FSDayAgenda
28
+ :value="AgendaMode.Day"
29
+ :events="$props.events"
30
+ :firstColumnWidth="dayColumnWidth"
31
+ :start="start"
32
+ :end="end"
33
+ :now="now"
34
+ :nowIsInSelectedRange="nowIsInSelectedRange"
35
+ :loading="$props.loading"
36
+ @click:event-id="$emit('click:eventId', $event)"
37
+ >
38
+ <FSAgendaVerticalTimeLineMarker
39
+ v-if="nowIsInSelectedRange"
40
+ :modelValue="now"
41
+ />
42
+ </FSDayAgenda>
43
+ <FSWeekAgenda
44
+ :value="AgendaMode.Week"
45
+ :events="$props.events"
46
+ :firstColumnWidth="dayColumnWidth"
47
+ :start="start"
48
+ :end="end"
49
+ :now="now"
50
+ :nowIsInSelectedRange="nowIsInSelectedRange"
51
+ :loading="$props.loading"
52
+ @click:event-id="$emit('click:eventId', $event)"
53
+ >
54
+ <FSAgendaHorizontalTimeLineMarker
55
+ v-if="nowIsInSelectedRange"
56
+ :modelValue="now"
57
+ />
58
+ </FSWeekAgenda>
59
+ <FSMonthAgenda
60
+ :value="AgendaMode.Month"
61
+ :events="$props.events"
62
+ :firstColumnWidth="dayColumnWidth"
63
+ :start="start"
64
+ :end="end"
65
+ :now="now"
66
+ :nowIsInSelectedRange="nowIsInSelectedRange"
67
+ :loading="$props.loading"
68
+ @click:event-id="$emit('click:eventId', $event)"
69
+ >
70
+ <FSAgendaHorizontalTimeLineMarker
71
+ v-if="nowIsInSelectedRange"
72
+ :modelValue="now"
73
+ />
74
+ </FSMonthAgenda>
75
+ </FSWindow>
76
+ </FSCol>
77
+ </FSCol>
78
+ </template>
79
+
80
+ <script lang="ts">
81
+ import { defineComponent, type PropType, computed, ref, onUnmounted, watch } from 'vue';
82
+
83
+ import { useDateFormat } from "@dative-gpi/foundation-shared-services/composables";
84
+ import { useBreakpoints } from "@dative-gpi/foundation-shared-components/composables";
85
+
86
+ import type { FSAgendaEvent } from "@dative-gpi/foundation-shared-components/models";
87
+ import { AgendaMode } from '@dative-gpi/foundation-shared-domain/enums/agendas';
88
+
89
+ import FSAgendaVerticalTimeLineMarker from './FSAgendaVerticalTimeLineMarker.vue';
90
+ import FSMonthAgenda from './FSMonthAgenda.vue';
91
+ import FSWeekAgenda from './FSWeekAgenda.vue';
92
+ import FSDayAgenda from './FSDayAgenda.vue';
93
+ import FSAgendaHorizontalTimeLineMarker from './FSAgendaHorizontalTimeLineMarker.vue';
94
+ import FSAgendaHeader from './FSAgendaHeader.vue';
95
+ import FSWindow from '../FSWindow.vue';
96
+ import FSCol from '../FSCol.vue';
97
+
98
+
99
+ export default defineComponent({
100
+ name: 'FSAgenda',
101
+ components: {
102
+ FSAgendaHeader,
103
+ FSAgendaHorizontalTimeLineMarker,
104
+ FSAgendaVerticalTimeLineMarker,
105
+ FSCol,
106
+ FSDayAgenda,
107
+ FSMonthAgenda,
108
+ FSWeekAgenda,
109
+ FSWindow
110
+ },
111
+ props: {
112
+ mode: {
113
+ type: Number as PropType<AgendaMode>,
114
+ default: AgendaMode.Week
115
+ },
116
+ height: {
117
+ type: [Array, String, Number] as PropType<"hug" | "fill" | string[] | number[] | string | number | null>,
118
+ required: false,
119
+ default: "100%"
120
+ },
121
+ width: {
122
+ type: [Array, String, Number] as PropType<"hug" | "fill" | string[] | number[] | string | number | null>,
123
+ required: false,
124
+ default: "100%"
125
+ },
126
+ loading: {
127
+ type: Boolean,
128
+ default: false
129
+ },
130
+ events: {
131
+ type: Array as PropType<FSAgendaEvent[]>,
132
+ default: () => []
133
+ },
134
+ start: {
135
+ type: Number as PropType<number | null>,
136
+ required: false
137
+ },
138
+ end: {
139
+ type: Number as PropType<number | null>,
140
+ required: false
141
+ }
142
+ },
143
+ emits: ['update:mode', 'click:eventId', 'update:start', 'update:end'],
144
+ setup(props, { emit }) {
145
+ const { todayToEpoch, epochToLocalDayStart, epochToLocalDayEnd } = useDateFormat();
146
+ const { isExtraSmall } = useBreakpoints();
147
+
148
+ const dayColumnWidth = '46px';
149
+
150
+ const now = ref(todayToEpoch());
151
+ const defaultMode = ref(props.mode);
152
+
153
+ const start = computed<number>(() => {
154
+ if (props.start) {
155
+ return props.start;
156
+ }
157
+ if (props.mode === AgendaMode.Week) {
158
+ return epochToLocalDayStart(now.value - (new Date(now.value).getDay() - 1) * 24 * 60 * 60 * 1000);
159
+ }
160
+ if (props.mode === AgendaMode.Month) {
161
+ return epochToLocalDayStart(new Date(now.value).setDate(1));
162
+ }
163
+ return epochToLocalDayStart(now.value);
164
+ });
165
+
166
+ const end = computed<number>(() => {
167
+ if (props.end) {
168
+ return props.end;
169
+ }
170
+ if (props.mode === AgendaMode.Week) {
171
+ return epochToLocalDayEnd(now.value + (7 - new Date(now.value).getDay()) * 24 * 60 * 60 * 1000);
172
+ }
173
+ if (props.mode === AgendaMode.Month) {
174
+ const lastDayOfMonth = new Date(new Date(now.value).getFullYear(), new Date(now.value).getMonth() + 1, 0);
175
+ return epochToLocalDayEnd(lastDayOfMonth.getTime());
176
+ }
177
+ return epochToLocalDayEnd(now.value);
178
+ });
179
+
180
+ const nowIsInSelectedRange = computed(() => {
181
+ return now.value >= start.value && now.value <= end.value;
182
+ });
183
+
184
+ const nowInterval = setInterval(() => {
185
+ now.value = todayToEpoch();
186
+ }, 10000);
187
+
188
+ onUnmounted(() => {
189
+ clearInterval(nowInterval);
190
+ });
191
+
192
+ watch(isExtraSmall, (value) => {
193
+ if (value && props.mode !== AgendaMode.Day) {
194
+ emit('update:mode', AgendaMode.Day);
195
+ } else if (!value && defaultMode.value !== AgendaMode.Day) {
196
+ emit('update:mode', defaultMode.value);
197
+ }
198
+ }, {immediate: true});
199
+
200
+ return {
201
+ AgendaMode,
202
+ start,
203
+ dayColumnWidth,
204
+ end,
205
+ now,
206
+ nowIsInSelectedRange
207
+ };
208
+ }
209
+ });
210
+ </script>
@@ -0,0 +1,76 @@
1
+ <template>
2
+ <FSDialog
3
+ :modelValue="$props.dialog"
4
+ @update:modelValue="$emit('update:dialog', $event)"
5
+ >
6
+ <FSCard
7
+ :elevation="true"
8
+ >
9
+ <FSCol
10
+ gap="12px"
11
+ padding="16px"
12
+ >
13
+ <FSCalendar
14
+ v-model="calendarValue"
15
+ />
16
+ <FSButton
17
+ color="primary"
18
+ width="100%"
19
+ :label="$tr('ui.agenda.calendar.dialog.submit', 'Validate')"
20
+ @click="onSubmit"
21
+ />
22
+ </FSCol>
23
+ </FSCard>
24
+ </FSDialog>
25
+ </template>
26
+
27
+ <script lang="ts">
28
+ import { defineComponent, ref, watch } from 'vue';
29
+
30
+ import FSCalendar from '../FSCalendar.vue';
31
+ import FSButton from '../FSButton.vue';
32
+ import FSCard from '../FSCard.vue';
33
+ import FSCol from '../FSCol.vue';
34
+ import FSDialog from '../FSDialog.vue';
35
+
36
+ export default defineComponent({
37
+ name: 'FSAgendaDialogCalendar',
38
+ components: {
39
+ FSCalendar,
40
+ FSButton,
41
+ FSCard,
42
+ FSCol,
43
+ FSDialog,
44
+ },
45
+ props: {
46
+ dialog: {
47
+ type: Boolean,
48
+ required: true,
49
+ },
50
+ modelValue: {
51
+ type: Number,
52
+ required: true,
53
+ },
54
+ },
55
+ emits: ['update:modelValue', 'update:dialog'],
56
+ setup(props, { emit }) {
57
+ const calendarValue = ref<number>(props.modelValue);
58
+
59
+ const onSubmit = () => {
60
+ emit('update:modelValue', calendarValue.value);
61
+ emit('update:dialog', false);
62
+ };
63
+
64
+ watch(() => props.modelValue, (newValue) => {
65
+ if (newValue) {
66
+ calendarValue.value = newValue;
67
+ }
68
+ }, {immediate: true});
69
+
70
+ return {
71
+ calendarValue,
72
+ onSubmit
73
+ };
74
+ },
75
+ });
76
+ </script>
@@ -0,0 +1,190 @@
1
+ <template>
2
+ <FSRow
3
+ align="center-center"
4
+ >
5
+ <template
6
+ v-if="$props.mode !== AgendaMode.Day"
7
+ >
8
+ <FSRow
9
+ align="center-left"
10
+ :wrap="false"
11
+ width="hug"
12
+ >
13
+ <FSButton
14
+ variant="icon"
15
+ icon="mdi-chevron-left"
16
+ @click="onPrevious"
17
+ />
18
+ <FSButton
19
+ width="180px"
20
+ color="primary"
21
+ :border="false"
22
+ :label="epochToMonthYearOnlyFormat($props.start)"
23
+ @click="showCalendarDialog = true"
24
+ />
25
+ <FSButton
26
+ variant="icon"
27
+ icon="mdi-chevron-right"
28
+ @click="onNext"
29
+ />
30
+ </FSRow>
31
+ <FSRow
32
+ align="center-right"
33
+ >
34
+ <FSRow
35
+ width="hug"
36
+ >
37
+ <FSSelectAgendaMode
38
+ :modelValue="$props.mode"
39
+ :hideHeader="true"
40
+ @update:modelValue="$emit('update:mode', $event)"
41
+ />
42
+ <FSButton
43
+ prependIcon="mdi-calendar-today-outline"
44
+ :label="$tr('ui.agenda.today', 'Today')"
45
+ @click="onToday"
46
+ />
47
+ </FSRow>
48
+ </FSRow>
49
+ </template>
50
+ <FSCol
51
+ v-else
52
+ >
53
+ <FSButton
54
+ prependIcon="mdi-calendar-today-outline"
55
+ :label="$tr('ui.agenda.today', 'Today')"
56
+ width="100%"
57
+ @click="onToday"
58
+ />
59
+ <FSRow
60
+ :wrap="false"
61
+ align="center-center"
62
+ padding="0 4px"
63
+ >
64
+ <FSButton
65
+ variant="icon"
66
+ icon="mdi-chevron-left"
67
+ @click="onPrevious"
68
+ />
69
+ <FSButton
70
+ width="100%"
71
+ color="primary"
72
+ :border="false"
73
+ :label="epochToDayMonthLongOnly($props.start)"
74
+ @click="showCalendarDialog = true"
75
+ />
76
+ <FSButton
77
+ variant="icon"
78
+ icon="mdi-chevron-right"
79
+ @click="onNext"
80
+ />
81
+ </FSRow>
82
+ </FSCol>
83
+ </FSRow>
84
+ <FSAgendaDialogCalendar
85
+ v-model:dialog="showCalendarDialog"
86
+ :modelValue="$props.start"
87
+ @update:modelValue="updateDateRange($event)"
88
+ />
89
+ </template>
90
+
91
+ <script lang="ts">
92
+ import { defineComponent, type PropType, ref } from 'vue';
93
+
94
+ import { useDateFormat } from '@dative-gpi/foundation-shared-services/composables';
95
+
96
+ import { AgendaMode } from '@dative-gpi/foundation-shared-domain/enums/agendas';
97
+
98
+ import FSCol from '../FSCol.vue';
99
+ import FSRow from '../FSRow.vue';
100
+ import FSButton from '../FSButton.vue';
101
+ import FSSelectAgendaMode from './FSSelectAgendaMode.vue';
102
+ import FSAgendaDialogCalendar from './FSAgendaDialogCalendar.vue';
103
+
104
+ export default defineComponent({
105
+ name: 'FSAgendaHeader',
106
+ components: {
107
+ FSAgendaDialogCalendar,
108
+ FSSelectAgendaMode,
109
+ FSCol,
110
+ FSButton,
111
+ FSRow
112
+ },
113
+ props: {
114
+ mode: {
115
+ type: Number as PropType<AgendaMode>,
116
+ required: true
117
+ },
118
+ start: {
119
+ type: Number,
120
+ required: true
121
+ },
122
+ end: {
123
+ type: Number,
124
+ required: true
125
+ },
126
+ now: {
127
+ type: Number,
128
+ required: true
129
+ }
130
+ },
131
+ emits: ['update:start', 'update:end', 'update:mode'],
132
+ setup(props, { emit }) {
133
+ const { epochToMonthYearOnlyFormat, epochToDayMonthLongOnly, epochToLocalDayStart, epochToLocalDayEnd } = useDateFormat();
134
+
135
+ const showCalendarDialog = ref(false);
136
+
137
+ const updateDateRange = (dayStart: number) => {
138
+ const newStart = epochToLocalDayStart(dayStart);
139
+ if (props.mode === AgendaMode.Week) {
140
+ emit('update:start', newStart);
141
+ emit('update:end', epochToLocalDayEnd(newStart + (7 - new Date(newStart).getDay()) * 24 * 60 * 60 * 1000));
142
+ return;
143
+ }
144
+ if (props.mode === AgendaMode.Month) {
145
+ emit('update:start', newStart);
146
+ const lastDayOfMonth = new Date(new Date(newStart).getFullYear(), new Date(newStart).getMonth() + 1, 0);
147
+ emit('update:end', epochToLocalDayEnd(lastDayOfMonth.getTime()));
148
+ return;
149
+ }
150
+ emit('update:start', newStart);
151
+ emit('update:end', epochToLocalDayEnd(newStart));
152
+ }
153
+
154
+ const onNext = () => {
155
+ updateDateRange(props.end + 1000 * 60);
156
+ }
157
+
158
+ const onPrevious = () => {
159
+ if (props.mode === AgendaMode.Week) {
160
+ updateDateRange(props.start - 7 * 24 * 60 * 60 * 1000);
161
+ } else if (props.mode === AgendaMode.Month) {
162
+ updateDateRange(new Date(props.start).setMonth(new Date(props.start).getMonth() - 1));
163
+ } else if (props.mode === AgendaMode.Day) {
164
+ updateDateRange(props.start - 24 * 60 * 60 * 1000);
165
+ }
166
+ }
167
+
168
+ const onToday = () => {
169
+ if (props.mode === AgendaMode.Week) {
170
+ updateDateRange(props.now - (new Date(props.now).getDay() - 1) * 24 * 60 * 60 * 1000);
171
+ } else if (props.mode === AgendaMode.Month) {
172
+ updateDateRange(new Date(props.now).setDate(1));
173
+ } else if (props.mode === AgendaMode.Day) {
174
+ updateDateRange(props.now);
175
+ }
176
+ }
177
+
178
+ return {
179
+ AgendaMode,
180
+ showCalendarDialog,
181
+ epochToDayMonthLongOnly,
182
+ epochToMonthYearOnlyFormat,
183
+ onNext,
184
+ onPrevious,
185
+ onToday,
186
+ updateDateRange
187
+ }
188
+ }
189
+ });
190
+ </script>