3
0

Update calendar configurator UX/UI

This commit is contained in:
Jože Fortun
2024-06-04 13:19:58 +02:00
parent 2ef3e50686
commit 07d49f0625
10 changed files with 288 additions and 296 deletions

View File

@@ -453,4 +453,20 @@ export default {
white-space: pre-wrap;
}
}
.fc-popover {
.fc-header {
padding: 0.5rem;
}
.fc-body {
padding: 0;
.fc-event-container {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
}
}
</style>

View File

@@ -1,83 +1,97 @@
<template>
<fieldset class="form-group">
<b-form-group
:label="$t('calendar.calendarHeader')"
horizontal
label-class="text-primary"
<b-row>
<b-col
cols="12"
lg="6"
>
<b-form-checkbox
v-model="options.header.hide"
<b-form-group
:label="$t('calendar.view.enabled')"
horizontal
label-class="text-primary"
>
{{ $t('calendar.hideHeader') }}
</b-form-checkbox>
<b-form-checkbox
v-model="options.header.hidePrevNext"
:disabled="options.header.hide"
>
{{ $t('calendar.hideNavigation') }}
</b-form-checkbox>
<b-form-checkbox
v-model="options.header.hideToday"
:disabled="options.header.hide"
>
{{ $t('calendar.hideToday') }}
</b-form-checkbox>
<b-form-checkbox
v-model="options.header.hideTitle"
:disabled="options.header.hide"
>
{{ $t('calendar.hideTitle') }}
</b-form-checkbox>
</b-form-group>
<b-form-group
:label="$t('calendar.view.enabled')"
horizontal
label-class="text-primary"
>
<b-form-checkbox-group
v-model="options.header.views"
:disabled="options.header.hide"
buttons
button-variant="outline-secondary"
size="sm"
name="buttons2"
:options="views"
/>
</b-form-group>
<b-form-checkbox-group
v-model="options.header.views"
:disabled="options.header.hide"
buttons
button-variant="outline-secondary"
size="sm"
name="buttons2"
:options="views"
/>
</b-form-group>
</b-col>
<b-form-group
:description="$t('calendar.view.footnote')"
:label="$t('calendar.view.default')"
horizontal
label-class="text-primary"
<b-col
cols="12"
lg="6"
>
<b-form-radio-group
v-model="options.defaultView"
buttons
button-variant="outline-secondary"
size="sm"
name="buttons2"
:options="views"
/>
</b-form-group>
<b-row>
<b-col
cols="12"
lg="6"
<b-form-group
:description="$t('calendar.view.footnote')"
:label="$t('calendar.view.default')"
horizontal
label-class="text-primary"
>
<b-form-group
:label="$t('calendar.view.onEventClick')"
label-class="text-primary"
<b-form-radio-group
v-model="options.defaultView"
buttons
button-variant="outline-secondary"
size="sm"
name="buttons2"
:options="views"
/>
</b-form-group>
</b-col>
<b-col
cols="12"
lg="6"
>
<b-form-group
:label="$t('calendar.view.onEventClick')"
label-class="text-primary"
>
<b-form-select
v-model="options.eventDisplayOption"
:options="eventDisplayOptions"
/>
</b-form-group>
</b-col>
<b-col
cols="12"
lg="6"
>
<b-form-group
:label="$t('calendar.calendarHeader')"
horizontal
label-class="text-primary"
>
<b-form-checkbox
v-model="options.header.hide"
>
<b-form-select
v-model="options.eventDisplayOption"
:options="eventDisplayOptions"
/>
</b-form-group>
</b-col>
</b-row>
</fieldset>
{{ $t('calendar.hideHeader') }}
</b-form-checkbox>
<b-form-checkbox
v-model="options.header.hidePrevNext"
:disabled="options.header.hide"
>
{{ $t('calendar.hideNavigation') }}
</b-form-checkbox>
<b-form-checkbox
v-model="options.header.hideToday"
:disabled="options.header.hide"
>
{{ $t('calendar.hideToday') }}
</b-form-checkbox>
<b-form-checkbox
v-model="options.header.hideTitle"
:disabled="options.header.hide"
>
{{ $t('calendar.hideTitle') }}
</b-form-checkbox>
</b-form-group>
</b-col>
</b-row>
</template>
<script>
import base from '../base'

View File

@@ -1,11 +1,11 @@
<template>
<div>
<template v-if="feed.options">
<b-row>
<b-col
cols="12"
lg="6"
>
<b-form-group
:label-cols="3"
:label="$t('calendar.recordFeed.moduleLabel')"
horizontal
breakpoint="md"
label-class="text-primary"
>
<b-input-group>
@@ -16,16 +16,104 @@
default-value="0"
:placeholder="$t('calendar.recordFeed.modulePlaceholder')"
label="name"
@input="onModuleChange"
/>
</b-input-group>
</b-form-group>
</b-col>
<template v-if="module">
<template v-if="module">
<b-col
cols="12"
lg="6"
>
<b-form-group
:label="$t('calendar.recordFeed.titleLabel')"
label-class="text-primary"
>
<c-input-select
v-model="feed.titleField"
:options="titleFields"
:reduce="o => o.name"
:placeholder="$t('calendar.recordFeed.titlePlaceholder')"
/>
</b-form-group>
</b-col>
<b-col
cols="12"
lg="6"
>
<b-form-group
:label="$t('calendar.recordFeed.eventStartFieldLabel')"
label-class="text-primary"
>
<c-input-select
v-model="feed.startField"
:options="dateFields"
:reduce="o => o.name"
:placeholder="$t('calendar.recordFeed.eventStartFieldPlaceholder')"
/>
</b-form-group>
</b-col>
<b-col
cols="12"
lg="6"
>
<b-form-group
:label="$t('calendar.recordFeed.eventEndFieldLabel')"
label-class="text-primary"
>
<c-input-select
v-model="feed.endField"
:options="dateFields"
:reduce="o => o.name"
:disabled="feed.allDay"
:placeholder="$t('calendar.recordFeed.eventEndFieldPlaceholder')"
/>
<b-form-checkbox
v-model="feed.allDay"
:value="true"
:unchecked-value="false"
class="mt-1"
>
{{ $t('calendar.recordFeed.eventAllDay') }}
</b-form-checkbox>
</b-form-group>
</b-col>
<b-col cols="12">
<b-form-group
:label="$t('calendar.recordFeed.prefilterLabel')"
label-class="text-primary"
>
<b-form-textarea
v-model="feed.options.prefilter"
:value="true"
:placeholder="$t('calendar.recordFeed.prefilterPlaceholder')"
/>
<i18next
path="interpolationFootnote"
tag="small"
class="text-muted"
>
<code>${record.values.fieldName}</code>
<code>${recordID}</code>
<code>${ownerID}</code>
<span><code>${userID}</code>, <code>${user.name}</code></span>
</i18next>
</b-form-group>
</b-col>
<b-col
cols="12"
lg="6"
>
<b-form-group
:label-cols="3"
:label="$t('calendar.recordFeed.colorLabel')"
horizontal
breakpoint="md"
label-class="text-primary"
>
<c-input-color-picker
@@ -40,105 +128,9 @@
:theme-settings="themeSettings"
/>
</b-form-group>
<b-form-group
:label="$t('calendar.recordFeed.titleLabel')"
:label-cols="3"
horizontal
breakpoint="md"
label-class="text-primary"
>
<c-input-select
v-model="feed.titleField"
:options="titleFields | optionizeFields"
:reduce="o => o.value"
label="text"
:placeholder="$t('calendar.recordFeed.titlePlaceholder')"
/>
</b-form-group>
<b-form-group
:label-cols="3"
:label="$t('calendar.recordFeed.eventStartFieldLabel')"
horizontal
breakpoint="md"
label-class="text-primary"
>
<b-form-select
v-model="feed.startField"
:options="dateFields | optionizeFields"
>
<template slot="first">
<option
disabled
value=""
>
{{ $t('calendar.recordFeed.eventStartFieldPlaceholder') }}
</option>
</template>
</b-form-select>
<b-form-text
v-if="hasMultiFields"
class="test-multi-field-ntf"
>
{{ $t('calendar.recordFeed.noMultiFields') }}
</b-form-text>
</b-form-group>
<b-form-group
:label-cols="3"
:label="$t('calendar.recordFeed.eventEndFieldLabel')"
horizontal
breakpoint="md"
label-class="text-primary"
>
<b-form-select
v-model="feed.endField"
:options="dateFields | optionizeFields"
>
<template slot="first">
<option value="">
{{ $t('calendar.recordFeed.eventEndFieldPlaceholder') }}
</option>
</template>
</b-form-select>
<b-form-text
v-if="hasMultiFields"
class="test-multi-field-ntf"
>
{{ $t('calendar.recordFeed.noMultiFields') }}
</b-form-text>
<b-form-checkbox
v-model="feed.allDay"
class="mt-3"
:value="true"
:unchecked-value="false"
>
{{ $t('calendar.recordFeed.eventAllDay') }}
</b-form-checkbox>
</b-form-group>
<br>
<b-form-group
:label-cols="3"
:label="$t('calendar.recordFeed.prefilterLabel')"
horizontal
breakpoint="md"
label-class="text-primary"
>
<b-form-textarea
v-model="feed.options.prefilter"
:value="true"
:placeholder="$t('calendar.recordFeed.prefilterPlaceholder')"
/>
</b-form-group>
</template>
</b-col>
</template>
</div>
</b-row>
</template>
<script>
@@ -177,17 +169,6 @@ export default {
]
},
/**
* Determines if given module has any multi-fields
* @returns {Boolean}
*/
hasMultiFields () {
if (!this.module) {
return false
}
return this.module.fields.reduce((acc, { isMulti }) => acc || isMulti, false)
},
/**
* Determines available title fields based on the given module.
* @returns {Array}
@@ -225,5 +206,13 @@ export default {
return this.$Settings.get('ui.studio.themes', [])
},
},
methods: {
onModuleChange () {
this.feed.titleField = ''
this.feed.startField = ''
this.feed.endField = ''
},
},
}
</script>

View File

@@ -1,25 +1,27 @@
<template>
<div>
<b-form-group
:label-cols="3"
:label="$t('calendar.reminderFeed.colorLabel')"
horizontal
breakpoint="md"
label-class="text-primary"
<b-row>
<b-col
cols="12"
lg="6"
>
<c-input-color-picker
v-model="feed.options.color"
:translations="{
modalTitle: $t('calendar.recordFeed.colorPicker'),
light: $t('general:themes.labels.light'),
dark: $t('general:themes.labels.dark'),
cancelBtnLabel: $t('general:label.cancel'),
saveBtnLabel: $t('general:label.saveAndClose')
}"
:theme-settings="themeSettings"
/>
</b-form-group>
</div>
<b-form-group
:label="$t('calendar.reminderFeed.colorLabel')"
label-class="text-primary"
>
<c-input-color-picker
v-model="feed.options.color"
:translations="{
modalTitle: $t('calendar.recordFeed.colorPicker'),
light: $t('general:themes.labels.light'),
dark: $t('general:themes.labels.dark'),
cancelBtnLabel: $t('general:label.cancel'),
saveBtnLabel: $t('general:label.saveAndClose')
}"
:theme-settings="themeSettings"
/>
</b-form-group>
</b-col>
</b-row>
</template>
<script>

View File

@@ -4,22 +4,6 @@
* Define common props, methods, ... in here.
*/
export default {
filters: {
/**
* Prepares a set of select options
* @param {Array} ff Raw options
* @returns {Array}
*/
optionizeFields (ff) {
return ff.map(f => {
return {
text: f.label || f.name,
value: f.name,
}
})
},
},
props: {
feed: {
type: Object,

View File

@@ -1,66 +1,58 @@
<template>
<div>
<b-row>
<!-- Feed list -->
<div
<b-col
v-for="(feed, i) in options.feeds"
:key="i"
cols="12"
class="p-0"
>
<div
v-if="feed.resource"
class="d-flex justify-content-end mb-3"
<b-card
class="list-background mx-3 mb-3"
>
<c-input-confirm
v-if="feed.resource"
show-icon
size="md"
@confirmed="onRemoveFeed(i)"
/>
</div>
<h5 class="d-flex align-items-center mb-3">
{{ $t('calendar.source.label') }} {{ i + 1 }}
<!-- define feed resource; eg. module, reminders, google calendar, ... -->
<b-form-group
:label="$t('calendar.eventSource')"
:label-cols="3"
horizontal
breakpoint="md"
label-class="text-primary"
>
<b-form-select
v-model="feed.resource"
:options="feedSources"
<c-input-confirm
show-icon
class="ml-auto mt-1"
@confirmed="onRemoveFeed(i)"
/>
</h5>
<!-- define feed resource; eg. module, reminders, google calendar, ... -->
<b-form-group
:label="$t('calendar.eventSource')"
label-class="text-primary"
>
<template slot="first">
<option
value=""
:disabled="true"
>
{{ $t('calendar.feedPlaceholder') }}
</option>
</template>
</b-form-select>
</b-form-group>
<c-input-select
v-model="feed.resource"
:options="feedSources"
:clearable="false"
label="text"
:reduce="o => o.value"
/>
</b-form-group>
<b-form-group horizontal>
<!-- source configurator -->
<component
:is="configurator(feed)"
v-if="feed.resource && configurator(feed)"
:feed="feed"
:modules="modules"
/>
</b-form-group>
</b-card>
</b-col>
<hr>
</div>
<b-button
variant="primary"
class="test-feed-add"
@click.prevent="handleAddButton"
>
{{ $t('calendar.addEventsSource') }}
</b-button>
</div>
<b-col cols="12">
<b-button
variant="primary"
class="test-feed-add"
@click.prevent="handleAddButton"
>
{{ $t('calendar.addEventsSource') }}
</b-button>
</b-col>
</b-row>
</template>
<script>
import { mapGetters } from 'vuex'
@@ -133,3 +125,9 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.list-background {
background-color: var(--body-bg);
}
</style>

View File

@@ -177,17 +177,6 @@ export default {
return this.modules.find(({ moduleID }) => moduleID === this.feed.options.moduleID)
},
/**
* Determines if given module has any multi-fields
* @returns {Boolean}
*/
hasMultiFields () {
if (!this.module) {
return false
}
return this.module.fields.reduce((acc, { isMulti }) => acc || isMulti, false)
},
/**
* Determines available title fields based on the given module.
* @returns {Array}

View File

@@ -20,7 +20,7 @@ export type FeedInput = Partial<Feed> | Feed | LegacyFeed
const defOptions = {
moduleID: NoID,
color: '#FFFFFF',
color: '#0B344E',
prefilter: '',
}
@@ -28,7 +28,7 @@ const defOptions = {
* Feed class represents an event feed for the given calendar
*/
export default class Feed {
public resource = ''
public resource = 'compose:record'
public startField = ''
public endField = ''
public titleField = ''

View File

@@ -11,7 +11,7 @@ export type FeedInput = Partial<Feed> | Feed
const defOptions = {
moduleID: NoID,
color: '#2f85cb',
color: '#0B344E',
prefilter: '',
}

View File

@@ -36,6 +36,8 @@ automation:
danger: Danger
warning: Warning
calendar:
source:
label: Source
addEventsSource: Add events source
calendarHeader: Calendar header
feedLabel: Configure events source
@@ -51,17 +53,16 @@ calendar:
colorLabel: Event color
eventAllDay: Show as all-day-events
eventEndFieldLabel: Event end
eventEndFieldPlaceholder: (No field, event will last 1 hour)
eventEndFieldPlaceholder: Event will last 1 hour
eventStartFieldLabel: Event start
eventStartFieldPlaceholder: (No field)
moduleLabel: Select module
modulePlaceholder: (No module)
noMultiFields: Multi-value fields are currently not supported
eventStartFieldPlaceholder: Field with event start date
moduleLabel: Module
modulePlaceholder: Select a module
optionLabel: Records
prefilterLabel: Prefilter events
prefilterPlaceholder: field1 = 1 AND field2 = 232
titleLabel: Title
titlePlaceholder: (No field)
titleLabel: Event title
titlePlaceholder: Field used as event title
reminderFeed:
colorLabel: Event color
optionLabel: Reminders
@@ -774,7 +775,6 @@ geometry:
colorPicker: Choose a color
moduleLabel: Module*
modulePlaceholder: (No module)
noMultiFields: Multi-value fields are currently not supported
optionLabel: Records
prefilterLabel: Prefilter sources
colorLabel: Marker color