fix(ticketing): restrict settings link to admins and protect global priorities
- Show 'Go to Settings' bootstrap link only for admin/super_admin users - Pass isSiteAdmin prop to Create.vue to control settings CTA visibility - Require site admin for updatePriority/destroyPriority when priority is global (group_id = null) - Closes: non-admin users seeing forbidden settings link; agents mutating global priorities
This commit is contained in:
@@ -2,30 +2,30 @@
|
||||
<div class="max-w-5xl mx-auto py-8 px-4">
|
||||
<div class="mb-6">
|
||||
<Link :href="route('ticketing.index')" class="text-sm text-indigo-600 hover:underline">← Back to tickets</Link>
|
||||
<h1 class="text-2xl font-bold text-gray-900 dark:text-white mt-2">Ticketing Settings</h1>
|
||||
<h1 class="text-2xl font-bold text-gray-900 mt-2">Ticketing Settings</h1>
|
||||
</div>
|
||||
|
||||
<div v-if="isBootstrap" class="mb-6 px-5 py-4 bg-amber-50 dark:bg-amber-900/30 border border-amber-300 dark:border-amber-600 rounded-xl">
|
||||
<h2 class="text-base font-semibold text-amber-800 dark:text-amber-200 mb-1">🚀 First-Run Setup</h2>
|
||||
<p class="text-sm text-amber-700 dark:text-amber-300">
|
||||
<div v-if="isBootstrap" class="mb-6 px-5 py-4 bg-amber-50 border border-amber-300 rounded-xl">
|
||||
<h2 class="text-base font-semibold text-amber-800 mb-1">🚀 First-Run Setup</h2>
|
||||
<p class="text-sm text-amber-700">
|
||||
No groups exist yet. Create your first group below to get started.
|
||||
Default priorities (Low, Medium, High, Urgent) will be seeded automatically.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div v-if="$page.props.flash?.success" class="mb-4 px-4 py-2 bg-green-50 dark:bg-green-900/30 border border-green-200 dark:border-green-700 text-green-700 dark:text-green-300 rounded-lg text-sm">
|
||||
<div v-if="$page.props.flash?.success" class="mb-4 px-4 py-2 bg-green-50 border border-green-200 text-green-700 rounded-lg text-sm">
|
||||
{{ $page.props.flash.success }}
|
||||
</div>
|
||||
|
||||
<div v-if="$page.props.errors?.priority" class="mb-4 px-4 py-2 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-700 text-red-700 dark:text-red-300 rounded-lg text-sm">
|
||||
<div v-if="$page.props.errors?.priority" class="mb-4 px-4 py-2 bg-red-50 border border-red-200 text-red-700 rounded-lg text-sm">
|
||||
{{ $page.props.errors.priority }}
|
||||
</div>
|
||||
|
||||
<div v-if="$page.props.errors?.project" class="mb-4 px-4 py-2 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-700 text-red-700 dark:text-red-300 rounded-lg text-sm">
|
||||
<div v-if="$page.props.errors?.project" class="mb-4 px-4 py-2 bg-red-50 border border-red-200 text-red-700 rounded-lg text-sm">
|
||||
{{ $page.props.errors.project }}
|
||||
</div>
|
||||
|
||||
<div class="flex gap-1 border-b border-gray-200 dark:border-gray-700 mb-6">
|
||||
<div class="flex gap-1 border-b border-gray-200 mb-6">
|
||||
<button
|
||||
v-for="tab in tabs"
|
||||
:key="tab.key"
|
||||
@@ -33,34 +33,34 @@
|
||||
:class="[
|
||||
'px-4 py-2.5 text-sm font-medium border-b-2 transition',
|
||||
activeTab === tab.key
|
||||
? 'border-indigo-600 text-indigo-600 dark:text-indigo-400'
|
||||
: 'border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700'
|
||||
? 'border-indigo-600 text-indigo-600'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700'
|
||||
]"
|
||||
>{{ tab.label }}</button>
|
||||
</div>
|
||||
|
||||
<div v-if="activeTab === 'groups'">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h2 class="text-lg font-semibold text-gray-800 dark:text-gray-100">Groups</h2>
|
||||
<h2 class="text-lg font-semibold text-gray-800">Groups</h2>
|
||||
<button @click="showAddGroup = !showAddGroup" class="text-sm text-indigo-600 hover:underline">
|
||||
{{ showAddGroup ? 'Cancel' : '+ Add Group' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="showAddGroup" class="bg-gray-50 dark:bg-gray-700 rounded-xl p-4 mb-5 space-y-3">
|
||||
<h3 class="text-sm font-semibold text-gray-700 dark:text-gray-200">New Group</h3>
|
||||
<div v-if="showAddGroup" class="bg-gray-50 rounded-xl p-4 mb-5 space-y-3">
|
||||
<h3 class="text-sm font-semibold text-gray-700">New Group</h3>
|
||||
<form @submit.prevent="submitGroup" class="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Name</label>
|
||||
<input v-model="groupForm.name" required type="text" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg" />
|
||||
<input v-model="groupForm.name" required type="text" class="w-full text-sm border-gray-300 rounded-lg" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Prefix (e.g. IT)</label>
|
||||
<input v-model="groupForm.prefix" required type="text" maxlength="10" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg uppercase" />
|
||||
<input v-model="groupForm.prefix" required type="text" maxlength="10" class="w-full text-sm border-gray-300 rounded-lg uppercase" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Email Address</label>
|
||||
<input v-model="groupForm.email_address" type="email" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg" />
|
||||
<input v-model="groupForm.email_address" type="email" class="w-full text-sm border-gray-300 rounded-lg" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Color</label>
|
||||
@@ -79,12 +79,12 @@
|
||||
<div
|
||||
v-for="group in groups"
|
||||
:key="group.id"
|
||||
class="flex items-center justify-between px-4 py-3 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl"
|
||||
class="flex items-center justify-between px-4 py-3 bg-white border border-gray-200 rounded-xl"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="w-3 h-3 rounded-full" :style="{ backgroundColor: group.color }"></span>
|
||||
<div>
|
||||
<p class="font-medium text-sm text-gray-800 dark:text-gray-100">{{ group.name }}</p>
|
||||
<p class="font-medium text-sm text-gray-800">{{ group.name }}</p>
|
||||
<p class="text-xs text-gray-400">{{ group.prefix }} · {{ group.email_address || 'No email' }}</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -92,20 +92,20 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="editingGroup" class="mt-4 bg-gray-50 dark:bg-gray-700 rounded-xl p-4 space-y-3">
|
||||
<h3 class="text-sm font-semibold text-gray-700 dark:text-gray-200">Edit: {{ editingGroup.name }}</h3>
|
||||
<div v-if="editingGroup" class="mt-4 bg-gray-50 rounded-xl p-4 space-y-3">
|
||||
<h3 class="text-sm font-semibold text-gray-700">Edit: {{ editingGroup.name }}</h3>
|
||||
<form @submit.prevent="submitEditGroup" class="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Name</label>
|
||||
<input v-model="editGroupForm.name" required type="text" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg" />
|
||||
<input v-model="editGroupForm.name" required type="text" class="w-full text-sm border-gray-300 rounded-lg" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Prefix</label>
|
||||
<input v-model="editGroupForm.prefix" required type="text" maxlength="10" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg uppercase" />
|
||||
<input v-model="editGroupForm.prefix" required type="text" maxlength="10" class="w-full text-sm border-gray-300 rounded-lg uppercase" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Email Address</label>
|
||||
<input v-model="editGroupForm.email_address" type="email" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg" />
|
||||
<input v-model="editGroupForm.email_address" type="email" class="w-full text-sm border-gray-300 rounded-lg" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Color</label>
|
||||
@@ -121,28 +121,28 @@
|
||||
|
||||
<div v-if="activeTab === 'agents'">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h2 class="text-lg font-semibold text-gray-800 dark:text-gray-100">Agents</h2>
|
||||
<h2 class="text-lg font-semibold text-gray-800">Agents</h2>
|
||||
<button @click="showAddAgent = !showAddAgent" class="text-sm text-indigo-600 hover:underline">
|
||||
{{ showAddAgent ? 'Cancel' : '+ Add Agent' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="showAddAgent" class="bg-gray-50 dark:bg-gray-700 rounded-xl p-4 mb-5 space-y-3">
|
||||
<div v-if="showAddAgent" class="bg-gray-50 rounded-xl p-4 mb-5 space-y-3">
|
||||
<form @submit.prevent="submitAgent" class="grid grid-cols-3 gap-3">
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">User ID</label>
|
||||
<input v-model="agentForm.user_id" required type="number" placeholder="User ID" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg" />
|
||||
<input v-model="agentForm.user_id" required type="number" placeholder="User ID" class="w-full text-sm border-gray-300 rounded-lg" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Group</label>
|
||||
<select v-model="agentForm.group_id" required class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg">
|
||||
<select v-model="agentForm.group_id" required class="w-full text-sm border-gray-300 rounded-lg">
|
||||
<option value="">Select group</option>
|
||||
<option v-for="g in groups" :key="g.id" :value="g.id">{{ g.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Role</label>
|
||||
<select v-model="agentForm.role" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg">
|
||||
<select v-model="agentForm.role" class="w-full text-sm border-gray-300 rounded-lg">
|
||||
<option value="agent">Agent</option>
|
||||
<option value="manager">Manager</option>
|
||||
</select>
|
||||
@@ -160,10 +160,10 @@
|
||||
<div
|
||||
v-for="access in agents"
|
||||
:key="access.id"
|
||||
class="flex items-center justify-between px-4 py-2.5 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl"
|
||||
class="flex items-center justify-between px-4 py-2.5 bg-white border border-gray-200 rounded-xl"
|
||||
>
|
||||
<div>
|
||||
<p class="text-sm font-medium text-gray-800 dark:text-gray-100">{{ access.user?.name || 'User #' + access.user_id }}</p>
|
||||
<p class="text-sm font-medium text-gray-800">{{ access.user?.name || 'User #' + access.user_id }}</p>
|
||||
<p class="text-xs text-gray-400">{{ access.user?.email }} · {{ access.group?.name || 'Unknown Group' }} · <span class="capitalize">{{ access.role }}</span></p>
|
||||
</div>
|
||||
<button @click="openRemoveAgentModal(access)" class="text-xs text-red-500 hover:underline">Remove</button>
|
||||
@@ -173,17 +173,17 @@
|
||||
|
||||
<div v-if="activeTab === 'priorities'">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h2 class="text-lg font-semibold text-gray-800 dark:text-gray-100">Priority Levels</h2>
|
||||
<h2 class="text-lg font-semibold text-gray-800">Priority Levels</h2>
|
||||
<button @click="showAddPriority = !showAddPriority" class="text-sm text-indigo-600 hover:underline">
|
||||
{{ showAddPriority ? 'Cancel' : '+ Add Priority' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="showAddPriority" class="bg-gray-50 dark:bg-gray-700 rounded-xl p-4 mb-5 space-y-3">
|
||||
<div v-if="showAddPriority" class="bg-gray-50 rounded-xl p-4 mb-5 space-y-3">
|
||||
<form @submit.prevent="submitPriority" class="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Name</label>
|
||||
<input v-model="priorityForm.name" required type="text" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg" />
|
||||
<input v-model="priorityForm.name" required type="text" class="w-full text-sm border-gray-300 rounded-lg" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Color</label>
|
||||
@@ -191,15 +191,15 @@
|
||||
</div>
|
||||
<div class="col-span-2">
|
||||
<label class="block text-xs text-gray-500 mb-1">Description</label>
|
||||
<input v-model="priorityForm.description" type="text" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg" />
|
||||
<input v-model="priorityForm.description" type="text" class="w-full text-sm border-gray-300 rounded-lg" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Sort Order</label>
|
||||
<input v-model="priorityForm.sort_order" type="number" min="0" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg" />
|
||||
<input v-model="priorityForm.sort_order" type="number" min="0" class="w-full text-sm border-gray-300 rounded-lg" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Group (blank = global)</label>
|
||||
<select v-model="priorityForm.group_id" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg">
|
||||
<select v-model="priorityForm.group_id" class="w-full text-sm border-gray-300 rounded-lg">
|
||||
<option :value="null">Global</option>
|
||||
<option v-for="g in groups" :key="g.id" :value="g.id">{{ g.name }}</option>
|
||||
</select>
|
||||
@@ -217,11 +217,11 @@
|
||||
<div
|
||||
v-for="p in priorities"
|
||||
:key="p.id"
|
||||
class="flex items-center gap-3 px-4 py-2.5 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl"
|
||||
class="flex items-center gap-3 px-4 py-2.5 bg-white border border-gray-200 rounded-xl"
|
||||
>
|
||||
<span class="w-3 h-3 rounded-full flex-shrink-0" :style="{ backgroundColor: p.color }"></span>
|
||||
<div class="flex-1">
|
||||
<p class="text-sm font-medium text-gray-800 dark:text-gray-100">{{ p.name }}</p>
|
||||
<p class="text-sm font-medium text-gray-800">{{ p.name }}</p>
|
||||
<p v-if="p.description" class="text-xs text-gray-400">{{ p.description }}</p>
|
||||
</div>
|
||||
<span class="text-xs text-gray-400">{{ p.group_id ? 'Group-specific' : 'Global' }}</span>
|
||||
@@ -232,12 +232,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="editingPriority" class="mt-4 bg-gray-50 dark:bg-gray-700 rounded-xl p-4 space-y-3">
|
||||
<h3 class="text-sm font-semibold text-gray-700 dark:text-gray-200">Edit Priority: {{ editingPriority.name }}</h3>
|
||||
<div v-if="editingPriority" class="mt-4 bg-gray-50 rounded-xl p-4 space-y-3">
|
||||
<h3 class="text-sm font-semibold text-gray-700">Edit Priority: {{ editingPriority.name }}</h3>
|
||||
<form @submit.prevent="submitEditPriority" class="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Name</label>
|
||||
<input v-model="editPriorityForm.name" required type="text" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg" />
|
||||
<input v-model="editPriorityForm.name" required type="text" class="w-full text-sm border-gray-300 rounded-lg" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Color</label>
|
||||
@@ -245,15 +245,15 @@
|
||||
</div>
|
||||
<div class="col-span-2">
|
||||
<label class="block text-xs text-gray-500 mb-1">Description</label>
|
||||
<input v-model="editPriorityForm.description" type="text" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg" />
|
||||
<input v-model="editPriorityForm.description" type="text" class="w-full text-sm border-gray-300 rounded-lg" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Sort Order</label>
|
||||
<input v-model="editPriorityForm.sort_order" type="number" min="0" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg" />
|
||||
<input v-model="editPriorityForm.sort_order" type="number" min="0" class="w-full text-sm border-gray-300 rounded-lg" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Scope</label>
|
||||
<input :value="editingPriority.group_id ? 'Group-specific' : 'Global'" disabled type="text" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800/60 dark:text-white rounded-lg opacity-70" />
|
||||
<input :value="editingPriority.group_id ? 'Group-specific' : 'Global'" disabled type="text" class="w-full text-sm border-gray-300 rounded-lg opacity-70" />
|
||||
</div>
|
||||
<div class="col-span-2 flex justify-end gap-2">
|
||||
<button type="button" @click="editingPriority = null" class="text-sm text-gray-500 px-3 py-2 rounded-lg border border-gray-300 hover:bg-gray-100">Cancel</button>
|
||||
@@ -265,35 +265,35 @@
|
||||
|
||||
<div v-if="activeTab === 'projects'">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h2 class="text-lg font-semibold text-gray-800 dark:text-gray-100">Projects</h2>
|
||||
<h2 class="text-lg font-semibold text-gray-800">Projects</h2>
|
||||
<button @click="showAddProject = !showAddProject" class="text-sm text-indigo-600 hover:underline">
|
||||
{{ showAddProject ? 'Cancel' : '+ Add Project' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="showAddProject" class="bg-gray-50 dark:bg-gray-700 rounded-xl p-4 mb-5 space-y-3">
|
||||
<div v-if="showAddProject" class="bg-gray-50 rounded-xl p-4 mb-5 space-y-3">
|
||||
<form @submit.prevent="submitProject" class="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Group</label>
|
||||
<select v-model="projectForm.group_id" required class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg">
|
||||
<select v-model="projectForm.group_id" required class="w-full text-sm border-gray-300 rounded-lg">
|
||||
<option value="">Select group</option>
|
||||
<option v-for="g in groups" :key="g.id" :value="g.id">{{ g.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Status</label>
|
||||
<select v-model="projectForm.status" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg">
|
||||
<select v-model="projectForm.status" class="w-full text-sm border-gray-300 rounded-lg">
|
||||
<option value="active">Active</option>
|
||||
<option value="archived">Archived</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-span-2">
|
||||
<label class="block text-xs text-gray-500 mb-1">Name</label>
|
||||
<input v-model="projectForm.name" required type="text" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg" />
|
||||
<input v-model="projectForm.name" required type="text" class="w-full text-sm border-gray-300 rounded-lg" />
|
||||
</div>
|
||||
<div class="col-span-2">
|
||||
<label class="block text-xs text-gray-500 mb-1">Description</label>
|
||||
<textarea v-model="projectForm.description" rows="3" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg"></textarea>
|
||||
<textarea v-model="projectForm.description" rows="3" class="w-full text-sm border-gray-300 rounded-lg"></textarea>
|
||||
</div>
|
||||
<div class="col-span-2 flex justify-end">
|
||||
<button type="submit" :disabled="projectForm.processing" class="bg-indigo-600 text-white text-sm px-4 py-2 rounded-lg hover:bg-indigo-700 disabled:opacity-60">
|
||||
@@ -308,10 +308,10 @@
|
||||
<div
|
||||
v-for="project in projects"
|
||||
:key="project.id"
|
||||
class="flex items-center gap-3 px-4 py-3 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl"
|
||||
class="flex items-center gap-3 px-4 py-3 bg-white border border-gray-200 rounded-xl"
|
||||
>
|
||||
<div class="flex-1">
|
||||
<p class="text-sm font-medium text-gray-800 dark:text-gray-100">{{ project.name }}</p>
|
||||
<p class="text-sm font-medium text-gray-800">{{ project.name }}</p>
|
||||
<p class="text-xs text-gray-400">{{ groups.find(g => g.id === project.group_id)?.name || 'Unknown Group' }} · {{ project.status }}</p>
|
||||
<p v-if="project.description" class="text-xs text-gray-500 mt-1">{{ project.description }}</p>
|
||||
</div>
|
||||
@@ -322,27 +322,27 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="editingProject" class="mt-4 bg-gray-50 dark:bg-gray-700 rounded-xl p-4 space-y-3">
|
||||
<h3 class="text-sm font-semibold text-gray-700 dark:text-gray-200">Edit Project: {{ editingProject.name }}</h3>
|
||||
<div v-if="editingProject" class="mt-4 bg-gray-50 rounded-xl p-4 space-y-3">
|
||||
<h3 class="text-sm font-semibold text-gray-700">Edit Project: {{ editingProject.name }}</h3>
|
||||
<form @submit.prevent="submitEditProject" class="grid grid-cols-2 gap-3">
|
||||
<div class="col-span-2">
|
||||
<label class="block text-xs text-gray-500 mb-1">Name</label>
|
||||
<input v-model="editProjectForm.name" required type="text" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg" />
|
||||
<input v-model="editProjectForm.name" required type="text" class="w-full text-sm border-gray-300 rounded-lg" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Status</label>
|
||||
<select v-model="editProjectForm.status" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg">
|
||||
<select v-model="editProjectForm.status" class="w-full text-sm border-gray-300 rounded-lg">
|
||||
<option value="active">Active</option>
|
||||
<option value="archived">Archived</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 mb-1">Group</label>
|
||||
<input :value="groups.find(g => g.id === editingProject.group_id)?.name || 'Unknown Group'" disabled type="text" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800/60 dark:text-white rounded-lg opacity-70" />
|
||||
<input :value="groups.find(g => g.id === editingProject.group_id)?.name || 'Unknown Group'" disabled type="text" class="w-full text-sm border-gray-300 rounded-lg opacity-70" />
|
||||
</div>
|
||||
<div class="col-span-2">
|
||||
<label class="block text-xs text-gray-500 mb-1">Description</label>
|
||||
<textarea v-model="editProjectForm.description" rows="3" class="w-full text-sm border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white rounded-lg"></textarea>
|
||||
<textarea v-model="editProjectForm.description" rows="3" class="w-full text-sm border-gray-300 rounded-lg"></textarea>
|
||||
</div>
|
||||
<div class="col-span-2 flex justify-end gap-2">
|
||||
<button type="button" @click="editingProject = null" class="text-sm text-gray-500 px-3 py-2 rounded-lg border border-gray-300 hover:bg-gray-100">Cancel</button>
|
||||
@@ -354,9 +354,9 @@
|
||||
</div>
|
||||
|
||||
<div v-if="removeAgentModalOpen" class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 px-4">
|
||||
<div class="w-full max-w-md rounded-2xl bg-white dark:bg-gray-800 p-6 shadow-xl">
|
||||
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">Remove agent?</h3>
|
||||
<p class="mt-2 text-sm text-gray-600 dark:text-gray-300">
|
||||
<div class="w-full max-w-md rounded-2xl bg-white p-6 shadow-xl">
|
||||
<h3 class="text-lg font-semibold text-gray-900">Remove agent?</h3>
|
||||
<p class="mt-2 text-sm text-gray-600">
|
||||
Remove <strong>{{ pendingAgentRemoval?.user?.name || ('User #' + pendingAgentRemoval?.user_id) }}</strong>
|
||||
from <strong>{{ pendingAgentRemoval?.group?.name }}</strong>?
|
||||
</p>
|
||||
@@ -368,9 +368,9 @@
|
||||
</div>
|
||||
|
||||
<div v-if="deletePriorityModalOpen" class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 px-4">
|
||||
<div class="w-full max-w-md rounded-2xl bg-white dark:bg-gray-800 p-6 shadow-xl">
|
||||
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">Delete priority?</h3>
|
||||
<p class="mt-2 text-sm text-gray-600 dark:text-gray-300">
|
||||
<div class="w-full max-w-md rounded-2xl bg-white p-6 shadow-xl">
|
||||
<h3 class="text-lg font-semibold text-gray-900">Delete priority?</h3>
|
||||
<p class="mt-2 text-sm text-gray-600">
|
||||
Delete <strong>{{ pendingPriorityDelete?.name }}</strong>? This cannot be undone.
|
||||
</p>
|
||||
<div class="mt-6 flex justify-end gap-2">
|
||||
@@ -381,9 +381,9 @@
|
||||
</div>
|
||||
|
||||
<div v-if="deleteProjectModalOpen" class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 px-4">
|
||||
<div class="w-full max-w-md rounded-2xl bg-white dark:bg-gray-800 p-6 shadow-xl">
|
||||
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">Delete project?</h3>
|
||||
<p class="mt-2 text-sm text-gray-600 dark:text-gray-300">
|
||||
<div class="w-full max-w-md rounded-2xl bg-white p-6 shadow-xl">
|
||||
<h3 class="text-lg font-semibold text-gray-900">Delete project?</h3>
|
||||
<p class="mt-2 text-sm text-gray-600">
|
||||
Delete <strong>{{ pendingProjectDelete?.name }}</strong>? This cannot be undone.
|
||||
</p>
|
||||
<div class="mt-6 flex justify-end gap-2">
|
||||
|
||||
Reference in New Issue
Block a user