Routes güncellemeleri
This commit is contained in:
parent
bbc2c9c1cb
commit
614be0c916
15 changed files with 423 additions and 295 deletions
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState, useEffect, useCallback } from 'react'
|
||||
import { useParams, useNavigate } from 'react-router-dom'
|
||||
import { useComponents } from '../../contexts/ComponentContext'
|
||||
import { FaRegSave, FaArrowLeft, FaExclamationCircle, FaSync } from 'react-icons/fa';
|
||||
import { FaRegSave, FaArrowLeft, FaExclamationCircle, FaSync } from 'react-icons/fa'
|
||||
import { parseReactCode } from '../../utils/codeParser'
|
||||
import ComponentPreview from '../../components/componentEditor/ComponentPreview'
|
||||
import { EditorState } from '../../@types/componentInfo'
|
||||
|
|
@ -129,7 +129,7 @@ const ComponentEditor: React.FC = () => {
|
|||
addComponent(componentData)
|
||||
}
|
||||
|
||||
navigate(ROUTES_ENUM.protected.saas.developerKitComponents)
|
||||
navigate(ROUTES_ENUM.protected.saas.developerKit.components)
|
||||
} catch (error) {
|
||||
console.error('Error saving component:', error)
|
||||
alert('Failed to save component. Please try again.')
|
||||
|
|
@ -159,7 +159,7 @@ const ComponentEditor: React.FC = () => {
|
|||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<button
|
||||
onClick={() => navigate(ROUTES_ENUM.protected.saas.developerKitComponents)}
|
||||
onClick={() => navigate(ROUTES_ENUM.protected.saas.developerKit.components)}
|
||||
className="flex items-center gap-2 text-slate-600 hover:text-slate-900 transition-colors"
|
||||
>
|
||||
<FaArrowLeft className="w-4 h-4" />
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ const ComponentManager: React.FC = () => {
|
|||
<p className="text-slate-600">{translate('::App.DeveloperKit.Component.Description')}</p>
|
||||
</div>
|
||||
<Link
|
||||
to={ROUTES_ENUM.protected.saas.developerKitComponentsNew}
|
||||
to={ROUTES_ENUM.protected.saas.developerKit.componentsNew}
|
||||
className="flex items-center gap-2 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors"
|
||||
>
|
||||
<FaPlus className="w-4 h-4" />
|
||||
|
|
@ -245,7 +245,7 @@ const ComponentManager: React.FC = () => {
|
|||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<Link
|
||||
to={ROUTES_ENUM.protected.saas.developerKitComponentsEdit.replace(
|
||||
to={ROUTES_ENUM.protected.saas.developerKit.componentsEdit.replace(
|
||||
':id',
|
||||
component.id,
|
||||
)}
|
||||
|
|
@ -256,7 +256,7 @@ const ComponentManager: React.FC = () => {
|
|||
<FaRegEdit className="w-4 h-4" />
|
||||
</Link>
|
||||
<Link
|
||||
to={ROUTES_ENUM.protected.saas.developerKitComponentsView.replace(
|
||||
to={ROUTES_ENUM.protected.saas.developerKit.componentsView.replace(
|
||||
':id',
|
||||
component.id,
|
||||
)}
|
||||
|
|
@ -296,7 +296,7 @@ const ComponentManager: React.FC = () => {
|
|||
</p>
|
||||
{!searchTerm && filterActive === 'all' && (
|
||||
<Link
|
||||
to={ROUTES_ENUM.protected.saas.developerKitComponentsNew}
|
||||
to={ROUTES_ENUM.protected.saas.developerKit.componentsNew}
|
||||
className="inline-flex items-center gap-2 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors"
|
||||
>
|
||||
<FaPlus className="w-4 h-4" />
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { useComponents } from "../../contexts/ComponentContext";
|
||||
import { useEntities } from "../../contexts/EntityContext";
|
||||
import { useSystemHealth } from "../../utils/hooks/useDeveloperKit";
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { useComponents } from '../../contexts/ComponentContext'
|
||||
import { useEntities } from '../../contexts/EntityContext'
|
||||
import { useSystemHealth } from '../../utils/hooks/useDeveloperKit'
|
||||
import {
|
||||
FaDatabase,
|
||||
FaBolt,
|
||||
|
|
@ -15,15 +15,15 @@ import {
|
|||
FaArrowRight,
|
||||
FaExclamationCircle,
|
||||
FaWifi,
|
||||
FaWindowClose
|
||||
} from 'react-icons/fa';
|
||||
import { ROUTES_ENUM } from "@/routes/route.constant";
|
||||
import { useLocalization } from "@/utils/hooks/useLocalization";
|
||||
FaWindowClose,
|
||||
} from 'react-icons/fa'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
||||
const Dashboard: React.FC = () => {
|
||||
const { components } = useComponents();
|
||||
const { entities, migrations, generatedEndpoints } = useEntities();
|
||||
const { isOnline, lastCheck, recheckHealth } = useSystemHealth();
|
||||
const { components } = useComponents()
|
||||
const { entities, migrations, generatedEndpoints } = useEntities()
|
||||
const { isOnline, lastCheck, recheckHealth } = useSystemHealth()
|
||||
const { translate } = useLocalization()
|
||||
|
||||
const stats = [
|
||||
|
|
@ -32,38 +32,38 @@ const Dashboard: React.FC = () => {
|
|||
value: entities.filter((e) => e.isActive).length,
|
||||
total: entities.length,
|
||||
icon: FaDatabase,
|
||||
color: "text-blue-600",
|
||||
bgColor: "bg-blue-100",
|
||||
href: ROUTES_ENUM.protected.saas.developerKitEntities,
|
||||
color: 'text-blue-600',
|
||||
bgColor: 'bg-blue-100',
|
||||
href: ROUTES_ENUM.protected.saas.developerKit.entities,
|
||||
},
|
||||
{
|
||||
name: translate('::App.DeveloperKit.Dashboard.Stats.Migrations'),
|
||||
value: migrations.filter((m) => m.status === "pending").length,
|
||||
value: migrations.filter((m) => m.status === 'pending').length,
|
||||
total: migrations.length,
|
||||
icon: FaBolt,
|
||||
color: "text-yellow-600",
|
||||
bgColor: "bg-yellow-100",
|
||||
href: ROUTES_ENUM.protected.saas.developerKitMigrations,
|
||||
color: 'text-yellow-600',
|
||||
bgColor: 'bg-yellow-100',
|
||||
href: ROUTES_ENUM.protected.saas.developerKit.migrations,
|
||||
},
|
||||
{
|
||||
name: translate('::App.DeveloperKit.Dashboard.Stats.APIs'),
|
||||
value: generatedEndpoints.filter((e) => e.isActive).length,
|
||||
total: generatedEndpoints.length,
|
||||
icon: FaServer,
|
||||
color: "text-emerald-600",
|
||||
bgColor: "bg-emerald-100",
|
||||
href: ROUTES_ENUM.protected.saas.developerKitEndpoints,
|
||||
color: 'text-emerald-600',
|
||||
bgColor: 'bg-emerald-100',
|
||||
href: ROUTES_ENUM.protected.saas.developerKit.endpoints,
|
||||
},
|
||||
{
|
||||
name: translate('::App.DeveloperKit.Dashboard.Stats.Components'),
|
||||
value: components?.filter((c) => c.isActive).length,
|
||||
total: components?.length,
|
||||
icon: FaPuzzlePiece,
|
||||
color: "text-purple-600",
|
||||
bgColor: "bg-purple-100",
|
||||
href: ROUTES_ENUM.protected.saas.developerKitComponents,
|
||||
color: 'text-purple-600',
|
||||
bgColor: 'bg-purple-100',
|
||||
href: ROUTES_ENUM.protected.saas.developerKit.components,
|
||||
},
|
||||
];
|
||||
]
|
||||
|
||||
const developmentFlow = [
|
||||
{
|
||||
|
|
@ -71,54 +71,50 @@ const Dashboard: React.FC = () => {
|
|||
title: translate('::App.DeveloperKit.Dashboard.Flow.CreateEntity'),
|
||||
description: translate('::App.DeveloperKit.Dashboard.Flow.CreateEntity.Desc'),
|
||||
icon: FaDatabase,
|
||||
color: "bg-blue-600",
|
||||
href: ROUTES_ENUM.protected.saas.developerKitEntitiesNew,
|
||||
status: "ready",
|
||||
color: 'bg-blue-600',
|
||||
href: ROUTES_ENUM.protected.saas.developerKit.entitiesNew,
|
||||
status: 'ready',
|
||||
},
|
||||
{
|
||||
step: 2,
|
||||
title: translate('::App.DeveloperKit.Dashboard.Flow.GenerateMigration'),
|
||||
description: translate('::App.DeveloperKit.Dashboard.Flow.GenerateMigration.Desc'),
|
||||
icon: FaBolt,
|
||||
color: "bg-yellow-600",
|
||||
href: ROUTES_ENUM.protected.saas.developerKitMigrations,
|
||||
status: entities.some((e) => e.migrationStatus === "pending")
|
||||
? "action-needed"
|
||||
: "ready",
|
||||
color: 'bg-yellow-600',
|
||||
href: ROUTES_ENUM.protected.saas.developerKit.migrations,
|
||||
status: entities.some((e) => e.migrationStatus === 'pending') ? 'action-needed' : 'ready',
|
||||
},
|
||||
{
|
||||
step: 3,
|
||||
title: translate('::App.DeveloperKit.Dashboard.Flow.ApplyMigration'),
|
||||
description: translate('::App.DeveloperKit.Dashboard.Flow.ApplyMigration.Desc'),
|
||||
icon: FaCheckCircle,
|
||||
color: "bg-green-600",
|
||||
href: ROUTES_ENUM.protected.saas.developerKitMigrations,
|
||||
status: migrations.some((m) => m.status === "pending")
|
||||
? "action-needed"
|
||||
: "ready",
|
||||
color: 'bg-green-600',
|
||||
href: ROUTES_ENUM.protected.saas.developerKit.migrations,
|
||||
status: migrations.some((m) => m.status === 'pending') ? 'action-needed' : 'ready',
|
||||
},
|
||||
{
|
||||
step: 4,
|
||||
title: translate('::App.DeveloperKit.Dashboard.Flow.GenerateAPI'),
|
||||
description: translate('::App.DeveloperKit.Dashboard.Flow.GenerateAPI.Desc'),
|
||||
icon: FaServer,
|
||||
color: "bg-emerald-600",
|
||||
href: ROUTES_ENUM.protected.saas.developerKitEndpoints,
|
||||
status: "ready",
|
||||
color: 'bg-emerald-600',
|
||||
href: ROUTES_ENUM.protected.saas.developerKit.endpoints,
|
||||
status: 'ready',
|
||||
},
|
||||
{
|
||||
step: 5,
|
||||
title: translate('::App.DeveloperKit.Dashboard.Flow.BuildComponent'),
|
||||
description: translate('::App.DeveloperKit.Dashboard.Flow.BuildComponent.Desc'),
|
||||
icon: FaPuzzlePiece,
|
||||
color: "bg-purple-600",
|
||||
href: ROUTES_ENUM.protected.saas.developerKitComponentsNew,
|
||||
status: "ready",
|
||||
color: 'bg-purple-600',
|
||||
href: ROUTES_ENUM.protected.saas.developerKit.componentsNew,
|
||||
status: 'ready',
|
||||
},
|
||||
];
|
||||
]
|
||||
|
||||
const recentEntities = entities.slice(0, 3);
|
||||
const recentMigrations = migrations.slice(0, 3);
|
||||
const recentEntities = entities.slice(0, 3)
|
||||
const recentMigrations = migrations.slice(0, 3)
|
||||
const recentEndpoints = [
|
||||
...generatedEndpoints.map((e) => ({
|
||||
id: e.id,
|
||||
|
|
@ -130,28 +126,36 @@ const Dashboard: React.FC = () => {
|
|||
lastModificationTime: e.lastModificationTime,
|
||||
creationTime: e.creationTime,
|
||||
})),
|
||||
].slice(0, 3);
|
||||
].slice(0, 3)
|
||||
|
||||
const systemHealth = [
|
||||
{ name: translate('::App.DeveloperKit.Dashboard.SystemHealth.Frontend'), status: translate('::App.DeveloperKit.Dashboard.SystemHealth.Healthy'), icon: FaCode },
|
||||
{
|
||||
name: translate('::App.DeveloperKit.Dashboard.SystemHealth.Frontend'),
|
||||
status: translate('::App.DeveloperKit.Dashboard.SystemHealth.Healthy'),
|
||||
icon: FaCode,
|
||||
},
|
||||
{
|
||||
name: translate('::App.DeveloperKit.Dashboard.SystemHealth.Backend'),
|
||||
status: isOnline ? translate('::App.DeveloperKit.Dashboard.SystemHealth.Healthy') : translate('::App.DeveloperKit.Dashboard.SystemHealth.Offline'),
|
||||
status: isOnline
|
||||
? translate('::App.DeveloperKit.Dashboard.SystemHealth.Healthy')
|
||||
: translate('::App.DeveloperKit.Dashboard.SystemHealth.Offline'),
|
||||
icon: FaServer,
|
||||
},
|
||||
{
|
||||
name: translate('::App.DeveloperKit.Dashboard.SystemHealth.Database'),
|
||||
status: isOnline ? translate('::App.DeveloperKit.Dashboard.SystemHealth.Healthy') : translate('::App.DeveloperKit.Dashboard.SystemHealth.Unknown'),
|
||||
status: isOnline
|
||||
? translate('::App.DeveloperKit.Dashboard.SystemHealth.Healthy')
|
||||
: translate('::App.DeveloperKit.Dashboard.SystemHealth.Unknown'),
|
||||
icon: FaDatabase,
|
||||
},
|
||||
{
|
||||
name: translate('::App.DeveloperKit.Dashboard.SystemHealth.Migrations'),
|
||||
status: migrations.some((m) => m.status === "failed")
|
||||
status: migrations.some((m) => m.status === 'failed')
|
||||
? translate('::App.DeveloperKit.Dashboard.SystemHealth.Warning')
|
||||
: translate('::App.DeveloperKit.Dashboard.SystemHealth.Healthy'),
|
||||
icon: FaBolt,
|
||||
},
|
||||
];
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
|
|
@ -161,25 +165,21 @@ const Dashboard: React.FC = () => {
|
|||
<h1 className="text-3xl font-bold text-slate-900 mb-2">
|
||||
{translate('::App.DeveloperKit.Dashboard.Title')}
|
||||
</h1>
|
||||
<p className="text-slate-600">
|
||||
{translate('::App.DeveloperKit.Dashboard.Description')}
|
||||
</p>
|
||||
<p className="text-slate-600">{translate('::App.DeveloperKit.Dashboard.Description')}</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<button
|
||||
onClick={recheckHealth}
|
||||
className={`flex items-center gap-2 px-3 py-1 rounded-full text-sm font-medium transition-colors duration-200 ${
|
||||
isOnline
|
||||
? "bg-green-100 text-green-700 hover:bg-green-200"
|
||||
: "bg-red-100 text-red-700 hover:bg-red-200"
|
||||
? 'bg-green-100 text-green-700 hover:bg-green-200'
|
||||
: 'bg-red-100 text-red-700 hover:bg-red-200'
|
||||
}`}
|
||||
title={`Son kontrol: ${lastCheck.toLocaleTimeString()}`}
|
||||
>
|
||||
<div
|
||||
className={`w-2 h-2 rounded-full ${
|
||||
isOnline
|
||||
? "bg-green-500 animate-pulse"
|
||||
: "bg-red-500 animate-pulse"
|
||||
isOnline ? 'bg-green-500 animate-pulse' : 'bg-red-500 animate-pulse'
|
||||
}`}
|
||||
/>
|
||||
{isOnline ? (
|
||||
|
|
@ -200,7 +200,7 @@ const Dashboard: React.FC = () => {
|
|||
{/* Stats Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
{stats.map((stat) => {
|
||||
const Icon = stat.icon;
|
||||
const Icon = stat.icon
|
||||
return (
|
||||
<Link
|
||||
key={stat.name}
|
||||
|
|
@ -216,18 +216,14 @@ const Dashboard: React.FC = () => {
|
|||
<FaArrowRight className="w-4 h-4 text-slate-400 group-hover:text-slate-600 transition-colors" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-medium text-slate-600">
|
||||
{stat.name}
|
||||
</p>
|
||||
<p className="text-sm font-medium text-slate-600">{stat.name}</p>
|
||||
<p className="text-2xl font-bold text-slate-900 mt-1">
|
||||
{stat.value}
|
||||
<span className="text-sm font-normal text-slate-500 ml-1">
|
||||
/ {stat.total}
|
||||
</span>
|
||||
<span className="text-sm font-normal text-slate-500 ml-1">/ {stat.total}</span>
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
|
|
@ -241,7 +237,7 @@ const Dashboard: React.FC = () => {
|
|||
</div>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-5 gap-6">
|
||||
{developmentFlow.map((flow, index) => {
|
||||
const Icon = flow.icon;
|
||||
const Icon = flow.icon
|
||||
return (
|
||||
<Link key={flow.step} to={flow.href} className="group relative">
|
||||
<div
|
||||
|
|
@ -258,7 +254,7 @@ const Dashboard: React.FC = () => {
|
|||
<h3 className="font-semibold text-lg mb-2 text-white">{flow.title}</h3>
|
||||
<p className="text-sm opacity-90">{flow.description}</p>
|
||||
|
||||
{flow.status === "action-needed" && (
|
||||
{flow.status === 'action-needed' && (
|
||||
<div className="absolute -top-2 -right-2">
|
||||
<div className="bg-red-500 text-white rounded-full w-6 h-6 flex items-center justify-center">
|
||||
<FaExclamationCircle className="w-4 h-4" />
|
||||
|
|
@ -273,7 +269,7 @@ const Dashboard: React.FC = () => {
|
|||
</div>
|
||||
)}
|
||||
</Link>
|
||||
);
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -284,12 +280,12 @@ const Dashboard: React.FC = () => {
|
|||
<div className="flex items-center gap-2 mb-4">
|
||||
<FaCog className="w-5 h-5 text-green-500" />
|
||||
<h3 className="text-lg font-semibold text-slate-900">
|
||||
{translate('::App.DeveloperKit.Dashboard.SystemHealth.Title') }
|
||||
{translate('::App.DeveloperKit.Dashboard.SystemHealth.Title')}
|
||||
</h3>
|
||||
</div>
|
||||
<div className="space-y-3">
|
||||
{systemHealth.map((system) => {
|
||||
const Icon = system.icon;
|
||||
const Icon = system.icon
|
||||
return (
|
||||
<div
|
||||
key={system.name}
|
||||
|
|
@ -297,38 +293,36 @@ const Dashboard: React.FC = () => {
|
|||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<Icon className="w-4 h-4 text-slate-600" />
|
||||
<span className="font-medium text-slate-900">
|
||||
{system.name}
|
||||
</span>
|
||||
<span className="font-medium text-slate-900">{system.name}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div
|
||||
className={`w-2 h-2 rounded-full ${
|
||||
system.status === "healthy"
|
||||
? "bg-green-500"
|
||||
: system.status === "warning"
|
||||
? "bg-yellow-500"
|
||||
: system.status === "offline"
|
||||
? "bg-red-500"
|
||||
: "bg-gray-500"
|
||||
system.status === 'healthy'
|
||||
? 'bg-green-500'
|
||||
: system.status === 'warning'
|
||||
? 'bg-yellow-500'
|
||||
: system.status === 'offline'
|
||||
? 'bg-red-500'
|
||||
: 'bg-gray-500'
|
||||
}`}
|
||||
/>
|
||||
<span
|
||||
className={`text-sm capitalize ${
|
||||
system.status === "healthy"
|
||||
? "text-green-600"
|
||||
: system.status === "warning"
|
||||
? "text-yellow-600"
|
||||
: system.status === "offline"
|
||||
? "text-red-600"
|
||||
: "text-gray-600"
|
||||
system.status === 'healthy'
|
||||
? 'text-green-600'
|
||||
: system.status === 'warning'
|
||||
? 'text-yellow-600'
|
||||
: system.status === 'offline'
|
||||
? 'text-red-600'
|
||||
: 'text-gray-600'
|
||||
}`}
|
||||
>
|
||||
{system.status === "offline" ? "Offline" : system.status}
|
||||
{system.status === 'offline' ? 'Offline' : system.status}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -340,7 +334,7 @@ const Dashboard: React.FC = () => {
|
|||
{translate('::App.DeveloperKit.Dashboard.RecentEntities.Title')}
|
||||
</h3>
|
||||
<Link
|
||||
to={ROUTES_ENUM.protected.saas.developerKitEntities}
|
||||
to={ROUTES_ENUM.protected.saas.developerKit.entities}
|
||||
className="text-blue-600 hover:text-blue-700 text-sm font-medium"
|
||||
>
|
||||
{translate('::App.DeveloperKit.Dashboard.ViewAll')}
|
||||
|
|
@ -354,9 +348,7 @@ const Dashboard: React.FC = () => {
|
|||
className="flex items-center justify-between p-3 bg-slate-50 rounded-lg hover:bg-slate-100 transition-colors"
|
||||
>
|
||||
<div>
|
||||
<p className="font-medium text-slate-900">
|
||||
{entity.displayName}
|
||||
</p>
|
||||
<p className="font-medium text-slate-900">{entity.displayName}</p>
|
||||
<p className="text-sm text-slate-500">
|
||||
{entity.fields.length} fields • {entity.migrationStatus}
|
||||
</p>
|
||||
|
|
@ -364,15 +356,18 @@ const Dashboard: React.FC = () => {
|
|||
<div className="flex items-center gap-2">
|
||||
<div
|
||||
className={`w-2 h-2 rounded-full ${
|
||||
entity.migrationStatus === "applied"
|
||||
? "bg-green-500"
|
||||
: entity.migrationStatus === "pending"
|
||||
? "bg-yellow-500"
|
||||
: "bg-red-500"
|
||||
entity.migrationStatus === 'applied'
|
||||
? 'bg-green-500'
|
||||
: entity.migrationStatus === 'pending'
|
||||
? 'bg-yellow-500'
|
||||
: 'bg-red-500'
|
||||
}`}
|
||||
/>
|
||||
<Link
|
||||
to={ROUTES_ENUM.protected.saas.developerKitEntitiesEdit.replace(':id', entity.id)}
|
||||
to={ROUTES_ENUM.protected.saas.developerKit.entitiesEdit.replace(
|
||||
':id',
|
||||
entity.id,
|
||||
)}
|
||||
className="text-blue-600 hover:text-blue-700"
|
||||
>
|
||||
<FaDatabase className="w-4 h-4" />
|
||||
|
|
@ -383,9 +378,11 @@ const Dashboard: React.FC = () => {
|
|||
) : (
|
||||
<div className="text-center py-8">
|
||||
<FaDatabase className="w-12 h-12 text-slate-300 mx-auto mb-2" />
|
||||
<p className="text-slate-500 mb-2">{translate('::App.DeveloperKit.Dashboard.Empty.Entity')}</p>
|
||||
<p className="text-slate-500 mb-2">
|
||||
{translate('::App.DeveloperKit.Dashboard.Empty.Entity')}
|
||||
</p>
|
||||
<Link
|
||||
to={ROUTES_ENUM.protected.saas.developerKitEntitiesNew}
|
||||
to={ROUTES_ENUM.protected.saas.developerKit.entitiesNew}
|
||||
className="text-blue-600 hover:text-blue-700 text-sm font-medium"
|
||||
>
|
||||
Create your first entity
|
||||
|
|
@ -402,7 +399,7 @@ const Dashboard: React.FC = () => {
|
|||
{translate('::App.DeveloperKit.Dashboard.RecentMigrations.Title')}
|
||||
</h3>
|
||||
<Link
|
||||
to={ROUTES_ENUM.protected.saas.developerKitMigrations}
|
||||
to={ROUTES_ENUM.protected.saas.developerKit.migrations}
|
||||
className="text-yellow-600 hover:text-yellow-700 text-sm font-medium"
|
||||
>
|
||||
{translate('::App.DeveloperKit.Dashboard.ViewAll')}
|
||||
|
|
@ -416,26 +413,23 @@ const Dashboard: React.FC = () => {
|
|||
className="flex items-center justify-between p-3 bg-slate-50 rounded-lg hover:bg-slate-100 transition-colors"
|
||||
>
|
||||
<div>
|
||||
<p className="font-medium text-slate-900">
|
||||
{migration.entityName}
|
||||
</p>
|
||||
<p className="font-medium text-slate-900">{migration.entityName}</p>
|
||||
<p className="text-sm text-slate-500">
|
||||
{migration.status} •{" "}
|
||||
{new Date(migration.creationTime).toLocaleDateString()}
|
||||
{migration.status} • {new Date(migration.creationTime).toLocaleDateString()}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div
|
||||
className={`w-2 h-2 rounded-full ${
|
||||
migration.status === "applied"
|
||||
? "bg-green-500"
|
||||
: migration.status === "pending"
|
||||
? "bg-yellow-500"
|
||||
: "bg-red-500"
|
||||
migration.status === 'applied'
|
||||
? 'bg-green-500'
|
||||
: migration.status === 'pending'
|
||||
? 'bg-yellow-500'
|
||||
: 'bg-red-500'
|
||||
}`}
|
||||
/>
|
||||
<Link
|
||||
to={ROUTES_ENUM.protected.saas.developerKitMigrations}
|
||||
to={ROUTES_ENUM.protected.saas.developerKit.migrations}
|
||||
className="text-yellow-600 hover:text-yellow-700"
|
||||
>
|
||||
<FaBolt className="w-4 h-4" />
|
||||
|
|
@ -446,9 +440,11 @@ const Dashboard: React.FC = () => {
|
|||
) : (
|
||||
<div className="text-center py-8">
|
||||
<FaBolt className="w-12 h-12 text-slate-300 mx-auto mb-2" />
|
||||
<p className="text-slate-500 mb-2">{translate('::App.DeveloperKit.Dashboard.Empty.Migration')}</p>
|
||||
<p className="text-slate-500 mb-2">
|
||||
{translate('::App.DeveloperKit.Dashboard.Empty.Migration')}
|
||||
</p>
|
||||
<Link
|
||||
to={ROUTES_ENUM.protected.saas.developerKitEntitiesNew}
|
||||
to={ROUTES_ENUM.protected.saas.developerKit.entitiesNew}
|
||||
className="text-yellow-600 hover:text-yellow-700 text-sm font-medium"
|
||||
>
|
||||
{translate('::App.DeveloperKit.Dashboard.Action.GenerateMigrations')}
|
||||
|
|
@ -465,7 +461,7 @@ const Dashboard: React.FC = () => {
|
|||
{translate('::App.DeveloperKit.Dashboard.RecentEndpoints.Title')}
|
||||
</h3>
|
||||
<Link
|
||||
to={ROUTES_ENUM.protected.saas.developerKitEndpoints}
|
||||
to={ROUTES_ENUM.protected.saas.developerKit.endpoints}
|
||||
className="text-emerald-600 hover:text-emerald-700 text-sm font-medium"
|
||||
>
|
||||
{translate('::App.DeveloperKit.Dashboard.ViewAll')}
|
||||
|
|
@ -482,33 +478,28 @@ const Dashboard: React.FC = () => {
|
|||
<div className="flex items-center gap-2 mb-1">
|
||||
<span
|
||||
className={`px-2 py-0.5 text-xs font-medium rounded ${
|
||||
endpoint.method === "GET"
|
||||
? "bg-blue-100 text-blue-800"
|
||||
: endpoint.method === "POST"
|
||||
? "bg-green-100 text-green-800"
|
||||
: endpoint.method === "PUT"
|
||||
? "bg-yellow-100 text-yellow-800"
|
||||
: "bg-red-100 text-red-800"
|
||||
endpoint.method === 'GET'
|
||||
? 'bg-blue-100 text-blue-800'
|
||||
: endpoint.method === 'POST'
|
||||
? 'bg-green-100 text-green-800'
|
||||
: endpoint.method === 'PUT'
|
||||
? 'bg-yellow-100 text-yellow-800'
|
||||
: 'bg-red-100 text-red-800'
|
||||
}`}
|
||||
>
|
||||
{endpoint.method}
|
||||
</span>
|
||||
<p className="font-medium text-slate-900 text-sm">
|
||||
{endpoint.name}
|
||||
</p>
|
||||
<p className="font-medium text-slate-900 text-sm">{endpoint.name}</p>
|
||||
</div>
|
||||
<p className="text-xs text-slate-500">{endpoint.path}</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div
|
||||
className={`w-2 h-2 rounded-full ${
|
||||
endpoint.isActive ? "bg-green-500" : "bg-slate-300"
|
||||
endpoint.isActive ? 'bg-green-500' : 'bg-slate-300'
|
||||
}`}
|
||||
/>
|
||||
<Link
|
||||
to="/docs"
|
||||
className="text-emerald-600 hover:text-emerald-700"
|
||||
>
|
||||
<Link to="/docs" className="text-emerald-600 hover:text-emerald-700">
|
||||
<FaServer className="w-4 h-4" />
|
||||
</Link>
|
||||
</div>
|
||||
|
|
@ -517,9 +508,11 @@ const Dashboard: React.FC = () => {
|
|||
) : (
|
||||
<div className="text-center py-8">
|
||||
<FaServer className="w-12 h-12 text-slate-300 mx-auto mb-2" />
|
||||
<p className="text-slate-500 mb-2">{translate('::App.DeveloperKit.Dashboard.Empty.Endpoint')}</p>
|
||||
<p className="text-slate-500 mb-2">
|
||||
{translate('::App.DeveloperKit.Dashboard.Empty.Endpoint')}
|
||||
</p>
|
||||
<Link
|
||||
to={ROUTES_ENUM.protected.saas.developerKitEndpointsNew}
|
||||
to={ROUTES_ENUM.protected.saas.developerKit.endpointsNew}
|
||||
className="text-emerald-600 hover:text-emerald-700 text-sm font-medium"
|
||||
>
|
||||
{translate('::App.DeveloperKit.Dashboard.Action.CreateEntity')}
|
||||
|
|
@ -530,7 +523,7 @@ const Dashboard: React.FC = () => {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default Dashboard;
|
||||
export default Dashboard
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import {
|
|||
FaPlus,
|
||||
FaTrashAlt,
|
||||
FaDatabase,
|
||||
FaQuestionCircle
|
||||
} from 'react-icons/fa';
|
||||
FaQuestionCircle,
|
||||
} from 'react-icons/fa'
|
||||
import { CreateUpdateCustomEntityFieldDto, CustomEntityField } from '@/proxy/developerKit/models'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
|
@ -150,7 +150,7 @@ const EntityEditor: React.FC = () => {
|
|||
addEntity(entityData)
|
||||
}
|
||||
|
||||
navigate(ROUTES_ENUM.protected.saas.developerKitEntities)
|
||||
navigate(ROUTES_ENUM.protected.saas.developerKit.entities)
|
||||
} catch (error) {
|
||||
console.error('Error saving entity:', error)
|
||||
alert('Failed to save entity. Please try again.')
|
||||
|
|
@ -176,7 +176,7 @@ const EntityEditor: React.FC = () => {
|
|||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<button
|
||||
onClick={() => navigate(ROUTES_ENUM.protected.saas.developerKitEntities)}
|
||||
onClick={() => navigate(ROUTES_ENUM.protected.saas.developerKit.entities)}
|
||||
className="flex items-center gap-2 text-slate-600 hover:text-slate-900 transition-colors"
|
||||
>
|
||||
<FaArrowLeft className="w-4 h-4" />
|
||||
|
|
@ -202,7 +202,9 @@ const EntityEditor: React.FC = () => {
|
|||
<div className="absolute -top-1 right-4 w-2 h-2 bg-slate-900 rotate-45"></div>
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<FaDatabase className="w-4 h-4 text-blue-400" />
|
||||
<h4 className="font-semibold text-blue-200">{translate('::App.DeveloperKit.EntityEditor.Tooltip.Title')}</h4>
|
||||
<h4 className="font-semibold text-blue-200">
|
||||
{translate('::App.DeveloperKit.EntityEditor.Tooltip.Title')}
|
||||
</h4>
|
||||
</div>
|
||||
<p className="text-slate-300 leading-relaxed">
|
||||
{translate('::App.DeveloperKit.EntityEditor.Tooltip.Content')}
|
||||
|
|
@ -216,7 +218,9 @@ const EntityEditor: React.FC = () => {
|
|||
className="flex items-center gap-2 bg-emerald-600 text-white px-4 py-2 rounded-lg hover:bg-emerald-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed shadow-sm"
|
||||
>
|
||||
<FaSave className="w-4 h-4" />
|
||||
{isSaving ? translate('::App.DeveloperKit.EntityEditor.Saving') : translate('::App.DeveloperKit.EntityEditor.Save')}
|
||||
{isSaving
|
||||
? translate('::App.DeveloperKit.EntityEditor.Saving')
|
||||
: translate('::App.DeveloperKit.EntityEditor.Save')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -224,10 +228,14 @@ const EntityEditor: React.FC = () => {
|
|||
|
||||
{/* Entity Basic Info */}
|
||||
<div className="bg-white rounded-lg border border-slate-200 p-6 mb-6 shadow-sm">
|
||||
<h2 className="text-lg font-semibold text-slate-900 mb-4">{translate('::App.DeveloperKit.EntityEditor.BasicInfo')}</h2>
|
||||
<h2 className="text-lg font-semibold text-slate-900 mb-4">
|
||||
{translate('::App.DeveloperKit.EntityEditor.BasicInfo')}
|
||||
</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-1">{translate('::App.DeveloperKit.EntityEditor.EntityName')}</label>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-1">
|
||||
{translate('::App.DeveloperKit.EntityEditor.EntityName')}
|
||||
</label>
|
||||
<input
|
||||
autoFocus
|
||||
type="text"
|
||||
|
|
@ -266,7 +274,9 @@ const EntityEditor: React.FC = () => {
|
|||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-1">{translate('::App.DeveloperKit.EntityEditor.TableName')} *</label>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-1">
|
||||
{translate('::App.DeveloperKit.EntityEditor.TableName')} *
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={tableName}
|
||||
|
|
@ -284,7 +294,9 @@ const EntityEditor: React.FC = () => {
|
|||
)}
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<label className="block text-sm font-medium text-slate-700 mb-1">{translate('::App.DeveloperKit.EntityEditor.Description')}</label>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-1">
|
||||
{translate('::App.DeveloperKit.EntityEditor.Description')}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={description}
|
||||
|
|
@ -297,10 +309,14 @@ const EntityEditor: React.FC = () => {
|
|||
|
||||
{isEditing && (
|
||||
<div className="mb-4 p-4 bg-slate-50 rounded-lg border border-slate-200">
|
||||
<h3 className="text-sm font-medium text-slate-700 mb-3">{translate('::App.DeveloperKit.EntityEditor.Status')}</h3>
|
||||
<h3 className="text-sm font-medium text-slate-700 mb-3">
|
||||
{translate('::App.DeveloperKit.EntityEditor.Status')}
|
||||
</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-slate-600">{translate('::App.DeveloperKit.EntityEditor.Status.Migration')}</span>
|
||||
<span className="text-sm text-slate-600">
|
||||
{translate('::App.DeveloperKit.EntityEditor.Status.Migration')}
|
||||
</span>
|
||||
<span
|
||||
className={`text-xs px-2 py-1 rounded-full ${
|
||||
getEntity(id!)?.migrationStatus === 'applied'
|
||||
|
|
@ -314,7 +330,9 @@ const EntityEditor: React.FC = () => {
|
|||
</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-slate-600">{translate('::App.DeveloperKit.EntityEditor.Status.Endpoint')}</span>
|
||||
<span className="text-sm text-slate-600">
|
||||
{translate('::App.DeveloperKit.EntityEditor.Status.Endpoint')}
|
||||
</span>
|
||||
<span
|
||||
className={`text-xs px-2 py-1 rounded-full ${
|
||||
getEntity(id!)?.endpointStatus === 'applied'
|
||||
|
|
@ -338,7 +356,9 @@ const EntityEditor: React.FC = () => {
|
|||
onChange={(e) => setIsActive(e.target.checked)}
|
||||
className="rounded border-slate-300 text-emerald-600 focus:ring-emerald-500"
|
||||
/>
|
||||
<span className="text-sm font-medium text-slate-700">{translate('::App.DeveloperKit.EntityEditor.Active')}</span>
|
||||
<span className="text-sm font-medium text-slate-700">
|
||||
{translate('::App.DeveloperKit.EntityEditor.Active')}
|
||||
</span>
|
||||
</label>
|
||||
<label className="flex items-center gap-2">
|
||||
<input
|
||||
|
|
@ -372,7 +392,9 @@ const EntityEditor: React.FC = () => {
|
|||
{/* Entity Fields */}
|
||||
<div className="bg-white rounded-lg border border-slate-200 p-6 shadow-sm">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h2 className="text-lg font-semibold text-slate-900">{translate('::App.DeveloperKit.EntityEditor.Fields')}</h2>
|
||||
<h2 className="text-lg font-semibold text-slate-900">
|
||||
{translate('::App.DeveloperKit.EntityEditor.Fields')}
|
||||
</h2>
|
||||
<button
|
||||
onClick={addField}
|
||||
className="flex items-center gap-2 bg-blue-600 text-white px-3 py-2 rounded-lg hover:bg-blue-700 transition-colors text-sm"
|
||||
|
|
@ -402,7 +424,9 @@ const EntityEditor: React.FC = () => {
|
|||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-1">{translate('::App.DeveloperKit.EntityEditor.Type')} *</label>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-1">
|
||||
{translate('::App.DeveloperKit.EntityEditor.Type')} *
|
||||
</label>
|
||||
<select
|
||||
value={field.type}
|
||||
onChange={(e) =>
|
||||
|
|
@ -475,7 +499,9 @@ const EntityEditor: React.FC = () => {
|
|||
}
|
||||
className="rounded border-slate-300 text-blue-600 focus:ring-blue-500"
|
||||
/>
|
||||
<span className="text-sm font-medium text-slate-700">{translate('::App.DeveloperKit.EntityEditor.Required')}</span>
|
||||
<span className="text-sm font-medium text-slate-700">
|
||||
{translate('::App.DeveloperKit.EntityEditor.Required')}
|
||||
</span>
|
||||
</label>
|
||||
<label className="flex items-center gap-2">
|
||||
<input
|
||||
|
|
@ -484,7 +510,9 @@ const EntityEditor: React.FC = () => {
|
|||
onChange={(e) => updateField(field.id, { isUnique: e.target.checked })}
|
||||
className="rounded border-slate-300 text-blue-600 focus:ring-blue-500"
|
||||
/>
|
||||
<span className="text-sm font-medium text-slate-700">{translate('::App.DeveloperKit.EntityEditor.Unique')}</span>
|
||||
<span className="text-sm font-medium text-slate-700">
|
||||
{translate('::App.DeveloperKit.EntityEditor.Unique')}
|
||||
</span>
|
||||
</label>
|
||||
<button
|
||||
onClick={() => removeField(field.id)}
|
||||
|
|
@ -503,7 +531,9 @@ const EntityEditor: React.FC = () => {
|
|||
<div className="text-center py-8 text-slate-500">
|
||||
<FaDatabase className="w-12 h-12 mx-auto mb-2 text-slate-300" />
|
||||
<p>{translate('::App.DeveloperKit.EntityEditor.NoFields')}</p>
|
||||
<p className="text-sm">{translate('::App.DeveloperKit.EntityEditor.NoFieldsDescription')}</p>
|
||||
<p className="text-sm">
|
||||
{translate('::App.DeveloperKit.EntityEditor.NoFieldsDescription')}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useEntities } from '../../contexts/EntityContext';
|
||||
import React, { useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { useEntities } from '../../contexts/EntityContext'
|
||||
import {
|
||||
FaPlus,
|
||||
FaSearch,
|
||||
|
|
@ -13,66 +13,72 @@ import {
|
|||
FaDatabase,
|
||||
FaCheckCircle,
|
||||
FaTable,
|
||||
FaBolt
|
||||
} from 'react-icons/fa';
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant';
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization';
|
||||
FaBolt,
|
||||
} from 'react-icons/fa'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
||||
const EntityManager: React.FC = () => {
|
||||
const { entities, deleteEntity, toggleEntityActiveStatus } = useEntities();
|
||||
const [searchTerm, setSearchTerm] = useState('');
|
||||
const [filterActive, setFilterActive] = useState<'all' | 'active' | 'inactive'>('all');
|
||||
const { entities, deleteEntity, toggleEntityActiveStatus } = useEntities()
|
||||
const [searchTerm, setSearchTerm] = useState('')
|
||||
const [filterActive, setFilterActive] = useState<'all' | 'active' | 'inactive'>('all')
|
||||
const { translate } = useLocalization()
|
||||
|
||||
const filteredEntities = entities.filter(entity => {
|
||||
const matchesSearch = entity.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
entity.displayName.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
(entity.description || '').toLowerCase().includes(searchTerm.toLowerCase());
|
||||
|
||||
const matchesActiveFilter = filterActive === 'all' ||
|
||||
(filterActive === 'active' && entity.isActive) ||
|
||||
(filterActive === 'inactive' && !entity.isActive);
|
||||
const filteredEntities = entities.filter((entity) => {
|
||||
const matchesSearch =
|
||||
entity.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
entity.displayName.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
(entity.description || '').toLowerCase().includes(searchTerm.toLowerCase())
|
||||
|
||||
return matchesSearch && matchesActiveFilter;
|
||||
});
|
||||
const matchesActiveFilter =
|
||||
filterActive === 'all' ||
|
||||
(filterActive === 'active' && entity.isActive) ||
|
||||
(filterActive === 'inactive' && !entity.isActive)
|
||||
|
||||
return matchesSearch && matchesActiveFilter
|
||||
})
|
||||
|
||||
const handleToggleActive = async (id: string) => {
|
||||
try {
|
||||
await toggleEntityActiveStatus(id);
|
||||
await toggleEntityActiveStatus(id)
|
||||
} catch (err) {
|
||||
console.error('Failed to toggle entity status:', err);
|
||||
console.error('Failed to toggle entity status:', err)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handleDelete = async (id: string, name: string) => {
|
||||
if (window.confirm(`Are you sure you want to delete the "${name}" entity?\n\nThis action will permanently remove:\n• The entity and all its fields\n• All related migrations\n• All related API endpoints\n\nThis cannot be undone.`)) {
|
||||
if (
|
||||
window.confirm(
|
||||
`Are you sure you want to delete the "${name}" entity?\n\nThis action will permanently remove:\n• The entity and all its fields\n• All related migrations\n• All related API endpoints\n\nThis cannot be undone.`,
|
||||
)
|
||||
) {
|
||||
try {
|
||||
await deleteEntity(id);
|
||||
await deleteEntity(id)
|
||||
} catch (err) {
|
||||
console.error('Failed to delete entity:', err);
|
||||
alert(translate('::App.DeveloperKit.Entity.DeleteFailed'));
|
||||
console.error('Failed to delete entity:', err)
|
||||
alert(translate('::App.DeveloperKit.Entity.DeleteFailed'))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const stats = {
|
||||
total: entities.length,
|
||||
active: entities.filter(e => e.isActive).length,
|
||||
migrationsPending: entities.filter(e => e.migrationStatus === 'pending').length,
|
||||
endpointsApplied: entities.filter(e => e.endpointStatus === 'applied').length
|
||||
};
|
||||
active: entities.filter((e) => e.isActive).length,
|
||||
migrationsPending: entities.filter((e) => e.migrationStatus === 'pending').length,
|
||||
endpointsApplied: entities.filter((e) => e.endpointStatus === 'applied').length,
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
<div className="flex items-center justify-between mb-8">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-slate-900 mb-2">{translate('::App.DeveloperKit.Entity.Title')}</h1>
|
||||
<p className="text-slate-600">
|
||||
{translate('::App.DeveloperKit.Entity.Description')}
|
||||
</p>
|
||||
<h1 className="text-3xl font-bold text-slate-900 mb-2">
|
||||
{translate('::App.DeveloperKit.Entity.Title')}
|
||||
</h1>
|
||||
<p className="text-slate-600">{translate('::App.DeveloperKit.Entity.Description')}</p>
|
||||
</div>
|
||||
<Link
|
||||
to={ROUTES_ENUM.protected.saas.developerKitEntitiesNew}
|
||||
to={ROUTES_ENUM.protected.saas.developerKit.entitiesNew}
|
||||
className="flex items-center gap-2 bg-emerald-600 text-white px-4 py-2 rounded-lg hover:bg-emerald-700 transition-colors shadow-sm hover:shadow-md"
|
||||
>
|
||||
<FaPlus className="w-4 h-4" />
|
||||
|
|
@ -85,7 +91,9 @@ const EntityManager: React.FC = () => {
|
|||
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-slate-600">{translate('::App.DeveloperKit.Entity.TotalEntities')}</p>
|
||||
<p className="text-sm font-medium text-slate-600">
|
||||
{translate('::App.DeveloperKit.Entity.TotalEntities')}
|
||||
</p>
|
||||
<p className="text-2xl font-bold text-slate-900 mt-1">{stats.total}</p>
|
||||
</div>
|
||||
<div className="bg-blue-100 text-blue-600 p-3 rounded-lg">
|
||||
|
|
@ -96,12 +104,12 @@ const EntityManager: React.FC = () => {
|
|||
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-slate-600">{translate('::App.DeveloperKit.Entity.ActiveEntities')}</p>
|
||||
<p className="text-sm font-medium text-slate-600">
|
||||
{translate('::App.DeveloperKit.Entity.ActiveEntities')}
|
||||
</p>
|
||||
<p className="text-2xl font-bold text-slate-900 mt-1">
|
||||
{stats.active}
|
||||
<span className="text-sm font-normal text-slate-500 ml-1">
|
||||
/ {stats.total}
|
||||
</span>
|
||||
<span className="text-sm font-normal text-slate-500 ml-1">/ {stats.total}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-green-100 text-green-600 p-3 rounded-lg">
|
||||
|
|
@ -112,7 +120,9 @@ const EntityManager: React.FC = () => {
|
|||
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-slate-600">{translate('::App.DeveloperKit.Entity.PendingMigrations')}</p>
|
||||
<p className="text-sm font-medium text-slate-600">
|
||||
{translate('::App.DeveloperKit.Entity.PendingMigrations')}
|
||||
</p>
|
||||
<p className="text-2xl font-bold text-slate-900 mt-1">{stats.migrationsPending}</p>
|
||||
</div>
|
||||
<div className="bg-purple-100 text-purple-600 p-3 rounded-lg">
|
||||
|
|
@ -123,7 +133,9 @@ const EntityManager: React.FC = () => {
|
|||
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-slate-600">{translate('::App.DeveloperKit.Entity.CrudEndpoints')}</p>
|
||||
<p className="text-sm font-medium text-slate-600">
|
||||
{translate('::App.DeveloperKit.Entity.CrudEndpoints')}
|
||||
</p>
|
||||
<p className="text-2xl font-bold text-slate-900 mt-1">{stats.endpointsApplied}</p>
|
||||
</div>
|
||||
<div className="bg-emerald-100 text-emerald-600 p-3 rounded-lg">
|
||||
|
|
@ -155,8 +167,12 @@ const EntityManager: React.FC = () => {
|
|||
className="px-3 py-2 border border-slate-300 rounded-lg focus:ring-2 focus:ring-emerald-500 focus:border-transparent transition-colors"
|
||||
>
|
||||
<option value="all">{translate('::App.DeveloperKit.Entity.Filter.All')}</option>
|
||||
<option value="active">{translate('::App.DeveloperKit.Entity.Filter.Active')}</option>
|
||||
<option value="inactive">{translate('::App.DeveloperKit.Entity.Filter.Inactive')}</option>
|
||||
<option value="active">
|
||||
{translate('::App.DeveloperKit.Entity.Filter.Active')}
|
||||
</option>
|
||||
<option value="inactive">
|
||||
{translate('::App.DeveloperKit.Entity.Filter.Inactive')}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -168,7 +184,10 @@ const EntityManager: React.FC = () => {
|
|||
<div className="grid grid-cols-1 xl:grid-cols-2 gap-6">
|
||||
{filteredEntities.map((entity) => {
|
||||
return (
|
||||
<div key={entity.id} className="bg-white rounded-lg border border-slate-200 shadow-sm hover:shadow-md transition-all duration-200 group">
|
||||
<div
|
||||
key={entity.id}
|
||||
className="bg-white rounded-lg border border-slate-200 shadow-sm hover:shadow-md transition-all duration-200 group"
|
||||
>
|
||||
<div className="p-6">
|
||||
<div className="flex items-start justify-between mb-4">
|
||||
<div className="flex-1">
|
||||
|
|
@ -180,25 +199,29 @@ const EntityManager: React.FC = () => {
|
|||
<h3 className="text-lg font-semibold text-slate-900">
|
||||
{entity.displayName}
|
||||
</h3>
|
||||
<p className="text-sm text-slate-500">{translate('::App.DeveloperKit.Entity.TableLabel')}: {entity.tableName}</p>
|
||||
<p className="text-sm text-slate-500">
|
||||
{translate('::App.DeveloperKit.Entity.TableLabel')}: {entity.tableName}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{entity.description && (
|
||||
<p className="text-slate-600 text-sm mb-3">
|
||||
{entity.description}
|
||||
</p>
|
||||
<p className="text-slate-600 text-sm mb-3">{entity.description}</p>
|
||||
)}
|
||||
<div className="flex items-center gap-4 text-xs text-slate-500 mb-3">
|
||||
<div className="flex items-center gap-1">
|
||||
<FaCalendarAlt className="w-3 h-3" />
|
||||
<span>
|
||||
{translate('::App.DeveloperKit.Entity.Updated')}: {entity.lastModificationTime ? new Date(entity.lastModificationTime).toLocaleDateString() : 'Never'}
|
||||
{translate('::App.DeveloperKit.Entity.Updated')}:{' '}
|
||||
{entity.lastModificationTime
|
||||
? new Date(entity.lastModificationTime).toLocaleDateString()
|
||||
: 'Never'}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<FaDatabase className="w-3 h-3" />
|
||||
<span>{entity.fields.length} {translate('::App.DeveloperKit.Entity.Fields')}</span>
|
||||
<span>
|
||||
{entity.fields.length} {translate('::App.DeveloperKit.Entity.Fields')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -207,17 +230,25 @@ const EntityManager: React.FC = () => {
|
|||
{/* Entity Fields Preview */}
|
||||
<div className="mb-4">
|
||||
<div className="bg-slate-50 rounded-lg p-3">
|
||||
<h4 className="text-sm font-medium text-slate-700 mb-2">{translate('::App.DeveloperKit.Entity.FieldsLabel')}:</h4>
|
||||
<h4 className="text-sm font-medium text-slate-700 mb-2">
|
||||
{translate('::App.DeveloperKit.Entity.FieldsLabel')}:
|
||||
</h4>
|
||||
<div className="grid grid-cols-2 gap-2 text-xs">
|
||||
{entity.fields.slice(0, 4).map(field => (
|
||||
{entity.fields.slice(0, 4).map((field) => (
|
||||
<div key={field.id} className="flex items-center gap-2">
|
||||
<span className={`px-2 py-1 rounded text-xs font-medium ${
|
||||
field.type === 'string' ? 'bg-blue-100 text-blue-700' :
|
||||
field.type === 'number' || field.type === 'decimal' ? 'bg-green-100 text-green-700' :
|
||||
field.type === 'boolean' ? 'bg-purple-100 text-purple-700' :
|
||||
field.type === 'date' ? 'bg-orange-100 text-orange-700' :
|
||||
'bg-slate-100 text-slate-700'
|
||||
}`}>
|
||||
<span
|
||||
className={`px-2 py-1 rounded text-xs font-medium ${
|
||||
field.type === 'string'
|
||||
? 'bg-blue-100 text-blue-700'
|
||||
: field.type === 'number' || field.type === 'decimal'
|
||||
? 'bg-green-100 text-green-700'
|
||||
: field.type === 'boolean'
|
||||
? 'bg-purple-100 text-purple-700'
|
||||
: field.type === 'date'
|
||||
? 'bg-orange-100 text-orange-700'
|
||||
: 'bg-slate-100 text-slate-700'
|
||||
}`}
|
||||
>
|
||||
{field.type}
|
||||
</span>
|
||||
<span className="text-slate-600">{field.name}</span>
|
||||
|
|
@ -226,7 +257,8 @@ const EntityManager: React.FC = () => {
|
|||
))}
|
||||
{entity.fields.length > 4 && (
|
||||
<div className="text-slate-500 italic">
|
||||
+{entity.fields.length - 4} {translate('::App.DeveloperKit.Entity.More')}
|
||||
+{entity.fields.length - 4}{' '}
|
||||
{translate('::App.DeveloperKit.Entity.More')}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -236,22 +268,34 @@ const EntityManager: React.FC = () => {
|
|||
{/* Migration and Endpoint Status */}
|
||||
<div className="mb-4 space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm font-medium text-slate-700">{translate('::App.DeveloperKit.Entity.MigrationStatus')}</span>
|
||||
<span className={`text-xs px-2 py-1 rounded-full ${
|
||||
entity.migrationStatus === 'applied' ? 'bg-green-100 text-green-700' :
|
||||
entity.migrationStatus === 'pending' ? 'bg-yellow-100 text-yellow-700' :
|
||||
'bg-red-100 text-red-700'
|
||||
}`}>
|
||||
<span className="text-sm font-medium text-slate-700">
|
||||
{translate('::App.DeveloperKit.Entity.MigrationStatus')}
|
||||
</span>
|
||||
<span
|
||||
className={`text-xs px-2 py-1 rounded-full ${
|
||||
entity.migrationStatus === 'applied'
|
||||
? 'bg-green-100 text-green-700'
|
||||
: entity.migrationStatus === 'pending'
|
||||
? 'bg-yellow-100 text-yellow-700'
|
||||
: 'bg-red-100 text-red-700'
|
||||
}`}
|
||||
>
|
||||
{entity.migrationStatus}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm font-medium text-slate-700">{translate('::App.DeveloperKit.Entity.EndpointStatus')}</span>
|
||||
<span className={`text-xs px-2 py-1 rounded-full ${
|
||||
entity.endpointStatus === 'applied' ? 'bg-blue-100 text-blue-700' :
|
||||
entity.endpointStatus === 'pending' ? 'bg-orange-100 text-orange-700' :
|
||||
'bg-red-100 text-red-700'
|
||||
}`}>
|
||||
<span className="text-sm font-medium text-slate-700">
|
||||
{translate('::App.DeveloperKit.Entity.EndpointStatus')}
|
||||
</span>
|
||||
<span
|
||||
className={`text-xs px-2 py-1 rounded-full ${
|
||||
entity.endpointStatus === 'applied'
|
||||
? 'bg-blue-100 text-blue-700'
|
||||
: entity.endpointStatus === 'pending'
|
||||
? 'bg-orange-100 text-orange-700'
|
||||
: 'bg-red-100 text-red-700'
|
||||
}`}
|
||||
>
|
||||
{entity.endpointStatus}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -283,7 +327,10 @@ const EntityManager: React.FC = () => {
|
|||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<Link
|
||||
to={ROUTES_ENUM.protected.saas.developerKitEntitiesEdit.replace(':id', entity.id)}
|
||||
to={ROUTES_ENUM.protected.saas.developerKit.entitiesEdit.replace(
|
||||
':id',
|
||||
entity.id,
|
||||
)}
|
||||
className="p-2 text-slate-600 hover:text-blue-600 hover:bg-blue-50 rounded transition-colors"
|
||||
title={translate('::App.DeveloperKit.Entity.Edit')}
|
||||
>
|
||||
|
|
@ -300,7 +347,7 @@ const EntityManager: React.FC = () => {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
|
|
@ -310,15 +357,16 @@ const EntityManager: React.FC = () => {
|
|||
<FaDatabase className="w-8 h-8 text-slate-500" />
|
||||
</div>
|
||||
<h3 className="text-lg font-medium text-slate-900 mb-2">
|
||||
{searchTerm || filterActive !== 'all' ? translate('::App.DeveloperKit.Entity.NoEntitiesFound') : translate('::App.DeveloperKit.Entity.NoEntitiesYet')}
|
||||
{searchTerm || filterActive !== 'all'
|
||||
? translate('::App.DeveloperKit.Entity.NoEntitiesFound')
|
||||
: translate('::App.DeveloperKit.Entity.NoEntitiesYet')}
|
||||
</h3>
|
||||
<p className="text-slate-600 mb-6">
|
||||
{searchTerm || filterActive !== 'all'
|
||||
? translate('::App.DeveloperKit.Entity.TryAdjustingFilters')
|
||||
: translate('::App.DeveloperKit.Entity.CreateFirstEntity')
|
||||
}
|
||||
: translate('::App.DeveloperKit.Entity.CreateFirstEntity')}
|
||||
</p>
|
||||
{(!searchTerm && filterActive === 'all') && (
|
||||
{!searchTerm && filterActive === 'all' && (
|
||||
<Link
|
||||
to={ROUTES_ENUM.protected.saas.developerKitEntitiesNew}
|
||||
className="inline-flex items-center gap-2 bg-emerald-600 text-white px-4 py-2 rounded-lg hover:bg-emerald-700 transition-colors shadow-sm hover:shadow-md"
|
||||
|
|
@ -331,7 +379,7 @@ const EntityManager: React.FC = () => {
|
|||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default EntityManager;
|
||||
export default EntityManager
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ import {
|
|||
FaEye,
|
||||
FaSync,
|
||||
FaTrashAlt,
|
||||
FaPlus
|
||||
} from 'react-icons/fa';
|
||||
FaPlus,
|
||||
} from 'react-icons/fa'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
||||
|
|
@ -102,7 +102,7 @@ const MigrationManager: React.FC = () => {
|
|||
setGeneratingEndpoints(entityId)
|
||||
await generateCrudEndpoints(entityId)
|
||||
// Navigate to API Endpoints page after successful generation
|
||||
navigate(ROUTES_ENUM.protected.saas.developerKitMigrations)
|
||||
navigate(ROUTES_ENUM.protected.saas.developerKit.migrations)
|
||||
} catch (error) {
|
||||
console.error('Failed to generate CRUD endpoints:', error)
|
||||
} finally {
|
||||
|
|
@ -186,7 +186,9 @@ const MigrationManager: React.FC = () => {
|
|||
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-slate-600">{translate('::App.DeveloperKit.Migration.Total')}</p>
|
||||
<p className="text-sm font-medium text-slate-600">
|
||||
{translate('::App.DeveloperKit.Migration.Total')}
|
||||
</p>
|
||||
<p className="text-2xl font-bold text-slate-900 mt-1">{stats.total}</p>
|
||||
</div>
|
||||
<div className="bg-blue-100 text-blue-600 p-3 rounded-lg">
|
||||
|
|
@ -197,7 +199,9 @@ const MigrationManager: React.FC = () => {
|
|||
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-slate-600">{translate('::App.DeveloperKit.Migration.Pending')}</p>
|
||||
<p className="text-sm font-medium text-slate-600">
|
||||
{translate('::App.DeveloperKit.Migration.Pending')}
|
||||
</p>
|
||||
<p className="text-2xl font-bold text-slate-900 mt-1">{stats.pending}</p>
|
||||
</div>
|
||||
<div className="bg-yellow-100 text-yellow-600 p-3 rounded-lg">
|
||||
|
|
@ -208,7 +212,9 @@ const MigrationManager: React.FC = () => {
|
|||
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-slate-600">{translate('::App.DeveloperKit.Migration.Applied')}</p>
|
||||
<p className="text-sm font-medium text-slate-600">
|
||||
{translate('::App.DeveloperKit.Migration.Applied')}
|
||||
</p>
|
||||
<p className="text-2xl font-bold text-slate-900 mt-1">{stats.applied}</p>
|
||||
</div>
|
||||
<div className="bg-green-100 text-green-600 p-3 rounded-lg">
|
||||
|
|
@ -219,7 +225,9 @@ const MigrationManager: React.FC = () => {
|
|||
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-slate-600">{translate('::App.DeveloperKit.Migration.Failed')}</p>
|
||||
<p className="text-sm font-medium text-slate-600">
|
||||
{translate('::App.DeveloperKit.Migration.Failed')}
|
||||
</p>
|
||||
<p className="text-2xl font-bold text-slate-900 mt-1">{stats.failed}</p>
|
||||
</div>
|
||||
<div className="bg-red-100 text-red-600 p-3 rounded-lg">
|
||||
|
|
@ -249,14 +257,18 @@ const MigrationManager: React.FC = () => {
|
|||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h4 className="font-medium text-slate-900">{entity.displayName}</h4>
|
||||
<p className="text-sm text-slate-600">{entity.fields.length} {translate('::App.DeveloperKit.Migration.Fields')}</p>
|
||||
<p className="text-sm text-slate-600">
|
||||
{entity.fields.length} {translate('::App.DeveloperKit.Migration.Fields')}
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => handleGenerateMigration(entity.id)}
|
||||
disabled={loading}
|
||||
className="bg-yellow-600 text-white px-3 py-1 rounded text-sm hover:bg-yellow-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
{loading ? translate('::App.DeveloperKit.Migration.Generating') : translate('::App.DeveloperKit.Migration.Generate')}
|
||||
{loading
|
||||
? translate('::App.DeveloperKit.Migration.Generating')
|
||||
: translate('::App.DeveloperKit.Migration.Generate')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -334,14 +346,16 @@ const MigrationManager: React.FC = () => {
|
|||
<div className="flex items-center gap-1">
|
||||
<FaCalendarAlt className="w-3 h-3" />
|
||||
<span>
|
||||
{translate('::App.DeveloperKit.Migration.Created')} {new Date(migration.creationTime).toLocaleDateString()}
|
||||
{translate('::App.DeveloperKit.Migration.Created')}{' '}
|
||||
{new Date(migration.creationTime).toLocaleDateString()}
|
||||
</span>
|
||||
</div>
|
||||
{migration.appliedAt && (
|
||||
<div className="flex items-center gap-1">
|
||||
<FaCheckCircle className="w-3 h-3" />
|
||||
<span>
|
||||
{translate('::App.DeveloperKit.Migration.AppliedLabel')} {new Date(migration.appliedAt).toLocaleDateString()}
|
||||
{translate('::App.DeveloperKit.Migration.AppliedLabel')}{' '}
|
||||
{new Date(migration.appliedAt).toLocaleDateString()}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -367,7 +381,9 @@ const MigrationManager: React.FC = () => {
|
|||
<FaEye className="w-4 h-4" />
|
||||
{translate('::App.DeveloperKit.Migration.ViewSQL')}
|
||||
{!migration.sqlScript && (
|
||||
<span className="ml-1 text-xs text-orange-500">({translate('::App.DeveloperKit.Migration.NoSQL')})</span>
|
||||
<span className="ml-1 text-xs text-orange-500">
|
||||
({translate('::App.DeveloperKit.Migration.NoSQL')})
|
||||
</span>
|
||||
)}
|
||||
</button>
|
||||
<button
|
||||
|
|
@ -441,7 +457,9 @@ const MigrationManager: React.FC = () => {
|
|||
{/* SQL Script Preview */}
|
||||
{selectedMigration === migration.id && (
|
||||
<div className="mt-4 pt-4 border-t border-slate-200">
|
||||
<h4 className="font-medium text-slate-900 mb-2">{translate('::App.DeveloperKit.Migration.SQLScriptLabel')}</h4>
|
||||
<h4 className="font-medium text-slate-900 mb-2">
|
||||
{translate('::App.DeveloperKit.Migration.SQLScriptLabel')}
|
||||
</h4>
|
||||
{migration.sqlScript ? (
|
||||
<div className="bg-slate-900 rounded-lg p-4 overflow-x-auto">
|
||||
<pre className="text-green-400 text-sm">
|
||||
|
|
@ -452,7 +470,9 @@ const MigrationManager: React.FC = () => {
|
|||
<div className="bg-yellow-50 border border-yellow-200 rounded-lg p-4">
|
||||
<div className="flex items-center gap-2 text-yellow-800">
|
||||
<FaRegBell className="w-5 h-5" />
|
||||
<span className="font-medium">{translate('::App.DeveloperKit.Migration.NoSQLScript')}</span>
|
||||
<span className="font-medium">
|
||||
{translate('::App.DeveloperKit.Migration.NoSQLScript')}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-yellow-700 text-sm mt-1">
|
||||
{translate('::App.DeveloperKit.Migration.NoSQLScriptDesc')}
|
||||
|
|
@ -468,7 +488,9 @@ const MigrationManager: React.FC = () => {
|
|||
<div className="bg-red-50 border border-red-200 rounded-lg p-4">
|
||||
<div className="flex items-center gap-2 text-red-800 mb-2">
|
||||
<FaRegBell className="w-5 h-5" />
|
||||
<span className="font-medium">{translate('::App.DeveloperKit.Migration.MigrationFailed')}</span>
|
||||
<span className="font-medium">
|
||||
{translate('::App.DeveloperKit.Migration.MigrationFailed')}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-red-700 text-sm">{migration.errorMessage}</p>
|
||||
</div>
|
||||
|
|
@ -486,7 +508,9 @@ const MigrationManager: React.FC = () => {
|
|||
<FaBolt className="w-8 h-8 text-slate-500" />
|
||||
</div>
|
||||
<h3 className="text-lg font-medium text-slate-900 mb-2">
|
||||
{searchTerm || filterStatus !== 'all' ? translate('::App.DeveloperKit.Migration.NoMigrationsFound') : translate('::App.DeveloperKit.Migration.NoMigrationsYet')}
|
||||
{searchTerm || filterStatus !== 'all'
|
||||
? translate('::App.DeveloperKit.Migration.NoMigrationsFound')
|
||||
: translate('::App.DeveloperKit.Migration.NoMigrationsYet')}
|
||||
</h3>
|
||||
<p className="text-slate-600">
|
||||
{searchTerm || filterStatus !== 'all'
|
||||
|
|
|
|||
|
|
@ -19,31 +19,31 @@ const DeveloperLayout: React.FC<DeveloperLayoutProps> = ({ children }) => {
|
|||
id: 'dashboard',
|
||||
label: translate('::App.DeveloperKit.Dashboard'),
|
||||
icon: FaTachometerAlt,
|
||||
path: ROUTES_ENUM.protected.saas.developerKit,
|
||||
path: ROUTES_ENUM.protected.saas.developerKit.dashboard,
|
||||
},
|
||||
{
|
||||
id: 'entities',
|
||||
label: translate('::App.DeveloperKit.Entity'),
|
||||
icon: FaDatabase,
|
||||
path: ROUTES_ENUM.protected.saas.developerKitEntities,
|
||||
path: ROUTES_ENUM.protected.saas.developerKit.entities,
|
||||
},
|
||||
{
|
||||
id: 'migrations',
|
||||
label: translate('::App.DeveloperKit.Migrations'),
|
||||
icon: FaBolt,
|
||||
path: ROUTES_ENUM.protected.saas.developerKitMigrations,
|
||||
path: ROUTES_ENUM.protected.saas.developerKit.migrations,
|
||||
},
|
||||
{
|
||||
id: 'endpoints',
|
||||
label: translate('::App.DeveloperKit.Endpoints'),
|
||||
icon: FaServer,
|
||||
path: ROUTES_ENUM.protected.saas.developerKitEndpoints,
|
||||
path: ROUTES_ENUM.protected.saas.developerKit.endpoints,
|
||||
},
|
||||
{
|
||||
id: 'components',
|
||||
label: translate('::App.DeveloperKit.Components'),
|
||||
icon: FaPuzzlePiece,
|
||||
path: ROUTES_ENUM.protected.saas.developerKitComponents,
|
||||
path: ROUTES_ENUM.protected.saas.developerKit.components,
|
||||
},
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { Button, Input, Dialog } from '../ui'
|
|||
import { FaFileAlt } from 'react-icons/fa'
|
||||
import { ReportTemplateDto } from '@/proxy/reports/models'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
|
||||
interface ReportGeneratorProps {
|
||||
isOpen: boolean
|
||||
|
|
@ -50,7 +51,7 @@ export const ReportGenerator: React.FC<ReportGeneratorProps> = ({
|
|||
|
||||
if (reportId) {
|
||||
// Yeni sekmede rapor URL'sini aç
|
||||
const reportUrl = `/admin/reports/${reportId}`
|
||||
const reportUrl = ROUTES_ENUM.protected.saas.reports.view.replace(':id', reportId)
|
||||
window.open(reportUrl, '_blank')
|
||||
onClose() // Modal'ı kapat
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,12 @@ export const ROUTES_ENUM = {
|
|||
about: '/about',
|
||||
products: '/products',
|
||||
checkout: '/checkout',
|
||||
success: '/success',
|
||||
payment: '/payment',
|
||||
success: '/success',
|
||||
services: '/services',
|
||||
demo: '/demo',
|
||||
blog: '/blog',
|
||||
blogDetail: '/blog/:id',
|
||||
demo: '/demo',
|
||||
contact: '/contact',
|
||||
accessDenied: '/access-denied',
|
||||
},
|
||||
|
|
@ -33,17 +34,23 @@ export const ROUTES_ENUM = {
|
|||
edit: '/admin/chart/edit/:chartCode',
|
||||
},
|
||||
forumManagement: '/admin/forumManagement',
|
||||
developerKit: '/admin/developerkit',
|
||||
developerKitEntities: '/admin/developerkit/entities',
|
||||
developerKitEntitiesNew: '/admin/developerkit/entities/new',
|
||||
developerKitEntitiesEdit: '/admin/developerkit/entities/edit/:id',
|
||||
developerKitMigrations: '/admin/developerkit/migrations',
|
||||
developerKitEndpoints: '/admin/developerkit/endpoints',
|
||||
developerKitEndpointsNew: '/admin/developerkit/endpoints/new',
|
||||
developerKitComponents: '/admin/developerkit/components',
|
||||
developerKitComponentsNew: '/admin/developerkit/components/new',
|
||||
developerKitComponentsView: '/admin/developerkit/components/view/:id',
|
||||
developerKitComponentsEdit: '/admin/developerkit/components/edit/:id',
|
||||
developerKit: {
|
||||
dashboard: '/admin/developerkit',
|
||||
entities: '/admin/developerkit/entities',
|
||||
entitiesNew: '/admin/developerkit/entities/new',
|
||||
entitiesEdit: '/admin/developerkit/entities/edit/:id',
|
||||
migrations: '/admin/developerkit/migrations',
|
||||
endpoints: '/admin/developerkit/endpoints',
|
||||
endpointsNew: '/admin/developerkit/endpoints/new',
|
||||
components: '/admin/developerkit/components',
|
||||
componentsNew: '/admin/developerkit/components/new',
|
||||
componentsView: '/admin/developerkit/components/view/:id',
|
||||
componentsEdit: '/admin/developerkit/components/edit/:id',
|
||||
},
|
||||
reports: {
|
||||
generator: '/admin/reports/generator',
|
||||
view: '/admin/reports/:id',
|
||||
},
|
||||
},
|
||||
admin: {
|
||||
ai: '/admin/ai',
|
||||
|
|
@ -54,7 +61,6 @@ export const ROUTES_ENUM = {
|
|||
},
|
||||
activityLog: '/admin/activityLog',
|
||||
changeLog: '/admin/changeLog',
|
||||
|
||||
settings: '/admin/settings',
|
||||
identity: {
|
||||
user: {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import { GridOptionsEditDto, ListFormCustomizationDto } from '@/proxy/form/model
|
|||
import { IdentityRoleDto, IdentityUserDto } from '@/proxy/admin/models'
|
||||
import { getListFormCustomizations } from '@/services/admin/list-form-customization.service'
|
||||
import { Container } from '@/components/shared'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
|
||||
export interface FormEditProps {
|
||||
onSubmit: (
|
||||
|
|
@ -153,7 +154,7 @@ const FormEdit = () => {
|
|||
<div className="lg:flex items-center justify-between mb-4 gap-3">
|
||||
<div className="mb-4 lg:mb-0">
|
||||
<h4>
|
||||
<Link to={`/admin/list/${listFormCode}`}>
|
||||
<Link to={ROUTES_ENUM.protected.admin.list.replace(':listFormCode', listFormCode)}>
|
||||
🔙 {listFormCode} - {translate(`::${listFormValues.title}`)}
|
||||
</Link>
|
||||
</h4>
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ import {
|
|||
FaUserShield,
|
||||
} from 'react-icons/fa'
|
||||
import { object, string } from 'yup'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
|
||||
const schema = object().shape({
|
||||
id: string(),
|
||||
|
|
@ -587,7 +588,10 @@ const OrganizationUnits = () => {
|
|||
</Td>
|
||||
<Td>
|
||||
<ActionLink
|
||||
href={`/admin/identity/users/${user.id}/details`}
|
||||
href={ROUTES_ENUM.protected.admin.identity.user.detail.replace(
|
||||
':userId',
|
||||
user.id!,
|
||||
)}
|
||||
className="font-bold"
|
||||
target="_blank"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import {
|
|||
PermissionWithStyle,
|
||||
UpdatePermissionDto,
|
||||
} from '@/proxy/admin/models'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
|
||||
const { Tr, Th, Td, THead, TBody } = Table
|
||||
|
||||
|
|
@ -249,7 +250,10 @@ const Users = () => {
|
|||
</Td>
|
||||
<Td>
|
||||
<ActionLink
|
||||
href={`/admin/identity/users/${user.id}/details`}
|
||||
href={ROUTES_ENUM.protected.admin.identity.user.detail.replace(
|
||||
':userId',
|
||||
user.id!,
|
||||
)}
|
||||
className="font-bold"
|
||||
>
|
||||
{user.name} {user.surname}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { useNavigate, useParams } from 'react-router-dom'
|
|||
import useAccount from '@/utils/hooks/useAccount'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
|
||||
const VerifyConfirmationCode = () => {
|
||||
const { userId, token } = useParams()
|
||||
|
|
@ -37,7 +38,11 @@ const VerifyConfirmationCode = () => {
|
|||
<Alert showIcon className="mb-4" type="danger">
|
||||
{error}
|
||||
</Alert>
|
||||
<Button block variant="solid" onClick={() => navigate('/account/confirm')}>
|
||||
<Button
|
||||
block
|
||||
variant="solid"
|
||||
onClick={() => navigate(ROUTES_ENUM.authenticated.sendConfirmationCode)}
|
||||
>
|
||||
{translate('::Abp.Account.VerifyConfirmationCode')}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import { addCss, addJs } from '../list/Utils'
|
|||
import { PermissionResults, RowMode, SimpleItemWithColData } from './types'
|
||||
import { EditingFormItemDto, GridDto, PlatformEditorTypes } from '@/proxy/form/models'
|
||||
import { getAccessDeniedPath } from '@/utils/routing'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
|
||||
const useGridData = (props: {
|
||||
mode: RowMode
|
||||
|
|
@ -125,7 +126,11 @@ const useGridData = (props: {
|
|||
var result = await dataSource.update(id, data)
|
||||
if (result.data > 0) {
|
||||
if (!isSubForm) {
|
||||
navigate(`/form/${listFormCode}/${id}`)
|
||||
navigate(
|
||||
ROUTES_ENUM.protected.admin.formView
|
||||
.replace(':listFormCode', listFormCode)
|
||||
.replace(':id', id!),
|
||||
)
|
||||
} else if (props.onSubmitAction) {
|
||||
props.onSubmitAction()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import { setGridPanelColor } from './Utils'
|
|||
import { useNavigate } from 'react-router-dom'
|
||||
import { usePermission } from '@/utils/hooks/usePermission'
|
||||
import { usePWA } from '@/utils/hooks/usePWA'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
|
||||
export interface ISelectBoxData {
|
||||
value?: string
|
||||
|
|
@ -177,9 +178,15 @@ const useFilters = ({
|
|||
// Kayitli bir filtreyi silmek icin ilgili ekrani ac
|
||||
setIsDeleteModalOpen(true)
|
||||
} else if (itemData.id === 'openPivotGrid') {
|
||||
navigate(`/pivot/${listFormCode}`)
|
||||
navigate(ROUTES_ENUM.protected.admin.pivot.replace(':listFormCode', listFormCode))
|
||||
} else if (itemData.id === 'openManage') {
|
||||
window.open(`/admin/listform/edit/${listFormCode}`, isPwaMode ? '_self' : '_blank')
|
||||
window.open(
|
||||
ROUTES_ENUM.protected.saas.listFormManagement.edit.replace(
|
||||
':listFormCode',
|
||||
listFormCode,
|
||||
),
|
||||
isPwaMode ? '_self' : '_blank',
|
||||
)
|
||||
} else if (itemData.id === 'clearFilter') {
|
||||
// gridin bütün filtrelerini temizle
|
||||
const grid = gridRef.current?.instance
|
||||
|
|
|
|||
Loading…
Reference in a new issue