Skip to content

Commit 781756b

Browse files
committed
New AdminUI: change password dialog. In development.
1 parent 091c943 commit 781756b

File tree

4 files changed

+120
-66
lines changed

4 files changed

+120
-66
lines changed

src/AdminUI/src/App.vue

+102-2
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,44 @@
2121
</template>
2222
<v-list>
2323
<v-list-item @click="logout">
24-
<v-list-item-title>{{ $t('app.logout') }}</v-list-item-title>
24+
<v-list-item-title>{{ $t('app.logout') }} <v-icon dark> mdi-logout </v-icon> </v-list-item-title>
25+
</v-list-item>
26+
<v-list-item @click="openChangePasswordDialog">
27+
<v-list-item-title>{{ $t('login.changePassword') }} <v-icon dark> mdi-lock-reset </v-icon>
28+
</v-list-item-title>
2529
</v-list-item>
2630
</v-list>
2731
</v-menu>
2832
</v-app-bar>
2933

34+
<!-- Change Password Dialog -->
35+
<v-dialog scrollable v-if="loggedInUser" v-model="showChangePasswordDialog" max-width="400px">
36+
<v-card>
37+
<v-card-title>{{ $t('login.changePassword') }}</v-card-title>
38+
<v-card-text>
39+
<v-text-field v-model="loggedInUser" :label="$t('login.username')" type="text" disabled></v-text-field>
40+
41+
<v-text-field v-model="currentPassword" :label="$t('login.currentPassword')" type="password"
42+
required></v-text-field>
43+
44+
<v-text-field v-model="newPassword" :label="$t('login.newPassword')" type="password" required></v-text-field>
45+
<v-text-field v-model="confirmNewPassword" :label="$t('login.confirmNewPassword')" type="password"
46+
required></v-text-field>
47+
</v-card-text>
48+
<v-card-actions>
49+
<v-alert v-if="errorMessage" type="error" dense>
50+
{{ errorMessage }}
51+
</v-alert>
52+
<v-btn color="orange" variant="tonal" @click="showChangePasswordDialog = false">
53+
{{ $t('common.cancel') }}
54+
</v-btn>
55+
<v-btn color="primary" variant="tonal" @click="changePwd">
56+
{{ $t('common.save') }}
57+
</v-btn>
58+
</v-card-actions>
59+
</v-card>
60+
</v-dialog>
61+
3062
<v-main class="flex-grow-1" style="overflow-y: auto; scrollbar-width: none; -ms-overflow-style: none;">
3163
<router-view></router-view>
3264
</v-main>
@@ -46,7 +78,12 @@ const vuetifyTheme = useTheme();
4678
const { locale, t } = useI18n();
4779
4880
const currentLocale = ref(locale.value);
49-
const loggedInUser = ref("?");
81+
const loggedInUser = ref("");
82+
const showChangePasswordDialog = ref(false);
83+
const newPassword = ref("");
84+
const confirmNewPassword = ref("");
85+
const currentPassword = ref("");
86+
const errorMessage = ref("");
5087
5188
const availableLocales = [
5289
{ title: 'English', value: 'en' },
@@ -98,6 +135,69 @@ const logout = () => {
98135
});
99136
};
100137
138+
const openChangePasswordDialog = () => {
139+
errorMessage.value = ""
140+
currentPassword.value = newPassword.value = confirmNewPassword.value = ""
141+
showChangePasswordDialog.value = true
142+
}
143+
144+
const changePwd = () => {
145+
146+
// Validate passwords
147+
if (newPassword.value !== confirmNewPassword.value) {
148+
errorMessage.value = t('login.passwordMismatch')
149+
setTimeout(() => {
150+
errorMessage.value = ""
151+
}, 1500)
152+
return
153+
}
154+
155+
if (newPassword.value.trim() === "" || newPassword.value.trim().length < 4) {
156+
errorMessage.value = t('login.invalidNewPassword')
157+
setTimeout(() => {
158+
errorMessage.value = ""
159+
}, 1500)
160+
return
161+
}
162+
163+
let ck = parseCookie(document.cookie)
164+
if ('json-scada-user' in ck) {
165+
ck = JSON.parse(ck['json-scada-user'])
166+
}
167+
168+
fetch('/Invoke/auth/changePassword', {
169+
method: 'post',
170+
headers: {
171+
Accept: 'application/json',
172+
'Content-Type': 'application/json',
173+
},
174+
body: JSON.stringify({
175+
username: ck.username,
176+
currentPassword: currentPassword.value.trim(),
177+
newPassword: newPassword.value.trim(),
178+
}),
179+
})
180+
.then((res) => res.json())
181+
.then((data) => {
182+
if (!('error' in data)) {
183+
errorMessage.value = ""
184+
showChangePasswordDialog.value = false
185+
} else {
186+
errorMessage.value = t('login.changePasswordFailed')
187+
setTimeout(() => {
188+
errorMessage.value = ""
189+
}, 1500)
190+
}
191+
})
192+
.catch((err) => {
193+
console.warn(err)
194+
errorMessage.value = t('login.changePasswordError')
195+
setTimeout(() => {
196+
errorMessage.value = ""
197+
}, 1500)
198+
})
199+
}
200+
101201
watch(currentLocale, (newLocale) => {
102202
locale.value = newLocale;
103203
localStorage.setItem(STORAGE_KEY, newLocale);

src/AdminUI/src/components/DashboardPage.vue

+10-1
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,19 @@
2121
</template>
2222

2323
<script setup>
24-
import { ref } from 'vue';
24+
import { ref, onMounted, onUnmounted } from 'vue';
2525
import { useRouter } from 'vue-router';
2626
import { Monitor, Bell, Table, Calendar, FileText, UserCog, HelpCircle, BarChart, Database } from 'lucide-vue-next';
2727
28+
// Lifecycle hooks
29+
onMounted(async () => {
30+
document.documentElement.style.overflowY = 'scroll';
31+
});
32+
33+
onUnmounted(async () => {
34+
document.documentElement.style.overflowY = 'hidden';
35+
});
36+
2837
const router = useRouter();
2938
3039
const shortcuts = ref([

src/AdminUI/src/components/LoginPage.vue

+3-63
Original file line numberDiff line numberDiff line change
@@ -18,39 +18,15 @@
1818
</v-form>
1919
</v-card-text>
2020
<v-card-actions>
21-
<v-btn text @click="showChangePasswordDialog = true">
22-
{{ $t('login.forgotPassword') }}
23-
</v-btn>
2421
<v-spacer></v-spacer>
25-
<v-btn color="primary" @click="login">{{
22+
<v-btn color="primary" variant="tonal" @click="login">{{
2623
$t('login.submit')
2724
}}</v-btn>
2825
</v-card-actions>
2926
</v-card>
3027
</v-col>
3128
</v-row>
3229

33-
<!-- Change Password Dialog -->
34-
<v-dialog v-model="showChangePasswordDialog" max-width="400px">
35-
<v-card>
36-
<v-card-title>{{ $t('login.changePassword') }}</v-card-title>
37-
<v-card-text>
38-
<v-form @submit.prevent="changePassword">
39-
<v-text-field v-model="changePasswordEmail" :label="$t('login.email')" type="email" required></v-text-field>
40-
<v-text-field v-model="newPassword" :label="$t('login.newPassword')" type="password"
41-
required></v-text-field>
42-
<v-text-field v-model="confirmNewPassword" :label="$t('login.confirmNewPassword')" type="password"
43-
required></v-text-field>
44-
</v-form>
45-
</v-card-text>
46-
<v-card-actions>
47-
<v-spacer></v-spacer>
48-
<v-btn color="primary" @click="changePassword">
49-
{{ $t('login.submit') }}
50-
</v-btn>
51-
</v-card-actions>
52-
</v-card>
53-
</v-dialog>
5430
</v-container>
5531
</template>
5632

@@ -65,10 +41,6 @@ const setLoggedInUser = inject('setLoggedInUser')
6541
6642
const username = ref('')
6743
const password = ref('')
68-
const showChangePasswordDialog = ref(false)
69-
const changePasswordEmail = ref('')
70-
const newPassword = ref('')
71-
const confirmNewPassword = ref('')
7244
const errorMessage = ref('')
7345
7446
onMounted(() => {
@@ -94,6 +66,8 @@ const login = () => {
9466
return
9567
}
9668
setLoggedInUser(username.value)
69+
errorMessage.value = ""
70+
username.value = password.value = ""
9771
router.push('/dashboard')
9872
})
9973
.catch((error) => {
@@ -104,27 +78,6 @@ const login = () => {
10478
})
10579
}
10680
107-
const changePassword = () => {
108-
// Here you would implement the logic to change the password
109-
// This is just a placeholder implementation
110-
if (newPassword.value !== confirmNewPassword.value) {
111-
alert(t('login.passwordMismatch'))
112-
return
113-
}
114-
115-
// Simulating an API call
116-
console.log('Changing password for:', changePasswordEmail.value)
117-
118-
// Reset form and close dialog
119-
changePasswordEmail.value = ''
120-
newPassword.value = ''
121-
confirmNewPassword.value = ''
122-
showChangePasswordDialog.value = false
123-
124-
// Show success message
125-
alert(t('login.passwordChanged'))
126-
}
127-
12881
const parseCookie = (str) => {
12982
if (str === '') return {}
13083
return str
@@ -140,19 +93,6 @@ function testLogin() {
14093
let ck = parseCookie(document.cookie)
14194
if ('json-scada-user' in ck) {
14295
ck = JSON.parse(ck['json-scada-user'])
143-
//let logoutButton = document.getElementById('logout')
144-
// let buttonMessage = 'Logout [' + ck.username + ']'
145-
//if (logoutButton.textContent !== buttonMessage)
146-
// logoutButton.textContent = buttonMessage
147-
148-
//if (ck.rights.isAdmin)
149-
// document.getElementById('divAdmin').style.display = ''
150-
//else document.getElementById('divAdmin').style.display = 'none'
151-
152-
// if (ck.rights.changePassword)
153-
// document.getElementById('changePasswordButton').style.display = ''
154-
//else
155-
// document.getElementById('changePasswordButton').style.display = 'none'
15696
}
15797
15898
fetch('/Invoke/test/user', {

src/AdminUI/src/locales/en.json

+5
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,12 @@
2828
"submit": "Login",
2929
"forgotPassword": "Forgot Password?",
3030
"changePassword": "Change Password",
31+
"currentPassword": "Current Password",
3132
"errorMessage": "Invalid username or password",
33+
"passwordMismatch": "New passwords don't match!",
34+
"changePasswordFailed": "Failed changing password!",
35+
"changePasswordError": "Error changing password!",
36+
"invalidNewPassword": "Invalid new password!",
3237
"email": "Email",
3338
"newPassword": "New Password",
3439
"confirmNewPassword": "Confirm New Password",

0 commit comments

Comments
 (0)