1<template>
2  <b-container fluid="xl">
3    <page-title />
4
5    <b-row>
6      <b-col md="8" lg="8" xl="6">
7        <page-section
8          :section-title="$t('pageProfileSettings.profileInfoTitle')"
9        >
10          <dl>
11            <dt>{{ $t('pageProfileSettings.username') }}</dt>
12            <dd>
13              {{ username }}
14            </dd>
15          </dl>
16        </page-section>
17      </b-col>
18    </b-row>
19
20    <b-form @submit.prevent="submitForm">
21      <b-row>
22        <b-col sm="8" md="6" xl="3">
23          <page-section
24            :section-title="$t('pageProfileSettings.changePassword')"
25          >
26            <b-form-group
27              id="input-group-0"
28              :label="$t('pageProfileSettings.currentPassword')"
29              label-for="input-0"
30            >
31              <input-password-toggle>
32                <b-form-input
33                  id="old-password"
34                  v-model="form.currentPassword"
35                  type="password"
36                  data-test-id="profileSettings-input-ocurrentPassword"
37                  class="form-control-with-button"
38                />
39              </input-password-toggle>
40            </b-form-group>
41            <b-form-group
42              id="input-group-1"
43              :label="$t('pageProfileSettings.newPassword')"
44              label-for="input-1"
45            >
46              <b-form-text id="password-help-block">
47                {{
48                  $t('pageUserManagement.modal.passwordMustBeBetween', {
49                    min: passwordRequirements.minLength,
50                    max: passwordRequirements.maxLength,
51                  })
52                }}
53              </b-form-text>
54              <input-password-toggle>
55                <b-form-input
56                  id="password"
57                  v-model="form.newPassword"
58                  type="password"
59                  aria-describedby="password-help-block"
60                  :state="getValidationState(v$.form.newPassword)"
61                  data-test-id="profileSettings-input-newPassword"
62                  class="form-control-with-button"
63                  @input="v$.form.newPassword.$touch()"
64                />
65                <b-form-invalid-feedback role="alert">
66                  <template
67                    v-if="
68                      v$.form.newPassword.minLength.$invalid ||
69                      v$.form.newPassword.maxLength.$invalid
70                    "
71                  >
72                    {{
73                      $t('pageProfileSettings.newPassLabelTextInfo', {
74                        min: passwordRequirements.minLength,
75                        max: passwordRequirements.maxLength,
76                      })
77                    }}
78                  </template>
79                </b-form-invalid-feedback>
80              </input-password-toggle>
81            </b-form-group>
82            <b-form-group
83              id="input-group-2"
84              :label="$t('pageProfileSettings.confirmPassword')"
85              label-for="input-2"
86            >
87              <input-password-toggle>
88                <b-form-input
89                  id="password-confirmation"
90                  v-model="form.confirmPassword"
91                  type="password"
92                  :state="getValidationState(v$.form.confirmPassword)"
93                  data-test-id="profileSettings-input-confirmPassword"
94                  class="form-control-with-button"
95                  @input="v$.form.confirmPassword.$touch()"
96                />
97                <b-form-invalid-feedback role="alert">
98                  <template
99                    v-if="v$.form.confirmPassword.sameAsPassword.$invalid"
100                  >
101                    {{ $t('pageProfileSettings.passwordsDoNotMatch') }}
102                  </template>
103                </b-form-invalid-feedback>
104              </input-password-toggle>
105            </b-form-group>
106          </page-section>
107        </b-col>
108      </b-row>
109      <page-section :section-title="$t('pageProfileSettings.timezoneDisplay')">
110        <p>{{ $t('pageProfileSettings.timezoneDisplayDesc') }}</p>
111        <b-row>
112          <b-col md="9" lg="8" xl="9">
113            <b-form-group :label="$t('pageProfileSettings.timezone')">
114              <b-form-radio
115                v-model="form.isUtcDisplay"
116                :value="true"
117                data-test-id="profileSettings-radio-defaultUTC"
118              >
119                {{ $t('pageProfileSettings.defaultUTC') }}
120              </b-form-radio>
121              <b-form-radio
122                v-model="form.isUtcDisplay"
123                :value="false"
124                data-test-id="profileSettings-radio-browserOffset"
125              >
126                {{
127                  $t('pageProfileSettings.browserOffset', {
128                    timezone,
129                  })
130                }}
131              </b-form-radio>
132            </b-form-group>
133          </b-col>
134        </b-row>
135      </page-section>
136      <b-button
137        variant="primary"
138        type="submit"
139        data-test-id="profileSettings-button-saveSettings"
140      >
141        {{ $t('global.action.saveSettings') }}
142      </b-button>
143    </b-form>
144  </b-container>
145</template>
146
147<script>
148import BVToastMixin from '@/components/Mixins/BVToastMixin';
149import InputPasswordToggle from '@/components/Global/InputPasswordToggle';
150import { maxLength, minLength, sameAs } from '@vuelidate/validators';
151import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin';
152import LocalTimezoneLabelMixin from '@/components/Mixins/LocalTimezoneLabelMixin';
153import PageTitle from '@/components/Global/PageTitle';
154import PageSection from '@/components/Global/PageSection';
155import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js';
156import { useVuelidate } from '@vuelidate/core';
157import { useI18n } from 'vue-i18n';
158import i18n from '@/i18n';
159
160export default {
161  name: 'ProfileSettings',
162  components: { InputPasswordToggle, PageSection, PageTitle },
163  mixins: [
164    BVToastMixin,
165    LocalTimezoneLabelMixin,
166    LoadingBarMixin,
167    VuelidateMixin,
168  ],
169  setup() {
170    return {
171      v$: useVuelidate(),
172    };
173  },
174  data() {
175    return {
176      $t: useI18n().t,
177      form: {
178        newPassword: '',
179        confirmPassword: '',
180        currentPassword: '',
181        isUtcDisplay: this.$store.getters['global/isUtcDisplay'],
182      },
183    };
184  },
185  computed: {
186    username() {
187      return this.$store.getters['global/username'];
188    },
189    passwordRequirements() {
190      return this.$store.getters['userManagement/accountPasswordRequirements'];
191    },
192    timezone() {
193      return this.localOffset();
194    },
195  },
196  created() {
197    this.startLoader();
198    this.$store
199      .dispatch('userManagement/getAccountSettings')
200      .finally(() => this.endLoader());
201  },
202  validations() {
203    return {
204      form: {
205        newPassword: {
206          minLength: minLength(this.passwordRequirements.minLength),
207          maxLength: maxLength(this.passwordRequirements.maxLength),
208        },
209        confirmPassword: {
210          sameAsPassword: sameAs('newPassword'),
211        },
212      },
213    };
214  },
215  methods: {
216    saveNewPasswordInputData() {
217      this.v$.form.confirmPassword.$touch();
218      this.v$.form.newPassword.$touch();
219      if (this.v$.$invalid) return;
220      let userData = {
221        originalUsername: this.username,
222        password: this.form.newPassword,
223      };
224
225      this.$store
226        .dispatch('userManagement/updateUser', userData)
227        .then((message) => {
228          (this.form.newPassword = ''),
229            (this.form.confirmPassword = ''),
230            (this.form.currentPassword = '');
231          this.v$.$reset();
232          this.successToast(message);
233          this.$store.dispatch('authentication/logout');
234        })
235        .catch(({ message }) => this.errorToast(message));
236    },
237    saveTimeZonePrefrenceData() {
238      localStorage.setItem('storedUtcDisplay', this.form.isUtcDisplay);
239      this.$store.commit('global/setUtcTime', this.form.isUtcDisplay);
240      this.successToast(
241        i18n.global.t('pageProfileSettings.toast.successUpdatingTimeZone'),
242      );
243    },
244    submitForm() {
245      if (
246        this.form.confirmPassword &&
247        this.form.newPassword &&
248        this.form.currentPassword
249      ) {
250        this.confirmAuthenticate();
251      }
252      if (
253        this.$store.getters['global/isUtcDisplay'] != this.form.isUtcDisplay
254      ) {
255        this.saveTimeZonePrefrenceData();
256      }
257    },
258    confirmAuthenticate() {
259      this.v$.form.newPassword.$touch();
260      if (this.v$.$invalid) return;
261
262      const username = this.username;
263      const password = this.form.currentPassword;
264
265      this.$store
266        .dispatch('authentication/login', { username, password })
267        .then(() => {
268          this.saveNewPasswordInputData();
269        })
270        .catch(() => {
271          this.v$.$reset();
272          this.errorToast(
273            i18n.global.t('pageProfileSettings.toast.wrongCredentials'),
274          );
275        });
276    },
277  },
278};
279</script>
280