Availability.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <template>
  2. <NcSettingsSection :name="$t('dav', 'Availability')"
  3. :description="$t('dav', 'If you configure your working hours, other users will see when you are out of office when they book a meeting.')">
  4. <div class="time-zone">
  5. <strong>
  6. {{ $t('dav', 'Time zone:') }}
  7. </strong>
  8. <span class="time-zone-text">
  9. <NcTimezonePicker v-model="timezone" />
  10. </span>
  11. </div>
  12. <CalendarAvailability :slots.sync="slots"
  13. :loading="loading"
  14. :l10n-to="$t('dav', 'to')"
  15. :l10n-delete-slot="$t('dav', 'Delete slot')"
  16. :l10n-empty-day="$t('dav', 'No working hours set')"
  17. :l10n-add-slot="$t('dav', 'Add slot')"
  18. :l10n-monday="$t('dav', 'Monday')"
  19. :l10n-tuesday="$t('dav', 'Tuesday')"
  20. :l10n-wednesday="$t('dav', 'Wednesday')"
  21. :l10n-thursday="$t('dav', 'Thursday')"
  22. :l10n-friday="$t('dav', 'Friday')"
  23. :l10n-saturday="$t('dav', 'Saturday')"
  24. :l10n-sunday="$t('dav', 'Sunday')" />
  25. <NcCheckboxRadioSwitch :checked.sync="automated">
  26. {{ $t('dav', 'Automatically set user status to "Do not disturb" outside of availability to mute all notifications.') }}
  27. </NcCheckboxRadioSwitch>
  28. <NcButton :disabled="loading || saving"
  29. type="primary"
  30. @click="save">
  31. {{ $t('dav', 'Save') }}
  32. </NcButton>
  33. </NcSettingsSection>
  34. </template>
  35. <script>
  36. import { CalendarAvailability } from '@nextcloud/calendar-availability-vue'
  37. import { loadState } from '@nextcloud/initial-state'
  38. import {
  39. showError,
  40. showSuccess,
  41. } from '@nextcloud/dialogs'
  42. import {
  43. findScheduleInboxAvailability,
  44. getEmptySlots,
  45. saveScheduleInboxAvailability,
  46. } from '../service/CalendarService.js'
  47. import {
  48. enableUserStatusAutomation,
  49. disableUserStatusAutomation,
  50. } from '../service/PreferenceService.js'
  51. import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
  52. import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js'
  53. import NcSettingsSection from '@nextcloud/vue/dist/Components/NcSettingsSection.js'
  54. import NcTimezonePicker from '@nextcloud/vue/dist/Components/NcTimezonePicker.js'
  55. export default {
  56. name: 'Availability',
  57. components: {
  58. NcButton,
  59. NcCheckboxRadioSwitch,
  60. CalendarAvailability,
  61. NcSettingsSection,
  62. NcTimezonePicker,
  63. },
  64. data() {
  65. // Try to determine the current timezone, and fall back to UTC otherwise
  66. const defaultTimezoneId = (new Intl.DateTimeFormat())?.resolvedOptions()?.timeZone ?? 'UTC'
  67. return {
  68. loading: true,
  69. saving: false,
  70. timezone: defaultTimezoneId,
  71. slots: getEmptySlots(),
  72. automated: loadState('dav', 'user_status_automation') === 'yes',
  73. }
  74. },
  75. async mounted() {
  76. try {
  77. const slotData = await findScheduleInboxAvailability()
  78. if (!slotData) {
  79. console.info('no availability is set')
  80. this.slots = getEmptySlots()
  81. } else {
  82. const { slots, timezoneId } = slotData
  83. this.slots = slots
  84. if (timezoneId) {
  85. this.timezone = timezoneId
  86. }
  87. console.info('availability loaded', this.slots, this.timezoneId)
  88. }
  89. } catch (e) {
  90. console.error('could not load existing availability', e)
  91. showError(t('dav', 'Failed to load availability'))
  92. } finally {
  93. this.loading = false
  94. }
  95. },
  96. methods: {
  97. async save() {
  98. try {
  99. this.saving = true
  100. await saveScheduleInboxAvailability(this.slots, this.timezone)
  101. if (this.automated) {
  102. await enableUserStatusAutomation()
  103. } else {
  104. await disableUserStatusAutomation()
  105. }
  106. showSuccess(t('dav', 'Saved availability'))
  107. } catch (e) {
  108. console.error('could not save availability', e)
  109. showError(t('dav', 'Failed to save availability'))
  110. } finally {
  111. this.saving = false
  112. }
  113. },
  114. },
  115. }
  116. </script>
  117. <style lang="scss" scoped>
  118. .availability-day {
  119. padding: 0 10px 0 10px;
  120. position: absolute;
  121. }
  122. .availability-slots {
  123. display: flex;
  124. white-space: nowrap;
  125. }
  126. .availability-slot {
  127. display: flex;
  128. flex-direction: row;
  129. align-items: center;
  130. }
  131. .availability-slot-group {
  132. display: flex;
  133. flex-direction: column;
  134. }
  135. ::v-deep .mx-input-wrapper {
  136. width: 85px;
  137. }
  138. ::v-deep .mx-datepicker {
  139. width: 97px;
  140. }
  141. ::v-deep .multiselect {
  142. border: 1px solid var(--color-border-dark);
  143. width: 120px;
  144. }
  145. .time-zone {
  146. padding: 32px 12px 12px 0;
  147. }
  148. .grid-table {
  149. display: grid;
  150. margin-bottom: 32px;
  151. grid-column-gap: 24px;
  152. grid-row-gap: 6px;
  153. grid-template-columns: min-content min-content min-content;
  154. }
  155. .button {
  156. align-self: flex-end;
  157. }
  158. .label-weekday {
  159. position: relative;
  160. display: inline-flex;
  161. padding-top: 4px;
  162. }
  163. .delete-slot {
  164. background-color: transparent;
  165. border: none;
  166. padding-bottom: 12px;
  167. opacity: .5;
  168. &:hover {
  169. opacity: 1;
  170. }
  171. }
  172. .add-another {
  173. background-color: transparent;
  174. border: none;
  175. opacity: .5;
  176. display: inline-flex;
  177. padding: 0;
  178. margin: 0;
  179. margin-bottom: 3px;
  180. &:hover {
  181. opacity: 1;
  182. }
  183. }
  184. .to-text {
  185. padding-right: 12px;
  186. }
  187. .time-zone-text{
  188. padding-left: 22px;
  189. }
  190. .empty-content {
  191. color: var(--color-text-lighter);
  192. margin-top: 4px;
  193. }
  194. </style>