diff --git a/dashboard/package-lock.json b/dashboard/package-lock.json
index 32ada0494..678acb658 100644
--- a/dashboard/package-lock.json
+++ b/dashboard/package-lock.json
@@ -26,7 +26,7 @@
"marked": "^15.0.12",
"moment": "^2.30.1",
"moment-timezone": "^0.6.0",
- "pankow": "^3.1.2",
+ "pankow": "^3.1.3",
"sass": "^1.89.2",
"vite": "^6.3.5",
"vue": "^3.5.16",
@@ -2370,9 +2370,9 @@
}
},
"node_modules/pankow": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/pankow/-/pankow-3.1.2.tgz",
- "integrity": "sha512-6DpIWDifgR4c3Rvs+X+V+XEdWBs8HUFFUo1K8LOWxsHwd7tbaUlBmPRM9aSrYiffWASpN1gj2Axsi/yBl50VXw==",
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/pankow/-/pankow-3.1.3.tgz",
+ "integrity": "sha512-9/qP8CbzIB8uu3LaTJfbnofw1wfFBRO6nLeS+o3XALvO3dB0Bf1ajxLqfEnaPSWvYi6kuOpKa5i0vAoX6oolqQ==",
"license": "ISC",
"dependencies": {
"@fontsource/inter": "^5.2.6",
@@ -4242,9 +4242,9 @@
}
},
"pankow": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/pankow/-/pankow-3.1.2.tgz",
- "integrity": "sha512-6DpIWDifgR4c3Rvs+X+V+XEdWBs8HUFFUo1K8LOWxsHwd7tbaUlBmPRM9aSrYiffWASpN1gj2Axsi/yBl50VXw==",
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/pankow/-/pankow-3.1.3.tgz",
+ "integrity": "sha512-9/qP8CbzIB8uu3LaTJfbnofw1wfFBRO6nLeS+o3XALvO3dB0Bf1ajxLqfEnaPSWvYi6kuOpKa5i0vAoX6oolqQ==",
"requires": {
"@fontsource/inter": "^5.2.6",
"@fortawesome/fontawesome-free": "^6.7.2",
diff --git a/dashboard/package.json b/dashboard/package.json
index 52780ebea..3395321fe 100644
--- a/dashboard/package.json
+++ b/dashboard/package.json
@@ -27,7 +27,7 @@
"marked": "^15.0.12",
"moment": "^2.30.1",
"moment-timezone": "^0.6.0",
- "pankow": "^3.1.2",
+ "pankow": "^3.1.3",
"sass": "^1.89.2",
"vite": "^6.3.5",
"vue": "^3.5.16",
diff --git a/dashboard/src/components/dialogs/PrimaryEmailDialog.vue b/dashboard/src/components/dialogs/PrimaryEmailDialog.vue
new file mode 100644
index 000000000..74991ab78
--- /dev/null
+++ b/dashboard/src/components/dialogs/PrimaryEmailDialog.vue
@@ -0,0 +1,92 @@
+
+
+
+
+
diff --git a/dashboard/src/models/ProfileModel.js b/dashboard/src/models/ProfileModel.js
index 409f6d8e2..93f3a1a12 100644
--- a/dashboard/src/models/ProfileModel.js
+++ b/dashboard/src/models/ProfileModel.js
@@ -92,17 +92,15 @@ function create() {
return null;
},
async setEmail(email, password) {
- let error, result;
+ let result;
try {
result = await fetcher.post(`${API_ORIGIN}/api/v1/profile/email`, { email, password }, { access_token: accessToken });
} catch (e) {
- error = e;
+ return [e];
}
- if (error) return error;
- if (result.status !== 204) return result;
-
- return null;
+ if (result.status !== 204) return [result];
+ return [null];
},
async setFallbackEmail(fallbackEmail, password) {
let error, result;
diff --git a/dashboard/src/views/ProfileView.vue b/dashboard/src/views/ProfileView.vue
index f60b3b97e..38c6c2521 100644
--- a/dashboard/src/views/ProfileView.vue
+++ b/dashboard/src/views/ProfileView.vue
@@ -10,6 +10,7 @@ import { TOKEN_TYPES } from '../constants.js';
import NotificationSettings from '../components/NotificationSettings.vue';
import AppPasswords from '../components/AppPasswords.vue';
import SettingsItem from '../components/SettingsItem.vue';
+import PrimaryEmailDialog from '../components/dialogs/PrimaryEmailDialog.vue';
import Section from '../components/Section.vue';
import ApiTokens from '../components/ApiTokens.vue';
import ImagePicker from '../components/ImagePicker.vue';
@@ -27,6 +28,7 @@ const tokensModel = TokensModel.create();
const config = ref({});
const user = ref({});
const inputDialog = useTemplateRef('inputDialog');
+const primaryEmailDialog = useTemplateRef('primaryEmailDialog');
// Language selector
const languages = ref([]);
@@ -66,24 +68,8 @@ async function onChangeDisplayName(currentDisplayName) {
await refreshProfile();
}
-async function onChangeEmail(currentEmail) {
- const result = await inputDialog.value.prompt({
- message: [ t('profile.changeEmail.title'), t('profile.changeEmail.password') ],
- type: [ 'email', 'password' ],
- modal: false,
- value: [ currentEmail, '' ],
- confirmLabel: t('main.dialog.save'),
- confirmStyle: 'primary',
- rejectLabel: t('main.dialog.cancel'),
- rejectStyle: 'secondary',
- });
-
- if (!result || !result[0] || !result[1] || currentEmail === result[0]) return;
-
- const error = await profileModel.setEmail(result[0], result[1]);
- if (error) return console.error('Failed to set email', error);
-
- await refreshProfile();
+function onChangeEmail(currentEmail) {
+ primaryEmailDialog.value.open(currentEmail);
}
async function onChangeFallbackEmail(currentFallbackEmail) {
@@ -240,6 +226,7 @@ onMounted(async () => {