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-1"
28              :label="$t('pageProfileSettings.newPassword')"
29              label-for="input-1"
30            >
31              <b-form-text id="password-help-block">
32                {{
33                  $t('pageLocalUserManagement.modal.passwordMustBeBetween', {
34                    min: passwordRequirements.minLength,
35                    max: passwordRequirements.maxLength
36                  })
37                }}
38              </b-form-text>
39              <input-password-toggle>
40                <b-form-input
41                  id="password"
42                  v-model="form.newPassword"
43                  type="password"
44                  aria-describedby="password-help-block"
45                  :state="getValidationState($v.form.newPassword)"
46                  data-test-id="profileSettings-input-newPassword"
47                  @input="$v.form.newPassword.$touch()"
48                />
49                <b-form-invalid-feedback role="alert">
50                  <template
51                    v-if="
52                      !$v.form.newPassword.minLength ||
53                        !$v.form.newPassword.maxLength
54                    "
55                  >
56                    {{
57                      $t('pageProfileSettings.newPassLabelTextInfo', {
58                        min: passwordRequirements.minLength,
59                        max: passwordRequirements.maxLength
60                      })
61                    }}
62                  </template>
63                </b-form-invalid-feedback>
64              </input-password-toggle>
65            </b-form-group>
66            <b-form-group
67              id="input-group-2"
68              :label="$t('pageProfileSettings.confirmPassword')"
69              label-for="input-2"
70            >
71              <input-password-toggle>
72                <b-form-input
73                  id="password-confirmation"
74                  v-model="form.confirmPassword"
75                  type="password"
76                  :state="getValidationState($v.form.confirmPassword)"
77                  data-test-id="profileSettings-input-confirmPassword"
78                  @input="$v.form.confirmPassword.$touch()"
79                />
80                <b-form-invalid-feedback role="alert">
81                  <template v-if="!$v.form.confirmPassword.sameAsPassword">
82                    {{ $t('pageProfileSettings.passwordsDoNotMatch') }}
83                  </template>
84                </b-form-invalid-feedback>
85              </input-password-toggle>
86            </b-form-group>
87          </page-section>
88        </b-col>
89      </b-row>
90      <page-section :section-title="$t('pageProfileSettings.timezoneDisplay')">
91        <p>{{ $t('pageProfileSettings.timezoneDisplayDesc') }}</p>
92        <b-row>
93          <b-col md="9" lg="8" xl="9">
94            <b-form-group :label="$t('pageProfileSettings.timezone')">
95              <b-form-radio
96                v-model="form.isUtcDisplay"
97                :value="true"
98                data-test-id="profileSettings-radio-defaultUTC"
99                @change="$v.form.isUtcDisplay.$touch()"
100              >
101                {{ $t('pageProfileSettings.defaultUTC') }}
102              </b-form-radio>
103              <b-form-radio
104                v-model="form.isUtcDisplay"
105                :value="false"
106                data-test-id="profileSettings-radio-browserOffset"
107                @change="$v.form.isUtcDisplay.$touch()"
108              >
109                {{
110                  $t('pageProfileSettings.browserOffset', {
111                    timezone
112                  })
113                }}
114              </b-form-radio>
115            </b-form-group>
116          </b-col>
117        </b-row>
118      </page-section>
119      <b-button
120        variant="primary"
121        type="submit"
122        data-test-id="profileSettings-button-saveSettings"
123      >
124        {{ $t('global.action.saveSettings') }}
125      </b-button>
126    </b-form>
127  </b-container>
128</template>
129
130<script>
131import i18n from '@/i18n';
132import BVToastMixin from '@/components/Mixins/BVToastMixin';
133import InputPasswordToggle from '@/components/Global/InputPasswordToggle';
134import { format } from 'date-fns-tz';
135import {
136  maxLength,
137  minLength,
138  required,
139  sameAs
140} from 'vuelidate/lib/validators';
141import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin';
142import PageTitle from '@/components/Global/PageTitle';
143import PageSection from '@/components/Global/PageSection';
144import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js';
145
146export default {
147  name: 'ProfileSettings',
148  components: { InputPasswordToggle, PageSection, PageTitle },
149  mixins: [BVToastMixin, LoadingBarMixin, VuelidateMixin],
150  data() {
151    return {
152      form: {
153        newPassword: '',
154        confirmPassword: '',
155        isUtcDisplay: this.$store.getters['global/isUtcDisplay']
156      }
157    };
158  },
159  computed: {
160    username() {
161      return this.$store.getters['global/username'];
162    },
163    passwordRequirements() {
164      return this.$store.getters['localUsers/accountPasswordRequirements'];
165    },
166    timezone() {
167      const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
168      const shortTz = this.$options.filters.shortTimeZone(new Date());
169      const pattern = `'${shortTz}' O`;
170      return format(new Date(), pattern, { timezone }).replace('GMT', 'UTC');
171    }
172  },
173  created() {
174    this.startLoader();
175    this.$store
176      .dispatch('localUsers/getAccountSettings')
177      .finally(() => this.endLoader());
178  },
179  validations() {
180    return {
181      form: {
182        isUtcDisplay: { required },
183        newPassword: {
184          minLength: minLength(this.passwordRequirements.minLength),
185          maxLength: maxLength(this.passwordRequirements.maxLength)
186        },
187        confirmPassword: {
188          sameAsPassword: sameAs('newPassword')
189        }
190      }
191    };
192  },
193  methods: {
194    saveNewPasswordInputData() {
195      this.$v.form.confirmPassword.$touch();
196      this.$v.form.newPassword.$touch();
197      if (this.$v.$invalid) return;
198      let userData = {
199        originalUsername: this.username,
200        password: this.form.newPassword
201      };
202
203      this.$store
204        .dispatch('localUsers/updateUser', userData)
205        .then(message => {
206          (this.form.newPassword = ''), (this.form.confirmPassword = '');
207          this.$v.$reset();
208          this.successToast(message);
209        })
210        .catch(({ message }) => this.errorToast(message));
211    },
212    saveTimeZonePrefrenceData() {
213      localStorage.setItem('storedUtcDisplay', this.form.isUtcDisplay);
214      this.$store.commit('global/setUtcTime', this.form.isUtcDisplay);
215      this.successToast(
216        i18n.t('pageProfileSettings.toast.successSaveSettings')
217      );
218    },
219    submitForm() {
220      if (this.form.confirmPassword || this.form.newPassword) {
221        this.saveNewPasswordInputData();
222      }
223      if (this.$v.form.isUtcDisplay.$anyDirty) {
224        this.saveTimeZonePrefrenceData();
225      }
226    }
227  }
228};
229</script>
230