diff --git a/cypress/integration/user/settings.spec.js b/cypress/integration/user/settings.spec.js index 42b1f893..29cb1ad0 100644 --- a/cypress/integration/user/settings.spec.js +++ b/cypress/integration/user/settings.spec.js @@ -8,7 +8,7 @@ describe('User Settings', () => { }) it('Changes the user avatar', () => { - cy.visit('/user/settings') + cy.visit('/user/settings/avatar') cy.get('input[name=avatarProvider][value=upload]') .click() @@ -28,9 +28,10 @@ describe('User Settings', () => { }) it('Updates the name', () => { - cy.visit('/user/settings') + cy.visit('/user/settings/general') - cy.get('input#newName') + cy.get('.general-settings .control input.input') + .first() .type('Lorem Ipsum') cy.get('.card.general-settings .button.is-primary') .contains('Save') diff --git a/src/components/home/navigation.vue b/src/components/home/navigation.vue index e043db6f..a2d2ec19 100644 --- a/src/components/home/navigation.vue +++ b/src/components/home/navigation.vue @@ -147,7 +147,7 @@ - + {{ $t('misc.poweredBy') }} @@ -160,6 +160,7 @@ import ListSettingsDropdown from '@/components/list/list-settings-dropdown.vue' import NamespaceSettingsDropdown from '@/components/namespace/namespace-settings-dropdown.vue' import draggable from 'vuedraggable' import {calculateItemPosition} from '@/helpers/calculateItemPosition' +import {POWERED_BY} from '@/urls' import logoUrl from '@/assets/logo-full.svg' @@ -175,6 +176,7 @@ export default { }, listUpdating: {}, logoUrl, + poweredByUrl: POWERED_BY, } }, components: { diff --git a/src/router/index.js b/src/router/index.js index 215e2964..378e9f97 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -48,6 +48,14 @@ import CreateSavedFilter from '../views/filters/CreateSavedFilter' const PasswordResetComponent = () => import('../views/user/PasswordReset') const GetPasswordResetComponent = () => import('../views/user/RequestPasswordReset') const UserSettingsComponent = () => import('../views/user/Settings') +const UserSettingsAvatarComponent = () => import('../views/user/settings/Avatar') +const UserSettingsCaldavComponent = () => import('../views/user/settings/Caldav') +const UserSettingsDataExportComponent = () => import('../views/user/settings/DataExport') +const UserSettingsDeletionComponent = () => import('../views/user/settings/Deletion') +const UserSettingsEmailUpdateComponent = () => import('../views/user/settings/EmailUpdate') +const UserSettingsGeneralComponent = () => import('../views/user/settings/General') +const UserSettingsPasswordUpdateComponent = () => import('../views/user/settings/PasswordUpdate') +const UserSettingsTOTPComponent = () => import('../views/user/settings/TOTP') // List Handling const NewListComponent = () => import('../views/list/NewList') @@ -115,6 +123,48 @@ const router = createRouter({ path: '/user/settings', name: 'user.settings', component: UserSettingsComponent, + children: [ + { + path: '/user/settings/avatar', + name: 'user.settings.avatar', + component: UserSettingsAvatarComponent, + }, + { + path: '/user/settings/caldav', + name: 'user.settings.caldav', + component: UserSettingsCaldavComponent, + }, + { + path: '/user/settings/data-export', + name: 'user.settings.data-export', + component: UserSettingsDataExportComponent, + }, + { + path: '/user/settings/deletion', + name: 'user.settings.deletion', + component: UserSettingsDeletionComponent, + }, + { + path: '/user/settings/email-update', + name: 'user.settings.email-update', + component: UserSettingsEmailUpdateComponent, + }, + { + path: '/user/settings/general', + name: 'user.settings.general', + component: UserSettingsGeneralComponent, + }, + { + path: '/user/settings/password-update', + name: 'user.settings.password-update', + component: UserSettingsPasswordUpdateComponent, + }, + { + path: '/user/settings/totp', + name: 'user.settings.totp', + component: UserSettingsTOTPComponent, + }, + ], }, { path: '/user/export/download', diff --git a/src/store/modules/config.js b/src/store/modules/config.js index e28a6b46..223e8098 100644 --- a/src/store/modules/config.js +++ b/src/store/modules/config.js @@ -2,6 +2,7 @@ import {CONFIG} from '../mutation-types' import {HTTPFactory} from '@/http-common' import {objectToCamelCase} from '@/helpers/case' import {redirectToProvider} from '../../helpers/redirectToProvider' +import {parseURL} from 'ufo' export default { namespaced: true, @@ -35,6 +36,13 @@ export default { }, }, }), + getters: { + migratorsEnabled: state => state.availableMigrators?.length > 0, + apiBase() { + const {host, protocol} = parseURL(window.API_URL) + return protocol + '//' + host + }, + }, mutations: { [CONFIG](state, config) { state.version = config.version @@ -63,7 +71,7 @@ export default { async update(ctx) { const HTTP = HTTPFactory() - const { data: info } = await HTTP.get('info') + const {data: info} = await HTTP.get('info') ctx.commit(CONFIG, info) return info }, diff --git a/src/styles/theme/content.scss b/src/styles/theme/content.scss index 2edbdbfd..4be780b1 100644 --- a/src/styles/theme/content.scss +++ b/src/styles/theme/content.scss @@ -1,20 +1,26 @@ .content h3 { - .icon, - .is-small { - font-size: 1rem; - } + .icon, + .is-small { + font-size: 1rem; + } } .table.has-actions { - border-top: 1px solid $grey-100; - border-radius: 4px; - overflow: hidden; + border-top: 1px solid $grey-100; + border-radius: 4px; + overflow: hidden; - td { - vertical-align: middle; - } + td { + vertical-align: middle; + } - td.actions { - text-align: right; - } + td.actions { + text-align: right; + } } + +.content-widescreen { + margin: 0 auto; + max-width: $widescreen; +} + diff --git a/src/urls.js b/src/urls.js new file mode 100644 index 00000000..dd939938 --- /dev/null +++ b/src/urls.js @@ -0,0 +1,2 @@ +export const POWERED_BY = 'https://vikunja.io' +export const CALDAV_DOCS = 'https://vikunja.io/docs/caldav/' diff --git a/src/views/user/Login.vue b/src/views/user/Login.vue index 9267d424..c4588d7d 100644 --- a/src/views/user/Login.vue +++ b/src/views/user/Login.vue @@ -43,6 +43,7 @@
-
- - -
- -
- -
-
-
- - -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
- - - {{ $t('misc.save') }} - -
- - - - - - -
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- - - {{ $t('misc.save') }} - -
- - - -
-
- -
- -
-
-
- -
- -
-
-
- - - {{ $t('misc.save') }} - -
- - - - - {{ $t('user.settings.totp.enroll') }} - - - - - - - - - - - - {{ $t('migrate.import') }} - - - - - - - - -

- {{ $t('user.settings.caldav.howTo') }} -

-
-
- -
-
- -
-
-

- - {{ $t('user.settings.caldav.more') }} - -

-
+
+
+ + diff --git a/src/components/user/avatar-settings.vue b/src/views/user/settings/Avatar.vue similarity index 94% rename from src/components/user/avatar-settings.vue rename to src/views/user/settings/Avatar.vue index 6d42f17d..72e09753 100644 --- a/src/components/user/avatar-settings.vue +++ b/src/views/user/settings/Avatar.vue @@ -66,11 +66,11 @@ import {Cropper} from 'vue-advanced-cropper' import 'vue-advanced-cropper/dist/style.css' -import AvatarService from '../../services/avatar' -import AvatarModel from '../../models/avatar' +import AvatarService from '@/services/avatar' +import AvatarModel from '@/models/avatar' export default { - name: 'avatar-settings', + name: 'user-settings-avatar', data() { return { avatarProvider: '', @@ -86,6 +86,9 @@ export default { components: { Cropper, }, + mounted() { + this.setTitle(`${this.$t('user.settings.avatar.title')} - ${this.$t('user.settings.title')}`) + }, methods: { async avatarStatus() { const { avatarProvider } = await this.avatarService.get({}) diff --git a/src/views/user/settings/Caldav.vue b/src/views/user/settings/Caldav.vue new file mode 100644 index 00000000..e6e196af --- /dev/null +++ b/src/views/user/settings/Caldav.vue @@ -0,0 +1,55 @@ + + + diff --git a/src/components/user/settings/data-export.vue b/src/views/user/settings/DataExport.vue similarity index 88% rename from src/components/user/settings/data-export.vue rename to src/views/user/settings/DataExport.vue index f092444f..03236d60 100644 --- a/src/components/user/settings/data-export.vue +++ b/src/views/user/settings/DataExport.vue @@ -37,10 +37,10 @@ diff --git a/src/views/user/settings/General.vue b/src/views/user/settings/General.vue new file mode 100644 index 00000000..db320542 --- /dev/null +++ b/src/views/user/settings/General.vue @@ -0,0 +1,169 @@ + + + diff --git a/src/views/user/settings/PasswordUpdate.vue b/src/views/user/settings/PasswordUpdate.vue new file mode 100644 index 00000000..b43376ff --- /dev/null +++ b/src/views/user/settings/PasswordUpdate.vue @@ -0,0 +1,82 @@ + + + diff --git a/src/views/user/settings/TOTP.vue b/src/views/user/settings/TOTP.vue new file mode 100644 index 00000000..e796d8bb --- /dev/null +++ b/src/views/user/settings/TOTP.vue @@ -0,0 +1,133 @@ + + + \ No newline at end of file