|
6 | 6 | <template> |
7 | 7 | <li class="import-modal-file-item"> |
8 | 8 | <div class="import-modal-file-item__filename"> |
9 | | - {{ file.name }} |
| 9 | + <div>{{ file.name }}</div> |
| 10 | + <div |
| 11 | + v-if="disabledHint" |
| 12 | + class="import-modal-file-item__calendar-disabled-hint"> |
| 13 | + {{ disabledHint }} |
| 14 | + </div> |
10 | 15 | </div> |
11 | 16 | <CalendarPicker |
12 | 17 | class="import-modal-file-item__calendar-select" |
13 | 18 | :value="calendar" |
14 | 19 | :calendars="calendars" |
| 20 | + :is-calendar-selectable="isCalendarSelectable" |
15 | 21 | @select-calendar="selectCalendar" /> |
16 | 22 | </li> |
17 | 23 | </template> |
@@ -39,59 +45,94 @@ export default { |
39 | 45 |
|
40 | 46 | computed: { |
41 | 47 | ...mapStores(usePrincipalsStore, useImportFilesStore, useCalendarsStore), |
42 | | - calendar() { |
43 | | - let calendarId = this.importFilesStore.importCalendarRelation[this.file.id] |
44 | | - if (!calendarId) { |
45 | | - this.setDefaultCalendarId() |
46 | | - calendarId = this.importFilesStore.importCalendarRelation[this.file.id] |
| 48 | + newCalendar() { |
| 49 | + return { |
| 50 | + id: 'new', |
| 51 | + displayName: this.$t('calendar', 'New calendar'), |
| 52 | + isSharedWithMe: false, |
| 53 | + color: uidToHexColor(this.$t('calendar', 'New calendar')), |
| 54 | + owner: this.principalsStore.getCurrentUserPrincipal.url, |
47 | 55 | } |
| 56 | + }, |
48 | 57 |
|
49 | | - if (calendarId === 'new') { |
50 | | - return { |
51 | | - id: 'new', |
52 | | - displayName: this.$t('calendar', 'New calendar'), |
53 | | - isSharedWithMe: false, |
54 | | - color: uidToHexColor(this.$t('calendar', 'New calendar')), |
55 | | - owner: this.principalsStore.getCurrentUserPrincipal.url, |
56 | | - } |
| 58 | + calendar() { |
| 59 | + const calendarId = this.importFilesStore.importCalendarRelation[this.file.id] |
| 60 | + if (calendarId === this.newCalendar.id) { |
| 61 | + return this.newCalendar |
57 | 62 | } |
58 | | -
|
59 | 63 | return this.calendarsStore.getCalendarById(calendarId) |
60 | 64 | }, |
61 | 65 |
|
62 | 66 | calendars() { |
63 | | - // TODO: remove once the false positive is fixed upstream |
64 | | -
|
65 | | - const calendars = this.calendarsStore.sortedCalendarFilteredByComponents( |
66 | | - this.file.parser.containsVEvents(), |
67 | | - this.file.parser.containsVJournals(), |
68 | | - this.file.parser.containsVTodos(), |
69 | | - ) |
| 67 | + const existingCalendars = this.calendarsStore.sortedWritableCalendarsEvenWithoutSupportForEvents |
| 68 | + return [...existingCalendars, this.newCalendar] |
| 69 | + }, |
70 | 70 |
|
71 | | - calendars.push({ |
72 | | - id: 'new', |
73 | | - displayName: this.$t('calendar', 'New calendar'), |
74 | | - isSharedWithMe: false, |
75 | | - color: uidToHexColor(this.$t('calendar', 'New calendar')), |
76 | | - owner: this.principalsStore.getCurrentUserPrincipal.url, |
77 | | - }) |
| 71 | + /** |
| 72 | + * Returns a hint explaining why some calendars cannot be selected. |
| 73 | + * |
| 74 | + * @return {string|undefined} A message, or undefined if all calendars can be selected. |
| 75 | + */ |
| 76 | + disabledHint() { |
| 77 | + const disalbedBecauseOfEvents = this.file.parser.containsVEvents() && this.calendars.some((calendar) => !calendar.supportsEvents) |
| 78 | + const disalbedBecauseOfTasks = this.file.parser.containsVTodos() && this.calendars.some((calendar) => !calendar.supportsTasks) |
| 79 | + const disalbedBecauseOfJournalEntries = this.file.parser.containsVJournals() && this.calendars.some((calendar) => !calendar.supportsJournals) |
78 | 80 |
|
79 | | - return calendars |
| 81 | + if (disalbedBecauseOfEvents && disalbedBecauseOfTasks && disalbedBecauseOfJournalEntries) { |
| 82 | + return this.$t('calendar', 'Some calendars are disabled because this file contains events, tasks and journal entries.') |
| 83 | + } |
| 84 | + if (disalbedBecauseOfEvents && disalbedBecauseOfTasks && !disalbedBecauseOfJournalEntries) { |
| 85 | + return this.$t('calendar', 'Some calendars are disabled because this file contains events and tasks.') |
| 86 | + } |
| 87 | + if (disalbedBecauseOfEvents && !disalbedBecauseOfTasks && disalbedBecauseOfJournalEntries) { |
| 88 | + return this.$t('calendar', 'Some calendars are disabled because this file contains events and journal entries.') |
| 89 | + } |
| 90 | + if (disalbedBecauseOfEvents && !disalbedBecauseOfTasks && !disalbedBecauseOfJournalEntries) { |
| 91 | + return this.$t('calendar', 'Some calendars are disabled because this file contains events.') |
| 92 | + } |
| 93 | + if (!disalbedBecauseOfEvents && disalbedBecauseOfTasks && disalbedBecauseOfJournalEntries) { |
| 94 | + return this.$t('calendar', 'Some calendars are disabled because this file contains tasks and journal entries.') |
| 95 | + } |
| 96 | + if (!disalbedBecauseOfEvents && disalbedBecauseOfTasks && !disalbedBecauseOfJournalEntries) { |
| 97 | + return this.$t('calendar', 'Some calendars are disabled because this file contains tasks.') |
| 98 | + } |
| 99 | + if (!disalbedBecauseOfEvents && !disalbedBecauseOfTasks && disalbedBecauseOfJournalEntries) { |
| 100 | + return this.$t('calendar', 'Some calendars are disabled because this file contains journal entries.') |
| 101 | + } |
| 102 | + return undefined |
80 | 103 | }, |
81 | 104 | }, |
82 | 105 |
|
| 106 | + created() { |
| 107 | + const preselectedCalendar = this.calendars.find((calendar) => this.isCalendarSelectable(calendar)) |
| 108 | + if (!preselectedCalendar) { |
| 109 | + // If no other calendar is selectable, at least `this.newCalendar` should be selectable and be preselected. |
| 110 | + throw new Error('Encountered illegal state. At least one calendar that can be selected should exist.') |
| 111 | + } |
| 112 | + this.selectCalendar(preselectedCalendar) |
| 113 | + }, |
| 114 | +
|
83 | 115 | methods: { |
84 | | - selectCalendar(newCalendar) { |
85 | | - this.importFilesStore.setCalendarForFileId({ |
86 | | - fileId: this.file.id, |
87 | | - calendarId: newCalendar.id, |
88 | | - }) |
| 116 | + isCalendarSelectable(calendar) { |
| 117 | + if (calendar.id === this.newCalendar.id) { |
| 118 | + return true |
| 119 | + } |
| 120 | + if (this.file.parser.containsVEvents() && !calendar.supportsEvents) { |
| 121 | + return false |
| 122 | + } |
| 123 | + if (this.file.parser.containsVTodos() && !calendar.supportsTasks) { |
| 124 | + return false |
| 125 | + } |
| 126 | + if (this.file.parser.containsVJournals() && !calendar.supportsJournals) { |
| 127 | + return false |
| 128 | + } |
| 129 | + return true |
89 | 130 | }, |
90 | 131 |
|
91 | | - setDefaultCalendarId() { |
| 132 | + selectCalendar(newCalendar) { |
92 | 133 | this.importFilesStore.setCalendarForFileId({ |
93 | 134 | fileId: this.file.id, |
94 | | - calendarId: this.calendars[0].id, |
| 135 | + calendarId: newCalendar.id, |
95 | 136 | }) |
96 | 137 | }, |
97 | 138 | }, |
|
0 commit comments