Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/polls.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRené Gieling <github@dartcafe.de>2021-04-18 23:12:36 +0300
committerGitHub <noreply@github.com>2021-04-18 23:12:36 +0300
commitcbeba6e6fcf83dd655a4b9a24afc6ebcf1569bdc (patch)
tree988435536a81c4c735c420c109edff175f83556a /src/js/components/Options/OptionsDateAdd.vue
parent373eab67e7d338c7fa949b8ade9992fce73d066e (diff)
Enhancement/option date picker (#1543)
* changed picker selection #1506 * changed design of picker buttons
Diffstat (limited to 'src/js/components/Options/OptionsDateAdd.vue')
-rw-r--r--src/js/components/Options/OptionsDateAdd.vue268
1 files changed, 208 insertions, 60 deletions
diff --git a/src/js/components/Options/OptionsDateAdd.vue b/src/js/components/Options/OptionsDateAdd.vue
index 3eb5b125..7a7161b9 100644
--- a/src/js/components/Options/OptionsDateAdd.vue
+++ b/src/js/components/Options/OptionsDateAdd.vue
@@ -21,22 +21,43 @@
-->
<template>
- <DatetimePicker v-model="pickedOption"
- v-bind="optionDatePicker"
+ <DatetimePicker v-model="pickerSelection"
+ v-bind="pickerOptions"
:open.sync="pickerOpen"
style="width: inherit;"
+ @change="changedDate"
@pick="pickedDate">
- <template slot="footer">
+ <template #input>
+ <ButtonDiv :title="t('polls', 'Add new date option')" />
+ </template>
+ <template #footer>
+ <div v-if="dateOption.isValid" class="selection">
+ <div>
+ {{ dateOption.text }}
+ </div>
+ <Spacer />
+ <button v-if="dateOption.option.duration >= 0 && !added" class="primary" @click="addOption">
+ {{ t('polls', 'Add') }}
+ </button>
+ <div v-if="added" v-tooltip.auto="t('polls', 'added')" class="icon-polls-yes" />
+ </div>
+ <div v-else>
+ {{ t('polls', 'Pick a day.') }}
+ </div>
+ </template>
+ <template #header>
<CheckBoxDiv v-model="useRange" class="range" :label="t('polls', 'Select range')" />
- <button v-if="!showTimePanel" class="mx-btn" @click="toggleTimePanel">
- {{ t('polls', 'Add time') }}
- </button>
- <button v-else class="mx-btn" @click="toggleTimePanel">
- {{ t('polls', 'Remove time') }}
- </button>
- <button class="mx-btn" @click="addOption">
- {{ t('polls', 'OK') }}
- </button>
+ <div class="picker-buttons">
+ <button v-if="useTime" @click="toggleTimePanel">
+ {{ t('polls', showTimePanel ? 'Change date': 'Change time') }}
+ </button>
+ <button v-if="useTime" @click="removeTime">
+ {{ t('polls', 'Remove time') }}
+ </button>
+ <button v-else @click="addTime">
+ {{ t('polls', 'Add time') }}
+ </button>
+ </div>
</template>
</DateTimePicker>
</template>
@@ -44,59 +65,115 @@
<script>
import CheckBoxDiv from '../Base/CheckBoxDiv'
+import { showError, showSuccess } from '@nextcloud/dialogs'
import moment from '@nextcloud/moment'
import { DatetimePicker } from '@nextcloud/vue'
+import ButtonDiv from '../Base/ButtonDiv'
+import Spacer from '../Base/Spacer'
export default {
name: 'OptionsDateAdd',
components: {
CheckBoxDiv,
+ ButtonDiv,
DatetimePicker,
+ Spacer,
},
data() {
return {
- pickedOption: null,
+ pickerSelection: null,
+ firstPick: true,
+ changed: false,
+ imcomplete: true,
lastPickedOption: null,
- startDate: moment(),
- endDate: moment(),
pickerOpen: false,
useRange: false,
+ useTime: false,
showTimePanel: false,
+ keepRange: true,
+ preservedTimeFrom: moment(),
+ preservedTimeTo: moment(),
+ lastPickedDate: moment(0),
+ timeValues: moment(),
+ added: false,
}
},
computed: {
- tempFormat() {
- if (this.showTimePanel) {
- return moment.localeData().longDateFormat('L LT')
+ dateOption() {
+ let from = moment()
+ let to = moment()
+ let text = ''
+
+ if (Array.isArray(this.pickerSelection)) {
+ from = moment(this.pickerSelection[0])
+ to = moment(this.pickerSelection[1])
+
+ // if a sigle day is selected while useRange is true and the paicker did not return a
+ // valid selection, use the single selected day
+ if (this.useRange && this.lastPickedDate) {
+ from = moment(this.lastPickedDate).hour(from.hour()).minute(from.minute())
+ to = moment(this.lastPickedDate).hour(to.hour()).minute(to.minute())
+ }
} else {
- return moment.localeData().longDateFormat('L')
+ from = moment(this.pickerSelection).startOf(this.useTime ? 'minute' : 'day')
+ to = moment(this.pickerSelection).startOf(this.useTime ? 'minute' : 'day')
}
- },
- dateOption() {
- const timeToAdd = this.showTimePanel ? 0 : 86400
-
- const startDate = this.useRange ? moment(this.pickedOption[0]) : moment(this.pickedOption)
- const endDate = this.useRange ? moment(this.pickedOption[1]).add(timeToAdd, 'seconds') : moment(this.pickedOption).add(timeToAdd, 'seconds')
- const pollOptionTextStart = startDate.utc().format(moment.defaultFormat)
- const pollOptionTextEnd = startDate === endDate ? '' : ' - ' + endDate.utc().format(moment.defaultFormat)
+ if (this.useRange) {
+ if (this.useTime) {
+ if (moment(from).startOf('day').valueOf() === moment(to).startOf('day').valueOf()) {
+ text = from.format('ll LT') + ' - ' + to.format('LT')
+ } else {
+ text = from.format('ll LT') + ' - ' + to.format('ll LT')
+ }
+ } else {
+ from = from.startOf('day')
+ to = to.startOf('day')
+ if (moment(from).startOf('day').valueOf() === moment(to).startOf('day').valueOf()) {
+ text = from.format('ll')
+ } else {
+ text = from.format('ll') + ' - ' + to.format('ll')
+ }
+ }
+ } else {
+ if (this.useTime) {
+ text = from.format('ll LT')
+ } else {
+ text = from.startOf('day').format('ll')
+ }
+ }
return {
- timestamp: startDate.unix(),
- pollOptionText: pollOptionTextStart + pollOptionTextEnd,
- duration: endDate.unix() - startDate.unix(),
+ isValid: from._isValid && to._isValid,
+ from,
+ to,
+ text,
+ option: {
+ timestamp: from.unix(),
+ duration: moment(to).add(this.useTime ? 0 : 1, 'day').unix() - from.unix(),
+ },
+ }
+ },
+
+ tempFormat() {
+ if (this.useTime) {
+ return moment.localeData().longDateFormat('L LT')
+ } else {
+ return moment.localeData().longDateFormat('L')
}
},
- optionDatePicker() {
+ pickerOptions() {
return {
+ appendToBody: true,
editable: false,
minuteStep: 5,
- type: this.showTimePanel ? 'datetime' : 'date',
+ type: this.useTime ? 'datetime' : 'date',
range: this.useRange,
+ showSecond: false,
showTimePanel: this.showTimePanel,
valueType: 'timestamp',
format: this.tempFormat,
@@ -116,54 +193,125 @@ export default {
watch: {
useRange() {
- if (this.useRange) {
- if (!Array.isArray(this.pickedOption)) {
- this.pickedOption = [this.pickedOption, this.pickedOption]
- }
- } else {
- if (Array.isArray(this.pickedOption)) {
- this.pickedOption = this.pickedOption[0]
- }
+ if (this.useRange && !Array.isArray(this.pickerSelection)) {
+ this.pickerSelection = [this.pickerSelection, this.pickerSelection]
+ } else if (!this.useRange && Array.isArray(this.pickerSelection)) {
+ this.pickerSelection = this.pickerSelection[0]
}
},
},
methods: {
- toggleTimePanel() {
- if (this.useRange) {
- if (Array.isArray(this.pickedOption)) {
- if (this.lastPickedOption !== this.pickedOption[0]
- && this.lastPickedOption !== this.pickedOption[1]) {
- this.pickedOption = [this.lastPickedOption, this.lastPickedOption]
- }
- } else {
- if (this.lastPickedOption) {
- this.pickedOption = [this.lastPickedOption, this.lastPickedOption]
- }
- }
- }
- this.showTimePanel = !this.showTimePanel
+ // if picker returned a valid selection
+ changedDate(value, type) {
+ this.added = false
+ this.changed = true
},
+ // The date picker does not update the values, if useRange is true and
+ // a single day is selected without a second click. Therfore we store
+ // the picked day to define the correct date selection inside the
+ // computed dateOptions property
pickedDate(value) {
- if (this.optionDatePicker.valueType === 'timestamp') {
- this.lastPickedOption = moment(value).valueOf()
+ // we rely on the behavior, that the changed event is fired before the picked event
+ // if the picker already returned a valid selection before, ignore picked date
+ this.added = false
+ if (this.changed) {
+ // reset changed status
+ this.changed = false
+ // reset the last picked date
+ this.lastPickedDate = null
} else {
- this.lastPickedOption = value
+ // otherwise store the selection of the picked date
+ this.lastPickedDate = moment(value)
}
+ // keep picker open
this.pickerOpen = true
},
- addOption() {
- this.pickerOpen = false
- this.$store.dispatch('options/add', this.dateOption)
+ addTime() {
+ this.added = false
+ if (this.useRange) {
+ // make sure, the pickerSelection is set to the last displayed status
+ this.pickerSelection = [this.dateOption.from.valueOf(), this.dateOption.to.valueOf()]
+ }
+ this.useTime = true
+ this.showTimePanel = true
+ },
+
+ removeTime() {
+ this.added = false
+ if (this.useRange) {
+ // make sure, the pickerSelection is set to the last displayed status
+ this.pickerSelection = [this.dateOption.from.valueOf(), this.dateOption.to.valueOf()]
+ }
+ this.useTime = false
+ this.showTimePanel = false
+ },
+
+ toggleTimePanel() {
+ if (this.showTimePanel) {
+ this.changed = false
+ } else if (this.useRange) {
+ // make sure, the pickerSelection is set to the last displayed status
+ this.pickerSelection = [this.dateOption.from.valueOf(), this.dateOption.to.valueOf()]
+ }
+ this.showTimePanel = !this.showTimePanel
+ },
+
+ async addOption() {
+ if (this.useRange) {
+ // make sure, the pickerSelection is set to the last displayed status
+ this.pickerSelection = [this.dateOption.from.valueOf(), this.dateOption.to.valueOf()]
+ }
+ try {
+ await this.$store.dispatch('options/add', this.dateOption.option)
+ this.added = true
+ showSuccess(t('polls', '{optionText} added', { optionText: this.dateOption.text }))
+ } catch (e) {
+ if (e.response.status === 409) {
+ showError(t('polls', '{optionText} already exists', { optionText: this.dateOption.text }))
+ } else {
+ showError(t('polls', 'Error adding {optionText}', { optionText: this.dateOption.text }))
+ }
+ }
},
},
}
</script>
+<style lang="scss">
+.mx-datepicker {
+ width: 100% !important;
+}
+
+.mx-input-wrapper {
+ &> button {
+ width: 100%;
+ }
+ .mx-icon-calendar {
+ display: none;
+ }
+}
+</style>
+
<style lang="scss" scoped>
+.icon-polls-yes {
+ padding: 5px 1px 5px 1px;
+ height: 34px;
+ margin: 3px 0;
+}
+
+.picker-buttons {
+ display: flex;
+ justify-content: flex-end;
+}
+
+.selection {
+ display: flex;
+ align-items: center;
+}
.range {
flex: 1;