feat(user-management): add popup with basic functionality to add or edit user info and module access
This commit is contained in:
parent
ff66a457d9
commit
a1b6748d95
|
|
@ -58,6 +58,21 @@ export default {
|
|||
company: "company",
|
||||
supervisor: "supervisor",
|
||||
hired_date: "hiring date",
|
||||
bankroll_id: "payroll ID",
|
||||
module_access: {
|
||||
dashboard: "Dashboard",
|
||||
employee_list: "employee list",
|
||||
employee_management: "employee management",
|
||||
personal_profile: "profile",
|
||||
timesheets: "timesheets",
|
||||
timesheets_approval: "timesheet approval",
|
||||
user_access: "module access",
|
||||
presets: "access presets",
|
||||
preset_admin: "admin",
|
||||
preset_employee: "employee",
|
||||
uncheck_all: "remove all",
|
||||
|
||||
},
|
||||
},
|
||||
preferences: {
|
||||
tab_title: "preferences",
|
||||
|
|
|
|||
|
|
@ -58,6 +58,20 @@ export default {
|
|||
company: "compagnie",
|
||||
supervisor: "nom du superviseur",
|
||||
hired_date: "date d'embauche",
|
||||
bankroll_id: "identifiant de paie",
|
||||
module_access: {
|
||||
dashboard: "accueil",
|
||||
employee_list: "liste employés",
|
||||
employee_management: "gestion employés",
|
||||
personal_profile: "profil",
|
||||
timesheets: "feuilles de temps",
|
||||
timesheets_approval: "valider feuilles de temps",
|
||||
user_access: "accès aux modules",
|
||||
presets: "accès prédéfinis",
|
||||
preset_admin: "administrateur",
|
||||
preset_employee: "employé",
|
||||
uncheck_all: "aucun accès",
|
||||
},
|
||||
},
|
||||
preferences: {
|
||||
tab_title: "préférences",
|
||||
|
|
|
|||
|
|
@ -16,20 +16,16 @@
|
|||
const user_preferences = ref(ui_store.user_preferences);
|
||||
|
||||
onMounted(async () => {
|
||||
console.log('current preferences on load: ', ui_store.user_preferences);
|
||||
if (ui_store.user_preferences.id === -1) {
|
||||
console.log('fetching preferences');
|
||||
await ui_store.getUserPreferences();
|
||||
}
|
||||
});
|
||||
|
||||
watch(user_preferences, async () => {
|
||||
if (ui_store.user_preferences.id !== -1) {
|
||||
console.log('triggered watcher');
|
||||
await ui_store.updateUserPreferences(t);
|
||||
return
|
||||
}
|
||||
console.log('watcher triggered but store has no preferences')
|
||||
await ui_store.getUserPreferences();
|
||||
}, {deep: true});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -49,12 +49,17 @@
|
|||
class="col-grow text-center text-h6 text-weight-medium text-uppercase q-pb-none"
|
||||
style="line-height: 0.8em;"
|
||||
>
|
||||
<div class="ellipsis" :class="row.last_work_day === undefined ? 'text-accent' : 'text-negative'"> {{ row.first_name }} {{ row.last_name }} </div>
|
||||
<div
|
||||
class="ellipsis"
|
||||
:class="row.last_work_day === undefined ? 'text-accent' : 'text-negative'"
|
||||
>
|
||||
{{ row.first_name }} {{ row.last_name }}
|
||||
</div>
|
||||
<q-separator
|
||||
color="accent"
|
||||
class="q-mx-sm q-mt-xs"
|
||||
/>
|
||||
<div class=" ellipsis-2-lines text-caption"> {{ row.job_title }} </div>
|
||||
<div class=" ellipsis-2-lines text-caption">{{ row.job_title }}</div>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section class="bg-primary text-white text-caption text-center q-py-none col-2 content-center">
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@
|
|||
<EmployeeListTableItem
|
||||
:row="props.row"
|
||||
:index="props.rowIndex"
|
||||
@on-profile-click="employee_store.openAddModifyDialog"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
|
@ -82,6 +83,7 @@
|
|||
icon="person_add"
|
||||
:label="$t('shared.label.add')"
|
||||
class="text-uppercase"
|
||||
@click.stop="_evt => employee_store.openAddModifyDialog()"
|
||||
/>
|
||||
|
||||
<q-space />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,244 @@
|
|||
<script
|
||||
setup
|
||||
lang="ts"
|
||||
>
|
||||
import { useEmployeeStore } from 'src/stores/employee-store';
|
||||
import { employee_access_options, type ModuleAccessPreset, type ModuleAccessName, employee_access_presets } from 'src/modules/employee-list/models/employee-profile.models';
|
||||
import { unwrapAndClone } from 'src/utils/unwrap-and-clone';
|
||||
|
||||
const employee_store = useEmployeeStore();
|
||||
|
||||
const toggleInSelected = (value: ModuleAccessName) => {
|
||||
const i = employee_store.employee.user_module_access.indexOf(value);
|
||||
if (i === -1) employee_store.employee.user_module_access.push(value);
|
||||
else employee_store.employee.user_module_access.splice(i, 1);
|
||||
}
|
||||
|
||||
const applyAccessPreset = (preset: ModuleAccessPreset) => {
|
||||
employee_store.employee.user_module_access = unwrapAndClone(employee_access_presets[preset]);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<q-form>
|
||||
<div
|
||||
class="q-ma-xs"
|
||||
:class="$q.screen.lt.md ? 'column' : 'row'"
|
||||
>
|
||||
<q-input
|
||||
v-model="employee_store.employee.first_name"
|
||||
standout="bg-accent"
|
||||
dense
|
||||
stack-label
|
||||
label-slot
|
||||
class="col q-ma-xs"
|
||||
>
|
||||
<template #label>
|
||||
<span class="text-weight-bolder text-uppercase" style="font-size: 0.85em;">
|
||||
{{ $t('profile.personal.first_name') }}
|
||||
</span>
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<q-input
|
||||
v-model="employee_store.employee.last_name"
|
||||
standout="bg-accent"
|
||||
dense
|
||||
stack-label
|
||||
label-slot
|
||||
class="col q-ma-xs"
|
||||
>
|
||||
<template #label>
|
||||
<span class="text-weight-bolder text-uppercase" style="font-size: 0.85em;">
|
||||
{{ $t('profile.personal.last_name') }}
|
||||
</span>
|
||||
</template>
|
||||
</q-input>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="q-ma-xs"
|
||||
:class="$q.screen.lt.md ? 'column' : 'row'"
|
||||
>
|
||||
<q-input
|
||||
v-model="employee_store.employee.email"
|
||||
standout="bg-accent"
|
||||
dense
|
||||
stack-label
|
||||
label-slot
|
||||
class="col q-ma-xs"
|
||||
>
|
||||
<template #label>
|
||||
<span class="text-weight-bolder text-uppercase" style="font-size: 0.85em;">
|
||||
{{ $t('profile.employee.email') }}
|
||||
</span>
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<q-input
|
||||
v-model="employee_store.employee.phone_number"
|
||||
standout="bg-accent"
|
||||
dense
|
||||
stack-label
|
||||
label-slot
|
||||
class="col q-ma-xs"
|
||||
>
|
||||
<template #label>
|
||||
<span class="text-weight-bolder text-uppercase" style="font-size: 0.85em;">
|
||||
{{ $t('profile.personal.phone_number') }}
|
||||
</span>
|
||||
</template>
|
||||
</q-input>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="q-ma-xs"
|
||||
:class="$q.screen.lt.md ? 'column' : 'row'"
|
||||
>
|
||||
<q-input
|
||||
v-model="employee_store.employee.job_title"
|
||||
standout="bg-accent"
|
||||
dense
|
||||
stack-label
|
||||
label-slot
|
||||
class="col q-ma-xs"
|
||||
>
|
||||
<template #label>
|
||||
<span class="text-weight-bolder text-uppercase" style="font-size: 0.85em;">
|
||||
{{ $t('profile.employee.job_title') }}
|
||||
</span>
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<q-input
|
||||
v-model="employee_store.employee.company_name"
|
||||
standout="bg-accent"
|
||||
dense
|
||||
stack-label
|
||||
label-slot
|
||||
class="col q-ma-xs"
|
||||
>
|
||||
<template #label>
|
||||
<span class="text-weight-bolder text-uppercase" style="font-size: 0.85em;">
|
||||
{{ $t('profile.employee.company') }}
|
||||
</span>
|
||||
</template>
|
||||
</q-input>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="q-ma-xs"
|
||||
:class="$q.screen.lt.md ? 'column' : 'row'"
|
||||
>
|
||||
<q-input
|
||||
v-model="employee_store.employee.supervisor_full_name"
|
||||
standout="bg-accent"
|
||||
dense
|
||||
stack-label
|
||||
label-slot
|
||||
class="col q-ma-xs"
|
||||
>
|
||||
<template #label>
|
||||
<span class="text-weight-bolder text-uppercase" style="font-size: 0.85em;">
|
||||
{{ $t('profile.employee.supervisor') }}
|
||||
</span>
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<q-input
|
||||
v-model="employee_store.employee.phone_number"
|
||||
standout="bg-accent"
|
||||
dense
|
||||
stack-label
|
||||
label-slot
|
||||
class="col q-ma-xs"
|
||||
>
|
||||
<template #label>
|
||||
<span class="text-weight-bolder text-uppercase" style="font-size: 0.85em;">
|
||||
{{ $t('profile.employee.bankroll_id') }}
|
||||
</span>
|
||||
</template>
|
||||
</q-input>
|
||||
</div>
|
||||
|
||||
<q-field
|
||||
v-model="employee_store.employee.user_module_access"
|
||||
dense
|
||||
stack-label
|
||||
label-slot
|
||||
standout="transparent"
|
||||
class="col-12 q-ma-sm"
|
||||
>
|
||||
<template #label>
|
||||
<span class="text-weight-bolder text-uppercase" style="font-size: 0.85em;">
|
||||
{{ $t('profile.employee.module_access.user_access') }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<div class="col-12 column full-width">
|
||||
<div class="row col-auto flex-center">
|
||||
<q-btn
|
||||
dense
|
||||
flat
|
||||
color="accent"
|
||||
:label="$t('profile.employee.module_access.preset_admin')"
|
||||
class="col-3 q-mx-sm q-pa-xs text-weight-bold"
|
||||
@click="applyAccessPreset('admin')"
|
||||
/>
|
||||
|
||||
<q-btn
|
||||
dense
|
||||
flat
|
||||
color="accent"
|
||||
:label="$t('profile.employee.module_access.preset_employee')"
|
||||
class="col-3 q-mx-sm q-pa-xs text-weight-bold"
|
||||
@click="applyAccessPreset('employee')"
|
||||
/>
|
||||
|
||||
<q-btn
|
||||
dense
|
||||
flat
|
||||
color="negative"
|
||||
:label="$t('profile.employee.module_access.uncheck_all')"
|
||||
class="col-3 q-mx-sm q-pa-xs text-weight-bold"
|
||||
@click="applyAccessPreset('none')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div
|
||||
v-for="option in employee_access_options"
|
||||
:key="option.label"
|
||||
class="col-xl-4 col-lg-6 col-sm-12 col-xs-12 q-pa-xs"
|
||||
>
|
||||
<div
|
||||
class="row full-width cursor-pointer flex-center q-pa-sm rounded-5 no-wrap shadow-1"
|
||||
:class="employee_store.employee.user_module_access.includes(option.value) ? 'bg-accent text-white' : ''"
|
||||
@click="toggleInSelected(option.value)"
|
||||
>
|
||||
<span class="text-uppercase text-caption">
|
||||
{{ $t('profile.employee.module_access.' + option.value) }}
|
||||
</span>
|
||||
<q-space />
|
||||
<q-icon
|
||||
:name="employee_store.employee.user_module_access.includes(option.value) ? 'check' : ''"
|
||||
size="sm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <q-option-group
|
||||
v-model="selected_permissions"
|
||||
dense
|
||||
inline
|
||||
left-label
|
||||
type="checkbox"
|
||||
color="accent"
|
||||
:options="employee_access_options"
|
||||
/> -->
|
||||
</q-field>
|
||||
</q-form>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<script
|
||||
setup
|
||||
lang="ts"
|
||||
>
|
||||
import AddModifyDialogForm from 'src/modules/employee-list/components/employee/add-modify-dialog-form.vue';
|
||||
|
||||
import { useEmployeeStore } from 'src/stores/employee-store';
|
||||
|
||||
const employee_store = useEmployeeStore();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<q-dialog v-model="employee_store.is_add_modify_dialog_open">
|
||||
<q-card>
|
||||
<q-card-section class="text-bolder text-white bg-primary text-center">
|
||||
<span >ADD EMPLOYEE</span>
|
||||
</q-card-section>
|
||||
|
||||
<AddModifyDialogForm />
|
||||
<q-inner-loading :showing="employee_store.is_loading" />
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { useEmployeeStore } from 'src/stores/employee-store';
|
||||
|
||||
const employee_store = useEmployeeStore();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<q-dialog v-model="employee_store.isShowingEmployeeAddModifyWindow">
|
||||
<q-card>
|
||||
<q-card-section>
|
||||
LOL
|
||||
</q-card-section>
|
||||
<q-inner-loading :showing="employee_store.is_loading"/>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
|
@ -1,4 +1,7 @@
|
|||
import type { QTableColumn } from "quasar";
|
||||
import type { QSelectOption, QTableColumn } from "quasar";
|
||||
|
||||
export type ModuleAccessName = 'dashboard' | 'employee_list' | 'employee_management' | 'personal_profile' | 'timesheets' | 'timesheets_approval';
|
||||
export type ModuleAccessPreset = 'admin' | 'employee' | 'none';
|
||||
|
||||
export class EmployeeProfile {
|
||||
first_name: string;
|
||||
|
|
@ -10,8 +13,10 @@ export class EmployeeProfile {
|
|||
phone_number: string;
|
||||
first_work_day: string;
|
||||
last_work_day: string;
|
||||
external_payroll_id: number;
|
||||
residence: string;
|
||||
birth_date: string;
|
||||
user_module_access: ModuleAccessName[];
|
||||
|
||||
constructor() {
|
||||
this.first_name = '';
|
||||
|
|
@ -25,6 +30,8 @@ export class EmployeeProfile {
|
|||
this.last_work_day = '';
|
||||
this.residence = '';
|
||||
this.birth_date = '';
|
||||
this.external_payroll_id = -1;
|
||||
this.user_module_access = ['dashboard',];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -67,6 +74,21 @@ export const employee_list_columns: QTableColumn<EmployeeProfile>[] = [
|
|||
},
|
||||
];
|
||||
|
||||
export const employee_access_options: QSelectOption<ModuleAccessName>[] = [
|
||||
{ label: 'dashboard', value: 'dashboard' },
|
||||
{ label: 'employee_list', value: 'employee_list' },
|
||||
{ label: 'employee_management', value: 'employee_management' },
|
||||
{ label: 'personal_profile', value: 'personal_profile' },
|
||||
{ label: 'timesheets', value: 'timesheets' },
|
||||
{ label: 'timesheets_approval', value: 'timesheets_approval' },
|
||||
]
|
||||
|
||||
export const employee_access_presets: Record<ModuleAccessPreset, ModuleAccessName[]> = {
|
||||
'admin' : ['dashboard', 'employee_list', 'employee_management', 'personal_profile', 'timesheets', 'timesheets_approval'],
|
||||
'employee' : ['dashboard', 'timesheets', 'personal_profile', 'employee_list'],
|
||||
'none' : [],
|
||||
}
|
||||
|
||||
export const getCompanyName = (company_code: number) => {
|
||||
switch (company_code) {
|
||||
case 271583: return 'Targo';
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@
|
|||
lang="ts"
|
||||
>
|
||||
import EmployeeListTable from 'src/modules/employee-list/components/employee-list-table.vue';
|
||||
import EmployeeListAddModifyDialog from 'src/modules/employee-list/components/employee/employee-list-add-modify-dialog.vue';
|
||||
import AddModifyDialog from 'src/modules/employee-list/components/employee/add-modify-dialog.vue';
|
||||
import PageHeaderTemplate from 'src/modules/shared/components/page-header-template.vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<q-page class="column flex-center">
|
||||
<EmployeeListAddModifyDialog />
|
||||
<AddModifyDialog />
|
||||
|
||||
<PageHeaderTemplate title="employee_list.page_header" />
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,25 @@ import { EmployeeProfile } from "src/modules/employee-list/models/employee-profi
|
|||
export const useEmployeeStore = defineStore('employee', () => {
|
||||
const employee = ref<EmployeeProfile>(new EmployeeProfile);
|
||||
const employee_list = ref<EmployeeProfile[]>([]);
|
||||
const isShowingEmployeeAddModifyWindow = ref<boolean>(false);
|
||||
const is_add_modify_dialog_open = ref<boolean>(false);
|
||||
const is_loading = ref(false);
|
||||
const isLoadingEmployeeList = ref(false);
|
||||
|
||||
const openAddModifyDialog = async (employee_email?: string) =>{
|
||||
console.log('open window triggered');
|
||||
is_add_modify_dialog_open.value = true;
|
||||
|
||||
if (employee_email === undefined) {
|
||||
employee.value = new EmployeeProfile();
|
||||
return;
|
||||
}
|
||||
|
||||
is_loading.value = true;
|
||||
await getEmployeeDetails(employee_email);
|
||||
is_loading.value = false;
|
||||
}
|
||||
|
||||
const getEmployeeList = async () => {
|
||||
isLoadingEmployeeList.value = true;
|
||||
is_loading.value = true;
|
||||
try {
|
||||
const response = await EmployeeListService.getEmployeeList();
|
||||
employee_list.value = response;
|
||||
|
|
@ -19,7 +32,7 @@ export const useEmployeeStore = defineStore('employee', () => {
|
|||
console.error("Ran into an error fetching employee list: ", error);
|
||||
//TODO: trigger an alert window with an error message here!
|
||||
}
|
||||
isLoadingEmployeeList.value = false;
|
||||
is_loading.value = false;
|
||||
};
|
||||
|
||||
const getEmployeeDetails = async (email?: string) => {
|
||||
|
|
@ -40,6 +53,14 @@ export const useEmployeeStore = defineStore('employee', () => {
|
|||
is_loading.value = false;
|
||||
};
|
||||
|
||||
return { employee, employee_list, isShowingEmployeeAddModifyWindow, isLoadingEmployeeList, is_loading, getEmployeeList, getEmployeeDetails };
|
||||
return {
|
||||
employee,
|
||||
employee_list,
|
||||
is_add_modify_dialog_open,
|
||||
is_loading,
|
||||
getEmployeeList,
|
||||
getEmployeeDetails,
|
||||
openAddModifyDialog,
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user