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

Disable notification emails #8911

Merged
merged 20 commits into from
Apr 27, 2023
252 changes: 198 additions & 54 deletions packages/web-runtime/src/pages/account.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<template>
<main id="account" class="oc-height-1-1 oc-m">
<app-loading-spinner v-if="isLoading" />
<main v-else id="account" class="oc-height-1-1 oc-m">
<div class="oc-flex oc-flex-between oc-flex-bottom oc-width-1-1 oc-border-b oc-py">
<h1 id="account-page-title" class="oc-page-title oc-m-rm">{{ pageTitle }}</h1>
<div>
Expand Down Expand Up @@ -68,12 +69,15 @@
/>
</dd>
</div>
<div v-if="isLanguageSupported" class="account-page-info-language oc-mb oc-width-1-2@s">
<div
v-if="isSettingsServiceSupported"
class="account-page-info-language oc-mb oc-width-1-2@s"
>
<dt class="oc-text-normal oc-text-muted" v-text="$gettext('Language')" />
<dd data-testid="language">
<oc-select
v-if="languageOptions"
:model-value="selectedLanguageOption"
:model-value="selectedLanguageValue"
:clearable="false"
:options="languageOptions"
@update:model-value="updateSelectedLanguage"
Expand All @@ -100,14 +104,26 @@
<gdpr-export />
</dd>
</div>
<div class="account-page-notification oc-mb oc-width-1-2@s">
AlexAndBear marked this conversation as resolved.
Show resolved Hide resolved
<dt class="oc-text-normal oc-text-muted" v-text="$gettext('Notifications')" />
<dd data-testid="notification-mails">
<oc-checkbox
:model-value="disableEmailNotificationsValue"
size="large"
:label="$gettext('Receive notification mails')"
data-testid="account-page-notification-mails-checkbox"
@update:model-value="updateDisableEmailNotifications"
/>
</dd>
</div>
</dl>
</main>
</template>

