Fix expiration display

Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
This commit is contained in:
John Molakvoæ (skjnldsv) 2020-05-01 11:38:26 +02:00
parent 224cc7d6d9
commit cd63980601
No known key found for this signature in database
GPG key ID: 60C25B8C072916CF
3 changed files with 132 additions and 57 deletions

View file

@ -24,10 +24,9 @@
<AppNavigationItem <AppNavigationItem
ref="navigationItem" ref="navigationItem"
:exact="true" :exact="true"
:icon="loading ? 'icon-loading-small' : ''" :icon="icon"
:title="form.title" :title="form.title"
:to="{ name: 'edit', params: { hash: form.hash } }"> :to="{ name: 'edit', params: { hash: form.hash } }">
<AppNavigationIconBullet slot="icon" :color="bulletColor" />
<template v-if="!loading" #actions> <template v-if="!loading" #actions>
<ActionLink <ActionLink
:href="formLink" :href="formLink"
@ -63,7 +62,6 @@ import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
import ActionLink from '@nextcloud/vue/dist/Components/ActionLink' import ActionLink from '@nextcloud/vue/dist/Components/ActionLink'
import ActionRouter from '@nextcloud/vue/dist/Components/ActionRouter' import ActionRouter from '@nextcloud/vue/dist/Components/ActionRouter'
import ActionSeparator from '@nextcloud/vue/dist/Components/ActionSeparator' import ActionSeparator from '@nextcloud/vue/dist/Components/ActionSeparator'
import AppNavigationIconBullet from '@nextcloud/vue/dist/Components/AppNavigationIconBullet'
import AppNavigationItem from '@nextcloud/vue/dist/Components/AppNavigationItem' import AppNavigationItem from '@nextcloud/vue/dist/Components/AppNavigationItem'
import axios from '@nextcloud/axios' import axios from '@nextcloud/axios'
import moment from '@nextcloud/moment' import moment from '@nextcloud/moment'
@ -77,7 +75,6 @@ export default {
components: { components: {
AppNavigationItem, AppNavigationItem,
AppNavigationIconBullet,
ActionButton, ActionButton,
ActionLink, ActionLink,
ActionRouter, ActionRouter,
@ -113,6 +110,20 @@ export default {
return style.getPropertyValue('--color-success').slice(-6) return style.getPropertyValue('--color-success').slice(-6)
}, },
icon() {
if (this.loading) {
return 'icon-loading-small'
}
if (this.isExpired) {
return 'icon-checkmark'
}
return 'icon-forms'
},
isExpired() {
return this.form.expires && moment().unix() > this.form.expires
},
/** /**
* Return the form share link * Return the form share link
* @returns {string} * @returns {string}

View file

@ -21,7 +21,10 @@
--> -->
<template> <template>
<AppSidebar v-show="opened" :title="form.title" @close="onClose"> <AppSidebar v-if="form"
v-show="opened"
:title="form.title"
@close="onClose">
<h3>{{ t('forms', 'Settings') }}</h3> <h3>{{ t('forms', 'Settings') }}</h3>
<ul> <ul>
<li> <li>
@ -38,7 +41,7 @@
<li> <li>
<input id="submitOnce" <input id="submitOnce"
v-model="form.submitOnce" v-model="form.submitOnce"
:disabled="form.access.type === 'public' || form.isAnonymous" :disabled="isPublic || form.isAnonymous"
type="checkbox" type="checkbox"
class="checkbox" class="checkbox"
@change="onSubmOnceChange"> @change="onSubmOnceChange">
@ -56,8 +59,15 @@
</label> </label>
<DatetimePicker v-show="formExpires" <DatetimePicker v-show="formExpires"
id="expiresDatetimePicker" id="expiresDatetimePicker"
v-model="form.expires" :clearable="false"
v-bind="expirationDatePicker" :disabled-date="notBeforeToday"
:disabled-time="notBeforeNow"
:format="format"
:minute-step="5"
:placeholder="t('forms', 'Expiration date')"
:show-second="false"
:value="expirationDate"
type="datetime"
@change="onExpiresChange" /> @change="onExpiresChange" />
</li> </li>
</ul> </ul>
@ -118,7 +128,7 @@ import AppSidebar from '@nextcloud/vue/dist/Components/AppSidebar'
import DatetimePicker from '@nextcloud/vue/dist/Components/DatetimePicker' import DatetimePicker from '@nextcloud/vue/dist/Components/DatetimePicker'
import moment from '@nextcloud/moment' import moment from '@nextcloud/moment'
import { subscribe, unsubscribe } from '@nextcloud/event-bus' import { subscribe, unsubscribe } from '@nextcloud/event-bus'
import { getLocale, getLanguage } from '@nextcloud/l10n' import { getLocale, getDayNamesShort, getMonthNamesShort } from '@nextcloud/l10n'
import ShareDiv from '../components/shareDiv' import ShareDiv from '../components/shareDiv'
import ViewsMixin from '../mixins/ViewsMixin' import ViewsMixin from '../mixins/ViewsMixin'
@ -136,69 +146,75 @@ export default {
data() { data() {
return { return {
opened: false, opened: false,
lang: '', lang: {
locale: '', days: getDayNamesShort(),
longDateFormat: '', months: getMonthNamesShort(),
dateTimeFormat: '', placeholder: {
formExpires: false, date: t('forms', 'Select expiration date'),
},
},
locale: 'en',
format: {
stringify: this.stringify,
parse: this.parse,
},
} }
}, },
computed: { computed: {
expirationDatePicker() {
return {
editable: true,
minuteStep: 1,
type: 'datetime',
valueType: 'X', // unix-timestamp
format: moment.localeData().longDateFormat('L') + ' ' + moment.localeData().longDateFormat('LT'),
lang: this.lang.split('-')[0],
placeholder: t('forms', 'Expiration date'),
timePickerOptions: {
start: '00:00',
step: '00:15',
end: '23:45',
},
}
},
},
watch: {
formExpires: { formExpires: {
handler: function() { get() {
if (!this.formExpires) { return this.form.expires !== 0
this.form.expires = 0 },
this.onExpiresChange() set(checked) {
} else { if (checked) {
this.form.expires = moment().unix() + 3600 // Expires in one hour. this.form.expires = moment().unix() + 3600 // Expires in one hour.
} else {
this.form.expires = 0
} }
this.saveFormProperty('expires')
}, },
}, },
isPublic() {
return this.form?.access?.type === 'public'
},
expirationDate() {
return moment(this.form.expires, 'X').toDate()
},
isExpired() {
return this.form.expires && moment().unix() > this.form.expires
},
}, },
created() { async created() {
this.lang = getLanguage() // Load the locale
// convert format like en_GB to en-gb for `moment.js`
let locale = getLocale().replace('_', '-').toLowerCase()
try { try {
this.locale = getLocale() // default load e.g. fr-fr
await import(/* webpackChunkName: 'moment' */'moment/locale/' + locale)
this.locale = locale
} catch (e) { } catch (e) {
if (e instanceof TypeError) { try {
this.locale = this.lang // failure: fallback to fr
} else { locale = locale.split('-')[0]
/* eslint-disable-next-line no-console */ await import(/* webpackChunkName: 'moment' */'moment/locale/' + locale)
console.log(e) } catch (e) {
// failure, fallback to english
console.debug('Fallback to locale', 'en')
locale = 'en'
} }
} finally {
// force locale change to update
// the component once done loading
this.locale = locale
console.debug('Locale used', locale)
} }
moment.locale(this.locale) },
this.longDateFormat = moment.localeData().longDateFormat('L')
this.dateTimeFormat = moment.localeData().longDateFormat('L') + ' ' + moment.localeData().longDateFormat('LT')
// Compute current formExpires for checkbox
if (this.form.expires) {
this.formExpires = true
} else {
this.formExpires = false
}
beforeMount() {
// Watch for Sidebar toggle // Watch for Sidebar toggle
subscribe('toggleSidebar', this.onToggle) subscribe('toggleSidebar', this.onToggle)
}, },
@ -242,9 +258,56 @@ export default {
onAccessChange() { onAccessChange() {
this.saveFormProperty('access') this.saveFormProperty('access')
}, },
onExpiresChange() {
/**
* On date picker change
* @param {Date} datetime the expiration Date
*/
onExpiresChange(datetime) {
this.form.expires = parseInt(moment(datetime).format('X'))
this.saveFormProperty('expires') this.saveFormProperty('expires')
}, },
/**
* Datepicker timestamp to string
* @param {Date} datetime the datepicker Date
* @returns {string}
*/
stringify(datetime) {
const date = moment(datetime).locale(this.locale).format('LLL')
if (this.isExpired) {
return t('forms', 'Expired on {date}', { date })
}
return t('forms', 'Expires on {date}', { date })
},
/**
* Form expires timestamp to Date form the datepicker
* @param {number} value the expires timestamp
* @returns {Date}
*/
parse(value) {
return moment(value, 'X').toDate()
},
/**
* Prevent selecting a day before today
* @param {Date} datetime the datepicker Date
* @returns {boolean}
*/
notBeforeToday(datetime) {
return datetime < moment().add(-1, 'day').toDate()
},
/**
* Prevent selecting a time before the current one + 1hour
* @param {Date} datetime the datepicker Date
* @returns {boolean}
*/
notBeforeNow(datetime) {
return datetime < moment().add(1, 'hour').toDate()
},
}, },
} }
</script> </script>

View file

@ -55,6 +55,7 @@ module.exports = {
// Make appName & appVersion available as a constant // Make appName & appVersion available as a constant
new webpack.DefinePlugin({ appName }), new webpack.DefinePlugin({ appName }),
new webpack.DefinePlugin({ appVersion }), new webpack.DefinePlugin({ appVersion }),
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
], ],
resolve: { resolve: {
extensions: ['*', '.js', '.vue'], extensions: ['*', '.js', '.vue'],