chore: migrate to nextcloud/vue 8

Signed-off-by: Grigory V <scratchx@gmx.com>
Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>
This commit is contained in:
Grigory Vodyanov 2023-12-08 11:42:59 +01:00 committed by Richard Steinmetz
parent dd04772ee0
commit fd355c9a15
No known key found for this signature in database
GPG Key ID: 27137D9E7D273FB2
50 changed files with 2337 additions and 14239 deletions

View File

@ -151,7 +151,7 @@
}
.app-navigation-entry-wrapper.deleted {
.app-navigation-entry__title {
.app-navigation-entry__name {
text-decoration: line-through;
}
}
@ -163,7 +163,7 @@
}
.app-navigation-entry-wrapper.disabled {
.app-navigation-entry__title {
.app-navigation-entry__name {
color: var(--color-text-lighter) !important;
}
}
@ -208,13 +208,13 @@
}
.app-navigation-entry-new-calendar {
.app-navigation-entry__title {
.app-navigation-entry__name {
color: var(--color-text-maxcontrast) !important;
}
&:hover,
&--open {
.app-navigation-entry__title {
.app-navigation-entry__name{
color: var(--color-text-light) !important;
}
}

View File

@ -38,11 +38,9 @@
}
/** Hide the submit button for the title, because it does not trigger a save */
.app-sidebar-header__desc {
.app-sidebar-header__maintitle-form {
button {
display: none;
}
.app-sidebar-header__mainname-form {
button {
display: none;
}
}
@ -141,7 +139,7 @@
display: flex;
align-items: center;
.multiselect {
.v-select {
width: 100%;
min-width: 100px !important; // Set a lower min-width
}
@ -202,7 +200,7 @@
&__label,
&__end-type-select {
display: block;
min-width: 75px;
min-width: 160px;
width: 25%;
}
@ -446,45 +444,6 @@
}
}
.resource-search__multiselect,
.invitees-search__multiselect {
width: 100%;
.resource-search-list-item,
.invitees-search-list-item {
display: flex;
align-items: center;
width: 100%;
// Account for avatar width (because it is position: relative)
padding-right: 32px;
&__label {
width: 100%;
padding: 0 8px;
&__availability {
color: var(--color-text-maxcontrast);
}
div {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
div:nth-child(1) {
color: var(--color-main-text)
}
div:nth-child(2) {
color: var(--color-text-lighter);
line-height: 1;
}
}
}
}
.resource-list-item,
.invitees-list-item {
display: flex;
@ -585,6 +544,7 @@
}
&__icon {
flex-shrink: 0;
margin-left: -5px;
margin-right: 5px;
}
@ -594,7 +554,7 @@
textarea,
input,
div.multiselect {
div.v-select {
width: 100%;
}
@ -639,9 +599,15 @@
.property-select,
.property-select-multiple {
.multiselect {
align-items: center;
.v-select {
min-width: unset !important;
}
&__input {
width: 100%;
}
}
.property-color {
@ -808,6 +774,7 @@
.calendar-picker-option {
display: flex;
align-items: center;
overflow: hidden;
&__color-indicator {
width: 12px;
@ -822,6 +789,7 @@
&__label {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex-grow: 1;
}
@ -843,6 +811,11 @@
border: none;
margin-right: 8px;
}
.icon {
margin-left: 4px;
scale: 0.8;
}
}
.resource-list-button-group,
@ -853,3 +826,42 @@
align-items: center;
margin-top: 20px;
}
.resource-search-list-item,
.invitees-search-list-item {
display: flex;
align-items: center;
width: 100%;
// Account for avatar width (because it is position: relative)
padding-right: 32px;
&__label {
width: 100%;
padding: 0 8px;
&__availability {
color: var(--color-text-maxcontrast);
}
div {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
div:nth-child(1) {
color: var(--color-main-text)
}
div:nth-child(2) {
color: var(--color-text-lighter);
line-height: 1;
}
}
}
.resource-search__multiselect,
.invitees-search__multiselect {
width: 100%;
}

16024
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -47,7 +47,7 @@
"@fullcalendar/vue": "6.1.10",
"@nextcloud/auth": "^2.2.1",
"@nextcloud/axios": "^2.4.0",
"@nextcloud/calendar-availability-vue": "^1.0.1",
"@nextcloud/calendar-availability-vue": "^2.0.1",
"@nextcloud/calendar-js": "^6.1.0",
"@nextcloud/cdav-library": "^1.1.0",
"@nextcloud/dialogs": "^4.2.5",
@ -57,7 +57,7 @@
"@nextcloud/logger": "^2.7.0",
"@nextcloud/moment": "^1.3.1",
"@nextcloud/router": "^2.2.1",
"@nextcloud/vue": "^7.12.7",
"@nextcloud/vue": "^8.6.2",
"@nextcloud/vue-dashboard": "^2.0.1",
"autosize": "^6.0.1",
"color-convert": "^2.0.1",

View File

@ -25,7 +25,7 @@
<NcButton v-shortkey="previousShortKeyConf"
:aria-label="previousLabel"
class="datepicker-button-section__previous button"
:title="previousLabel"
:name="previousLabel"
@click="navigateToPreviousTimeRange"
@shortkey="navigateToPreviousTimeRange">
<template #icon>
@ -48,7 +48,7 @@
<NcButton v-shortkey="nextShortKeyConf"
:aria-label="nextLabel"
class="datepicker-button-section__next button"
:title="nextLabel"
:name="nextLabel"
@click="navigateToNextTimeRange"
@shortkey="navigateToNextTimeRange">
<template #icon>

View File

@ -28,7 +28,7 @@
<div v-if="hasAtLeastOneCalendar"
class="appointment-config-list">
<AppNavigationCaption class="appointment-config-list__caption"
:title="t('calendar', 'Appointments')">
:name="t('calendar', 'Appointments')">
<template v-if="hasUserEmailAddress"
#actions>
<ActionButton :close-after-click="true"

View File

@ -22,7 +22,7 @@
<template>
<div>
<AppNavigationItem :title="config.name"
<AppNavigationItem :name="config.name"
@click.prevent>
<template #icon>
<CalendarCheckIcon :size="20" decorative />

View File

@ -24,7 +24,7 @@
<template>
<AppNavigationItem :loading="calendar.loading"
:aria-description="descriptionAppNavigationItem"
:title="calendar.displayName || $t('calendar', 'Untitled calendar')"
:name="calendar.displayName || $t('calendar', 'Untitled calendar')"
:class="{deleted: isBeingDeleted, disabled: !calendar.enabled}"
@click.prevent.stop="toggleEnabled"
@update:menuOpen="actionsMenuOpen = $event">
@ -48,8 +48,8 @@
<template #actions>
<template v-if="!isBeingDeleted">
<template v-if="isSharedWithMe">
<NcActionCaption :title="$t('calendar', 'Shared with you by')" />
<NcActionText :title="ownerDisplayname">
<NcActionCaption :name="$t('calendar', 'Shared with you by')" />
<NcActionText :name="ownerDisplayname">
<template #icon>
<div class="actions-icon-avatar">
<NcAvatar :user="ownerUserId" :display-name="ownerDisplayname" :size="30" />

View File

@ -25,7 +25,7 @@
<template>
<AppNavigationItem class="app-navigation-entry-new-calendar"
:class="{'app-navigation-entry-new-calendar--open': isOpen}"
:title="$t('calendar', 'New calendar')"
:name="$t('calendar', 'New calendar')"
:menu-open.sync="isOpen"
@click.prevent.stop="toggleDialog">
<template #icon>

View File

@ -1,5 +1,5 @@
<template>
<span class="live-relative-timestamp" :data-timestamp="numericTimestamp * 1000" :title="title">{{ formatted }}</span>
<span class="live-relative-timestamp" :data-timestamp="numericTimestamp * 1000" :name="title">{{ formatted }}</span>
</template>
<script>

View File

@ -21,7 +21,7 @@
<template>
<AppNavigationItem :loading="calendar.loading"
:title="calendar.displayName || $t('calendar', 'Untitled calendar')"
:name="calendar.displayName || $t('calendar', 'Untitled calendar')"
:menu-open.sync="menuOpen"
@click.prevent.stop="toggleEnabled">
<template #icon>

View File

@ -21,7 +21,7 @@
-->
<template>
<AppNavigationItem :title="t('calendar', 'Trash bin')"
<AppNavigationItem :name="t('calendar', 'Trash bin')"
:pinned="true"
@click.prevent="onShow">
<template #icon>

View File

@ -50,7 +50,7 @@
<div class="edit-calendar-modal__sharing">
<SharingSearch :calendar="calendar" />
<PublishCalendar :calendar="calendar" v-if="canBePublished" />
<PublishCalendar v-if="canBePublished" :calendar="calendar" />
<InternalLink :calendar="calendar" />
<ShareItem v-for="sharee in calendar.shares"
:key="sharee.uri"

View File

@ -34,6 +34,7 @@
:class="{ 'showContent': inputGiven, 'icon-loading': isLoading }"
:user-select="true"
:filter-by="filterResults"
:clearable="false"
open-direction="above"
track-by="user"
label="displayName"

View File

@ -24,7 +24,7 @@
<div class="today-button-section">
<NcButton :aria-label="title"
class="button"
:title="title"
:name="title"
@click="today()">
{{ $t('calendar', 'Today') }}
</NcButton>

View File

@ -21,7 +21,7 @@
<template>
<AppNavigationSettings exclude-click-outside-classes="import-modal"
:title="settingsTitle">
:name="settingsTitle">
<ul class="settings-fieldset-interior">
<SettingsImportSection :is-disabled="loadingCalendars" />
<ActionCheckbox class="settings-fieldset-interior-item"
@ -62,25 +62,25 @@
</ActionCheckbox>
<li class="settings-fieldset-interior-item settings-fieldset-interior-item--slotDuration">
<label for="slotDuration">{{ $t('calendar', 'Time increments') }}</label>
<Multiselect :id="slotDuration"
:allow-empty="false"
<NcSelect :id="slotDuration"
:options="slotDurationOptions"
:value="selectedDurationOption"
:disabled="savingSlotDuration"
track-by="value"
:clearable="false"
input-id="value"
label="label"
@select="changeSlotDuration" />
@option:selected="changeSlotDuration" />
</li>
<li class="settings-fieldset-interior-item settings-fieldset-interior-item--defaultReminder">
<label for="defaultReminder">{{ $t('calendar', 'Default reminder') }}</label>
<Multiselect :id="defaultReminder"
:allow-empty="false"
<NcSelect :id="defaultReminder"
:options="defaultReminderOptions"
:value="selectedDefaultReminderOption"
:disabled="savingDefaultReminder"
track-by="value"
:clearable="false"
input-id="value"
label="label"
@select="changeDefaultReminder" />
@option:selected="changeDefaultReminder" />
</li>
<SettingsTimezoneSelect :is-disabled="loadingCalendars" />
<SettingsAttachmentsFolder />
@ -122,7 +122,7 @@ import {
NcActionCheckbox as ActionCheckbox,
NcActionLink as ActionLink,
NcAppNavigationSettings as AppNavigationSettings,
NcMultiselect as Multiselect,
NcSelect,
} from '@nextcloud/vue'
import {
generateRemoteUrl,
@ -164,7 +164,7 @@ export default {
ActionCheckbox,
ActionLink,
AppNavigationSettings,
Multiselect,
NcSelect,
SettingsImportSection,
SettingsTimezoneSelect,
SettingsAttachmentsFolder,

View File

@ -36,10 +36,11 @@
</template>
<script>
/* eslint-disable-next-line n/no-missing-import */
import NcInputField from '@nextcloud/vue/dist/Components/NcInputField.js'
import debounce from 'debounce'
import { mapState } from 'vuex'
import { getFilePickerBuilder, showError, showSuccess } from '@nextcloud/dialogs'
import NcInputField from '@nextcloud/vue/dist/Components/NcInputField.js'
export default {
name: 'SettingsAttachmentsFolder',

View File

@ -21,7 +21,7 @@
<template>
<Modal class="shortcut-overview-modal"
size="large"
:title="$t('calendar', 'Shortcut overview')"
:name="$t('calendar', 'Shortcut overview')"
@close="$emit('close')">
<section v-for="category in shortcuts"
:key="category.categoryId"

View File

@ -22,7 +22,7 @@
<template>
<div class="app-config-modal-confirmation">
<EmptyContent :title="title">
<EmptyContent :name="title">
<template #icon>
<CheckIcon />
</template>

View File

@ -21,7 +21,7 @@
-->
<template>
<AppNavigationItem :title="title"
<AppNavigationItem :name="title"
@click="openUserSettings">
<template #icon>
<AlertCircleIcon :size="20" />

View File

@ -22,7 +22,7 @@
<template>
<div class="appointment-booking-confirmation">
<EmptyContent :title="$t('calendar', 'Please confirm your reservation')" :description="$t('calendar', 'We sent you an email with details. Please confirm your appointment using the link in the email. You can close this page now.')">
<EmptyContent :name="$t('calendar', 'Please confirm your reservation')" :description="$t('calendar', 'We sent you an email with details. Please confirm your appointment using the link in the email. You can close this page now.')">
<template #icon>
<EmailIcon decorative />
</template>

View File

@ -28,7 +28,7 @@
<div class="property-alarm-item__icon"
:class="{ 'property-alarm-item__icon--hidden': !showIcon }">
<Bell :size="20"
:title="t('calendar', 'Reminder')"
:name="t('calendar', 'Reminder')"
class="icon" />
</div>
<div v-if="!isEditing"

View File

@ -21,22 +21,23 @@
-->
<template>
<Multiselect :allow-empty="false"
<NcSelect :allow-empty="false"
:options="options"
:value="selected"
:disabled="disabled"
track-by="unit"
:clearable="false"
input-id="unit"
label="label"
@select="select" />
@input="select" />
</template>
<script>
import { NcMultiselect as Multiselect } from '@nextcloud/vue'
import { NcSelect } from '@nextcloud/vue'
export default {
name: 'AlarmTimeUnitSelect',
components: {
Multiselect,
NcSelect,
},
props: {
unit: {

View File

@ -39,7 +39,7 @@
<NcListItem v-for="attachment in attachments"
:key="attachment.path"
:force-display-actions="true"
:title="getBaseName(attachment.fileName)"
:name="getBaseName(attachment.fileName)"
@click="openFile(attachment.uri)">
<template #icon>
<img :src="getPreview(attachment)" class="attachment-icon">

View File

@ -22,7 +22,7 @@
<template>
<Modal size="large"
:title="$t('calendar', 'Availability of attendees, resources and rooms')"
:name="$t('calendar', 'Availability of attendees, resources and rooms')"
@close="$emit('close')">
<div class="modal__content modal--scheduler">
<div v-if="loadingIndicator" class="loading-indicator">

View File

@ -24,21 +24,18 @@
-->
<template>
<Multiselect class="invitees-search__multiselect"
<NcSelect class="invitees-search__multiselect"
:options="matches"
:searchable="true"
:internal-search="false"
:max-height="600"
:show-no-results="true"
:show-no-options="false"
:placeholder="placeholder"
:class="{ 'showContent': inputGiven, 'icon-loading': isLoading }"
open-direction="bottom"
track-by="uid"
:clearable="false"
input-id="uid"
label="dropdownName"
@search-change="findAttendees"
@select="addAttendee">
<template #option="{ option }">
@search="findAttendees"
@option:selected="addAttendee">
<template #option="option">
<div class="invitees-search-list-item">
<!-- We need to specify a unique key here for the avatar to be reactive. -->
<Avatar v-if="option.isUser"
@ -68,13 +65,13 @@
</div>
</div>
</template>
</Multiselect>
</NcSelect>
</template>
<script>
import {
NcAvatar as Avatar,
NcMultiselect as Multiselect,
NcSelect,
} from '@nextcloud/vue'
import { principalPropertySearchByDisplaynameOrEmail } from '../../../services/caldavService.js'
import isCirclesEnabled from '../../../services/isCirclesEnabled.js'
@ -93,7 +90,7 @@ export default {
name: 'InviteesListSearch',
components: {
Avatar,
Multiselect,
NcSelect,
GoogleCirclesCommunitiesIcon,
},
props: {

View File

@ -25,7 +25,7 @@
<div class="property-color">
<component :is="icon"
:size="20"
:title="readableName"
:name="readableName"
class="property-color__icon"
:class="{ 'property-color__icon--hidden': !showIcon }"
decorative />

View File

@ -25,22 +25,22 @@
<div v-if="display" class="property-select">
<component :is="icon"
:size="20"
:title="readableName"
:name="readableName"
class="property-select__icon"
:class="{ 'property-select__icon--hidden': !showIcon }" />
<div class="property-select__input"
:class="{ 'property-select__input--readonly': isReadOnly }">
<Multiselect v-if="!isReadOnly"
<NcSelect v-if="!isReadOnly"
:options="options"
:searchable="false"
:allow-empty="false"
:title="readableName"
:name="readableName"
:value="selectedValue"
:placeholder="placeholder"
track-by="value"
:clearable="false"
input-id="value"
label="label"
@select="changeValue" />
@input="changeValue" />
<!-- eslint-disable-next-line vue/singleline-html-element-content-newline -->
<div v-else>{{ selectedValue.label }}</div>
</div>
@ -56,14 +56,14 @@
<script>
import PropertyMixin from '../../../mixins/PropertyMixin.js'
import { NcMultiselect as Multiselect } from '@nextcloud/vue'
import { NcSelect } from '@nextcloud/vue'
import InformationVariant from 'vue-material-design-icons/InformationVariant.vue'
export default {
name: 'PropertySelect',
components: {
Multiselect,
NcSelect,
InformationVariant,
},
mixins: [

View File

@ -25,34 +25,33 @@
<div v-if="display" class="property-select-multiple">
<component :is="icon"
:size="20"
:title="readableName"
:name="readableName"
class="property-select-multiple__icon"
:class="{ 'property-select-multiple__icon--hidden': !showIcon }" />
<div class="property-select-multiple__input"
:class="{ 'property-select-multiple__input--readonly': isReadOnly }">
<Multiselect v-if="!isReadOnly"
v-model="selectionData"
<NcSelect v-if="!isReadOnly"
:value="selectionData"
:options="options"
:searchable="true"
:placeholder="placeholder"
:tag-placeholder="tagPlaceholder"
:allow-empty="true"
:title="readableName"
:name="readableName"
:multiple="true"
:taggable="true"
track-by="label"
:no-wrap="false"
:deselect-from-dropdown="true"
input-id="label"
label="label"
@select="selectValue"
@tag="tag"
@remove="unselectValue">
<template v-if="coloredOptions" #tag="scope">
<PropertySelectMultipleColoredTag v-bind="scope" />
</template>
@option:selecting="tag"
@option:deselected="unselectValue">
<template v-if="coloredOptions" #option="scope">
<PropertySelectMultipleColoredOption v-bind="scope" />
<PropertySelectMultipleColoredOption :option="scope" />
</template>
</Multiselect>
<template v-if="coloredOptions" #selected-option-container="scope">
<PropertySelectMultipleColoredOption :option="scope.option" :closeable="true" @deselect="unselectValue" />
</template>
</NcSelect>
<!-- eslint-disable-next-line vue/singleline-html-element-content-newline -->
<div v-else class="property-select-multiple-colored-tag-wrapper">
<PropertySelectMultipleColoredTag v-for="singleValue in value"
@ -72,7 +71,7 @@
<script>
import PropertyMixin from '../../../mixins/PropertyMixin.js'
import { NcMultiselect as Multiselect } from '@nextcloud/vue'
import { NcSelect } from '@nextcloud/vue'
import PropertySelectMultipleColoredTag from './PropertySelectMultipleColoredTag.vue'
import PropertySelectMultipleColoredOption from './PropertySelectMultipleColoredOption.vue'
import { getLocale } from '@nextcloud/l10n'
@ -84,7 +83,8 @@ export default {
components: {
PropertySelectMultipleColoredOption,
PropertySelectMultipleColoredTag,
Multiselect,
// eslint-disable-next-line vue/no-reserved-component-names
NcSelect,
InformationVariant,
},
mixins: [
@ -124,8 +124,8 @@ export default {
}
for (const category of this.value) {
if (!options.find(option => option.value === category)) {
options.push({ value: category, label: category })
if (!options.find(option => option.value === category) && category !== undefined) {
options.splice(options.findIndex(options => options.value === category), 1)
}
}
@ -156,13 +156,6 @@ export default {
}
},
methods: {
selectValue(value) {
if (!value) {
return
}
this.$emit('add-single-value', value.value)
},
unselectValue(value) {
if (!value) {
return
@ -170,6 +163,8 @@ export default {
this.$emit('remove-single-value', value.value)
this.selectionData.splice(this.selectionData.findIndex(option => option.value === value.value), 1)
// store removed custom options to keep it in the option list
const options = this.propModel.options.slice()
if (!options.find(option => option.value === value.value)) {
@ -184,7 +179,12 @@ export default {
return
}
this.selectionData.push({ value, label: value })
// budget deselectFromDropdown since the vue-select implementation doesn't work
if (this.selectionData.find(option => option.value === value.value)) {
this.selectionData.splice(this.selectionData.findIndex(option => option.value === value.value), 1)
}
this.selectionData.push(value)
this.$emit('add-single-value', value)
},
},

View File

@ -25,6 +25,7 @@
<span class="property-select-multiple-colored-tag">
<div class="property-select-multiple-colored-tag__color-indicator" :style="{ 'background-color': color}" />
<span class="property-select-multiple-colored-tag__label">{{ label }}</span>
<div v-if="closeable" class="icon icon-close" @click="deselect" />
</span>
</template>
@ -39,7 +40,12 @@ export default {
type: [String, Object],
required: true,
},
closeable: {
type: Boolean,
default: false,
},
},
emits: ['deselect'],
computed: {
label() {
const option = this.option
@ -58,5 +64,10 @@ export default {
return `rgb(${color.r},${color.g},${color.b})`
},
},
methods: {
deselect() {
this.$emit('deselect', this.option)
},
},
}
</script>

View File

@ -25,7 +25,7 @@
<div v-if="display" class="property-text">
<component :is="icon"
:size="20"
:title="readableName"
:name="readableName"
class="property-text__icon"
:class="{ 'property-text__icon--hidden': !showIcon }" />
@ -35,7 +35,7 @@
v-autosize="true"
:placeholder="placeholder"
:rows="rows"
:title="readableName"
:name="readableName"
:value="value"
@focus="handleToggleTextareaFocus(true)"
@blur="handleToggleTextareaFocus(false)"

View File

@ -51,7 +51,7 @@
{{ formattedStart }}
</div>
<IconTimezone v-if="!isAllDay"
:title="endTimezone"
:name="endTimezone"
:class="{ 'highlighted-timezone-icon': highlightStartTimezone }"
:size="20" />
</div>
@ -60,7 +60,7 @@
{{ formattedEnd }}
</div>
<IconTimezone v-if="!isAllDay"
:title="endTimezone"
:name="endTimezone"
:class="{ 'highlighted-timezone-icon': highlightStartTimezone }"
:size="20" />
</div>

View File

@ -25,7 +25,7 @@
<div class="property-repeat">
<div class="property-repeat__summary">
<RepeatIcon class="property-repeat__summary__icon"
:title="$t('calendar', 'Repeat')"
:name="$t('calendar', 'Repeat')"
:size="20" />
<RepeatSummary class="property-repeat__summary__content"
:recurrence-rule="recurrenceRule" />

View File

@ -23,15 +23,15 @@
<template>
<div class="repeat-option-set repeat-option-set--end">
<span class="repeat-option-end__label">{{ $t('calendar', 'End repeat') }}</span>
<Multiselect class="repeat-option-end__end-type-select"
<NcSelect class="repeat-option-end__end-type-select"
:options="options"
:searchable="false"
:allow-empty="false"
:title="$t('calendar', 'Select to end repeat')"
:name="$t('calendar', 'Select to end repeat')"
:value="selectedOption"
track-by="value"
:clearable="false"
input-id="value"
label="label"
@select="changeEndType" />
@input="changeEndType" />
<DatePicker v-if="isUntil"
class="repeat-option-end__until"
:min="minimumDate"
@ -54,13 +54,13 @@
<script>
import DatePicker from '../../Shared/DatePicker.vue'
import { NcMultiselect as Multiselect } from '@nextcloud/vue'
import { NcSelect } from '@nextcloud/vue'
export default {
name: 'RepeatEndRepeat',
components: {
DatePicker,
Multiselect,
NcSelect,
},
props: {
/**

View File

@ -21,23 +21,24 @@
-->
<template>
<Multiselect :allow-empty="false"
<NcSelect :allow-empty="false"
:options="options"
:value="selected"
:disabled="disabled"
:placeholder="$t('calendar', 'first')"
track-by="value"
:clearable="false"
input-id="value"
label="label"
@select="select" />
@input="select" />
</template>
<script>
import { NcMultiselect as Multiselect } from '@nextcloud/vue'
import { NcSelect } from '@nextcloud/vue'
export default {
name: 'RepeatFirstLastSelect',
components: {
Multiselect,
NcSelect,
},
props: {
/**

View File

@ -21,22 +21,22 @@
-->
<template>
<Multiselect :allow-empty="false"
<NcSelect :allow-empty="false"
:options="options"
:value="selected"
open-direction="bottom"
track-by="freq"
:clearable="false"
input-id="freq"
label="label"
@select="select" />
@input="select" />
</template>
<script>
import { NcMultiselect as Multiselect } from '@nextcloud/vue'
import { NcSelect } from '@nextcloud/vue'
export default {
name: 'RepeatFreqSelect',
components: {
Multiselect,
NcSelect,
},
props: {
freq: {

View File

@ -21,24 +21,25 @@
-->
<template>
<Multiselect :allow-empty="false"
<NcSelect :allow-empty="false"
:options="options"
:value="selected"
:disabled="disabled"
:placeholder="$t('calendar', 'Monday')"
track-by="value"
:clearable="false"
input-id="value"
label="label"
@select="select" />
@input="select" />
</template>
<script>
import { NcMultiselect as Multiselect } from '@nextcloud/vue'
import { NcSelect } from '@nextcloud/vue'
import { getDayNames } from '@nextcloud/l10n'
export default {
name: 'RepeatOnTheSelect',
components: {
Multiselect,
NcSelect,
},
props: {
/**

View File

@ -44,15 +44,15 @@
</actions>
<Actions v-else-if="isViewedByOrganizer">
<ActionCaption v-if="seatingCapacity"
:title="seatingCapacity" />
:name="seatingCapacity" />
<ActionCaption v-if="roomType"
:title="roomType" />
:name="roomType" />
<ActionCaption v-if="hasProjector"
:title="$t('calendar', 'Has a projector')" />
:name="$t('calendar', 'Has a projector')" />
<ActionCaption v-if="hasWhiteboard"
:title="$t('calendar', 'Has a whiteboard')" />
:name="$t('calendar', 'Has a whiteboard')" />
<ActionCaption v-if="isAccessible"
:title="$t('calendar', 'Wheelchair accessible')" />
:name="$t('calendar', 'Wheelchair accessible')" />
<ActionSeparator v-if="seatingCapacity || roomType || hasProjector || hasWhiteboard || isAccessible" />
<ActionButton @click="removeResource">
<template #icon>

View File

@ -22,21 +22,18 @@
<template>
<div class="resource-search">
<Multiselect class="resource-search__multiselect"
<NcSelect class="resource-search__multiselect"
:options="matches"
:searchable="true"
:internal-search="false"
:max-height="600"
:show-no-results="true"
:show-no-options="false"
:placeholder="placeholder"
:class="{ 'showContent': inputGiven, 'icon-loading': isLoading }"
open-direction="bottom"
track-by="email"
input-id="email"
label="displayName"
@search-change="findResources"
@select="addResource">
<template #option="{ option }">
:clearable="false"
@search="findResources"
@input="addResource">
<template #option="option">
<div class="resource-search-list-item">
<Avatar :disable-tooltip="true"
:display-name="option.displayName" />
@ -48,13 +45,13 @@
({{ formatAvailability(option.isAvailable) }})
</span>
</div>
<div :title="option.subLine">
<div :name="option.subLine">
{{ option.subLine }}
</div>
</div>
</div>
</template>
</Multiselect>
</NcSelect>
<template>
<div class="resource-search__capacity">
@ -85,7 +82,7 @@ import {
NcAvatar as Avatar,
NcActions as Actions,
NcActionCheckbox as ActionCheckbox,
NcMultiselect as Multiselect,
NcSelect,
} from '@nextcloud/vue'
import { checkResourceAvailability } from '../../../services/freeBusyService.js'
import debounce from 'debounce'
@ -98,7 +95,7 @@ export default {
name: 'ResourceListSearch',
components: {
Avatar,
Multiselect,
NcSelect,
ResourceSeatingCapacity,
Actions,
ActionCheckbox,

View File

@ -23,28 +23,29 @@
<template>
<div class="resource-room-type">
<div class="resource-room-type__input">
<Multiselect :value="getOption(value)"
<NcSelect :value="getOption(value)"
:options="options"
:placeholder="placeholder"
track-by="value"
:clearable="false"
input-id="value"
label="label"
@update:value="changeValue">
<template #option="{ option }">
<div>{{ option.label }}</div>
@option:selected="changeValue">
<template #option="option">
<div>{{ option.label !== null ? option.label : "" }}</div>
</template>
</Multiselect>
</NcSelect>
</div>
</div>
</template>
<script>
import { NcMultiselect as Multiselect } from '@nextcloud/vue'
import { NcSelect } from '@nextcloud/vue'
import { getAllRoomTypes } from '../../../models/resourceProps.js'
export default {
name: 'ResourceRoomType',
components: {
Multiselect,
NcSelect,
},
props: {
value: {
@ -78,3 +79,9 @@ export default {
},
}
</script>
<style scoped>
:deep(#value) {
width: 0;
}
</style>

View File

@ -21,7 +21,7 @@
-->
<template>
<EmptyContent :title="$t('calendar', 'Public calendar does not exist')"
<EmptyContent :name="$t('calendar', 'Public calendar does not exist')"
:description="$t('calendar', 'Maybe the share was deleted or has expired?' )">
<template #icon>
<CalendarBlank :size="20" decorative />

View File

@ -1,34 +1,35 @@
<template>
<Multiselect label="displayName"
track-by="url"
<NcSelect label="id"
input-id="url"
:disabled="isDisabled"
:options="calendars"
:value="value"
:options="options"
:value="valueIds"
:multiple="multiple"
@select="change"
@remove="remove">
<template #singleLabel="{ option }">
<CalendarPickerOption v-bind="option" />
@option:selected="change"
@option:deselected="remove">
<template #option="{ id }">
<CalendarPickerOption :color="getCalendarById(id).color"
:display-name="getCalendarById(id).displayName"
:is-shared-with-me="getCalendarById(id).isSharedWithMe"
:owner="getCalendarById(id).owner" />
</template>
<template #option="{ option }">
<CalendarPickerOption v-bind="option" />
<template #selected-option="{ id }">
<CalendarPickerOption :color="getCalendarById(id).color"
:display-name="getCalendarById(id).displayName"
:is-shared-with-me="getCalendarById(id).isSharedWithMe"
:owner="getCalendarById(id).owner" />
</template>
<template #tag="{ option }">
<div class="calendar-picker__tag">
<CalendarPickerOption v-bind="option" />
</div>
</template>
</Multiselect>
</NcSelect>
</template>
<script>
import { NcMultiselect as Multiselect } from '@nextcloud/vue'
import { NcSelect } from '@nextcloud/vue'
import CalendarPickerOption from './CalendarPickerOption.vue'
export default {
name: 'CalendarPicker',
components: {
CalendarPickerOption,
Multiselect,
NcSelect,
},
props: {
value: {
@ -54,18 +55,31 @@ export default {
// for calendars where only one calendar can be selected, disable if there are < 2
return this.multiple ? this.calendars.length < 1 : this.calendars.length < 2
},
valueIds() {
if (Array.isArray(this.value)) {
return this.value.map(({ id }) => id)
}
return this.value.id
},
options() {
return this.calendars.map((calendar) => ({ id: calendar.id }))
},
},
methods: {
/**
* TODO: this should emit the calendar id instead
*
* @param {object} newCalendar The selected calendar
* @param {{id: string}|{id: string}[]} options All selected options (including the new one)
*/
change(newCalendar) {
if (!newCalendar) {
change(options) {
if (!options || options.length === 0) {
return
}
// The new option will always be the last element
const newOption = Array.isArray(options) ? options[options.length - 1] : options
const newCalendar = this.getCalendarById(newOption.id)
if (this.showCalendarOnSelect && !newCalendar.enabled) {
this.$store.dispatch('toggleCalendarEnabled', {
calendar: newCalendar,
@ -74,11 +88,19 @@ export default {
this.$emit('select-calendar', newCalendar)
},
remove(calendar) {
remove(option) {
if (this.multiple) {
this.$emit('remove-calendar', calendar)
this.$emit('remove-calendar', this.getCalendarById(option))
}
},
/**
* @param {string} id The calendar id
* @return {object|undefined} The calendar object (if it exists)
*/
getCalendarById(id) {
return this.calendars.find((cal) => cal.id === id)
},
},
}
</script>
@ -98,3 +120,14 @@ export default {
margin-left: 5px;
}
</style>
<style lang="scss">
.vs__search {
// Prevent search from collapsing the actual picked option
flex-basis: 0;
}
.vs__dropdown-menu {
z-index: 10000010 !important;
}
</style>

View File

@ -21,13 +21,13 @@
-->
<template>
<DatetimePicker :lang="lang"
<DateTimePicker :lang="lang"
:first-day-of-week="firstDay"
:format="'YYYY-MM-DD HH:mm'"
:formatter="formatter"
:value="date"
:type="actualType"
:clearable="false"
::clearable="false"
:minute-step="5"
:disabled-date="disabledDate"
:show-second="false"
@ -54,6 +54,7 @@
</template>
</NcButton>
<Popover :shown.sync="showTimezonePopover"
:focus-trap="false"
open-class="timezone-popover-wrapper">
<div class="timezone-popover-wrapper__title">
<strong>
@ -78,13 +79,13 @@
{{ $t('calendar', 'Pick a date') }}
</NcButton>
</template>
</DatetimePicker>
</DateTimePicker>
</template>
<script>
import {
NcButton,
NcDatetimePicker as DatetimePicker,
NcDateTimePicker as DateTimePicker,
NcPopover as Popover,
NcTimezonePicker as TimezonePicker,
} from '@nextcloud/vue'
@ -105,7 +106,7 @@ export default {
name: 'DatePicker',
components: {
NcButton,
DatetimePicker,
DateTimePicker,
Popover,
TimezonePicker,
IconTimezone,

View File

@ -21,7 +21,7 @@
-->
<template>
<DatetimePicker :clearable="false"
<DateTimePicker ::clearable="false"
:first-day-of-week="firstDay"
:format="format"
:lang="lang"
@ -36,7 +36,7 @@
</template>
<script>
import { NcDatetimePicker as DatetimePicker } from '@nextcloud/vue'
import { NcDateTimePicker as DateTimePicker } from '@nextcloud/vue'
import moment from '@nextcloud/moment'
import { mapState } from 'vuex'
import {
@ -47,7 +47,7 @@ import { getLangConfigForVue2DatePicker } from '../../utils/localization.js'
export default {
name: 'TimePicker',
components: {
DatetimePicker,
DateTimePicker,
},
props: {
date: {

View File

@ -1,9 +1,10 @@
<template>
<Multiselect :value="selectedTimezone"
<NcSelect :value="selectedTimezone"
:options="options"
:multiple="false"
:group-select="false"
:placeholder="placeholder"
:clearable="false"
group-values="regions"
group-label="continent"
track-by="timezoneId"
@ -14,7 +15,7 @@
<script>
import { getReadableTimezoneName, getSortedTimezoneList } from '@nextcloud/calendar-js'
import { NcMultiselect as Multiselect } from '@nextcloud/vue'
import { NcSelect } from '@nextcloud/vue'
import { translate as t } from '@nextcloud/l10n'
import getTimezoneManager from '../../services/timezoneDataProviderService.js'
@ -22,7 +23,7 @@ import getTimezoneManager from '../../services/timezoneDataProviderService.js'
export default {
name: 'TimezoneSelect',
components: {
Multiselect,
NcSelect,
},
props: {
additionalTimezones: {

View File

@ -42,7 +42,7 @@
<div class="booking__date-selection">
<h3>{{ $t('calendar', 'Select date') }}</h3>
<div class="booking__date">
<DatetimePicker v-model="selectedDate"
<DateTimePicker v-model="selectedDate"
:disabled-date="disabledDate"
type="date"
@change="fetchSlots" />
@ -92,7 +92,7 @@ import '@nextcloud/dialogs/dist/index.css'
import {
NcAvatar as Avatar,
NcDatetimePicker as DatetimePicker,
NcDateTimePicker as DateTimePicker,
NcTimezonePicker as TimezonePicker,
NcGuestContent,
} from '@nextcloud/vue'
@ -121,7 +121,7 @@ export default {
components: {
AppointmentSlot,
Avatar,
DatetimePicker,
DateTimePicker,
TimezonePicker,
AppointmentDetails,
AppointmentBookingConfirmation,

View File

@ -51,7 +51,7 @@
</div>
</template>
<div v-else>
<EmptyContent :title="$t('calendar', 'No public appointments found for {name}', { name: userInfo.displayName })">
<EmptyContent :name="$t('calendar', 'No public appointments found for {name}', { name: userInfo.displayName })">
<template #icon>
<CalendarBlankIcon decorative />
</template>

View File

@ -28,7 +28,7 @@
<EmptyContent v-if="item.isEmptyItem"
id="calendar-widget-empty-content"
class="half-screen"
:title="t('calendar', 'No more events today')">
:name="t('calendar', 'No more events today')">
<template #icon>
<IconCheck :size="67" />
</template>
@ -41,7 +41,7 @@
<div v-if="item.componentName === 'VEVENT'"
class="calendar-dot"
:style="{'background-color': item.calendarColor}"
:title="item.calendarDisplayName" />
:name="item.calendarDisplayName" />
<IconCheckbox v-else
:fill-color="item.calendarColor" />
</template>
@ -49,7 +49,7 @@
</template>
<template #empty-content>
<EmptyContent id="calendar-widget-empty-content"
:title="t('calendar', 'No upcoming events')">
:name="t('calendar', 'No upcoming events')">
<template #icon>
<EmptyCalendar />
</template>

View File

@ -25,21 +25,21 @@
-->
<template>
<NcAppSidebar :title="title"
:title-editable="!isReadOnly && !isLoading"
:title-placeholder="$t('calendar', 'Event title')"
<NcAppSidebar :name="title"
:name-editable="!isReadOnly && !isLoading"
:name-placeholder="$t('calendar', 'Event title')"
:subtitle="subTitle"
:empty="isLoading || isError"
:force-menu="true"
@close="cancel"
@update:title="updateTitle">
@update:name="updateTitle">
<template v-if="isLoading">
<div class="app-sidebar__loading-indicator">
<div class="icon icon-loading app-sidebar-tab-loading-indicator__icon" />
</div>
</template>
<template v-else-if="isError">
<NcEmptyContent :title="$t('calendar', 'Event does not exist')" :description="error">
<NcEmptyContent :name="$t('calendar', 'Event does not exist')" :description="error">
<template #icon>
<CalendarBlank :size="20" decorative />
</template>
@ -178,7 +178,7 @@
:is-read-only="isReadOnly" />
<NcModal v-if="showModal && !isPrivate()"
:title="t('calendar', 'Managing shared access')"
:name="t('calendar', 'Managing shared access')"
@close="closeAttachmentsModal">
<div class="modal-content">
<div v-if="showPreloader" class="modal-content-preloader">
@ -191,7 +191,7 @@
<NcListItemIcon v-for="attendee in showModalUsers"
:key="attendee.uri"
class="user-list-item"
:title="attendee.commonName"
:name="attendee.commonName"
:subtitle="emailWithoutMailto(attendee.uri)"
:is-no-user="true" />
</div>
@ -202,7 +202,7 @@
<NcListItemIcon v-for="attachment in showModalNewAttachments"
:key="attachment.xNcFileId"
class="attachment-list-item"
:title="getBaseName(attachment.fileName)"
:name="getBaseName(attachment.fileName)"
:url="getPreview(attachment)"
:force-display-actions="false" />
</div>

View File

@ -46,7 +46,7 @@
</Actions>
</div>
<EmptyContent :title="$t('calendar', 'Event does not exist')" :description="error">
<EmptyContent :name="$t('calendar', 'Event does not exist')" :description="error">
<template #icon>
<CalendarBlank :size="20" decorative />
</template>