<script lang="ts">
import { mapActions } from 'vuex'
import EditPasswordModal from '../components/EditPasswordModal.vue'
import { computed, defineComponent, onMounted, unref } from 'vue'
import { computed, defineComponent, onMounted, unref, ref } from 'vue'
import {
useAccessToken,
useCapabilityGraphPersonalDataExport,
Expand All @@ -123,22 +139,29 @@ import { setCurrentLanguage } from 'web-runtime/src/helpers/language'
import GdprExport from 'web-runtime/src/components/Account/GdprExport.vue'
import { useConfigurationManager } from 'web-pkg/src/composables/configuration'
import { isPersonalSpaceResource } from 'web-client/src/helpers'
import AppLoadingSpinner from 'web-pkg/src/components/AppLoadingSpinner.vue'

export default defineComponent({
name: 'Personal',
components: {
AppLoadingSpinner,
EditPasswordModal,
GdprExport
},
setup() {
const store = useStore()
const accessToken = useAccessToken({ store })
const language = useGettext()
const { $gettext } = language
const clientService = useClientService()
const configurationManager = useConfigurationManager()
const valuesList = ref()
const bundlesList = ref()
const selectedLanguageValue = ref()
const disableEmailNotificationsValue = ref()

// FIXME: Use graph capability when we have it
const isLanguageSupported = useCapabilitySpacesEnabled()
const isSettingsServiceSupported = useCapabilitySpacesEnabled()
const isChangePasswordEnabled = useCapabilitySpacesEnabled()
const isPersonalDataExportEnabled = useCapabilityGraphPersonalDataExport()
const user = computed(() => {
Expand All @@ -152,7 +175,32 @@ export default defineComponent({
)
})

const loadAccountBundleTask = useTask(function* () {
const loadValuesList = useTask(function* () {
try {
const {
data: { values }
} = yield axios.post(
'/api/v0/settings/values-list',
{ account_uuid: 'me' },
{
headers: {
authorization: `Bearer ${unref(accessToken)}`,
'X-Request-ID': uuidV4()
}
}
)
valuesList.value = values || []
} catch (e) {
console.error(e)
store.dispatch('showMessage', {
title: $gettext('Unable to load account data…'),
status: 'danger'
})
valuesList.value = []
}
}).restartable()

const loadBundlesList = useTask(function* () {
try {
const {
data: { bundles }
Expand All @@ -166,63 +214,40 @@ export default defineComponent({
}
}
)
bundlesList.value = bundles.find((b) => b.extension === 'ocis-accounts')
return bundles.find((b) => b.extension === 'ocis-accounts')
} catch (e) {
console.error(e)
return []
store.dispatch('showMessage', {
title: $gettext('Unable to load account data…'),
status: 'danger'
})
bundlesList.value = []
}
}).restartable()

const accountSettingIdentifier = {
extension: 'ocis-accounts',
bundle: 'profile',
setting: 'language'
}
const languageSetting = computed(() => {
return store.getters.getSettingsValue(accountSettingIdentifier)
const isLoading = computed(() => {
if (!isSettingsServiceSupported) {
return false
}
return (
loadValuesList.isRunning ||
!loadValuesList.last ||
loadBundlesList.isRunning ||
!loadBundlesList.last
)
})

const languageOptions = computed(() => {
const languageOptions = loadAccountBundleTask.last?.value?.settings.find(
(s) => s.name === 'language'
)?.singleChoiceValue.options
const languageOptions = unref(bundlesList).settings.find((s) => s.name === 'language')
?.singleChoiceValue.options
return languageOptions?.map((l) => ({
label: l.displayValue,
value: l.value.stringValue,
default: l.default
}))
})
const selectedLanguageOption = computed(() => {
const current = unref(languageSetting)?.listValue.values[0].stringValue
if (!current) {
return unref(languageOptions).find((o) => o.default)
}
return unref(languageOptions).find((o) => o.value === current)
})
const updateSelectedLanguage = (option) => {
const bundle = loadAccountBundleTask.last?.value
const value = {
bundleId: bundle?.id,
settingId: bundle?.settings.find((s) => s.name === 'language')?.id,
resource: { type: 'TYPE_USER' },
listValue: { values: [{ stringValue: option.value }] },
...(unref(languageSetting) && { id: unref(languageSetting).id })
}

axios.post(
'/api/v0/settings/values-save',
{ value: { ...value, accountUuid: 'me' } },
{
headers: {
authorization: `Bearer ${unref(accessToken)}`,
'X-Request-ID': uuidV4()
}
}
)

const newSetting = { identifier: accountSettingIdentifier, value }
store.commit('SET_SETTINGS_VALUE', newSetting)
setCurrentLanguage({ language, languageSetting: newSetting })
}
const accountEditLink = computed(() => {
return store.getters.configuration?.options?.accountEditLink
})
Expand All @@ -241,24 +266,143 @@ export default defineComponent({
return configurationManager.logoutUrl
})

onMounted(() => {
if (unref(isLanguageSupported)) {
loadAccountBundleTask.perform()
const updateSelectedLanguage = async (option) => {
const settingsId = unref(valuesList).find((cV) => cV.identifier.setting === 'language')?.value
?.id

const value = {
bundleId: unref(bundlesList)?.id,
settingId: unref(bundlesList)?.settings.find((s) => s.name === 'language')?.id,
resource: { type: 'TYPE_USER' },
listValue: { values: [{ stringValue: option.value }] },
...(settingsId && { id: settingsId })
}

try {
await axios.post(
'/api/v0/settings/values-save',
{ value: { ...value, accountUuid: 'me' } },
{
headers: {
authorization: `Bearer ${unref(accessToken)}`,
'X-Request-ID': uuidV4()
}
}
)

selectedLanguageValue.value = option
setCurrentLanguage({
language,
languageSetting: {
identifier: {
extension: 'ocis-accounts',
bundle: 'profile',
setting: 'language'
},
value
}
})

/**
* Edge case: we need to reload the values list to retrieve the settingsId if not set,
* otherwise the backend saves multiple entries
*/
if (!settingsId) {
loadValuesList.perform()
}
} catch (e) {
console.error(e)
store.dispatch('showMessage', {
title: $gettext('Unable to save language…'),
status: 'danger'
})
}
}

const updateDisableEmailNotifications = async (option) => {
option = !option
console.log(option)
const bundle = loadBundlesList.last?.value

const settingsId = unref(valuesList).find(
(cV) => cV.identifier.setting === "'disable email notifications"
AlexAndBear marked this conversation as resolved.
Show resolved Hide resolved
)?.value?.id

const value = {
bundleId: bundle?.id,
settingId: bundle?.settings.find((s) => s.name === 'disable email notifications')?.id,
resource: { type: 'TYPE_USER' },
boolValue: option,
...(settingsId && { id: settingsId })
}

try {
await axios.post(
'/api/v0/settings/values-save',
{ value: { ...value, accountUuid: 'me' } },
{
headers: {
authorization: `Bearer ${unref(accessToken)}`,
'X-Request-ID': uuidV4()
}
}
)
disableEmailNotificationsValue.value = option
/**
* Edge case: we need to reload the values list to retrieve the settingsId if not set,
* otherwise the backend saves multiple entries
*/
if (!settingsId) {
loadValuesList.perform()
}
} catch (e) {
console.error(e)
store.dispatch('showMessage', {
title: $gettext('Unable to save notifications email setting…'),
status: 'danger'
})
}
}

onMounted(async () => {
if (unref(isSettingsServiceSupported)) {
await loadBundlesList.perform()
await loadValuesList.perform()

const languageConfiguration = unref(valuesList).find(
(cV) => cV.identifier.setting === 'language'
)
selectedLanguageValue.value = languageConfiguration
? unref(languageOptions).find(
(lO) => lO.value === languageConfiguration.value?.listValue?.values?.[0]?.stringValue
)
: unref(languageOptions).find((o) => o.default)

const disableEmailNotificationsConfiguration = unref(valuesList).find(
(cV) => cV.identifier.setting === 'disable email notifications'
AlexAndBear marked this conversation as resolved.
Show resolved Hide resolved
)

disableEmailNotificationsValue.value = disableEmailNotificationsConfiguration
? !disableEmailNotificationsConfiguration.value?.boolValue
: true
}
})

return {
clientService,
languageOptions,
selectedLanguageOption,
selectedLanguageValue,
updateSelectedLanguage,
updateDisableEmailNotifications,
accountEditLink,
isChangePasswordEnabled,
showGdprExport,
isLanguageSupported,
isSettingsServiceSupported,
groupNames,
user,
logoutUrl
logoutUrl,
isLoading,
disableEmailNotificationsValue
}
},
data() {
Expand Down
1 change: 0 additions & 1 deletion packages/web-runtime/src/services/auth/userManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@ export class UserManager extends OidcUserManager {
let roles
;[graphUser, roles] = await Promise.all([graphClient.users.getMe(), this.fetchRoles()])
this.store.commit('SET_ROLES', roles)
this.store.commit('SET_SETTINGS_VALUES', settings)

role = await this.fetchRole({ graphUser, roles })
} else {
Expand Down
2 changes: 0 additions & 2 deletions packages/web-runtime/src/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import apps from './apps'
import auth from './auth'
import config from './config'
import user from './user'
import settings from './settings'
import modal from './modal'
import navigation from './navigation'
import spaces from './spaces'
Expand All @@ -24,7 +23,6 @@ export default {
apps,
user,
config,
settings,
modal,
navigation,
runtime
Expand Down
Loading