feat(workflow) : DTOs front Workflow + category sur TaskStatus + workflow embarqué sur Project + service + i18n
This commit is contained in:
@@ -56,6 +56,37 @@
|
|||||||
"moveTo": "Déplacer vers",
|
"moveTo": "Déplacer vers",
|
||||||
"backlog": "Backlog (sans statut)"
|
"backlog": "Backlog (sans statut)"
|
||||||
},
|
},
|
||||||
|
"workflows": {
|
||||||
|
"title": "Workflows",
|
||||||
|
"addWorkflow": "Ajouter un workflow",
|
||||||
|
"editWorkflow": "Modifier le workflow",
|
||||||
|
"name": "Nom",
|
||||||
|
"isDefault": "Workflow par défaut",
|
||||||
|
"statuses": "Statuts",
|
||||||
|
"addStatus": "Ajouter un statut",
|
||||||
|
"category": "Catégorie",
|
||||||
|
"created": "Workflow créé",
|
||||||
|
"updated": "Workflow mis à jour",
|
||||||
|
"deleted": "Workflow supprimé",
|
||||||
|
"switched": "Workflow du projet changé",
|
||||||
|
"switchTitle": "Changer de workflow",
|
||||||
|
"switchTargetLabel": "Nouveau workflow",
|
||||||
|
"switchMappingTitle": "Mapping des statuts",
|
||||||
|
"switchSourceCol": "Statut actuel",
|
||||||
|
"switchTargetCol": "Statut cible",
|
||||||
|
"switchTaskCountCol": "Tâches",
|
||||||
|
"switchToBacklog": "Mapper vers le backlog",
|
||||||
|
"switchConfirm": "Confirmer la migration",
|
||||||
|
"switchSummary": "{count} tâche(s) migrée(s), projet sur workflow « {name} »",
|
||||||
|
"deleteUsedBy": "Workflow utilisé par {count} projet(s) — impossible de supprimer.",
|
||||||
|
"categories": {
|
||||||
|
"todo": "À faire",
|
||||||
|
"in_progress": "En cours",
|
||||||
|
"blocked": "Bloqué",
|
||||||
|
"review": "En validation",
|
||||||
|
"done": "Terminé"
|
||||||
|
}
|
||||||
|
},
|
||||||
"taskEfforts": {
|
"taskEfforts": {
|
||||||
"created": "Effort créé avec succès.",
|
"created": "Effort créé avec succès.",
|
||||||
"updated": "Effort mis à jour avec succès.",
|
"updated": "Effort mis à jour avec succès.",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { Client } from './client'
|
import type { Client } from './client'
|
||||||
|
import type { Workflow } from './workflow'
|
||||||
|
|
||||||
export type Project = {
|
export type Project = {
|
||||||
id: number
|
id: number
|
||||||
@@ -8,6 +9,7 @@ export type Project = {
|
|||||||
description: string | null
|
description: string | null
|
||||||
color: string
|
color: string
|
||||||
client: Client | null
|
client: Client | null
|
||||||
|
workflow: Workflow
|
||||||
giteaOwner: string | null
|
giteaOwner: string | null
|
||||||
giteaRepo: string | null
|
giteaRepo: string | null
|
||||||
bookstackShelfId: number | null
|
bookstackShelfId: number | null
|
||||||
@@ -22,6 +24,7 @@ export type ProjectWrite = {
|
|||||||
description: string | null
|
description: string | null
|
||||||
color: string
|
color: string
|
||||||
client: string | null // IRI : "/api/clients/1" ou null
|
client: string | null // IRI : "/api/clients/1" ou null
|
||||||
|
workflow?: string // IRI : "/api/workflows/1"
|
||||||
giteaOwner?: string | null
|
giteaOwner?: string | null
|
||||||
giteaRepo?: string | null
|
giteaRepo?: string | null
|
||||||
bookstackShelfId?: number | null
|
bookstackShelfId?: number | null
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import type { StatusCategory } from './workflow'
|
||||||
|
|
||||||
export type TaskStatus = {
|
export type TaskStatus = {
|
||||||
id: number
|
id: number
|
||||||
'@id'?: string
|
'@id'?: string
|
||||||
@@ -5,6 +7,8 @@ export type TaskStatus = {
|
|||||||
color: string
|
color: string
|
||||||
position: number
|
position: number
|
||||||
isFinal: boolean
|
isFinal: boolean
|
||||||
|
category: StatusCategory
|
||||||
|
workflow?: { '@id': string, id: number } | string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TaskStatusWrite = {
|
export type TaskStatusWrite = {
|
||||||
@@ -12,4 +16,6 @@ export type TaskStatusWrite = {
|
|||||||
color: string
|
color: string
|
||||||
position: number
|
position: number
|
||||||
isFinal: boolean
|
isFinal: boolean
|
||||||
|
category: StatusCategory
|
||||||
|
workflow?: string
|
||||||
}
|
}
|
||||||
|
|||||||
27
frontend/services/dto/workflow.ts
Normal file
27
frontend/services/dto/workflow.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import type { TaskStatus, TaskStatusWrite } from './task-status'
|
||||||
|
|
||||||
|
export type StatusCategory = 'todo' | 'in_progress' | 'blocked' | 'review' | 'done'
|
||||||
|
|
||||||
|
export const STATUS_CATEGORY_LABEL: Record<StatusCategory, string> = {
|
||||||
|
todo: 'À faire',
|
||||||
|
in_progress: 'En cours',
|
||||||
|
blocked: 'Bloqué',
|
||||||
|
review: 'En validation',
|
||||||
|
done: 'Terminé',
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Workflow = {
|
||||||
|
id: number
|
||||||
|
'@id'?: string
|
||||||
|
name: string
|
||||||
|
isDefault: boolean
|
||||||
|
position: number
|
||||||
|
statuses: TaskStatus[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type WorkflowWrite = {
|
||||||
|
name: string
|
||||||
|
isDefault: boolean
|
||||||
|
position: number
|
||||||
|
statuses?: TaskStatusWrite[]
|
||||||
|
}
|
||||||
55
frontend/services/workflows.ts
Normal file
55
frontend/services/workflows.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import type { Workflow, WorkflowWrite } from './dto/workflow'
|
||||||
|
import type { HydraCollection } from '~/utils/api'
|
||||||
|
import { extractHydraMembers } from '~/utils/api'
|
||||||
|
|
||||||
|
type SwitchPayload = {
|
||||||
|
workflowId: number
|
||||||
|
mapping: Record<string, number | null>
|
||||||
|
}
|
||||||
|
|
||||||
|
type SwitchResult = {
|
||||||
|
projectId: number
|
||||||
|
workflowId: number
|
||||||
|
migratedTaskCount: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useWorkflowService() {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
async function getAll(): Promise<Workflow[]> {
|
||||||
|
const data = await api.get<HydraCollection<Workflow>>('/workflows')
|
||||||
|
return extractHydraMembers(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getOne(id: number): Promise<Workflow> {
|
||||||
|
return api.get<Workflow>(`/workflows/${id}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function create(payload: WorkflowWrite): Promise<Workflow> {
|
||||||
|
return api.post<Workflow>('/workflows', payload as Record<string, unknown>, {
|
||||||
|
toastSuccessKey: 'workflows.created',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function update(id: number, payload: Partial<WorkflowWrite>): Promise<Workflow> {
|
||||||
|
return api.patch<Workflow>(`/workflows/${id}`, payload as Record<string, unknown>, {
|
||||||
|
toastSuccessKey: 'workflows.updated',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function remove(id: number): Promise<void> {
|
||||||
|
await api.delete(`/workflows/${id}`, {}, {
|
||||||
|
toastSuccessKey: 'workflows.deleted',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function switchOnProject(projectId: number, payload: SwitchPayload): Promise<SwitchResult> {
|
||||||
|
return api.post<SwitchResult>(
|
||||||
|
`/projects/${projectId}/switch-workflow`,
|
||||||
|
payload as unknown as Record<string, unknown>,
|
||||||
|
{ toastSuccessKey: 'workflows.switched' },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return { getAll, getOne, create, update, remove, switchOnProject }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user