hide actions and pages in the frontend according to permissions

This commit is contained in:
Gregor Vostrak
2024-04-25 04:12:10 +02:00
parent 77cedb160e
commit f22d423fff
21 changed files with 176 additions and 18 deletions

View File

@@ -2,6 +2,7 @@
import Dropdown from '@/Components/Dropdown.vue';
import { TrashIcon } from '@heroicons/vue/20/solid';
import type { Client } from '@/utils/api';
import { canDeleteClients } from '@/utils/permissions';
const emit = defineEmits<{
delete: [];
@@ -31,6 +32,7 @@ const props = defineProps<{
</template>
<template #content>
<button
v-if="canDeleteClients()"
@click="emit('delete')"
:aria-label="'Delete Client ' + props.client.name"
data-testid="client_delete"

View File

@@ -8,6 +8,7 @@ import { useClientsStore } from '@/utils/useClients';
import ClientTableRow from '@/Components/Common/Client/ClientTableRow.vue';
import ClientCreateModal from '@/Components/Common/Client/ClientCreateModal.vue';
import ClientTableHeading from '@/Components/Common/Client/ClientTableHeading.vue';
import { canCreateClients } from '@/utils/permissions';
const { clients } = storeToRefs(useClientsStore());
@@ -29,8 +30,11 @@ const createClient = ref(false);
<UserCircleIcon
class="w-8 text-icon-default inline pb-2"></UserCircleIcon>
<h3 class="text-white font-semibold">No clients found</h3>
<p class="pb-5">Create your first client now!</p>
<p class="pb-5" v-if="canCreateClients()">
Create your first client now!
</p>
<SecondaryButton
v-if="canCreateClients()"
@click="createClient = true"
:icon="PlusIcon"
>Create your First Client

View File

@@ -2,6 +2,7 @@
import Dropdown from '@/Components/Dropdown.vue';
import { TrashIcon } from '@heroicons/vue/20/solid';
import type { Member } from '@/utils/api';
import { canDeleteMembers } from '@/utils/permissions';
const emit = defineEmits<{
delete: [];
@@ -31,6 +32,7 @@ const props = defineProps<{
</template>
<template #content>
<button
v-if="canDeleteMembers()"
@click="emit('delete')"
:aria-label="'Delete Member ' + props.member.name"
data-testid="client_delete"

View File

@@ -9,6 +9,7 @@ import SecondaryButton from '@/Components/SecondaryButton.vue';
import { api } from '../../../../../openapi.json.client';
import { getCurrentOrganizationId } from '@/utils/useUser';
import { useNotificationsStore } from '@/utils/notification';
import { canInvitePlaceholderMembers } from '@/utils/permissions';
const props = defineProps<{
member: Member;
@@ -70,7 +71,10 @@ async function invitePlaceholder(id: string) {
<div
class="relative whitespace-nowrap flex items-center pl-3 text-right text-sm font-medium sm:pr-0 pr-4 sm:pr-6 lg:pr-8 3xl:pr-12">
<SecondaryButton
v-if="member.is_placeholder === true"
v-if="
member.is_placeholder === true &&
canInvitePlaceholderMembers()
"
@click="invitePlaceholder(member.id)"
size="small"
>Invite</SecondaryButton

View File

@@ -2,6 +2,7 @@
import Dropdown from '@/Components/Dropdown.vue';
import { TrashIcon, PencilSquareIcon } from '@heroicons/vue/20/solid';
import type { Project } from '@/utils/api';
import { canDeleteProjects, canUpdateProjects } from '@/utils/permissions';
const emit = defineEmits<{
delete: [];
edit: [];
@@ -34,12 +35,14 @@ const props = defineProps<{
@click.prevent="emit('delete')"
:aria-label="'Delete Project ' + props.project.name"
data-testid="project_delete"
v-if="canDeleteProjects()"
class="border-b border-card-background-separator flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out">
<TrashIcon class="w-5 text-icon-active"></TrashIcon>
<span>Delete</span>
</button>
<button
@click.prevent="emit('edit')"
v-if="canUpdateProjects()"
:aria-label="'Edit Project ' + props.project.name"
data-testid="project_edit"
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out">

View File

@@ -8,6 +8,7 @@ import ProjectCreateModal from '@/Components/Common/Project/ProjectCreateModal.v
import { storeToRefs } from 'pinia';
import ProjectTableHeading from '@/Components/Common/Project/ProjectTableHeading.vue';
import ProjectTableRow from '@/Components/Common/Project/ProjectTableRow.vue';
import { canCreateProjects } from '@/utils/permissions';
const { projects } = storeToRefs(useProjectsStore());
@@ -29,8 +30,11 @@ const createProject = ref(false);
<FolderPlusIcon
class="w-8 text-icon-default inline pb-2"></FolderPlusIcon>
<h3 class="text-white font-semibold">No projects found</h3>
<p class="pb-5">Create your first project now!</p>
<p class="pb-5" v-if="canCreateProjects()">
Create your first project now!
</p>
<SecondaryButton
v-if="canCreateProjects()"
@click="createProject = true"
:icon="PlusIcon"
>Create your First Project

View File

@@ -8,6 +8,7 @@ import { useTagsStore } from '@/utils/useTags';
import TagTableRow from '@/Components/Common/Tag/TagTableRow.vue';
import TagCreateModal from '@/Components/Common/Tag/TagCreateModal.vue';
import TagTableHeading from '@/Components/Common/Tag/TagTableHeading.vue';
import { canCreateTags } from '@/utils/permissions';
const { tags } = storeToRefs(useTagsStore());
const createTag = ref(false);
@@ -28,8 +29,13 @@ const createTag = ref(false);
<FolderPlusIcon
class="w-8 text-icon-default inline pb-2"></FolderPlusIcon>
<h3 class="text-white font-semibold">No tags found</h3>
<p class="pb-5">Create your first tag now!</p>
<SecondaryButton @click="createTag = true" :icon="PlusIcon"
<p class="pb-5" v-if="canCreateTags()">
Create your first tag now!
</p>
<SecondaryButton
v-if="canCreateTags()"
@click="createTag = true"
:icon="PlusIcon"
>Create your First Tag</SecondaryButton
>
</div>

View File

@@ -3,6 +3,7 @@ import type { Tag } from '@/utils/api';
import { useTagsStore } from '@/utils/useTags';
import TagMoreOptionsDropdown from '@/Components/Common/Tag/TagMoreOptionsDropdown.vue';
import TableRow from '@/Components/TableRow.vue';
import { canDeleteTags } from '@/utils/permissions';
const props = defineProps<{
tag: Tag;
@@ -24,6 +25,7 @@ function deleteTag() {
<div
class="relative whitespace-nowrap flex items-center pl-3 text-right text-sm font-medium sm:pr-0 pr-4 sm:pr-6 lg:pr-8 3xl:pr-12">
<TagMoreOptionsDropdown
v-if="canDeleteTags()"
:tag="tag"
@delete="deleteTag"></TagMoreOptionsDropdown>
</div>

View File

@@ -8,6 +8,7 @@ import { useTasksStore } from '@/utils/useTasks';
import TaskTableRow from '@/Components/Common/Task/TaskTableRow.vue';
import TaskTableHeading from '@/Components/Common/Task/TaskTableHeading.vue';
import TaskCreateModal from '@/Components/Common/Task/TaskCreateModal.vue';
import { canCreateTasks } from '@/utils/permissions';
const { tasks } = storeToRefs(useTasksStore());
@@ -39,8 +40,13 @@ const createTask = ref(false);
<PlusCircleIcon
class="w-8 text-icon-default inline pb-2"></PlusCircleIcon>
<h3 class="text-white font-semibold">No tasks found</h3>
<p class="pb-5">Create your first task now!</p>
<SecondaryButton @click="createTask = true" :icon="PlusIcon"
<p class="pb-5" v-if="canCreateTasks()">
Create your first task now!
</p>
<SecondaryButton
v-if="canCreateTasks()"
@click="createTask = true"
:icon="PlusIcon"
>Create your First Task
</SecondaryButton>
</div>

View File

@@ -6,6 +6,7 @@ import { router, usePage } from '@inertiajs/vue3';
import type { Organization, User } from '@/types/models';
import { isBillingActivated } from '@/utils/billing';
import { initializeStores } from '@/utils/init';
import { canUpdateOrganization } from '@/utils/permissions';
const page = usePage<{
jetstream: {
@@ -88,7 +89,9 @@ const switchToTeam = (team: Organization) => {
Organization Settings
</DropdownLink>
<DropdownLink v-if="isBillingActivated()" href="/billing">
<DropdownLink
v-if="canUpdateOrganization() && isBillingActivated()"
href="/billing">
Billing
</DropdownLink>