Refactor ProcessSettingsModal to Simplify Settings and Enhance Permissions Management
- Updated the modal to use a smaller size for improved usability. - Removed unnecessary fields related to priority, owner, and execution settings to streamline the process configuration. - Introduced a new loading state for permissions and error handling for better user feedback. - Simplified the settings tabs to focus on essential configurations, enhancing the user experience. - Added functionality to dynamically load available roles and permissions from the database, improving flexibility in process management.
This commit is contained in:
parent
c5edf2abfe
commit
5261bf601e
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<RsModal v-model="showModal" title="Process Settings" size="xl" position="center">
|
<RsModal v-model="showModal" title="Process Settings" size="lg" position="center">
|
||||||
<div>
|
<div>
|
||||||
<RsTab :tabs="settingsTabs" v-model="activeTab">
|
<RsTab :tabs="settingsTabs" v-model="activeTab">
|
||||||
<!-- Process Info Tab -->
|
<!-- Process Info Tab -->
|
||||||
@ -21,19 +21,6 @@
|
|||||||
rows="3"
|
rows="3"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FormKit
|
|
||||||
type="select"
|
|
||||||
label="Priority Level"
|
|
||||||
v-model="localProcess.priority"
|
|
||||||
:options="[
|
|
||||||
{ label: 'Low Priority', value: 'low' },
|
|
||||||
{ label: 'Normal Priority', value: 'normal' },
|
|
||||||
{ label: 'High Priority', value: 'high' },
|
|
||||||
{ label: 'Critical Priority', value: 'critical' }
|
|
||||||
]"
|
|
||||||
help="Set the priority level for this process"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormKit
|
<FormKit
|
||||||
type="text"
|
type="text"
|
||||||
label="Process Category"
|
label="Process Category"
|
||||||
@ -41,27 +28,19 @@
|
|||||||
help="Category or department this process belongs to"
|
help="Category or department this process belongs to"
|
||||||
placeholder="e.g., HR, Finance, Operations"
|
placeholder="e.g., HR, Finance, Operations"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FormKit
|
|
||||||
type="text"
|
|
||||||
label="Owner/Manager"
|
|
||||||
v-model="localProcess.owner"
|
|
||||||
help="Person responsible for this process"
|
|
||||||
placeholder="e.g., John Doe, HR Manager"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- Execution Settings Tab -->
|
<!-- Basic Settings Tab -->
|
||||||
<template #execution>
|
<template #basic>
|
||||||
<div class="p-4 space-y-4">
|
<div class="p-4 space-y-4">
|
||||||
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-4">
|
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-4">
|
||||||
<div class="flex items-center mb-2">
|
<div class="flex items-center mb-2">
|
||||||
<Icon name="material-symbols:info" class="w-5 h-5 text-blue-600 mr-2" />
|
<Icon name="material-symbols:info" class="w-5 h-5 text-blue-600 mr-2" />
|
||||||
<h4 class="font-medium text-blue-900">Execution Settings</h4>
|
<h4 class="font-medium text-blue-900">Basic Settings</h4>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-sm text-blue-700">
|
<p class="text-sm text-blue-700">
|
||||||
Configure how this process should execute and handle different scenarios.
|
Configure the essential behavior of your process.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -73,32 +52,11 @@
|
|||||||
{ label: 'Standard Process', value: 'standard' },
|
{ label: 'Standard Process', value: 'standard' },
|
||||||
{ label: 'Approval Workflow', value: 'approval' },
|
{ label: 'Approval Workflow', value: 'approval' },
|
||||||
{ label: 'Data Collection', value: 'data_collection' },
|
{ label: 'Data Collection', value: 'data_collection' },
|
||||||
{ label: 'Automated Task', value: 'automation' },
|
{ label: 'Automated Task', value: 'automation' }
|
||||||
{ label: 'Review Process', value: 'review' }
|
|
||||||
]"
|
]"
|
||||||
help="Type of process workflow"
|
help="Type of process workflow"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="grid grid-cols-2 gap-4">
|
|
||||||
<FormKit
|
|
||||||
type="number"
|
|
||||||
label="Max Execution Time (minutes)"
|
|
||||||
v-model="localProcess.maxExecutionTime"
|
|
||||||
help="Maximum time allowed for process completion"
|
|
||||||
min="1"
|
|
||||||
max="10080"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormKit
|
|
||||||
type="number"
|
|
||||||
label="Auto-Timeout (hours)"
|
|
||||||
v-model="localProcess.autoTimeout"
|
|
||||||
help="Automatically timeout after specified hours"
|
|
||||||
min="1"
|
|
||||||
max="168"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<FormKit
|
<FormKit
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
label="Allow Parallel Execution"
|
label="Allow Parallel Execution"
|
||||||
@ -106,13 +64,6 @@
|
|||||||
help="Allow multiple instances of this process to run simultaneously"
|
help="Allow multiple instances of this process to run simultaneously"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FormKit
|
|
||||||
type="checkbox"
|
|
||||||
label="Enable Error Recovery"
|
|
||||||
v-model="localProcess.enableErrorRecovery"
|
|
||||||
help="Automatically retry failed steps before stopping"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormKit
|
<FormKit
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
label="Send Completion Notifications"
|
label="Send Completion Notifications"
|
||||||
@ -122,58 +73,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- Variables & Data Tab -->
|
|
||||||
<template #variables>
|
|
||||||
<div class="p-4 space-y-4">
|
|
||||||
<div class="bg-purple-50 border border-purple-200 rounded-lg p-4 mb-4">
|
|
||||||
<div class="flex items-center mb-2">
|
|
||||||
<Icon name="material-symbols:data-object" class="w-5 h-5 text-purple-600 mr-2" />
|
|
||||||
<h4 class="font-medium text-purple-900">Variable Configuration</h4>
|
|
||||||
</div>
|
|
||||||
<p class="text-sm text-purple-700">
|
|
||||||
Configure data handling and variable persistence settings.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<FormKit
|
|
||||||
type="select"
|
|
||||||
label="Data Persistence"
|
|
||||||
v-model="localProcess.dataPersistence"
|
|
||||||
:options="[
|
|
||||||
{ label: 'Session Only', value: 'session' },
|
|
||||||
{ label: 'Temporary (24 hours)', value: 'temporary' },
|
|
||||||
{ label: 'Short Term (7 days)', value: 'short_term' },
|
|
||||||
{ label: 'Long Term (30 days)', value: 'long_term' },
|
|
||||||
{ label: 'Permanent', value: 'permanent' }
|
|
||||||
]"
|
|
||||||
help="How long should process data be stored"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormKit
|
|
||||||
type="checkbox"
|
|
||||||
label="Log Variable Changes"
|
|
||||||
v-model="localProcess.logVariableChanges"
|
|
||||||
help="Keep a log of all variable modifications during execution"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormKit
|
|
||||||
type="checkbox"
|
|
||||||
label="Encrypt Sensitive Data"
|
|
||||||
v-model="localProcess.encryptSensitiveData"
|
|
||||||
help="Automatically encrypt variables marked as sensitive"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormKit
|
|
||||||
type="textarea"
|
|
||||||
label="Data Retention Policy"
|
|
||||||
v-model="localProcess.dataRetentionPolicy"
|
|
||||||
help="Describe how data should be handled after process completion"
|
|
||||||
rows="3"
|
|
||||||
placeholder="e.g., Delete personal data after 30 days, archive business data for 7 years"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- Permissions Tab -->
|
<!-- Permissions Tab -->
|
||||||
<template #permissions>
|
<template #permissions>
|
||||||
<div class="p-4 space-y-4">
|
<div class="p-4 space-y-4">
|
||||||
@ -183,59 +82,80 @@
|
|||||||
<h4 class="font-medium text-green-900">Access Control</h4>
|
<h4 class="font-medium text-green-900">Access Control</h4>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-sm text-green-700">
|
<p class="text-sm text-green-700">
|
||||||
Define who can execute, modify, and view this process.
|
Define who can execute and modify this process.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<FormKit
|
<!-- Loading State -->
|
||||||
type="select"
|
<div v-if="loadingPermissions" class="flex justify-center items-center py-8">
|
||||||
label="Execution Permission"
|
<div class="text-center">
|
||||||
v-model="localProcess.executionPermission"
|
<Icon name="material-symbols:progress-activity" class="w-6 h-6 animate-spin text-green-500 mx-auto mb-2" />
|
||||||
:options="[
|
<p class="text-gray-500">Loading permissions...</p>
|
||||||
{ label: 'Anyone', value: 'public' },
|
</div>
|
||||||
{ label: 'Authenticated Users', value: 'authenticated' },
|
</div>
|
||||||
{ label: 'Specific Roles', value: 'roles' },
|
|
||||||
{ label: 'Process Managers Only', value: 'managers' },
|
|
||||||
{ label: 'Administrators Only', value: 'admin' }
|
|
||||||
]"
|
|
||||||
help="Who can start and execute this process"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormKit
|
<!-- Error State -->
|
||||||
type="text"
|
<div v-else-if="permissionsError" class="bg-red-50 border border-red-200 rounded-lg p-4">
|
||||||
label="Allowed Roles"
|
<div class="flex items-center">
|
||||||
v-model="localProcess.allowedRoles"
|
<Icon name="material-symbols:error-outline" class="w-5 h-5 text-red-500 mr-2" />
|
||||||
help="Comma-separated list of roles that can execute this process"
|
<p class="text-sm text-red-700">{{ permissionsError }}</p>
|
||||||
placeholder="e.g., manager, hr_admin, finance_user"
|
</div>
|
||||||
v-if="localProcess.executionPermission === 'roles'"
|
</div>
|
||||||
/>
|
|
||||||
|
|
||||||
<FormKit
|
<!-- Permissions Form -->
|
||||||
type="select"
|
<div v-else class="space-y-4">
|
||||||
label="Modification Permission"
|
<FormKit
|
||||||
v-model="localProcess.modificationPermission"
|
type="select"
|
||||||
:options="[
|
label="Execution Permission"
|
||||||
{ label: 'Process Owner Only', value: 'owner' },
|
v-model="localProcess.executionPermission"
|
||||||
{ label: 'Process Managers', value: 'managers' },
|
:options="executionPermissionOptions"
|
||||||
{ label: 'Administrators', value: 'admin' },
|
help="Who can start and execute this process"
|
||||||
{ label: 'Anyone with Edit Rights', value: 'editors' }
|
/>
|
||||||
]"
|
|
||||||
help="Who can modify this process"
|
<!-- Role-based Assignment -->
|
||||||
/>
|
<div v-if="localProcess.executionPermission === 'roles'" class="bg-blue-50 p-4 rounded-md border border-blue-200">
|
||||||
|
<div class="flex items-center mb-3">
|
||||||
<FormKit
|
<Icon name="material-symbols:group" class="text-blue-600 mr-2" />
|
||||||
type="checkbox"
|
<h5 class="text-sm font-medium text-blue-900">Select Allowed Roles</h5>
|
||||||
label="Require Approval for Changes"
|
</div>
|
||||||
v-model="localProcess.requireApproval"
|
|
||||||
help="Changes to this process must be approved before taking effect"
|
<div class="space-y-3">
|
||||||
/>
|
<!-- Role Dropdown -->
|
||||||
|
<div class="relative">
|
||||||
<FormKit
|
<FormKit
|
||||||
type="checkbox"
|
type="select"
|
||||||
label="Enable Audit Trail"
|
v-model="selectedRoleId"
|
||||||
v-model="localProcess.enableAuditTrail"
|
:options="filteredAvailableRoles"
|
||||||
help="Keep detailed logs of who accessed and modified this process"
|
placeholder="Select a role to add..."
|
||||||
/>
|
:classes="{ outer: 'mb-0' }"
|
||||||
|
/>
|
||||||
|
<p class="mt-1 text-xs text-blue-700">Select roles that will be able to execute this process</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Selected Roles Pills -->
|
||||||
|
<div v-if="localProcess.allowedRoles && localProcess.allowedRoles.length > 0" class="mt-3">
|
||||||
|
<label class="block text-sm font-medium text-blue-700 mb-2">Selected Roles</label>
|
||||||
|
<div class="flex flex-wrap gap-2 p-2 bg-white border border-blue-100 rounded-md min-h-[40px]">
|
||||||
|
<div v-for="(role, index) in localProcess.allowedRoles" :key="'role-' + role.value"
|
||||||
|
class="inline-flex items-center px-2 py-1 rounded-full text-xs bg-blue-100 text-blue-800 border border-blue-200">
|
||||||
|
<span class="mr-1">{{ role.label }}</span>
|
||||||
|
<button @click="removeAllowedRole(index)" class="text-blue-600 hover:text-blue-800">
|
||||||
|
<Icon name="material-symbols:close" class="w-4 h-4" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<FormKit
|
||||||
|
type="select"
|
||||||
|
label="Modification Permission"
|
||||||
|
v-model="localProcess.modificationPermission"
|
||||||
|
:options="modificationPermissionOptions"
|
||||||
|
help="Who can modify this process"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -303,7 +223,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, watch } from 'vue'
|
import { ref, computed, watch, onMounted, nextTick } from 'vue'
|
||||||
import { useProcessBuilderStore } from '~/stores/processBuilder'
|
import { useProcessBuilderStore } from '~/stores/processBuilder'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -323,39 +243,160 @@ const showModal = computed({
|
|||||||
set: (value) => emit('update:modelValue', value)
|
set: (value) => emit('update:modelValue', value)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Settings tabs configuration
|
// Settings tabs configuration - simplified to only essential tabs
|
||||||
const settingsTabs = [
|
const settingsTabs = [
|
||||||
{ key: 'info', label: 'Process Info', icon: 'material-symbols:info-outline' },
|
{ key: 'info', label: 'Process Info', icon: 'material-symbols:info-outline' },
|
||||||
{ key: 'execution', label: 'Execution', icon: 'material-symbols:play-circle-outline' },
|
{ key: 'basic', label: 'Basic Settings', icon: 'material-symbols:settings' },
|
||||||
{ key: 'variables', label: 'Variables & Data', icon: 'material-symbols:data-object' },
|
|
||||||
{ key: 'permissions', label: 'Permissions', icon: 'material-symbols:security' },
|
{ key: 'permissions', label: 'Permissions', icon: 'material-symbols:security' },
|
||||||
{ key: 'json', label: 'Source', icon: 'material-symbols:code' }
|
{ key: 'json', label: 'Source', icon: 'material-symbols:code' }
|
||||||
]
|
]
|
||||||
|
|
||||||
const activeTab = ref('info')
|
const activeTab = ref('info')
|
||||||
|
|
||||||
// Local process data (copy of current process)
|
// Available roles and permissions from database
|
||||||
|
const availableRoles = ref([])
|
||||||
|
const availablePermissions = ref([])
|
||||||
|
const loadingPermissions = ref(false)
|
||||||
|
const permissionsError = ref(null)
|
||||||
|
|
||||||
|
// Role selection for pill design
|
||||||
|
const selectedRoleId = ref('')
|
||||||
|
const filteredAvailableRoles = ref([])
|
||||||
|
|
||||||
|
// Local process data - simplified to only essential settings
|
||||||
const localProcess = ref({
|
const localProcess = ref({
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
priority: 'normal',
|
|
||||||
category: '',
|
category: '',
|
||||||
owner: '',
|
|
||||||
processType: 'standard',
|
processType: 'standard',
|
||||||
maxExecutionTime: 60,
|
|
||||||
autoTimeout: 24,
|
|
||||||
allowParallel: false,
|
allowParallel: false,
|
||||||
enableErrorRecovery: true,
|
|
||||||
sendNotifications: true,
|
sendNotifications: true,
|
||||||
dataPersistence: 'short_term',
|
|
||||||
logVariableChanges: true,
|
|
||||||
encryptSensitiveData: false,
|
|
||||||
dataRetentionPolicy: '',
|
|
||||||
executionPermission: 'authenticated',
|
executionPermission: 'authenticated',
|
||||||
allowedRoles: '',
|
allowedRoles: [],
|
||||||
modificationPermission: 'managers',
|
modificationPermission: 'managers'
|
||||||
requireApproval: false,
|
})
|
||||||
enableAuditTrail: true
|
|
||||||
|
// Load permissions and roles from database
|
||||||
|
const loadPermissionsFromDatabase = async () => {
|
||||||
|
try {
|
||||||
|
loadingPermissions.value = true
|
||||||
|
permissionsError.value = null
|
||||||
|
|
||||||
|
// Load available roles
|
||||||
|
const rolesResponse = await $fetch('/api/roles')
|
||||||
|
if (rolesResponse.success) {
|
||||||
|
availableRoles.value = rolesResponse.roles || []
|
||||||
|
// Update filtered roles (exclude already selected ones)
|
||||||
|
updateFilteredRoles()
|
||||||
|
} else {
|
||||||
|
console.error('Failed to load roles:', rolesResponse.message)
|
||||||
|
permissionsError.value = 'Failed to load roles from database'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load available permissions
|
||||||
|
const permissionsResponse = await $fetch('/api/permissions')
|
||||||
|
if (permissionsResponse.success) {
|
||||||
|
availablePermissions.value = permissionsResponse.data?.permissions || permissionsResponse.permissions || []
|
||||||
|
} else {
|
||||||
|
console.error('Failed to load permissions:', permissionsResponse.message)
|
||||||
|
permissionsError.value = 'Failed to load permissions from database'
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error loading permissions:', error)
|
||||||
|
permissionsError.value = 'Failed to load permissions and roles'
|
||||||
|
} finally {
|
||||||
|
loadingPermissions.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update filtered roles (exclude already selected ones)
|
||||||
|
const updateFilteredRoles = () => {
|
||||||
|
const selectedRoleIds = localProcess.value.allowedRoles?.map(role => role.value) || []
|
||||||
|
filteredAvailableRoles.value = availableRoles.value
|
||||||
|
.filter(role => !selectedRoleIds.includes(role.roleID))
|
||||||
|
.map(role => ({
|
||||||
|
label: role.roleName,
|
||||||
|
value: role.roleID
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Watch for changes to selectedRoleId to handle role selection
|
||||||
|
watch(selectedRoleId, (newRoleId) => {
|
||||||
|
if (newRoleId) {
|
||||||
|
console.log('Role selected:', newRoleId, typeof newRoleId);
|
||||||
|
|
||||||
|
// Convert roleId to string to ensure consistent comparison
|
||||||
|
const roleIdStr = String(newRoleId);
|
||||||
|
|
||||||
|
// Find the selected role from available roles
|
||||||
|
const selectedRole = availableRoles.value.find(role => String(role.roleID) === roleIdStr);
|
||||||
|
|
||||||
|
if (selectedRole) {
|
||||||
|
console.log('Found role:', selectedRole);
|
||||||
|
|
||||||
|
// Initialize the array if needed
|
||||||
|
if (!localProcess.value.allowedRoles) {
|
||||||
|
localProcess.value.allowedRoles = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if role already exists
|
||||||
|
const roleExists = localProcess.value.allowedRoles.some(role => String(role.value) === roleIdStr);
|
||||||
|
|
||||||
|
if (!roleExists) {
|
||||||
|
// Add the role to the allowed roles
|
||||||
|
localProcess.value.allowedRoles.push({
|
||||||
|
label: selectedRole.roleName,
|
||||||
|
value: String(selectedRole.roleID)
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update filtered roles
|
||||||
|
updateFilteredRoles();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn('Selected role not found in available roles', roleIdStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the selection
|
||||||
|
selectedRoleId.value = '';
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Remove allowed role
|
||||||
|
const removeAllowedRole = (index) => {
|
||||||
|
if (localProcess.value.allowedRoles && localProcess.value.allowedRoles[index]) {
|
||||||
|
localProcess.value.allowedRoles.splice(index, 1)
|
||||||
|
// Update filtered roles
|
||||||
|
updateFilteredRoles()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Computed properties for form options
|
||||||
|
const roleOptions = computed(() => {
|
||||||
|
return availableRoles.value.map(role => ({
|
||||||
|
label: role.roleName,
|
||||||
|
value: role.roleID
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
|
// Computed properties for permission options
|
||||||
|
const executionPermissionOptions = computed(() => {
|
||||||
|
return availablePermissions.value
|
||||||
|
.filter(permission => permission.category === 'execution')
|
||||||
|
.map(permission => ({
|
||||||
|
label: permission.name,
|
||||||
|
value: permission.id,
|
||||||
|
help: permission.description
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
|
const modificationPermissionOptions = computed(() => {
|
||||||
|
return availablePermissions.value
|
||||||
|
.filter(permission => permission.category === 'modification')
|
||||||
|
.map(permission => ({
|
||||||
|
label: permission.name,
|
||||||
|
value: permission.id,
|
||||||
|
help: permission.description
|
||||||
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
// Computed properties for metadata
|
// Computed properties for metadata
|
||||||
@ -375,37 +416,24 @@ const variableCount = computed(() => {
|
|||||||
return Object.keys(processVariables).length
|
return Object.keys(processVariables).length
|
||||||
})
|
})
|
||||||
|
|
||||||
// JSON export functionality
|
// JSON export functionality - simplified
|
||||||
const formattedJson = computed(() => {
|
const formattedJson = computed(() => {
|
||||||
const exportData = {
|
const exportData = {
|
||||||
processInfo: {
|
processInfo: {
|
||||||
id: localProcess.value.id,
|
id: localProcess.value.id,
|
||||||
name: localProcess.value.name,
|
name: localProcess.value.name,
|
||||||
description: localProcess.value.description,
|
description: localProcess.value.description,
|
||||||
priority: localProcess.value.priority,
|
category: localProcess.value.category
|
||||||
category: localProcess.value.category,
|
|
||||||
owner: localProcess.value.owner
|
|
||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
processType: localProcess.value.processType,
|
processType: localProcess.value.processType,
|
||||||
maxExecutionTime: localProcess.value.maxExecutionTime,
|
|
||||||
autoTimeout: localProcess.value.autoTimeout,
|
|
||||||
allowParallel: localProcess.value.allowParallel,
|
allowParallel: localProcess.value.allowParallel,
|
||||||
enableErrorRecovery: localProcess.value.enableErrorRecovery,
|
|
||||||
sendNotifications: localProcess.value.sendNotifications
|
sendNotifications: localProcess.value.sendNotifications
|
||||||
},
|
},
|
||||||
dataSettings: {
|
|
||||||
dataPersistence: localProcess.value.dataPersistence,
|
|
||||||
logVariableChanges: localProcess.value.logVariableChanges,
|
|
||||||
encryptSensitiveData: localProcess.value.encryptSensitiveData,
|
|
||||||
dataRetentionPolicy: localProcess.value.dataRetentionPolicy
|
|
||||||
},
|
|
||||||
permissions: {
|
permissions: {
|
||||||
executionPermission: localProcess.value.executionPermission,
|
executionPermission: localProcess.value.executionPermission,
|
||||||
allowedRoles: localProcess.value.allowedRoles,
|
allowedRoles: localProcess.value.allowedRoles,
|
||||||
modificationPermission: localProcess.value.modificationPermission,
|
modificationPermission: localProcess.value.modificationPermission
|
||||||
requireApproval: localProcess.value.requireApproval,
|
|
||||||
enableAuditTrail: localProcess.value.enableAuditTrail
|
|
||||||
},
|
},
|
||||||
workflow: {
|
workflow: {
|
||||||
nodes: processStore.currentProcess?.nodes || [],
|
nodes: processStore.currentProcess?.nodes || [],
|
||||||
@ -426,15 +454,40 @@ const formattedJson = computed(() => {
|
|||||||
// Watch for changes to current process and sync with local data
|
// Watch for changes to current process and sync with local data
|
||||||
watch(() => processStore.currentProcess, (newProcess) => {
|
watch(() => processStore.currentProcess, (newProcess) => {
|
||||||
if (newProcess) {
|
if (newProcess) {
|
||||||
|
// Handle roles conversion - convert string to array if needed
|
||||||
|
let allowedRoles = newProcess.settings?.allowedRoles || []
|
||||||
|
if (typeof allowedRoles === 'string' && allowedRoles.trim()) {
|
||||||
|
// Convert comma-separated string to array
|
||||||
|
allowedRoles = allowedRoles.split(',').map(role => role.trim()).filter(role => role)
|
||||||
|
} else if (!Array.isArray(allowedRoles)) {
|
||||||
|
allowedRoles = []
|
||||||
|
}
|
||||||
|
|
||||||
localProcess.value = {
|
localProcess.value = {
|
||||||
...localProcess.value,
|
...localProcess.value,
|
||||||
id: newProcess.id,
|
id: newProcess.id,
|
||||||
name: newProcess.name || '',
|
name: newProcess.name || '',
|
||||||
description: newProcess.description || '',
|
description: newProcess.description || '',
|
||||||
...newProcess.settings
|
category: newProcess.category || '',
|
||||||
|
processType: newProcess.settings?.processType || 'standard',
|
||||||
|
allowParallel: newProcess.settings?.allowParallel || false,
|
||||||
|
sendNotifications: newProcess.settings?.sendNotifications !== false,
|
||||||
|
executionPermission: newProcess.settings?.executionPermission || 'authenticated',
|
||||||
|
allowedRoles: allowedRoles,
|
||||||
|
modificationPermission: newProcess.settings?.modificationPermission || 'managers'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update filtered roles after setting the data
|
||||||
|
updateFilteredRoles()
|
||||||
}
|
}
|
||||||
}, { immediate: true, deep: true })
|
}, { immediate: true })
|
||||||
|
|
||||||
|
// Load permissions when modal opens
|
||||||
|
watch(() => showModal.value, (isOpen) => {
|
||||||
|
if (isOpen && availableRoles.value.length === 0) {
|
||||||
|
loadPermissionsFromDatabase()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
const closeModal = () => {
|
const closeModal = () => {
|
||||||
@ -442,31 +495,25 @@ const closeModal = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const saveSettings = () => {
|
const saveSettings = () => {
|
||||||
// Update the process in the store
|
// Update the process in the store with simplified settings
|
||||||
if (processStore.currentProcess) {
|
if (processStore.currentProcess) {
|
||||||
|
// Convert roles array to string for storage (for backward compatibility)
|
||||||
|
const allowedRolesString = Array.isArray(localProcess.value.allowedRoles)
|
||||||
|
? localProcess.value.allowedRoles.join(', ')
|
||||||
|
: localProcess.value.allowedRoles
|
||||||
|
|
||||||
const updatedProcess = {
|
const updatedProcess = {
|
||||||
...processStore.currentProcess,
|
...processStore.currentProcess,
|
||||||
name: localProcess.value.name,
|
name: localProcess.value.name,
|
||||||
description: localProcess.value.description,
|
description: localProcess.value.description,
|
||||||
|
category: localProcess.value.category,
|
||||||
settings: {
|
settings: {
|
||||||
priority: localProcess.value.priority,
|
|
||||||
category: localProcess.value.category,
|
|
||||||
owner: localProcess.value.owner,
|
|
||||||
processType: localProcess.value.processType,
|
processType: localProcess.value.processType,
|
||||||
maxExecutionTime: localProcess.value.maxExecutionTime,
|
|
||||||
autoTimeout: localProcess.value.autoTimeout,
|
|
||||||
allowParallel: localProcess.value.allowParallel,
|
allowParallel: localProcess.value.allowParallel,
|
||||||
enableErrorRecovery: localProcess.value.enableErrorRecovery,
|
|
||||||
sendNotifications: localProcess.value.sendNotifications,
|
sendNotifications: localProcess.value.sendNotifications,
|
||||||
dataPersistence: localProcess.value.dataPersistence,
|
|
||||||
logVariableChanges: localProcess.value.logVariableChanges,
|
|
||||||
encryptSensitiveData: localProcess.value.encryptSensitiveData,
|
|
||||||
dataRetentionPolicy: localProcess.value.dataRetentionPolicy,
|
|
||||||
executionPermission: localProcess.value.executionPermission,
|
executionPermission: localProcess.value.executionPermission,
|
||||||
allowedRoles: localProcess.value.allowedRoles,
|
allowedRoles: allowedRolesString, // Store as string for compatibility
|
||||||
modificationPermission: localProcess.value.modificationPermission,
|
modificationPermission: localProcess.value.modificationPermission
|
||||||
requireApproval: localProcess.value.requireApproval,
|
|
||||||
enableAuditTrail: localProcess.value.enableAuditTrail
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,7 +527,6 @@ const saveSettings = () => {
|
|||||||
const copyToClipboard = async () => {
|
const copyToClipboard = async () => {
|
||||||
try {
|
try {
|
||||||
await navigator.clipboard.writeText(formattedJson.value)
|
await navigator.clipboard.writeText(formattedJson.value)
|
||||||
// You might want to show a toast notification here
|
|
||||||
console.log('JSON copied to clipboard')
|
console.log('JSON copied to clipboard')
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to copy JSON:', err)
|
console.error('Failed to copy JSON:', err)
|
||||||
|
57
server/api/permissions/index.get.js
Normal file
57
server/api/permissions/index.get.js
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
try {
|
||||||
|
// Define standard permission types for process management
|
||||||
|
const permissions = [
|
||||||
|
{
|
||||||
|
id: 'public',
|
||||||
|
name: 'Anyone',
|
||||||
|
description: 'Public access for all users (including guests)',
|
||||||
|
category: 'execution'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'authenticated',
|
||||||
|
name: 'Authenticated Users',
|
||||||
|
description: 'Only logged-in users can access',
|
||||||
|
category: 'execution'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'roles',
|
||||||
|
name: 'Specific Roles',
|
||||||
|
description: 'Users with specific roles can access',
|
||||||
|
category: 'execution'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'admin',
|
||||||
|
name: 'Administrators Only',
|
||||||
|
description: 'Only system administrators can access',
|
||||||
|
category: 'execution'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'owner',
|
||||||
|
name: 'Process Owner Only',
|
||||||
|
description: 'Only the process creator can modify',
|
||||||
|
category: 'modification'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'managers',
|
||||||
|
name: 'Process Managers',
|
||||||
|
description: 'Process managers and administrators can modify',
|
||||||
|
category: 'modification'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data: {
|
||||||
|
permissions: permissions
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching permissions:', error);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: 'Failed to fetch permissions'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user