Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to native date picker #4668

Merged
merged 3 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions cypress/e2e/cardFeatures.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { randUser } from '../utils/index.js'
import { sampleBoard } from '../utils/sampleBoard'
import moment from '@nextcloud/moment'

const user = randUser()
const boardData = sampleBoard()
Expand Down Expand Up @@ -177,6 +178,46 @@ describe('Card', function() {
cy.get('#app-sidebar-vue')
.find('.ProseMirror h1').contains('Hello world writing more text').should('be.visible')
})

it('Set a due date', function() {
const newCardTitle = 'Card with a due date'

cy.get('.button-vue[aria-label*="Add card"]')
.first().click()
cy.get('.stack__card-add form input#new-stack-input-main')
.type(newCardTitle)
cy.get('.stack__card-add form input[type=submit]')
.first().click()
cy.get(`.card:contains("${newCardTitle}")`).should('be.visible')

cy.get('.card:contains("Card with a due date")').should('be.visible').click()

cy.get('#app-sidebar-vue [data-cy-due-date-actions]').should('be.visible').click()

// Set a due date through shortcut
cy.get('[data-cy-due-date-shortcut="tomorrow"] button').should('be.visible').click()

const tomorrow = moment().add(1, 'days').hour(8).minutes(0).seconds(0)
cy.get('#card-duedate-picker').should('have.value', tomorrow.format('YYYY-MM-DDTHH:mm'))

const now = moment().hour(11).minutes(0).seconds(0).toDate()
cy.clock(now)
cy.log(now)
cy.tick(60_000)

cy.get(`.card:contains("${newCardTitle}")`).find('[data-due-state="Now"]').should('be.visible').should('contain', '21 hours')


// Remove the due date again
cy.get('#app-sidebar-vue [data-cy-due-date-actions]').should('be.visible').click()
// tick needed to show the popover menu
cy.tick(1_000)
cy.get('[data-cy-due-date-remove] button').should('be.visible').click()

cy.get(`.card:contains("${newCardTitle}")`).find('[data-due-state]').should('not.be.visible')

})

})

})
35 changes: 8 additions & 27 deletions src/components/card/CardSidebarTabDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
@select="assignUserToCard"
@remove="removeUserFromCard" />

<DueDateSelector :card="card" :can-edit="canEdit && !saving" @change="updateCardDue" />
<DueDateSelector :card="card" :can-edit="canEdit" @change="updateCardDue" />

