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