xref: /openbmc/webui-vue/src/views/SecurityAndAccess/UserManagement/UserManagement.vue (revision d1ef18e6f9ed1527b66cec07eba6acaf9a95819c)
1b440616cSSandeepa Singh<template>
2b440616cSSandeepa Singh  <b-container fluid="xl">
3b440616cSSandeepa Singh    <page-title />
4b440616cSSandeepa Singh    <b-row>
5b440616cSSandeepa Singh      <b-col xl="9" class="text-right">
6b440616cSSandeepa Singh        <b-button variant="link" @click="initModalSettings">
7b440616cSSandeepa Singh          <icon-settings />
8b440616cSSandeepa Singh          {{ $t('pageUserManagement.accountPolicySettings') }}
9b440616cSSandeepa Singh        </b-button>
10b440616cSSandeepa Singh        <b-button
11b440616cSSandeepa Singh          variant="primary"
12b440616cSSandeepa Singh          data-test-id="userManagement-button-addUser"
13b440616cSSandeepa Singh          @click="initModalUser(null)"
14b440616cSSandeepa Singh        >
15b440616cSSandeepa Singh          <icon-add />
16b440616cSSandeepa Singh          {{ $t('pageUserManagement.addUser') }}
17b440616cSSandeepa Singh        </b-button>
18b440616cSSandeepa Singh      </b-col>
19b440616cSSandeepa Singh    </b-row>
20b440616cSSandeepa Singh    <b-row>
21b440616cSSandeepa Singh      <b-col xl="9">
22b440616cSSandeepa Singh        <table-toolbar
23b440616cSSandeepa Singh          ref="toolbar"
24b440616cSSandeepa Singh          :selected-items-count="selectedRows.length"
25b440616cSSandeepa Singh          :actions="tableToolbarActions"
26b440616cSSandeepa Singh          @clear-selected="clearSelectedRows($refs.table)"
27b440616cSSandeepa Singh          @batch-action="onBatchAction"
28b440616cSSandeepa Singh        />
29b440616cSSandeepa Singh        <b-table
30b440616cSSandeepa Singh          ref="table"
31b440616cSSandeepa Singh          responsive="md"
32b440616cSSandeepa Singh          selectable
33b440616cSSandeepa Singh          show-empty
34b440616cSSandeepa Singh          no-select-on-click
35b440616cSSandeepa Singh          hover
3641057853SKenneth Fullbright          :busy="isBusy"
37b440616cSSandeepa Singh          :fields="fields"
38b440616cSSandeepa Singh          :items="tableItems"
39b440616cSSandeepa Singh          :empty-text="$t('global.table.emptyMessage')"
40b440616cSSandeepa Singh          @row-selected="onRowSelected($event, tableItems.length)"
41b440616cSSandeepa Singh        >
42b440616cSSandeepa Singh          <!-- Checkbox column -->
43b440616cSSandeepa Singh          <template #head(checkbox)>
44b440616cSSandeepa Singh            <b-form-checkbox
45b440616cSSandeepa Singh              v-model="tableHeaderCheckboxModel"
46b440616cSSandeepa Singh              data-test-id="userManagement-checkbox-tableHeaderCheckbox"
47b440616cSSandeepa Singh              :indeterminate="tableHeaderCheckboxIndeterminate"
48b440616cSSandeepa Singh              @change="onChangeHeaderCheckbox($refs.table)"
49b440616cSSandeepa Singh            >
50b440616cSSandeepa Singh              <span class="sr-only">{{ $t('global.table.selectAll') }}</span>
51b440616cSSandeepa Singh            </b-form-checkbox>
52b440616cSSandeepa Singh          </template>
53b440616cSSandeepa Singh          <template #cell(checkbox)="row">
54b440616cSSandeepa Singh            <b-form-checkbox
55b440616cSSandeepa Singh              v-model="row.rowSelected"
56b440616cSSandeepa Singh              data-test-id="userManagement-checkbox-toggleSelectRow"
57b440616cSSandeepa Singh              @change="toggleSelectRow($refs.table, row.index)"
58b440616cSSandeepa Singh            >
59b440616cSSandeepa Singh              <span class="sr-only">{{ $t('global.table.selectItem') }}</span>
60b440616cSSandeepa Singh            </b-form-checkbox>
61b440616cSSandeepa Singh          </template>
62b440616cSSandeepa Singh
63b440616cSSandeepa Singh          <!-- table actions column -->
64b440616cSSandeepa Singh          <template #cell(actions)="{ item }">
65b440616cSSandeepa Singh            <table-row-action
66b440616cSSandeepa Singh              v-for="(action, index) in item.actions"
67b440616cSSandeepa Singh              :key="index"
68b440616cSSandeepa Singh              :value="action.value"
69b440616cSSandeepa Singh              :enabled="action.enabled"
70b440616cSSandeepa Singh              :title="action.title"
71b440616cSSandeepa Singh              @click-table-action="onTableRowAction($event, item)"
72b440616cSSandeepa Singh            >
73b440616cSSandeepa Singh              <template #icon>
74b440616cSSandeepa Singh                <icon-edit
75b440616cSSandeepa Singh                  v-if="action.value === 'edit'"
76b440616cSSandeepa Singh                  :data-test-id="`userManagement-tableRowAction-edit-${index}`"
77b440616cSSandeepa Singh                />
78b440616cSSandeepa Singh                <icon-trashcan
79b440616cSSandeepa Singh                  v-if="action.value === 'delete'"
80b440616cSSandeepa Singh                  :data-test-id="`userManagement-tableRowAction-delete-${index}`"
81b440616cSSandeepa Singh                />
82b440616cSSandeepa Singh              </template>
83b440616cSSandeepa Singh            </table-row-action>
84b440616cSSandeepa Singh          </template>
85b440616cSSandeepa Singh        </b-table>
86b440616cSSandeepa Singh      </b-col>
87b440616cSSandeepa Singh    </b-row>
88b440616cSSandeepa Singh    <b-row>
89b440616cSSandeepa Singh      <b-col xl="8">
90b440616cSSandeepa Singh        <b-button
91b440616cSSandeepa Singh          v-b-toggle.collapse-role-table
92b440616cSSandeepa Singh          data-test-id="userManagement-button-viewPrivilegeRoleDescriptions"
93b440616cSSandeepa Singh          variant="link"
94b440616cSSandeepa Singh          class="mt-3"
95b440616cSSandeepa Singh        >
96b440616cSSandeepa Singh          <icon-chevron />
97b440616cSSandeepa Singh          {{ $t('pageUserManagement.viewPrivilegeRoleDescriptions') }}
98b440616cSSandeepa Singh        </b-button>
99b440616cSSandeepa Singh        <b-collapse id="collapse-role-table" class="mt-3">
100b440616cSSandeepa Singh          <table-roles />
101b440616cSSandeepa Singh        </b-collapse>
102b440616cSSandeepa Singh      </b-col>
103b440616cSSandeepa Singh    </b-row>
104b440616cSSandeepa Singh    <!-- Modals -->
1056ad19aacSkirankumarb07    <modal-settings :settings="setting" @ok="saveAccountSettings" />
106b440616cSSandeepa Singh    <modal-user
107b440616cSSandeepa Singh      :user="activeUser"
108b440616cSSandeepa Singh      :password-requirements="passwordRequirements"
109b440616cSSandeepa Singh      @ok="saveUser"
110b440616cSSandeepa Singh      @hidden="activeUser = null"
111b440616cSSandeepa Singh    />
112b440616cSSandeepa Singh  </b-container>
113b440616cSSandeepa Singh</template>
114b440616cSSandeepa Singh
115b440616cSSandeepa Singh<script>
116b440616cSSandeepa Singhimport IconTrashcan from '@carbon/icons-vue/es/trash-can/20';
117b440616cSSandeepa Singhimport IconEdit from '@carbon/icons-vue/es/edit/20';
118b440616cSSandeepa Singhimport IconAdd from '@carbon/icons-vue/es/add--alt/20';
119b440616cSSandeepa Singhimport IconSettings from '@carbon/icons-vue/es/settings/20';
120b440616cSSandeepa Singhimport IconChevron from '@carbon/icons-vue/es/chevron--up/20';
121b440616cSSandeepa Singh
122b440616cSSandeepa Singhimport ModalUser from './ModalUser';
123b440616cSSandeepa Singhimport ModalSettings from './ModalSettings';
124b440616cSSandeepa Singhimport PageTitle from '@/components/Global/PageTitle';
125b440616cSSandeepa Singhimport TableRoles from './TableRoles';
126b440616cSSandeepa Singhimport TableToolbar from '@/components/Global/TableToolbar';
127b440616cSSandeepa Singhimport TableRowAction from '@/components/Global/TableRowAction';
128b440616cSSandeepa Singh
129b440616cSSandeepa Singhimport BVTableSelectableMixin, {
130b440616cSSandeepa Singh  selectedRows,
131b440616cSSandeepa Singh  tableHeaderCheckboxModel,
132b440616cSSandeepa Singh  tableHeaderCheckboxIndeterminate,
133b440616cSSandeepa Singh} from '@/components/Mixins/BVTableSelectableMixin';
134b440616cSSandeepa Singhimport BVToastMixin from '@/components/Mixins/BVToastMixin';
135b440616cSSandeepa Singhimport LoadingBarMixin from '@/components/Mixins/LoadingBarMixin';
136b440616cSSandeepa Singh
137b440616cSSandeepa Singhexport default {
138b440616cSSandeepa Singh  name: 'UserManagement',
139b440616cSSandeepa Singh  components: {
140b440616cSSandeepa Singh    IconAdd,
141b440616cSSandeepa Singh    IconChevron,
142b440616cSSandeepa Singh    IconEdit,
143b440616cSSandeepa Singh    IconSettings,
144b440616cSSandeepa Singh    IconTrashcan,
145b440616cSSandeepa Singh    ModalSettings,
146b440616cSSandeepa Singh    ModalUser,
147b440616cSSandeepa Singh    PageTitle,
148b440616cSSandeepa Singh    TableRoles,
149b440616cSSandeepa Singh    TableRowAction,
150b440616cSSandeepa Singh    TableToolbar,
151b440616cSSandeepa Singh  },
152b440616cSSandeepa Singh  mixins: [BVTableSelectableMixin, BVToastMixin, LoadingBarMixin],
153b440616cSSandeepa Singh  beforeRouteLeave(to, from, next) {
154b440616cSSandeepa Singh    this.hideLoader();
155b440616cSSandeepa Singh    next();
156b440616cSSandeepa Singh  },
157b440616cSSandeepa Singh  data() {
158b440616cSSandeepa Singh    return {
15941057853SKenneth Fullbright      isBusy: true,
160b440616cSSandeepa Singh      activeUser: null,
1616ad19aacSkirankumarb07      setting: {},
162b440616cSSandeepa Singh      fields: [
163b440616cSSandeepa Singh        {
164b440616cSSandeepa Singh          key: 'checkbox',
165b440616cSSandeepa Singh        },
166b440616cSSandeepa Singh        {
167b440616cSSandeepa Singh          key: 'username',
168b440616cSSandeepa Singh          label: this.$t('pageUserManagement.table.username'),
169b440616cSSandeepa Singh        },
170b440616cSSandeepa Singh        {
171b440616cSSandeepa Singh          key: 'privilege',
172b440616cSSandeepa Singh          label: this.$t('pageUserManagement.table.privilege'),
173b440616cSSandeepa Singh        },
174b440616cSSandeepa Singh        {
175b440616cSSandeepa Singh          key: 'status',
176b440616cSSandeepa Singh          label: this.$t('pageUserManagement.table.status'),
177b440616cSSandeepa Singh        },
178b440616cSSandeepa Singh        {
179b440616cSSandeepa Singh          key: 'actions',
180b440616cSSandeepa Singh          label: '',
181b440616cSSandeepa Singh          tdClass: 'text-right text-nowrap',
182b440616cSSandeepa Singh        },
183b440616cSSandeepa Singh      ],
184b440616cSSandeepa Singh      tableToolbarActions: [
185b440616cSSandeepa Singh        {
186b440616cSSandeepa Singh          value: 'delete',
187b440616cSSandeepa Singh          label: this.$t('global.action.delete'),
188b440616cSSandeepa Singh        },
189b440616cSSandeepa Singh        {
190b440616cSSandeepa Singh          value: 'enable',
191b440616cSSandeepa Singh          label: this.$t('global.action.enable'),
192b440616cSSandeepa Singh        },
193b440616cSSandeepa Singh        {
194b440616cSSandeepa Singh          value: 'disable',
195b440616cSSandeepa Singh          label: this.$t('global.action.disable'),
196b440616cSSandeepa Singh        },
197b440616cSSandeepa Singh      ],
198b440616cSSandeepa Singh      selectedRows: selectedRows,
199b440616cSSandeepa Singh      tableHeaderCheckboxModel: tableHeaderCheckboxModel,
200b440616cSSandeepa Singh      tableHeaderCheckboxIndeterminate: tableHeaderCheckboxIndeterminate,
201b440616cSSandeepa Singh    };
202b440616cSSandeepa Singh  },
203b440616cSSandeepa Singh  computed: {
204b440616cSSandeepa Singh    allUsers() {
205b440616cSSandeepa Singh      return this.$store.getters['userManagement/allUsers'];
206b440616cSSandeepa Singh    },
207b440616cSSandeepa Singh    tableItems() {
208b440616cSSandeepa Singh      // transform user data to table data
209b440616cSSandeepa Singh      return this.allUsers.map((user) => {
210b440616cSSandeepa Singh        return {
211b440616cSSandeepa Singh          username: user.UserName,
212b440616cSSandeepa Singh          privilege: user.RoleId,
213b440616cSSandeepa Singh          status: user.Locked
214b440616cSSandeepa Singh            ? 'Locked'
215b440616cSSandeepa Singh            : user.Enabled
216b440616cSSandeepa Singh              ? 'Enabled'
217b440616cSSandeepa Singh              : 'Disabled',
218b440616cSSandeepa Singh          actions: [
219b440616cSSandeepa Singh            {
220b440616cSSandeepa Singh              value: 'edit',
2212897447bSSivaprabu Ganesan              enabled: this.editEnable(user),
222b440616cSSandeepa Singh              title: this.$t('pageUserManagement.editUser'),
223b440616cSSandeepa Singh            },
224b440616cSSandeepa Singh            {
225b440616cSSandeepa Singh              value: 'delete',
2262897447bSSivaprabu Ganesan              enabled:
2272897447bSSivaprabu Ganesan                user.UserName === this.$store.getters['global/username']
2282897447bSSivaprabu Ganesan                  ? false
2292897447bSSivaprabu Ganesan                  : true && user.UserName === 'root'
2302897447bSSivaprabu Ganesan                    ? false
2312897447bSSivaprabu Ganesan                    : true,
232b440616cSSandeepa Singh              title: this.$tc('pageUserManagement.deleteUser'),
233b440616cSSandeepa Singh            },
234b440616cSSandeepa Singh          ],
235b440616cSSandeepa Singh          ...user,
236b440616cSSandeepa Singh        };
237b440616cSSandeepa Singh      });
238b440616cSSandeepa Singh    },
239b440616cSSandeepa Singh    settings() {
240b440616cSSandeepa Singh      return this.$store.getters['userManagement/accountSettings'];
241b440616cSSandeepa Singh    },
242b440616cSSandeepa Singh    passwordRequirements() {
243b440616cSSandeepa Singh      return this.$store.getters['userManagement/accountPasswordRequirements'];
244b440616cSSandeepa Singh    },
245b440616cSSandeepa Singh  },
246b440616cSSandeepa Singh  created() {
247b440616cSSandeepa Singh    this.startLoader();
24841057853SKenneth Fullbright    this.$store.dispatch('userManagement/getUsers').finally(() => {
24941057853SKenneth Fullbright      this.endLoader();
25041057853SKenneth Fullbright      this.isBusy = false;
25141057853SKenneth Fullbright    });
252b440616cSSandeepa Singh    this.$store.dispatch('userManagement/getAccountSettings');
253b440616cSSandeepa Singh    this.$store.dispatch('userManagement/getAccountRoles');
254b440616cSSandeepa Singh  },
255b440616cSSandeepa Singh  methods: {
2562897447bSSivaprabu Ganesan    editEnable(user) {
2572897447bSSivaprabu Ganesan      if ('root' === this.$store.getters['global/username']) {
2582897447bSSivaprabu Ganesan        return true;
2592897447bSSivaprabu Ganesan      } else {
2602897447bSSivaprabu Ganesan        return user.UserName === 'root' ? false : true;
2612897447bSSivaprabu Ganesan      }
2622897447bSSivaprabu Ganesan    },
263b440616cSSandeepa Singh    initModalUser(user) {
264b440616cSSandeepa Singh      this.activeUser = user;
265b440616cSSandeepa Singh      this.$bvModal.show('modal-user');
266b440616cSSandeepa Singh    },
267b440616cSSandeepa Singh    initModalDelete(user) {
268b440616cSSandeepa Singh      this.$bvModal
269b440616cSSandeepa Singh        .msgBoxConfirm(
270b440616cSSandeepa Singh          this.$t('pageUserManagement.modal.deleteConfirmMessage', {
271b440616cSSandeepa Singh            user: user.username,
272b440616cSSandeepa Singh          }),
273b440616cSSandeepa Singh          {
274b440616cSSandeepa Singh            title: this.$tc('pageUserManagement.deleteUser'),
275b440616cSSandeepa Singh            okTitle: this.$tc('pageUserManagement.deleteUser'),
276b440616cSSandeepa Singh            cancelTitle: this.$t('global.action.cancel'),
277*d1ef18e6SPaul Fertser            autoFocusButton: 'ok',
2788132399cSEd Tanous          },
279b440616cSSandeepa Singh        )
280b440616cSSandeepa Singh        .then((deleteConfirmed) => {
281b440616cSSandeepa Singh          if (deleteConfirmed) {
282b440616cSSandeepa Singh            this.deleteUser(user);
283b440616cSSandeepa Singh          }
284b440616cSSandeepa Singh        });
285b440616cSSandeepa Singh    },
286b440616cSSandeepa Singh    initModalSettings() {
2876ad19aacSkirankumarb07      this.setting = this.settings;
288b440616cSSandeepa Singh      this.$bvModal.show('modal-settings');
289b440616cSSandeepa Singh    },
290b440616cSSandeepa Singh    saveUser({ isNewUser, userData }) {
291b440616cSSandeepa Singh      this.startLoader();
292b440616cSSandeepa Singh      if (isNewUser) {
293b440616cSSandeepa Singh        this.$store
294b440616cSSandeepa Singh          .dispatch('userManagement/createUser', userData)
295b440616cSSandeepa Singh          .then((success) => this.successToast(success))
296b440616cSSandeepa Singh          .catch(({ message }) => this.errorToast(message))
297b440616cSSandeepa Singh          .finally(() => this.endLoader());
298b440616cSSandeepa Singh      } else {
299b440616cSSandeepa Singh        this.$store
300b440616cSSandeepa Singh          .dispatch('userManagement/updateUser', userData)
301b440616cSSandeepa Singh          .then((success) => this.successToast(success))
302b440616cSSandeepa Singh          .catch(({ message }) => this.errorToast(message))
303b440616cSSandeepa Singh          .finally(() => this.endLoader());
304b440616cSSandeepa Singh      }
305b440616cSSandeepa Singh    },
306b440616cSSandeepa Singh    deleteUser({ username }) {
307b440616cSSandeepa Singh      this.startLoader();
308b440616cSSandeepa Singh      this.$store
309b440616cSSandeepa Singh        .dispatch('userManagement/deleteUser', username)
310b440616cSSandeepa Singh        .then((success) => this.successToast(success))
311b440616cSSandeepa Singh        .catch(({ message }) => this.errorToast(message))
312b440616cSSandeepa Singh        .finally(() => this.endLoader());
313b440616cSSandeepa Singh    },
314b440616cSSandeepa Singh    onBatchAction(action) {
315b440616cSSandeepa Singh      switch (action) {
316b440616cSSandeepa Singh        case 'delete':
317b440616cSSandeepa Singh          this.$bvModal
318b440616cSSandeepa Singh            .msgBoxConfirm(
319b440616cSSandeepa Singh              this.$tc(
320b440616cSSandeepa Singh                'pageUserManagement.modal.batchDeleteConfirmMessage',
3218132399cSEd Tanous                this.selectedRows.length,
322b440616cSSandeepa Singh              ),
323b440616cSSandeepa Singh              {
324b440616cSSandeepa Singh                title: this.$tc(
325b440616cSSandeepa Singh                  'pageUserManagement.deleteUser',
3268132399cSEd Tanous                  this.selectedRows.length,
327b440616cSSandeepa Singh                ),
328b440616cSSandeepa Singh                okTitle: this.$tc(
329b440616cSSandeepa Singh                  'pageUserManagement.deleteUser',
3308132399cSEd Tanous                  this.selectedRows.length,
331b440616cSSandeepa Singh                ),
332b440616cSSandeepa Singh                cancelTitle: this.$t('global.action.cancel'),
333*d1ef18e6SPaul Fertser                autoFocusButton: 'ok',
3348132399cSEd Tanous              },
335b440616cSSandeepa Singh            )
336b440616cSSandeepa Singh            .then((deleteConfirmed) => {
337b440616cSSandeepa Singh              if (deleteConfirmed) {
338b440616cSSandeepa Singh                this.startLoader();
339b440616cSSandeepa Singh                this.$store
340b440616cSSandeepa Singh                  .dispatch('userManagement/deleteUsers', this.selectedRows)
341b440616cSSandeepa Singh                  .then((messages) => {
342b440616cSSandeepa Singh                    messages.forEach(({ type, message }) => {
343b440616cSSandeepa Singh                      if (type === 'success') this.successToast(message);
344b440616cSSandeepa Singh                      if (type === 'error') this.errorToast(message);
345b440616cSSandeepa Singh                    });
346b440616cSSandeepa Singh                  })
347b440616cSSandeepa Singh                  .finally(() => this.endLoader());
348b440616cSSandeepa Singh              }
349b440616cSSandeepa Singh            });
350b440616cSSandeepa Singh          break;
351b440616cSSandeepa Singh        case 'enable':
352b440616cSSandeepa Singh          this.startLoader();
353b440616cSSandeepa Singh          this.$store
354b440616cSSandeepa Singh            .dispatch('userManagement/enableUsers', this.selectedRows)
355b440616cSSandeepa Singh            .then((messages) => {
356b440616cSSandeepa Singh              messages.forEach(({ type, message }) => {
357b440616cSSandeepa Singh                if (type === 'success') this.successToast(message);
358b440616cSSandeepa Singh                if (type === 'error') this.errorToast(message);
359b440616cSSandeepa Singh              });
360b440616cSSandeepa Singh            })
361b440616cSSandeepa Singh            .finally(() => this.endLoader());
362b440616cSSandeepa Singh          break;
363b440616cSSandeepa Singh        case 'disable':
364b440616cSSandeepa Singh          this.startLoader();
365b440616cSSandeepa Singh          this.$store
366b440616cSSandeepa Singh            .dispatch('userManagement/disableUsers', this.selectedRows)
367b440616cSSandeepa Singh            .then((messages) => {
368b440616cSSandeepa Singh              messages.forEach(({ type, message }) => {
369b440616cSSandeepa Singh                if (type === 'success') this.successToast(message);
370b440616cSSandeepa Singh                if (type === 'error') this.errorToast(message);
371b440616cSSandeepa Singh              });
372b440616cSSandeepa Singh            })
373b440616cSSandeepa Singh            .finally(() => this.endLoader());
374b440616cSSandeepa Singh          break;
375b440616cSSandeepa Singh      }
376b440616cSSandeepa Singh    },
377b440616cSSandeepa Singh    onTableRowAction(action, row) {
378b440616cSSandeepa Singh      switch (action) {
379b440616cSSandeepa Singh        case 'edit':
380b440616cSSandeepa Singh          this.initModalUser(row);
381b440616cSSandeepa Singh          break;
382b440616cSSandeepa Singh        case 'delete':
383b440616cSSandeepa Singh          this.initModalDelete(row);
384b440616cSSandeepa Singh          break;
385b440616cSSandeepa Singh        default:
386b440616cSSandeepa Singh          break;
387b440616cSSandeepa Singh      }
388b440616cSSandeepa Singh    },
389b440616cSSandeepa Singh    saveAccountSettings(settings) {
390b440616cSSandeepa Singh      this.startLoader();
391b440616cSSandeepa Singh      this.$store
392b440616cSSandeepa Singh        .dispatch('userManagement/saveAccountSettings', settings)
393b440616cSSandeepa Singh        .then((message) => this.successToast(message))
394b440616cSSandeepa Singh        .catch(({ message }) => this.errorToast(message))
395b440616cSSandeepa Singh        .finally(() => this.endLoader());
396b440616cSSandeepa Singh    },
397b440616cSSandeepa Singh  },
398b440616cSSandeepa Singh};
399b440616cSSandeepa Singh</script>
400b440616cSSandeepa Singh
401b440616cSSandeepa Singh<style lang="scss" scoped>
402b440616cSSandeepa Singh.btn.collapsed {
403b440616cSSandeepa Singh  svg {
404b440616cSSandeepa Singh    transform: rotate(180deg);
405b440616cSSandeepa Singh  }
406b440616cSSandeepa Singh}
407b440616cSSandeepa Singh</style>
408