Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 0 additions & 46 deletions src/components/access-control/GroupsMenu.vue

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,24 @@
class="d-inline-block pr-2"
v-model="flags.showOnMemberProfile"
label="Show on employee profile"
v-tooltip="{text: `Show employees who their ${groupName.toLowerCase()} is`, location: 'top', offset: -10 }"
v-tooltip="{text: `Show employees who their ${roleName.toLowerCase()} is`, location: 'top', offset: -10 }"
/>
<v-checkbox
class="d-inline-block pr-2"
v-model="flags.contractLink"
label="Contract link"
disabled
v-tooltip="{text: 'Make this group editable in contract settings', location: 'top', offset: -10 }"
v-tooltip="{text: 'Make this role editable in contract settings', location: 'top', offset: -10 }"
/>
<v-checkbox
class="d-inline-block pr-2"
v-model="flags.projectLink"
label="Project link"
disabled
v-tooltip="{ text: 'Make this group editable in project settings', location: 'top', offset: -10 }"
v-tooltip="{ text: 'Make this role editable in project settings', location: 'top', offset: -10 }"
/>
</v-row>
</template>

<script setup>
const flags = defineModel();
const props = defineProps(['groupName']);

/**
* TODO
* - [ ] Add link to contracts page
* - [ ] Add link to projects page
*/
const props = defineProps(['roleName']);
</script>
40 changes: 40 additions & 0 deletions src/components/access-control/RolesMenu.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<template>
<div>
<div class="d-flex align-center justify-center">
<h3 class="my-0 ml-0">Roles</h3>
<v-spacer />
<v-btn icon="mdi-plus-circle" variant="plain" size="small" @click="addRole()" />
</div>
<v-list nav density="compact" class="pr-0">
<v-list-item
v-for="(role, i) in props.roles"
:key="i"
:title="role.name"
@click="selectRole(i)"
class="overflow-auto"
>
<template #append>
<v-icon v-if="props.isLocked(role)" icon="mdi-lock" color="black" size="small" />
</template>
</v-list-item>
</v-list>
</div>
</template>

<script setup>
// Vue & Component imports
import { inject } from 'vue';
// Store and stuff
const emitter = inject('emitter');

const props = defineProps(['roles', 'isLocked']);

function addRole() {
emitter.emit('add-role');
}

function selectRole(index) {
emitter.emit('select-role', { index });
}

</script>
75 changes: 55 additions & 20 deletions src/components/contracts/ContractsTable.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div>
<div @click="api.getContractAccessControl()">
<v-container fluid class="pa-0 pa-md-2">
<v-row class="d-flex justify-space-between">
<v-col cols="12" md="3">
Expand Down Expand Up @@ -255,8 +255,8 @@ import _forEach from 'lodash/forEach';
import _some from 'lodash/some';
import _map from 'lodash/map';
import api from '@/shared/api';
import { updateStoreEmployees } from '@/utils/storeUtils';
import { asyncForEach, isMobile } from '@/utils/utils';
import { updateStoreEmployees, updateStoreContracts, updateStoreAccessRoles } from '@/utils/storeUtils';
import { asyncForEach, isMobile, indexBy } from '@/utils/utils';
import { getProject, getProjectCurrentEmployees } from '@/shared/contractUtils';
import { contractFilter } from '@/shared/filterUtils';

Expand All @@ -275,7 +275,6 @@ import { ref, inject, onBeforeMount, onBeforeUnmount, computed, watch } from 'vu
import { useDisplay } from 'vuetify';
import { useStore } from 'vuex';
import { useDisplayError, useDisplaySuccess } from '@/components/shared/StatusSnackbar.vue';
import { updateStoreContracts } from '../../utils/storeUtils';

