665 lines
22 KiB
Vue
665 lines
22 KiB
Vue
<template>
|
|
<div>
|
|
<LayoutsBreadcrumb />
|
|
|
|
<!-- Header Section -->
|
|
<rs-card class="mb-6">
|
|
<template #header>
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center">
|
|
<Icon class="mr-2 text-primary" name="ic:outline-priority-high"></Icon>
|
|
<h1 class="text-xl font-bold text-primary">Priority Queue Management</h1>
|
|
</div>
|
|
<rs-button @click="showCreatePriorityModal = true">
|
|
<Icon class="mr-1" name="ic:outline-add"></Icon>
|
|
Create Priority Level
|
|
</rs-button>
|
|
</div>
|
|
</template>
|
|
<template #body>
|
|
<p class="text-gray-600">
|
|
Manage different priority levels for notifications to ensure critical messages are processed first.
|
|
Higher priority notifications will be processed before lower priority ones in the queue.
|
|
</p>
|
|
</template>
|
|
</rs-card>
|
|
|
|
<!-- Priority Level Statistics -->
|
|
<div class="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-4 gap-6 mb-6">
|
|
<rs-card
|
|
v-for="(stat, index) in priorityStats"
|
|
:key="index"
|
|
class="transition-all duration-300 hover:shadow-lg"
|
|
>
|
|
<div class="pt-5 pb-3 px-5 flex items-center gap-4">
|
|
<div
|
|
class="p-4 flex justify-center items-center rounded-2xl"
|
|
:class="stat.bgColor"
|
|
>
|
|
<Icon class="text-2xl" :class="stat.iconColor" :name="stat.icon"></Icon>
|
|
</div>
|
|
<div class="flex-1 truncate">
|
|
<span class="block font-bold text-2xl leading-tight" :class="stat.valueColor">
|
|
{{ stat.value }}
|
|
</span>
|
|
<span class="text-sm font-medium text-gray-600">
|
|
{{ stat.title }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</rs-card>
|
|
</div>
|
|
|
|
<!-- Priority Levels Configuration -->
|
|
<rs-card class="mb-6">
|
|
<template #header>
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center">
|
|
<Icon class="mr-2 text-primary" name="ic:outline-settings"></Icon>
|
|
<h3 class="text-lg font-semibold text-primary">Priority Levels</h3>
|
|
</div>
|
|
<div class="flex items-center gap-3">
|
|
<rs-button variant="outline" size="sm" @click="refreshPriorityLevels">
|
|
<Icon class="mr-1" name="ic:outline-refresh"></Icon>
|
|
Refresh
|
|
</rs-button>
|
|
<rs-button variant="outline" size="sm" @click="showBulkEditModal = true">
|
|
<Icon class="mr-1" name="ic:outline-edit"></Icon>
|
|
Bulk Edit
|
|
</rs-button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<template #body>
|
|
<div class="space-y-4">
|
|
<div
|
|
v-for="(priority, index) in priorityLevels"
|
|
:key="index"
|
|
class="flex items-center justify-between p-4 border rounded-lg"
|
|
:class="{
|
|
'border-red-200 bg-red-50': priority.level === 'critical',
|
|
'border-orange-200 bg-orange-50': priority.level === 'high',
|
|
'border-yellow-200 bg-yellow-50': priority.level === 'medium',
|
|
'border-blue-200 bg-blue-50': priority.level === 'low',
|
|
'border-gray-200 bg-gray-50': priority.level === 'bulk'
|
|
}"
|
|
>
|
|
<div class="flex items-center gap-4">
|
|
<div class="flex items-center gap-2">
|
|
<div
|
|
class="w-4 h-4 rounded-full"
|
|
:class="{
|
|
'bg-red-500': priority.level === 'critical',
|
|
'bg-orange-500': priority.level === 'high',
|
|
'bg-yellow-500': priority.level === 'medium',
|
|
'bg-blue-500': priority.level === 'low',
|
|
'bg-gray-500': priority.level === 'bulk'
|
|
}"
|
|
></div>
|
|
<span class="font-medium text-lg">{{ priority.name }}</span>
|
|
<span class="text-sm text-gray-500">({{ priority.level }})</span>
|
|
</div>
|
|
<div class="flex items-center gap-6">
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-600">Weight</p>
|
|
<p class="font-bold">{{ priority.weight }}</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-600">Queue Count</p>
|
|
<p class="font-bold">{{ priority.queueCount.toLocaleString() }}</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-600">Avg Processing</p>
|
|
<p class="font-bold">{{ priority.avgProcessingTime }}</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-600">Status</p>
|
|
<span
|
|
class="inline-flex px-2 py-1 text-xs font-semibold rounded-full"
|
|
:class="{
|
|
'bg-green-100 text-green-800': priority.status === 'active',
|
|
'bg-red-100 text-red-800': priority.status === 'paused',
|
|
'bg-yellow-100 text-yellow-800': priority.status === 'throttled'
|
|
}"
|
|
>
|
|
{{ priority.status }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center gap-2">
|
|
<rs-button
|
|
variant="outline"
|
|
size="sm"
|
|
@click="editPriority(priority)"
|
|
>
|
|
<Icon class="mr-1" name="ic:outline-edit"></Icon>
|
|
Edit
|
|
</rs-button>
|
|
<rs-button
|
|
variant="outline"
|
|
size="sm"
|
|
:class="priority.status === 'active' ? 'text-red-600' : 'text-green-600'"
|
|
@click="togglePriorityStatus(priority)"
|
|
>
|
|
<Icon
|
|
class="mr-1"
|
|
:name="priority.status === 'active' ? 'ic:outline-pause' : 'ic:outline-play-arrow'"
|
|
></Icon>
|
|
{{ priority.status === 'active' ? 'Pause' : 'Resume' }}
|
|
</rs-button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</rs-card>
|
|
|
|
<!-- Queue Processing Order -->
|
|
<rs-card class="mb-6">
|
|
<template #header>
|
|
<div class="flex items-center">
|
|
<Icon class="mr-2 text-primary" name="ic:outline-sort"></Icon>
|
|
<h3 class="text-lg font-semibold text-primary">Processing Order Visualization</h3>
|
|
</div>
|
|
</template>
|
|
<template #body>
|
|
<div class="space-y-4">
|
|
<p class="text-gray-600 mb-4">
|
|
Notifications are processed in the following order based on priority weights:
|
|
</p>
|
|
|
|
<!-- Processing Flow -->
|
|
<div class="flex items-center justify-between bg-gray-50 p-4 rounded-lg">
|
|
<div
|
|
v-for="(level, index) in sortedPriorityLevels"
|
|
:key="index"
|
|
class="flex flex-col items-center"
|
|
>
|
|
<div
|
|
class="w-16 h-16 rounded-full flex items-center justify-center text-white font-bold text-lg mb-2"
|
|
:class="{
|
|
'bg-red-500': level.level === 'critical',
|
|
'bg-orange-500': level.level === 'high',
|
|
'bg-yellow-500': level.level === 'medium',
|
|
'bg-blue-500': level.level === 'low',
|
|
'bg-gray-500': level.level === 'bulk'
|
|
}"
|
|
>
|
|
{{ level.weight }}
|
|
</div>
|
|
<span class="text-sm font-medium">{{ level.name }}</span>
|
|
<span class="text-xs text-gray-500">{{ level.queueCount }} jobs</span>
|
|
|
|
<!-- Arrow -->
|
|
<Icon
|
|
v-if="index < sortedPriorityLevels.length - 1"
|
|
class="text-gray-400 mt-2"
|
|
name="ic:outline-arrow-forward"
|
|
></Icon>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Processing Rules -->
|
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mt-6">
|
|
<div class="bg-blue-50 p-4 rounded-lg">
|
|
<h4 class="font-medium text-blue-800 mb-2">Processing Rules</h4>
|
|
<ul class="text-sm text-blue-700 space-y-1">
|
|
<li>• Higher weight = Higher priority</li>
|
|
<li>• Critical jobs always processed first</li>
|
|
<li>• Same priority jobs use FIFO order</li>
|
|
<li>• Bulk jobs processed during low traffic</li>
|
|
</ul>
|
|
</div>
|
|
<div class="bg-green-50 p-4 rounded-lg">
|
|
<h4 class="font-medium text-green-800 mb-2">Performance Impact</h4>
|
|
<ul class="text-sm text-green-700 space-y-1">
|
|
<li>• Critical: < 1 second processing</li>
|
|
<li>• High: < 5 seconds processing</li>
|
|
<li>• Medium: < 30 seconds processing</li>
|
|
<li>• Low/Bulk: Best effort processing</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</rs-card>
|
|
|
|
<!-- Recent Priority Queue Activity -->
|
|
<rs-card>
|
|
<template #header>
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center">
|
|
<Icon class="mr-2 text-primary" name="ic:outline-history"></Icon>
|
|
<h3 class="text-lg font-semibold text-primary">Recent Priority Queue Activity</h3>
|
|
</div>
|
|
<rs-button variant="outline" size="sm" @click="navigateTo('/notification/queue-scheduler/monitor')">
|
|
View Full Monitor
|
|
</rs-button>
|
|
</div>
|
|
</template>
|
|
<template #body>
|
|
<div class="overflow-x-auto">
|
|
<table class="min-w-full divide-y divide-gray-200">
|
|
<thead class="bg-gray-50">
|
|
<tr>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
Job ID
|
|
</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
Priority
|
|
</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
Type
|
|
</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
Status
|
|
</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
Queue Time
|
|
</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
Processing Time
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="bg-white divide-y divide-gray-200">
|
|
<tr v-for="(job, index) in recentJobs" :key="index">
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
|
|
{{ job.id }}
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
<span
|
|
class="inline-flex px-2 py-1 text-xs font-semibold rounded-full"
|
|
:class="{
|
|
'bg-red-100 text-red-800': job.priority === 'critical',
|
|
'bg-orange-100 text-orange-800': job.priority === 'high',
|
|
'bg-yellow-100 text-yellow-800': job.priority === 'medium',
|
|
'bg-blue-100 text-blue-800': job.priority === 'low',
|
|
'bg-gray-100 text-gray-800': job.priority === 'bulk'
|
|
}"
|
|
>
|
|
{{ job.priority }}
|
|
</span>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
|
|
{{ job.type }}
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
<span
|
|
class="inline-flex px-2 py-1 text-xs font-semibold rounded-full"
|
|
:class="{
|
|
'bg-green-100 text-green-800': job.status === 'completed',
|
|
'bg-yellow-100 text-yellow-800': job.status === 'processing',
|
|
'bg-red-100 text-red-800': job.status === 'failed',
|
|
'bg-blue-100 text-blue-800': job.status === 'queued'
|
|
}"
|
|
>
|
|
{{ job.status }}
|
|
</span>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
|
{{ job.queueTime }}
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
|
{{ job.processingTime }}
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</template>
|
|
</rs-card>
|
|
|
|
<!-- Create Priority Level Modal -->
|
|
<rs-modal v-model="showCreatePriorityModal" title="Create Priority Level">
|
|
<div class="space-y-6">
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-2">Priority Name</label>
|
|
<input
|
|
type="text"
|
|
v-model="newPriority.name"
|
|
class="w-full p-2 border border-gray-300 rounded-md"
|
|
placeholder="e.g., Emergency Alerts"
|
|
>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-2">Priority Level</label>
|
|
<select v-model="newPriority.level" class="w-full p-2 border border-gray-300 rounded-md">
|
|
<option value="critical">Critical</option>
|
|
<option value="high">High</option>
|
|
<option value="medium">Medium</option>
|
|
<option value="low">Low</option>
|
|
<option value="bulk">Bulk</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-2">Weight (1-100)</label>
|
|
<input
|
|
type="number"
|
|
v-model="newPriority.weight"
|
|
class="w-full p-2 border border-gray-300 rounded-md"
|
|
min="1"
|
|
max="100"
|
|
>
|
|
<p class="text-xs text-gray-500 mt-1">Higher weight = Higher priority</p>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-2">Description</label>
|
|
<textarea
|
|
v-model="newPriority.description"
|
|
class="w-full p-2 border border-gray-300 rounded-md"
|
|
rows="3"
|
|
placeholder="Describe when this priority level should be used..."
|
|
></textarea>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-2">Max Processing Time (seconds)</label>
|
|
<input
|
|
type="number"
|
|
v-model="newPriority.maxProcessingTime"
|
|
class="w-full p-2 border border-gray-300 rounded-md"
|
|
min="1"
|
|
>
|
|
<p class="text-xs text-gray-500 mt-1">Maximum time allowed for processing jobs of this priority</p>
|
|
</div>
|
|
</div>
|
|
|
|
<template #footer>
|
|
<div class="flex justify-end gap-3">
|
|
<rs-button variant="outline" @click="showCreatePriorityModal = false">
|
|
Cancel
|
|
</rs-button>
|
|
<rs-button @click="createPriorityLevel">
|
|
Create Priority Level
|
|
</rs-button>
|
|
</div>
|
|
</template>
|
|
</rs-modal>
|
|
|
|
<!-- Edit Priority Modal -->
|
|
<rs-modal v-model="showEditPriorityModal" title="Edit Priority Level">
|
|
<div class="space-y-6" v-if="editingPriority">
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-2">Priority Name</label>
|
|
<input
|
|
type="text"
|
|
v-model="editingPriority.name"
|
|
class="w-full p-2 border border-gray-300 rounded-md"
|
|
>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-2">Weight (1-100)</label>
|
|
<input
|
|
type="number"
|
|
v-model="editingPriority.weight"
|
|
class="w-full p-2 border border-gray-300 rounded-md"
|
|
min="1"
|
|
max="100"
|
|
>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-2">Max Processing Time (seconds)</label>
|
|
<input
|
|
type="number"
|
|
v-model="editingPriority.maxProcessingTime"
|
|
class="w-full p-2 border border-gray-300 rounded-md"
|
|
min="1"
|
|
>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-2">Status</label>
|
|
<select v-model="editingPriority.status" class="w-full p-2 border border-gray-300 rounded-md">
|
|
<option value="active">Active</option>
|
|
<option value="paused">Paused</option>
|
|
<option value="throttled">Throttled</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<template #footer>
|
|
<div class="flex justify-end gap-3">
|
|
<rs-button variant="outline" @click="showEditPriorityModal = false">
|
|
Cancel
|
|
</rs-button>
|
|
<rs-button @click="savePriorityChanges">
|
|
Save Changes
|
|
</rs-button>
|
|
</div>
|
|
</template>
|
|
</rs-modal>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
definePageMeta({
|
|
title: "Priority Queue Management",
|
|
middleware: ["auth"],
|
|
requiresAuth: true,
|
|
breadcrumb: [
|
|
{
|
|
name: "Notification",
|
|
path: "/notification",
|
|
},
|
|
{
|
|
name: "Queue & Scheduler",
|
|
path: "/notification/queue-scheduler",
|
|
},
|
|
{
|
|
name: "Priority Management",
|
|
path: "/notification/queue-scheduler/priority",
|
|
},
|
|
],
|
|
});
|
|
|
|
// Reactive data
|
|
const showCreatePriorityModal = ref(false);
|
|
const showEditPriorityModal = ref(false);
|
|
const showBulkEditModal = ref(false);
|
|
const editingPriority = ref(null);
|
|
|
|
// Priority statistics
|
|
const priorityStats = ref([
|
|
{
|
|
title: "Critical Jobs",
|
|
value: "47",
|
|
icon: "ic:outline-priority-high",
|
|
bgColor: "bg-red-100",
|
|
iconColor: "text-red-600",
|
|
valueColor: "text-red-600"
|
|
},
|
|
{
|
|
title: "High Priority",
|
|
value: "234",
|
|
icon: "ic:outline-trending-up",
|
|
bgColor: "bg-orange-100",
|
|
iconColor: "text-orange-600",
|
|
valueColor: "text-orange-600"
|
|
},
|
|
{
|
|
title: "Medium Priority",
|
|
value: "1,847",
|
|
icon: "ic:outline-remove",
|
|
bgColor: "bg-yellow-100",
|
|
iconColor: "text-yellow-600",
|
|
valueColor: "text-yellow-600"
|
|
},
|
|
{
|
|
title: "Low/Bulk Priority",
|
|
value: "5,923",
|
|
icon: "ic:outline-trending-down",
|
|
bgColor: "bg-blue-100",
|
|
iconColor: "text-blue-600",
|
|
valueColor: "text-blue-600"
|
|
}
|
|
]);
|
|
|
|
// Priority levels configuration
|
|
const priorityLevels = ref([
|
|
{
|
|
name: "Emergency Alerts",
|
|
level: "critical",
|
|
weight: 100,
|
|
queueCount: 47,
|
|
avgProcessingTime: "0.8s",
|
|
status: "active",
|
|
maxProcessingTime: 5,
|
|
description: "System emergencies and critical security alerts"
|
|
},
|
|
{
|
|
name: "Real-time Notifications",
|
|
level: "high",
|
|
weight: 80,
|
|
queueCount: 234,
|
|
avgProcessingTime: "2.1s",
|
|
status: "active",
|
|
maxProcessingTime: 10,
|
|
description: "Time-sensitive notifications like OTP, payment confirmations"
|
|
},
|
|
{
|
|
name: "Standard Notifications",
|
|
level: "medium",
|
|
weight: 50,
|
|
queueCount: 1847,
|
|
avgProcessingTime: "5.3s",
|
|
status: "active",
|
|
maxProcessingTime: 30,
|
|
description: "Regular app notifications and updates"
|
|
},
|
|
{
|
|
name: "Marketing Messages",
|
|
level: "low",
|
|
weight: 30,
|
|
queueCount: 3421,
|
|
avgProcessingTime: "12.7s",
|
|
status: "active",
|
|
maxProcessingTime: 60,
|
|
description: "Promotional content and marketing campaigns"
|
|
},
|
|
{
|
|
name: "Bulk Operations",
|
|
level: "bulk",
|
|
weight: 10,
|
|
queueCount: 2502,
|
|
avgProcessingTime: "45.2s",
|
|
status: "throttled",
|
|
maxProcessingTime: 300,
|
|
description: "Large batch operations and system maintenance"
|
|
}
|
|
]);
|
|
|
|
// New priority form
|
|
const newPriority = ref({
|
|
name: "",
|
|
level: "medium",
|
|
weight: 50,
|
|
description: "",
|
|
maxProcessingTime: 30
|
|
});
|
|
|
|
// Computed sorted priority levels
|
|
const sortedPriorityLevels = computed(() => {
|
|
return [...priorityLevels.value].sort((a, b) => b.weight - a.weight);
|
|
});
|
|
|
|
// Recent jobs data
|
|
const recentJobs = ref([
|
|
{
|
|
id: "job-001",
|
|
priority: "critical",
|
|
type: "Security Alert",
|
|
status: "completed",
|
|
queueTime: "0.1s",
|
|
processingTime: "0.8s"
|
|
},
|
|
{
|
|
id: "job-002",
|
|
priority: "high",
|
|
type: "OTP SMS",
|
|
status: "completed",
|
|
queueTime: "0.3s",
|
|
processingTime: "1.2s"
|
|
},
|
|
{
|
|
id: "job-003",
|
|
priority: "medium",
|
|
type: "App Notification",
|
|
status: "processing",
|
|
queueTime: "2.1s",
|
|
processingTime: "3.4s"
|
|
},
|
|
{
|
|
id: "job-004",
|
|
priority: "low",
|
|
type: "Newsletter",
|
|
status: "queued",
|
|
queueTime: "15.2s",
|
|
processingTime: "-"
|
|
},
|
|
{
|
|
id: "job-005",
|
|
priority: "bulk",
|
|
type: "Data Export",
|
|
status: "queued",
|
|
queueTime: "45.7s",
|
|
processingTime: "-"
|
|
}
|
|
]);
|
|
|
|
// Methods
|
|
const refreshPriorityLevels = () => {
|
|
console.log('Refreshing priority levels...');
|
|
// Simulate data refresh
|
|
};
|
|
|
|
const createPriorityLevel = () => {
|
|
console.log('Creating priority level:', newPriority.value);
|
|
|
|
// Add to priority levels
|
|
priorityLevels.value.push({
|
|
...newPriority.value,
|
|
queueCount: 0,
|
|
avgProcessingTime: "0s",
|
|
status: "active"
|
|
});
|
|
|
|
// Reset form
|
|
newPriority.value = {
|
|
name: "",
|
|
level: "medium",
|
|
weight: 50,
|
|
description: "",
|
|
maxProcessingTime: 30
|
|
};
|
|
|
|
showCreatePriorityModal.value = false;
|
|
};
|
|
|
|
const editPriority = (priority) => {
|
|
editingPriority.value = { ...priority };
|
|
showEditPriorityModal.value = true;
|
|
};
|
|
|
|
const savePriorityChanges = () => {
|
|
const index = priorityLevels.value.findIndex(p => p.name === editingPriority.value.name);
|
|
if (index !== -1) {
|
|
priorityLevels.value[index] = { ...editingPriority.value };
|
|
}
|
|
showEditPriorityModal.value = false;
|
|
editingPriority.value = null;
|
|
};
|
|
|
|
const togglePriorityStatus = (priority) => {
|
|
const newStatus = priority.status === 'active' ? 'paused' : 'active';
|
|
priority.status = newStatus;
|
|
console.log(`Priority ${priority.name} status changed to ${newStatus}`);
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped></style> |