Skip to content

Commit

Permalink
Improved: Added support to link user to multiple security groups (#267).
Browse files Browse the repository at this point in the history
  • Loading branch information
ravilodhi committed Sep 9, 2024
1 parent 453c703 commit 1a3aabd
Show file tree
Hide file tree
Showing 6 changed files with 347 additions and 78 deletions.
107 changes: 107 additions & 0 deletions src/components/SecurityGroupActionsPopover.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<template>
<ion-content>
<ion-list>
<ion-list-header>{{ securityGroup.groupName || securityGroup.groupId }}</ion-list-header>
<ion-item>
<ion-label>
{{ getDateTime(securityGroup.fromDate) }}
<p>{{ translate('added to group') }}</p>
</ion-label>
</ion-item>
<ion-item button @click="confirmRemove()" lines="none">
{{ translate("Remove") }}
</ion-item>
</ion-list>
</ion-content>
</template>

<script lang="ts">
import {
alertController,
IonContent,
IonItem,
IonLabel,
IonList,
IonListHeader,
popoverController,
} from "@ionic/vue";
import { defineComponent } from "vue";
import { translate } from "@hotwax/dxp-components";
import { mapGetters, useStore } from 'vuex';
import { UserService } from "@/services/UserService";
import { DateTime } from "luxon";
import { showToast } from "@/utils";
import { hasError } from "@/adapter";
import logger from '@/logger';
export default defineComponent({
name: "SecurityGroupActionsPopover",
components: {
IonContent,
IonItem,
IonLabel,
IonList,
IonListHeader
},
props: ['securityGroup'],
computed: {
...mapGetters({
selectedUser: 'user/getSelectedUser',
userSecurityGroups: 'user/getUserSecurityGroups',
})
},
methods: {
closePopover() {
popoverController.dismiss();
},
getDateTime(time: any) {
return DateTime.fromMillis(time).toLocaleString(DateTime.DATETIME_MED);
},
async removeUserSecurityGroup() {
try {
const resp = await UserService.removeUserSecurityGroup({
groupId: this.securityGroup.groupId,
userLoginId: this.selectedUser.userLoginId
})
if (hasError(resp)) throw resp.data
showToast(translate('Security group removed successfully.'))
} catch (error) {
showToast(translate('Something went wrong.'));
logger.error(error)
}
// refetching security groups
const userSecurityGroups = await UserService.getUserSecurityGroups(this.selectedUser.userLoginId)
this.store.dispatch('user/updateSelectedUser', { ...this.selectedUser, securityGroups: userSecurityGroups })
this.closePopover()
},
async confirmRemove() {
const message = 'Are you sure you want to perform this action?'
const alert = await alertController.create({
header: translate("Remove security group"),
message: translate(message),
buttons: [
{
text: translate("No"),
},
{
text: translate("Yes"),
handler: async () => {
await this.removeUserSecurityGroup();
}
}
],
});
return alert.present();
}
},
setup() {
const store = useStore();
return {
store,
translate
}
}
});
</script>
124 changes: 124 additions & 0 deletions src/components/SelectSecurityGroupModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
<template>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-button @click="closeModal">
<ion-icon slot="icon-only" :icon="closeOutline" />
</ion-button>
</ion-buttons>
<ion-title>{{ translate("Select security groups") }}</ion-title>
</ion-toolbar>
</ion-header>

<ion-content>
<ion-list>
<ion-item v-for="securityGroup in securityGroups" :key="securityGroup.groupId">
<ion-checkbox :checked="isSelected(securityGroup.groupId)" @ionChange="toggleSecurityGroupSelection(securityGroup)">
<ion-label>
{{ securityGroup.groupName || securityGroup.groupId }}
<p>{{ securityGroup.groupId }}</p>
</ion-label>
</ion-checkbox>
</ion-item>
</ion-list>

<ion-fab @click="saveSecurityGroups()" vertical="bottom" horizontal="end" slot="fixed">
<ion-fab-button>
<ion-icon :icon="saveOutline" />
</ion-fab-button>
</ion-fab>
</ion-content>
</template>

<script lang="ts">
import {
IonButtons,
IonButton,
IonCheckbox,
IonContent,
IonFab,
IonFabButton,
IonHeader,
IonIcon,
IonItem,
IonLabel,
IonList,
IonTitle,
IonToolbar,
modalController
} from "@ionic/vue";
import { defineComponent } from "vue";
import { closeOutline, saveOutline } from "ionicons/icons";
import { mapGetters, useStore } from "vuex";
import { translate } from '@hotwax/dxp-components'
export default defineComponent({
name: "SelectSecurityGroupModal",
components: {
IonButtons,
IonButton,
IonCheckbox,
IonContent,
IonFab,
IonFabButton,
IonHeader,
IonIcon,
IonItem,
IonLabel,
IonList,
IonTitle,
IonToolbar,
},
props: ["selectedSecurityGroups"],
data() {
return {
selectedSecurityGroupValues: JSON.parse(JSON.stringify(this.selectedSecurityGroups)),
}
},
computed: {
...mapGetters({
securityGroups: 'util/getSecurityGroups'
})
},
methods: {
closeModal() {
modalController.dismiss({ dismissed: true});
},
saveSecurityGroups() {
const securityGroupsToCreate = this.selectedSecurityGroupValues.filter((selectedGroup: any) => !this.selectedSecurityGroups.some((group: any) => group.groupId === selectedGroup.groupId))
const securityGroupsToRemove = this.selectedSecurityGroups.filter((group: any) => !this.selectedSecurityGroupValues.some((selectedGroup: any) => group.groupId === selectedGroup.groupId))
modalController.dismiss({
dismissed: true,
value: {
selectedSecurityGroups: this.selectedSecurityGroupValues,
securityGroupsToCreate,
securityGroupsToRemove
}
});
},
toggleSecurityGroupSelection(updatedSecurityGroup: any) {
let selectedGroup = this.selectedSecurityGroupValues.some((group :any) => group.groupId === updatedSecurityGroup.groupId);
if (selectedGroup) {
this.selectedSecurityGroupValues = this.selectedSecurityGroupValues.filter((group :any) => group.groupId !== updatedSecurityGroup.groupId);
} else {
this.selectedSecurityGroupValues.push(updatedSecurityGroup);
}
},
isSelected (securityGroupId: any) {
return this.selectedSecurityGroupValues.some((securityGroup :any) => securityGroup.groupId === securityGroupId);
}
},
setup() {
const store = useStore();
return {
closeOutline,
saveOutline,
store,
translate
};
},
});
</script>

23 changes: 10 additions & 13 deletions src/services/UserService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,15 +292,15 @@ const sendResetPasswordEmail = async (payload: any): Promise <any> => {
}


const getUserSecurityGroup = async (userLoginId: string): Promise<any> => {
let userSecurityGroup = {} as any
const getUserSecurityGroups = async (userLoginId: string): Promise<any> => {
let userSecurityGroups = [] as any
const payload = {
inputFields: {
userLoginId,
},
entityName: "UserLoginSecurityGroup",
filterByDate: "Y",
viewSize: 10,
viewSize: 20, //Don't think there will be more than 20 security groups associated with any user
fieldList: ["groupId", "userLoginId", "fromDate"]
}

Expand All @@ -313,18 +313,15 @@ const getUserSecurityGroup = async (userLoginId: string): Promise<any> => {


if (!hasError(resp) || resp.data.error === 'No record found') {
userSecurityGroup = {
groupId: resp.data.docs ? resp.data.docs[0].groupId : '',
fromDate: resp.data.docs && resp.data.docs[0].fromDate
}
userSecurityGroups = resp.data.docs ? resp.data.docs : []
} else {
throw resp.data
}
} catch (error) {
logger.error('Failed to fetch user associated security group.', error)
logger.error('Failed to fetch user associated security groups.', error)
}

return userSecurityGroup
return userSecurityGroups
}

const removeUserSecurityGroup = async (payload: any): Promise <any> => {
Expand All @@ -337,7 +334,7 @@ const removeUserSecurityGroup = async (payload: any): Promise <any> => {

const addUserToSecurityGroup = async (payload: any): Promise <any> => {
return api({
url: "service/addSecurityGroupToUserLogin",
url: "service/addPartyUserPermission",
method: "post",
data: payload
});
Expand Down Expand Up @@ -536,8 +533,8 @@ const finishSetup = async (payload: any): Promise <any> => {
});
if (!hasError(resp)) {
addUserToSecurityGroup({
"partyIdTo": partyId,
"securityGroupId": payload.selectedTemplate.securityGroupId ? payload.selectedTemplate.securityGroupId : "STORE_MANAGER",
"userLoginId": payload.formData.userLoginId,
"groupIds": payload.selectedTemplate.securityGroupId ? [payload.selectedTemplate.securityGroupId] : ["STORE_MANAGER"],
});
} else {
throw resp.data;
Expand Down Expand Up @@ -786,7 +783,7 @@ export const UserService = {
getUserProfile,
getUserFacilities,
getUserProductStores,
getUserSecurityGroup,
getUserSecurityGroups,
isUserLoginIdAlreadyExists,
isRoleTypeExists,
login,
Expand Down
2 changes: 1 addition & 1 deletion src/store/modules/user/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ const actions: ActionTree<UserState, RootState> = {

if (Object.keys(selectedUser).length) {
selectedUser.facilities = await UserService.getUserFacilities(selectedUser.partyId)
selectedUser.securityGroup = await UserService.getUserSecurityGroup(selectedUser.userLoginId)
selectedUser.securityGroups = await UserService.getUserSecurityGroups(selectedUser.userLoginId)
selectedUser.productStores = await UserService.getUserProductStores(selectedUser.partyId)
if (selectedUser.userLoginId) {
const userFavorites = await UserService.getUserFavorites({userLoginId: selectedUser.userLoginId})
Expand Down
3 changes: 3 additions & 0 deletions src/store/modules/user/getters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,8 @@ const getters: GetterTree<UserState, RootState> = {
getUserProductStores(state) {
return state.selectedUser.productStores;
},
getUserSecurityGroups(state) {
return state.selectedUser.securityGroups;
}
}
export default getters;
Loading

0 comments on commit 1a3aabd

Please sign in to comment.