// |--------------------------------------------------|
// | |
Expand Down Expand Up @@ -405,6 +404,13 @@ const contractHeaders = ref([
class: 'smaller-text description',
type: 'textarea'
},
{
title: 'Access Control',
key: 'accessControlLink',
align: 'start',
customWidth: 'large',
disableEdit: true
},
{
title: 'Active Employees',
key: 'activeEmployees',
Expand All @@ -423,6 +429,9 @@ const contractHeaders = ref([
const contractHeadcounts = ref({});
const form = ref(null);

let accessControl = {};
let employeeIndex = {};

// |--------------------------------------------------|
// | |
// | LIFECYCLE HOOKS |
Expand Down Expand Up @@ -490,6 +499,23 @@ onBeforeMount(async () => {
emitter.on('toggle-project-checkBox', ({ contract, project }) => {
toggleProjectCheckBox(contract, project);
});

// get any missing data from API
let [contractAC, projectAC] = await Promise.all([
api.getContractAccessControl(),
api.getProjectAccessControl(),
store.getters.employees ? '' : updateStoreEmployees(),
store.getters.contracts ? '' : updateStoreContracts()
]);

accessControl = {
contract: contractAC,
project: projectAC
}

employeeIndex = indexBy(store.getters.employees, 'id');

// set everything for UI
resetAllCheckBoxes();
expanded.value = _map(store.getters.contracts, 'id'); // expands all contracts in table
await getContractEmployeesHeadcount(); // get headcounts for each contract
Expand Down Expand Up @@ -520,6 +546,20 @@ onBeforeUnmount(() => {
// | |
// |--------------------------------------------------|

/**
* Digs into the access control link and makes it users instead of IDs
*
* @param id ID of project or contract
*/
function ACExpand(id) {
let names = [];
let getName = (eId) => `${employeeIndex[eId]?.nickname || employeeIndex[eId]?.firstName} ${employeeIndex[eId]?.lastName}`
// go through contract or project arrays and add names to matches
for (let eId of accessControl.contract?.[id] ?? []) names.push(getName(eId));
for (let eId of accessControl.project?.[id] ?? []) names.push(getName(eId));
return names;
}

/**
* Sets the item to be edited.
*
Expand Down Expand Up @@ -646,8 +686,6 @@ async function clickedDelete() {
* Fills in the contractHeadcounts variable.
*/
async function getContractEmployeesHeadcount() {
if (!store.getters.employees) await updateStoreEmployees();
if (!store.getters.contracts) await updateStoreContracts();
for (let contract of store.getters.contracts) {
let contractEmployees = new Set();
let projectEmployees;
Expand Down Expand Up @@ -719,9 +757,6 @@ async function updateStatus(status) {
* [{contract: "", prime: "", project: {...}, employees: [...]}, ...]
*/
async function getActiveEmployeeContractRelationships(contract, project = null) {
if (!store.getters.employees) {
await updateStoreEmployees();
}
let employees = store.getters.employees;
let theRelationships = [];
employees.forEach((e) => {
Expand Down Expand Up @@ -778,9 +813,6 @@ async function getActiveEmployeeContractRelationships(contract, project = null)
* [{contract: "", prime: "", project: {...}, employees: [...]}, ...]
*/
async function getEmployeeContractRelationships(contract, project = null) {
if (!store.getters.employees) {
await updateStoreEmployees();
}
let employees = store.getters.employees;
let theRelationships = [];
employees.forEach((e) => {
Expand Down Expand Up @@ -1030,15 +1062,18 @@ const storeContracts = computed(() => {
// get projects
let projects = contract.projects.filter((p) => status.has(p.status));

if (projects.length !== 0) {
for (let p of projects) p.checkBox = cbIndexProjects[p.id];
contracts.push({
...contract,
...cbIndexContracts[contract.id],
contractId: contract.id, // used for quick-edit
projects
});
for (let p of (projects || [])) {
p.checkBox = cbIndexProjects[p.id];
p.accessControlLink = ACExpand(p.id).join(', ')
}

contracts.push({
...contract,
...cbIndexContracts[contract.id],
accessControlLink: ACExpand(contract.id).join(', '),
contractId: contract.id, // used for quick-edit
projects
});
}

// :)
Expand Down
7 changes: 7 additions & 0 deletions src/components/contracts/ExpandedContractTableRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,13 @@ const projectHeaders = ref([
class: 'smaller-text description',
type: 'textarea'
},
{
title: 'Access Control',
key: 'accessControlLink',
align: 'start',
customWidth: 'large',
disableEdit: true
},
{
title: 'Active Employees',
key: 'projectActiveEmployees',
Expand Down
2 changes: 1 addition & 1 deletion src/components/reports/ReportsCertifications.vue
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ function buildCertificationsColumns() {
for (let emp of employeesInfo.value) {
certIndex[emp.employeeNumber] = [];
let activeCerts = certIndex[emp.employeeNumber]; // pointer-esque
for (let cert of (emp.certifications || [])) {
for (let cert of emp.certifications || []) {
if (!cert.expirationDate || (isSameOrBefore(getTodaysDate(), cert.expirationDate))) {
activeCerts.push(cert.name);
}
Expand Down
30 changes: 26 additions & 4 deletions src/shared/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const HIGH_FIVES = 'highFives';
const PTO_CASH_OUTS = 'ptoCashOuts';
const SETTINGS = 'settings';
const TAGS = 'tags';
const ACCESS_GROUPS = 'accessGroups';
const ACCESS_ROLES = 'accessRoles';
const API_HOSTNAME = API_CONFIG.apiHostname;
const API_PORT = API_CONFIG.apiPort;
const PORT = API_PORT === '443' ? '' : `:${API_PORT}`;
Expand Down Expand Up @@ -506,7 +506,7 @@ async function getEmployeesFromAdp() {
* @return - Array of IDs of employees who can see the user's data
*/
async function getAccessControlUsers(id) {
return await execute('get', `/${ACCESS_GROUPS}/employee/groupUsers/${id}`)
return await execute('get', `/${ACCESS_ROLES}/employee/roleUsers/${id}`)
}

/**
Expand All @@ -516,7 +516,27 @@ async function getAccessControlUsers(id) {
* @return - Array of IDs of employees who can see the user's data
*/
async function getUserProfileAccessControl(id) {
return await execute('get', `/${ACCESS_GROUPS}/employee/showOnProfile/${id}`)
return await execute('get', `/${ACCESS_ROLES}/link/showOnProfile/${id}`)
}

/**
* Gets access control data linked to contracts and projects.
* Convenience wrapper for projects and contracts
*
* @return - Array of IDs of employees who can see the user's data
*/
async function getProjectAccessControl() {
return await execute('get', `/${ACCESS_ROLES}/link/type/projects`);
}

/**
* Gets access control data linked to contracts and projects.
* Convenience wrapper for projects and contracts
*
* @return - Array of IDs of employees who can see the user's data
*/
async function getContractAccessControl() {
return await execute('get', `/${ACCESS_ROLES}/link/type/contracts`);
}

export default {
Expand Down Expand Up @@ -562,13 +582,15 @@ export default {
getEmployeesFromAdp,
getAccessControlUsers,
getUserProfileAccessControl,
getContractAccessControl,
getProjectAccessControl,
EXPENSE_TYPES,
EXPENSES,
EMPLOYEES,
CONTRACTS,
PTO_CASH_OUTS,
TAGS,
ACCESS_GROUPS,
ACCESS_ROLES,
UTILITY,
TIMESHEETS,
AUDIT,
Expand Down
Loading