Missions Corrections
This commit is contained in:
parent
ed2175c080
commit
98f0f8532a
@ -126,27 +126,27 @@ export async function POST(request: Request) {
|
|||||||
} = {};
|
} = {};
|
||||||
|
|
||||||
// Mapper les champs N8N vers notre schéma Prisma
|
// Mapper les champs N8N vers notre schéma Prisma
|
||||||
|
// Vérifier que les valeurs ne sont pas des chaînes vides
|
||||||
if (body.gitRepoUrl !== undefined) {
|
if (body.gitRepoUrl !== undefined) {
|
||||||
updateData.giteaRepositoryUrl = body.gitRepoUrl || null;
|
updateData.giteaRepositoryUrl = (body.gitRepoUrl && body.gitRepoUrl.trim() !== '') ? body.gitRepoUrl : null;
|
||||||
logger.debug('Updating giteaRepositoryUrl', { hasUrl: !!body.gitRepoUrl });
|
logger.debug('Updating giteaRepositoryUrl', { hasUrl: !!updateData.giteaRepositoryUrl, value: body.gitRepoUrl });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (body.leantimeProjectId !== undefined) {
|
if (body.leantimeProjectId !== undefined) {
|
||||||
// N8N peut retourner un number, on le convertit en string
|
// N8N peut retourner un number, on le convertit en string
|
||||||
updateData.leantimeProjectId = body.leantimeProjectId
|
const projectId = body.leantimeProjectId ? String(body.leantimeProjectId).trim() : '';
|
||||||
? String(body.leantimeProjectId)
|
updateData.leantimeProjectId = projectId !== '' ? projectId : null;
|
||||||
: null;
|
logger.debug('Updating leantimeProjectId', { hasId: !!updateData.leantimeProjectId, value: body.leantimeProjectId });
|
||||||
logger.debug('Updating leantimeProjectId', { hasId: !!updateData.leantimeProjectId });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (body.documentationCollectionId !== undefined) {
|
if (body.documentationCollectionId !== undefined) {
|
||||||
updateData.outlineCollectionId = body.documentationCollectionId || null;
|
updateData.outlineCollectionId = (body.documentationCollectionId && body.documentationCollectionId.trim() !== '') ? body.documentationCollectionId : null;
|
||||||
logger.debug('Updating outlineCollectionId', { hasId: !!updateData.outlineCollectionId });
|
logger.debug('Updating outlineCollectionId', { hasId: !!updateData.outlineCollectionId, value: body.documentationCollectionId });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (body.rocketchatChannelId !== undefined) {
|
if (body.rocketchatChannelId !== undefined) {
|
||||||
updateData.rocketChatChannelId = body.rocketchatChannelId || null;
|
updateData.rocketChatChannelId = (body.rocketchatChannelId && body.rocketchatChannelId.trim() !== '') ? body.rocketchatChannelId : null;
|
||||||
logger.debug('Updating rocketChatChannelId', { hasId: !!updateData.rocketChatChannelId });
|
logger.debug('Updating rocketChatChannelId', { hasId: !!updateData.rocketChatChannelId, value: body.rocketchatChannelId });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vérifier qu'il y a au moins un champ à mettre à jour
|
// Vérifier qu'il y a au moins un champ à mettre à jour
|
||||||
|
|||||||
@ -384,11 +384,14 @@ export default function MissionTabDetailPage() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Ressources Métiers */}
|
{/* Ressources Métiers */}
|
||||||
{(mission.rocketChatChannelId || mission.outlineCollectionId || mission.giteaRepositoryUrl || mission.leantimeProjectId) && (
|
{((mission.rocketChatChannelId && mission.rocketChatChannelId.trim() !== '') ||
|
||||||
|
(mission.outlineCollectionId && mission.outlineCollectionId.trim() !== '') ||
|
||||||
|
(mission.giteaRepositoryUrl && mission.giteaRepositoryUrl.trim() !== '') ||
|
||||||
|
(mission.leantimeProjectId && mission.leantimeProjectId.toString().trim() !== '')) && (
|
||||||
<div className="bg-white rounded-lg shadow-sm border border-gray-100 p-6">
|
<div className="bg-white rounded-lg shadow-sm border border-gray-100 p-6">
|
||||||
<h2 className="text-lg font-semibold text-gray-900 mb-4">Ressources Métiers</h2>
|
<h2 className="text-lg font-semibold text-gray-900 mb-4">Ressources Métiers</h2>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
{mission.rocketChatChannelId && (() => {
|
{mission.rocketChatChannelId && mission.rocketChatChannelId.trim() !== '' && (() => {
|
||||||
// Build RocketChat URL: parole.slm-lab.net/channel/[channelId]
|
// Build RocketChat URL: parole.slm-lab.net/channel/[channelId]
|
||||||
// If it's already a full URL, use it; otherwise build from ID
|
// If it's already a full URL, use it; otherwise build from ID
|
||||||
const rocketChatUrl = mission.rocketChatChannelId.startsWith('http')
|
const rocketChatUrl = mission.rocketChatChannelId.startsWith('http')
|
||||||
@ -413,7 +416,7 @@ export default function MissionTabDetailPage() {
|
|||||||
);
|
);
|
||||||
})()}
|
})()}
|
||||||
|
|
||||||
{mission.outlineCollectionId && (() => {
|
{mission.outlineCollectionId && mission.outlineCollectionId.trim() !== '' && (() => {
|
||||||
// Build Outline URL: chapitre.slm-lab.net/collection/[collectionId]
|
// Build Outline URL: chapitre.slm-lab.net/collection/[collectionId]
|
||||||
// If it's already a full URL, use it; otherwise build from ID
|
// If it's already a full URL, use it; otherwise build from ID
|
||||||
const outlineUrl = mission.outlineCollectionId.startsWith('http')
|
const outlineUrl = mission.outlineCollectionId.startsWith('http')
|
||||||
@ -438,7 +441,7 @@ export default function MissionTabDetailPage() {
|
|||||||
);
|
);
|
||||||
})()}
|
})()}
|
||||||
|
|
||||||
{mission.giteaRepositoryUrl && (() => {
|
{mission.giteaRepositoryUrl && mission.giteaRepositoryUrl.trim() !== '' && (() => {
|
||||||
// Use mission name (sanitized) as repo name
|
// Use mission name (sanitized) as repo name
|
||||||
const repoName = sanitizeMissionName(mission.name);
|
const repoName = sanitizeMissionName(mission.name);
|
||||||
|
|
||||||
@ -469,7 +472,7 @@ export default function MissionTabDetailPage() {
|
|||||||
);
|
);
|
||||||
})()}
|
})()}
|
||||||
|
|
||||||
{mission.leantimeProjectId && (() => {
|
{mission.leantimeProjectId && mission.leantimeProjectId.toString().trim() !== '' && (() => {
|
||||||
// Build Leantime URL: agilite.slm-lab.net/projects/showProject/[projectId]
|
// Build Leantime URL: agilite.slm-lab.net/projects/showProject/[projectId]
|
||||||
// If it's already a full URL, use it; otherwise build from ID
|
// If it's already a full URL, use it; otherwise build from ID
|
||||||
const leantimeUrl = mission.leantimeProjectId.startsWith('http')
|
const leantimeUrl = mission.leantimeProjectId.startsWith('http')
|
||||||
|
|||||||
@ -18,7 +18,8 @@ import {
|
|||||||
Loader2,
|
Loader2,
|
||||||
FileText,
|
FileText,
|
||||||
Lock,
|
Lock,
|
||||||
CheckCircle
|
CheckCircle,
|
||||||
|
ArrowLeft
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useToast } from "@/components/ui/use-toast";
|
import { useToast } from "@/components/ui/use-toast";
|
||||||
import { useParams, useRouter } from "next/navigation";
|
import { useParams, useRouter } from "next/navigation";
|
||||||
@ -396,6 +397,18 @@ export default function MissionDetailPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-gray-50 min-h-screen p-6">
|
<div className="bg-gray-50 min-h-screen p-6">
|
||||||
|
{/* Back Button */}
|
||||||
|
<div className="mb-4">
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
className="flex items-center text-gray-600 hover:text-gray-900"
|
||||||
|
onClick={() => router.push('/missions')}
|
||||||
|
>
|
||||||
|
<ArrowLeft className="mr-2 h-4 w-4" />
|
||||||
|
Retour aux missions
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Header with Name and Logo */}
|
{/* Header with Name and Logo */}
|
||||||
<div className="bg-white rounded-lg shadow-sm border border-gray-100 mb-6 p-6">
|
<div className="bg-white rounded-lg shadow-sm border border-gray-100 mb-6 p-6">
|
||||||
<div className="flex justify-between items-start">
|
<div className="flex justify-between items-start">
|
||||||
@ -591,11 +604,14 @@ export default function MissionDetailPage() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Ressources Métiers */}
|
{/* Ressources Métiers */}
|
||||||
{(mission.rocketChatChannelId || mission.outlineCollectionId || mission.giteaRepositoryUrl || mission.leantimeProjectId) && (
|
{((mission.rocketChatChannelId && mission.rocketChatChannelId.trim() !== '') ||
|
||||||
|
(mission.outlineCollectionId && mission.outlineCollectionId.trim() !== '') ||
|
||||||
|
(mission.giteaRepositoryUrl && mission.giteaRepositoryUrl.trim() !== '') ||
|
||||||
|
(mission.leantimeProjectId && mission.leantimeProjectId.toString().trim() !== '')) && (
|
||||||
<div className="bg-white rounded-lg shadow-sm border border-gray-100 p-6">
|
<div className="bg-white rounded-lg shadow-sm border border-gray-100 p-6">
|
||||||
<h2 className="text-xl font-semibold text-gray-800 mb-4">Ressources Métiers</h2>
|
<h2 className="text-xl font-semibold text-gray-800 mb-4">Ressources Métiers</h2>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
{mission.rocketChatChannelId && (() => {
|
{mission.rocketChatChannelId && mission.rocketChatChannelId.trim() !== '' && (() => {
|
||||||
// Build RocketChat URL: parole.slm-lab.net/channel/[channelId]
|
// Build RocketChat URL: parole.slm-lab.net/channel/[channelId]
|
||||||
// If it's already a full URL, use it; otherwise build from ID
|
// If it's already a full URL, use it; otherwise build from ID
|
||||||
const rocketChatUrl = mission.rocketChatChannelId.startsWith('http')
|
const rocketChatUrl = mission.rocketChatChannelId.startsWith('http')
|
||||||
@ -620,7 +636,7 @@ export default function MissionDetailPage() {
|
|||||||
);
|
);
|
||||||
})()}
|
})()}
|
||||||
|
|
||||||
{mission.outlineCollectionId && (() => {
|
{mission.outlineCollectionId && mission.outlineCollectionId.trim() !== '' && (() => {
|
||||||
// Build Outline URL: chapitre.slm-lab.net/collection/[collectionId]
|
// Build Outline URL: chapitre.slm-lab.net/collection/[collectionId]
|
||||||
// If it's already a full URL, use it; otherwise build from ID
|
// If it's already a full URL, use it; otherwise build from ID
|
||||||
const outlineUrl = mission.outlineCollectionId.startsWith('http')
|
const outlineUrl = mission.outlineCollectionId.startsWith('http')
|
||||||
@ -645,7 +661,7 @@ export default function MissionDetailPage() {
|
|||||||
);
|
);
|
||||||
})()}
|
})()}
|
||||||
|
|
||||||
{mission.giteaRepositoryUrl && (() => {
|
{mission.giteaRepositoryUrl && mission.giteaRepositoryUrl.trim() !== '' && (() => {
|
||||||
// Use mission name (sanitized) as repo name
|
// Use mission name (sanitized) as repo name
|
||||||
const repoName = sanitizeMissionName(mission.name);
|
const repoName = sanitizeMissionName(mission.name);
|
||||||
|
|
||||||
@ -676,7 +692,7 @@ export default function MissionDetailPage() {
|
|||||||
);
|
);
|
||||||
})()}
|
})()}
|
||||||
|
|
||||||
{mission.leantimeProjectId && (() => {
|
{mission.leantimeProjectId && mission.leantimeProjectId.toString().trim() !== '' && (() => {
|
||||||
// Build Leantime URL: agilite.slm-lab.net/projects/showProject/[projectId]
|
// Build Leantime URL: agilite.slm-lab.net/projects/showProject/[projectId]
|
||||||
// If it's already a full URL, use it; otherwise build from ID
|
// If it's already a full URL, use it; otherwise build from ID
|
||||||
const leantimeUrl = mission.leantimeProjectId.startsWith('http')
|
const leantimeUrl = mission.leantimeProjectId.startsWith('http')
|
||||||
|
|||||||
@ -769,14 +769,15 @@ export default function EquipePage() {
|
|||||||
<td className="px-4 py-3 text-sm text-gray-600">{user.email}</td>
|
<td className="px-4 py-3 text-sm text-gray-600">{user.email}</td>
|
||||||
<td className="px-4 py-3">
|
<td className="px-4 py-3">
|
||||||
<div className="flex flex-wrap gap-1">
|
<div className="flex flex-wrap gap-1">
|
||||||
{(user.roles || []).slice(0, 3).map(role => (
|
{Array.isArray(user.roles) && user.roles.length > 0 ? (
|
||||||
|
user.roles.map(role => (
|
||||||
<span key={role} className="px-2 py-0.5 text-xs bg-blue-50 text-blue-700 rounded-full">
|
<span key={role} className="px-2 py-0.5 text-xs bg-blue-50 text-blue-700 rounded-full">
|
||||||
{role}
|
{role}
|
||||||
</span>
|
</span>
|
||||||
))}
|
))
|
||||||
{(user.roles || []).length > 3 && (
|
) : (
|
||||||
<span className="px-2 py-0.5 text-xs bg-gray-100 text-gray-600 rounded-full">
|
<span className="px-2 py-0.5 text-xs bg-gray-100 text-gray-400 rounded-full">
|
||||||
+{user.roles.length - 3}
|
Aucun rôle
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -481,15 +481,21 @@ export function MissionMembersPanel({
|
|||||||
{selectedTab === 'users' ? (
|
{selectedTab === 'users' ? (
|
||||||
filteredUsers.length > 0 ? (
|
filteredUsers.length > 0 ? (
|
||||||
<div className="divide-y divide-gray-200">
|
<div className="divide-y divide-gray-200">
|
||||||
{filteredUsers.map(user => (
|
{filteredUsers.map(user => {
|
||||||
|
const displayName = (user.firstName && user.lastName)
|
||||||
|
? `${user.firstName} ${user.lastName}`
|
||||||
|
: user.firstName || user.lastName || user.username || user.email || 'Utilisateur';
|
||||||
|
const initials = (user.firstName?.[0] || "") + (user.lastName?.[0] || "") || user.username?.[0]?.toUpperCase() || user.email?.[0]?.toUpperCase() || "?";
|
||||||
|
|
||||||
|
return (
|
||||||
<div key={user.id} className="p-3 hover:bg-gray-50 flex items-center justify-between">
|
<div key={user.id} className="p-3 hover:bg-gray-50 flex items-center justify-between">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="h-10 w-10 rounded-full bg-gray-100 flex items-center justify-center text-gray-600 font-medium mr-3">
|
<div className="h-10 w-10 rounded-full bg-gray-100 flex items-center justify-center text-gray-600 font-medium mr-3">
|
||||||
{user.firstName?.[0] || ""}{user.lastName?.[0] || ""}
|
{initials}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="font-medium text-gray-900">{user.firstName} {user.lastName}</div>
|
<div className="font-medium text-gray-900">{displayName}</div>
|
||||||
<div className="text-sm text-gray-500">{user.email}</div>
|
<div className="text-sm text-gray-500">{user.email || user.username || ''}</div>
|
||||||
{isUserAssigned(user.id) && (
|
{isUserAssigned(user.id) && (
|
||||||
<div className="flex flex-wrap gap-1 mt-1">
|
<div className="flex flex-wrap gap-1 mt-1">
|
||||||
{getUserRoles(user.id).map((role) => (
|
{getUserRoles(user.id).map((role) => (
|
||||||
@ -570,7 +576,8 @@ export function MissionMembersPanel({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="p-4 text-center text-gray-500">
|
<div className="p-4 text-center text-gray-500">
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user