<div v-if="projectsEnabled" class="section-wrapper">
<CollectionList v-if="card.id"
Expand Down Expand Up @@ -85,7 +85,6 @@ export default {
},
data() {
return {
saving: false,
addedLabelToCard: null,
copiedCard: null,
locale: getLocale(),
Expand All @@ -105,7 +104,6 @@ export default {
this.$store.dispatch('setConfig', { cardDetailsInModal: newValue })
},
},

labelsSorted() {
return [...this.currentBoard.labels].sort((a, b) => (a.title < b.title) ? -1 : 1)
},
Expand Down Expand Up @@ -133,15 +131,6 @@ export default {
localStorage.setItem('deck.selectedStackId', this.card.stackId)
},

async updateCardDue(val) {
this.saving = true
await this.$store.dispatch('updateCardDue', {
...this.copiedCard,
duedate: val ? (new Date(val)).toISOString() : null,
})
this.saving = false
},

assignUserToCard(user) {
this.$store.dispatch('assignCardToUser', {
card: this.copiedCard,
Expand All @@ -162,6 +151,13 @@ export default {
})
},

updateCardDue(val) {
this.$store.dispatch('updateCardDue', {
...this.copiedCard,
duedate: val ? (new Date(val)).toISOString() : null,
})
},

addLabelToCard(newLabel) {
this.copiedCard.labels.push(newLabel)
const data = {
Expand Down Expand Up @@ -205,15 +201,6 @@ export default {
}
</script>
<style lang="scss" scoped>

.section-wrapper:deep(.mx-datepicker-main.mx-datepicker-popup) {
left: 0 !important;
}

.section-wrapper:deep(.mx-datepicker-main.mx-datepicker-popup.mx-datepicker-sidebar) {
padding: 0 !important;
}

.section-wrapper {
display: flex;
max-width: 100%;
Expand Down Expand Up @@ -266,9 +253,3 @@ export default {
z-index: 0;
}
</style>
<style>
.mx-datepicker-main.mx-datepicker-popup {
/* above the modal */
z-index: 9999 !important;
}
</style>
160 changes: 102 additions & 58 deletions src/components/card/DueDateSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,42 @@
<Calendar :size="20" />
</div>
<div class="duedate-selector">
<NcDatetimePicker v-model="duedate"
<NcDateTimePickerNative v-if="duedate"
id="card-duedate-picker"
v-model="duedate"
:placeholder="t('deck', 'Set a due date')"
type="datetime"
:minute-step="5"
:show-second="false"
:lang="lang"
:formatter="format"
:disabled="!canEdit"
:shortcuts="shortcuts"
:append-to-body="true"
confirm />
<NcActions v-if="canEdit">
<NcActionButton v-if="duedate" icon="icon-delete" @click="removeDue()">
:hide-label="true"
type="datetime-local" />
<NcActions v-if="canEdit"
:menu-title="!duedate ? t('deck', 'Add due date') : null"
type="tertiary"
data-cy-due-date-actions>
<template v-if="!duedate" #icon>
<Plus :size="20" />
</template>
<NcActionButton v-for="shortcut in reminderOptions"
:key="shortcut.key"
close-after-click
:data-cy-due-date-shortcut="shortcut.key"
@click="() => selectShortcut(shortcut)">
{{ shortcut.label }}
</NcActionButton>
<NcActionSeparator />

<NcActionButton v-if="!duedate"
close-after-click
data-cy-due-date-pick
@click="initDate">
<template #icon>
<Plus :size="20" />
</template>
{{ t('deck', 'Choose a date') }}
</NcActionButton>
<NcActionButton v-else
icon="icon-delete"
close-after-click
data-cy-due-date-remove
@click="removeDue">
{{ t('deck', 'Remove due date') }}
</NcActionButton>
</NcActions>
Expand All @@ -26,17 +49,21 @@

<script>
import { defineComponent } from 'vue'
import { NcActionButton, NcActions, NcDatetimePicker } from '@nextcloud/vue'
import { NcActionButton, NcActions, NcActionSeparator, NcDateTimePickerNative } from '@nextcloud/vue'
import { getDayNamesMin, getFirstDay, getMonthNamesShort } from '@nextcloud/l10n'
import Plus from 'vue-material-design-icons/Plus.vue'
import Calendar from 'vue-material-design-icons/Calendar.vue'
import moment from '@nextcloud/moment'

export default defineComponent({
name: 'DueDateSelector',
components: {
Plus,
Calendar,
NcActions,
NcActionButton,
NcDatetimePicker,
NcActionSeparator,
NcDateTimePickerNative,
},
props: {
card: {
Expand Down Expand Up @@ -64,64 +91,81 @@ export default defineComponent({
stringify: this.stringify,
parse: this.parse,
},
shortcuts: [
{
text: t('deck', 'Today'),
onClick() {
const date = new Date()
date.setDate(date.getDate())
date.setHours(23)
date.setMinutes(59)
return date
},
},
{
text: t('deck', 'Tomorrow'),
onClick() {
const date = new Date()
date.setDate(date.getDate() + 1)
date.setHours(23)
date.setMinutes(59)
return date
},
},
{
text: t('deck', 'Next week'),
onClick() {
const date = new Date()
date.setDate(date.getDate() + 7)
date.setHours(23)
date.setMinutes(59)
return date
},
},
{
text: t('deck', 'Next month'),
onClick() {
const date = new Date()
date.setDate(date.getDate() + 30)
date.setHours(23)
date.setMinutes(59)
return date
},
},
],
}
},
computed: {
duedate: {
get() {
return this.card.duedate ? new Date(this.card.duedate) : null
return this.card?.duedate ? new Date(this.card.duedate) : null
},
set(val) {
this.$emit('change', val)
this.$emit('change', val ? new Date(val) : null)
},
},

reminderOptions() {
const currentDateTime = moment()
juliusknorr marked this conversation as resolved.
Show resolved Hide resolved
// Same day 18:00 PM (or hidden)
const laterTodayTime = (currentDateTime.hour() < 18)
? moment().hour(18)
: null
// Tomorrow 08:00 AM
const tomorrowTime = moment().add(1, 'days').hour(8)
// Saturday 08:00 AM (or hidden)
const thisWeekendTime = (currentDateTime.day() !== 6 && currentDateTime.day() !== 0)
? moment().day(6).hour(8)
: null
// Next Monday 08:00 AM
const nextWeekTime = moment().add(1, 'weeks').day(1).hour(8)
return [
{
key: 'laterToday',
timestamp: this.getTimestamp(laterTodayTime),
label: t('deck', 'Later today – {timeLocale}', { timeLocale: laterTodayTime?.format('LT') }),
ariaLabel: t('deck', 'Set due date for later today'),
},
{
key: 'tomorrow',
timestamp: this.getTimestamp(tomorrowTime),
label: t('deck', 'Tomorrow – {timeLocale}', { timeLocale: tomorrowTime?.format('ddd LT') }),
ariaLabel: t('deck', 'Set due date for tomorrow'),
},
{
key: 'thisWeekend',
timestamp: this.getTimestamp(thisWeekendTime),
label: t('deck', 'This weekend – {timeLocale}', { timeLocale: thisWeekendTime?.format('ddd LT') }),
ariaLabel: t('deck', 'Set due date for this weekend'),
},
{
key: 'nextWeek',
timestamp: this.getTimestamp(nextWeekTime),
label: t('deck', 'Next week – {timeLocale}', { timeLocale: nextWeekTime?.format('ddd LT') }),
ariaLabel: t('deck', 'Set due date for next week'),
},
].filter(option => option.timestamp !== null)
},
},
methods: {
initDate() {
if (this.duedate === null) {
// We initialize empty dates with a time once clicked to make picking a day easier
const now = new Date()
now.setDate(now.getDate() + 1)
now.setHours(8)
now.setMinutes(0)
now.setMilliseconds(0)
this.duedate = now
}
},
removeDue() {
this.duedate = null
},
selectShortcut(shortcut) {
this.duedate = shortcut.timestamp
},
getTimestamp(momentObject) {
return momentObject?.minute(0).second(0).millisecond(0).toDate() || null
},
},
})
</script>
Expand Down
4 changes: 0 additions & 4 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,6 @@ new Vue({
this.$store.commit('setSearchQuery', '')
})

// FIXME remove this once Nextcloud 20 is minimum required version
// eslint-disable-next-line
new OCA.Search(this.filter, this.cleanSearch)

this.interval = setInterval(() => {
this.time = Date.now()
}, 1000)
Expand Down
Loading