i18n ve Localization düzenlemesi
This commit is contained in:
parent
00eb20d55f
commit
012f507cd3
42 changed files with 1462 additions and 678 deletions
|
|
@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict';
|
||||||
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
||||||
}, {
|
}, {
|
||||||
"url": "index.html",
|
"url": "index.html",
|
||||||
"revision": "0.4akve1tmvk"
|
"revision": "0.ettrttb2g3"
|
||||||
}], {});
|
}], {});
|
||||||
workbox.cleanupOutdatedCaches();
|
workbox.cleanupOutdatedCaches();
|
||||||
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
||||||
|
|
|
||||||
1500
ui/package-lock.json
generated
1500
ui/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -44,7 +44,6 @@
|
||||||
"formik": "^2.4.6",
|
"formik": "^2.4.6",
|
||||||
"framer-motion": "^11.15.0",
|
"framer-motion": "^11.15.0",
|
||||||
"history": "^5.3.0",
|
"history": "^5.3.0",
|
||||||
"i18next": "^23.7.11",
|
|
||||||
"jspdf": "^3.0.1",
|
"jspdf": "^3.0.1",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
|
@ -57,7 +56,6 @@
|
||||||
"react-error-boundary": "^5.0.0",
|
"react-error-boundary": "^5.0.0",
|
||||||
"react-helmet": "^6.1.0",
|
"react-helmet": "^6.1.0",
|
||||||
"react-highlight-words": "^0.20.0",
|
"react-highlight-words": "^0.20.0",
|
||||||
"react-i18next": "^15.2.0",
|
|
||||||
"react-icons": "^5.4.0",
|
"react-icons": "^5.4.0",
|
||||||
"react-modal": "^3.16.3",
|
"react-modal": "^3.16.3",
|
||||||
"react-quill": "^2.0.0",
|
"react-quill": "^2.0.0",
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,31 @@
|
||||||
import { MenuDto } from "@/proxy/menus";
|
import { MenuDto } from '@/proxy/menus/models'
|
||||||
|
|
||||||
export interface MenuItem extends MenuDto {
|
export interface MenuItem extends MenuDto {
|
||||||
children?: MenuItem[];
|
children?: MenuItem[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MenuApiResponse {
|
export interface MenuApiResponse {
|
||||||
totalCount: number;
|
totalCount: number
|
||||||
items: MenuItem[];
|
items: MenuItem[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DragEndEvent {
|
export interface DragEndEvent {
|
||||||
active: {
|
active: {
|
||||||
id: string;
|
id: string
|
||||||
data: {
|
data: {
|
||||||
current: {
|
current: {
|
||||||
type: string;
|
type: string
|
||||||
item: MenuItem;
|
item: MenuItem
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
over: {
|
over: {
|
||||||
id: string;
|
id: string
|
||||||
data: {
|
data: {
|
||||||
current: {
|
current: {
|
||||||
type: string;
|
type: string
|
||||||
item?: MenuItem;
|
item?: MenuItem
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
} | null;
|
} | null
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import Theme from '@/components/template/Theme'
|
||||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||||
import { StoreProvider } from 'easy-peasy'
|
import { StoreProvider } from 'easy-peasy'
|
||||||
import { BrowserRouter } from 'react-router-dom'
|
import { BrowserRouter } from 'react-router-dom'
|
||||||
import './locales'
|
|
||||||
import { store } from './store'
|
import { store } from './store'
|
||||||
import { DynamicRoutesProvider } from './routes/dynamicRoutesContext'
|
import { DynamicRoutesProvider } from './routes/dynamicRoutesContext'
|
||||||
import { ComponentProvider } from './contexts/ComponentContext'
|
import { ComponentProvider } from './contexts/ComponentContext'
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,9 @@ import {
|
||||||
import { FileUploadArea } from './FileUploadArea'
|
import { FileUploadArea } from './FileUploadArea'
|
||||||
import { ImportPreview } from './ImportPreview'
|
import { ImportPreview } from './ImportPreview'
|
||||||
import { ImportProgress } from './ImportProgress'
|
import { ImportProgress } from './ImportProgress'
|
||||||
import { GridDto } from '@/proxy/form'
|
|
||||||
import { ListFormImportDto, ListFormImportExecuteDto } from '@/proxy/imports/models'
|
import { ListFormImportDto, ListFormImportExecuteDto } from '@/proxy/imports/models'
|
||||||
import { ImportService } from '@/services/import.service'
|
import { ImportService } from '@/services/import.service'
|
||||||
|
import { GridDto } from '@/proxy/form/models'
|
||||||
|
|
||||||
interface ImportDashboardProps {
|
interface ImportDashboardProps {
|
||||||
gridDto: GridDto
|
gridDto: GridDto
|
||||||
|
|
@ -47,7 +47,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
||||||
gridDto.gridOptions.listFormCode || '',
|
gridDto.gridOptions.listFormCode || '',
|
||||||
)
|
)
|
||||||
setImportHistory(history)
|
setImportHistory(history)
|
||||||
|
|
||||||
// Execute cache'ini temizle çünkü history değişmiş olabilir
|
// Execute cache'ini temizle çünkü history değişmiş olabilir
|
||||||
setSessionExecutes({})
|
setSessionExecutes({})
|
||||||
setExpandedSessions(new Set())
|
setExpandedSessions(new Set())
|
||||||
|
|
@ -97,17 +97,26 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
||||||
if (session.status !== 'failed') {
|
if (session.status !== 'failed') {
|
||||||
// Daha uzun süreli ve gerçekçi bir progression
|
// Daha uzun süreli ve gerçekçi bir progression
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
session = await importService.updateSession(session.id, { status: 'validating', listFormCode: gridDto.gridOptions.listFormCode || '' })
|
session = await importService.updateSession(session.id, {
|
||||||
|
status: 'validating',
|
||||||
|
listFormCode: gridDto.gridOptions.listFormCode || '',
|
||||||
|
})
|
||||||
setCurrentSession(session)
|
setCurrentSession(session)
|
||||||
}, 1000) // 1 saniye sonra validating
|
}, 1000) // 1 saniye sonra validating
|
||||||
|
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
session = await importService.updateSession(session.id, { status: 'processing', listFormCode: gridDto.gridOptions.listFormCode || '' })
|
session = await importService.updateSession(session.id, {
|
||||||
|
status: 'processing',
|
||||||
|
listFormCode: gridDto.gridOptions.listFormCode || '',
|
||||||
|
})
|
||||||
setCurrentSession(session)
|
setCurrentSession(session)
|
||||||
}, 2000) // 2 saniye sonra processing başlangıç
|
}, 2000) // 2 saniye sonra processing başlangıç
|
||||||
|
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
session = await importService.updateSession(session.id, { status: 'uploaded', listFormCode: gridDto.gridOptions.listFormCode || '' })
|
session = await importService.updateSession(session.id, {
|
||||||
|
status: 'uploaded',
|
||||||
|
listFormCode: gridDto.gridOptions.listFormCode || '',
|
||||||
|
})
|
||||||
setCurrentSession(session)
|
setCurrentSession(session)
|
||||||
}, 3000) // 3 saniye sonra uploaded
|
}, 3000) // 3 saniye sonra uploaded
|
||||||
|
|
||||||
|
|
@ -146,7 +155,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
||||||
const session = await importService.executeImport(sessionId, listFormCode, selectedRows)
|
const session = await importService.executeImport(sessionId, listFormCode, selectedRows)
|
||||||
pollImportStatus(session.importId)
|
pollImportStatus(session.importId)
|
||||||
await loadImportHistory()
|
await loadImportHistory()
|
||||||
|
|
||||||
// Execute sonrası History sekmesine geç ki kullanıcı yeni execute'i görebilsin
|
// Execute sonrası History sekmesine geç ki kullanıcı yeni execute'i görebilsin
|
||||||
setActiveTab('history')
|
setActiveTab('history')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -199,7 +208,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
||||||
|
|
||||||
const getEditableColumns = () => {
|
const getEditableColumns = () => {
|
||||||
return gridDto.columnFormats.filter(
|
return gridDto.columnFormats.filter(
|
||||||
(col) =>
|
(col: any) =>
|
||||||
col.visible &&
|
col.visible &&
|
||||||
col.columnEditingDto.allowEditing &&
|
col.columnEditingDto.allowEditing &&
|
||||||
col.canCreate &&
|
col.canCreate &&
|
||||||
|
|
@ -287,7 +296,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody className="divide-y divide-slate-100">
|
<tbody className="divide-y divide-slate-100">
|
||||||
{editableColumns.map((column) => (
|
{editableColumns.map((column: any) => (
|
||||||
<tr key={column.fieldName} className="hover:bg-slate-50">
|
<tr key={column.fieldName} className="hover:bg-slate-50">
|
||||||
<td className="px-2 py-2 font-medium text-slate-800">
|
<td className="px-2 py-2 font-medium text-slate-800">
|
||||||
{column.captionName || column.fieldName}
|
{column.captionName || column.fieldName}
|
||||||
|
|
@ -308,7 +317,9 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-4 py-2">
|
<td className="px-4 py-2">
|
||||||
{column.validationRuleDto.some((rule) => rule.type === 'required') ? (
|
{column.validationRuleDto.some(
|
||||||
|
(rule: any) => rule.type === 'required',
|
||||||
|
) ? (
|
||||||
<span className="text-red-500 font-medium">Yes</span>
|
<span className="text-red-500 font-medium">Yes</span>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-slate-400">No</span>
|
<span className="text-slate-400">No</span>
|
||||||
|
|
@ -455,7 +466,9 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
||||||
if (sessionExecutes[session.id]) {
|
if (sessionExecutes[session.id]) {
|
||||||
setLoadingExecutes((prev) => new Set([...prev, session.id]))
|
setLoadingExecutes((prev) => new Set([...prev, session.id]))
|
||||||
try {
|
try {
|
||||||
const executes = await importService.getListFormImportExecutes(session.id)
|
const executes = await importService.getListFormImportExecutes(
|
||||||
|
session.id,
|
||||||
|
)
|
||||||
setSessionExecutes((prev) => ({
|
setSessionExecutes((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
[session.id]: executes,
|
[session.id]: executes,
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,17 @@
|
||||||
import React, { useState, useEffect, useRef } from 'react'
|
import React, { useState, useEffect, useRef } from 'react'
|
||||||
import { CheckCircle, AlertTriangle, Eye, Play, X } from 'lucide-react'
|
import { CheckCircle, AlertTriangle, Eye, Play, X } from 'lucide-react'
|
||||||
import { ListFormImportDto } from '@/proxy/imports/models'
|
import { ListFormImportDto } from '@/proxy/imports/models'
|
||||||
import { GridDto } from '@/proxy/form'
|
import { GridDto } from '@/proxy/form/models'
|
||||||
import { ImportService } from '@/services/import.service'
|
import { ImportService } from '@/services/import.service'
|
||||||
|
|
||||||
interface ImportPreviewProps {
|
interface ImportPreviewProps {
|
||||||
session: ListFormImportDto
|
session: ListFormImportDto
|
||||||
gridDto: GridDto
|
gridDto: GridDto
|
||||||
onExecute: (sessionId: string, listFormCode: string, selectedRows?: number[]) => Promise<{ successCount?: number } | void>
|
onExecute: (
|
||||||
|
sessionId: string,
|
||||||
|
listFormCode: string,
|
||||||
|
selectedRows?: number[],
|
||||||
|
) => Promise<{ successCount?: number } | void>
|
||||||
loading: boolean
|
loading: boolean
|
||||||
importService: ImportService
|
importService: ImportService
|
||||||
onPreviewLoaded?: () => void
|
onPreviewLoaded?: () => void
|
||||||
|
|
@ -20,13 +24,15 @@ export const ImportPreview: React.FC<ImportPreviewProps> = ({
|
||||||
loading,
|
loading,
|
||||||
importService,
|
importService,
|
||||||
onPreviewLoaded,
|
onPreviewLoaded,
|
||||||
|
|
||||||
}) => {
|
}) => {
|
||||||
const [previewData, setPreviewData] = useState<any>(null)
|
const [previewData, setPreviewData] = useState<any>(null)
|
||||||
const [selectedRows, setSelectedRows] = useState<number[]>([])
|
const [selectedRows, setSelectedRows] = useState<number[]>([])
|
||||||
const [selectAll, setSelectAll] = useState(false)
|
const [selectAll, setSelectAll] = useState(false)
|
||||||
const [showSuccessMessage, setShowSuccessMessage] = useState(false)
|
const [showSuccessMessage, setShowSuccessMessage] = useState(false)
|
||||||
const [lastExecutionResult, setLastExecutionResult] = useState<{ selectedCount: number; successCount: number } | null>(null)
|
const [lastExecutionResult, setLastExecutionResult] = useState<{
|
||||||
|
selectedCount: number
|
||||||
|
successCount: number
|
||||||
|
} | null>(null)
|
||||||
const hasCalledOnPreviewLoaded = useRef(false)
|
const hasCalledOnPreviewLoaded = useRef(false)
|
||||||
|
|
||||||
// Selection handlers
|
// Selection handlers
|
||||||
|
|
@ -103,18 +109,18 @@ export const ImportPreview: React.FC<ImportPreviewProps> = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
const canExecute = (previewData?.rows?.length || 0) > 0 && selectedRows.length > 0 && !loading
|
const canExecute = (previewData?.rows?.length || 0) > 0 && selectedRows.length > 0 && !loading
|
||||||
|
|
||||||
// Execute handler to clear selections after execution
|
// Execute handler to clear selections after execution
|
||||||
const handleExecute = async () => {
|
const handleExecute = async () => {
|
||||||
const selectedCount = selectedRows.length
|
const selectedCount = selectedRows.length
|
||||||
try {
|
try {
|
||||||
const result = await onExecute(session.id, session.listFormCode, selectedRows)
|
const result = await onExecute(session.id, session.listFormCode, selectedRows)
|
||||||
|
|
||||||
// Check if execution was successful
|
// Check if execution was successful
|
||||||
if (result && typeof result === 'object' && 'successCount' in result) {
|
if (result && typeof result === 'object' && 'successCount' in result) {
|
||||||
const successCount = result.successCount || 0
|
const successCount = result.successCount || 0
|
||||||
setLastExecutionResult({ selectedCount, successCount })
|
setLastExecutionResult({ selectedCount, successCount })
|
||||||
|
|
||||||
// Show success message if all selected rows were processed successfully
|
// Show success message if all selected rows were processed successfully
|
||||||
if (successCount === selectedCount) {
|
if (successCount === selectedCount) {
|
||||||
setShowSuccessMessage(true)
|
setShowSuccessMessage(true)
|
||||||
|
|
@ -124,7 +130,7 @@ export const ImportPreview: React.FC<ImportPreviewProps> = ({
|
||||||
}, 5000)
|
}, 5000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear selections after execute
|
// Clear selections after execute
|
||||||
setSelectedRows([])
|
setSelectedRows([])
|
||||||
setSelectAll(false)
|
setSelectAll(false)
|
||||||
|
|
@ -173,9 +179,7 @@ export const ImportPreview: React.FC<ImportPreviewProps> = ({
|
||||||
{/* Preview Data */}
|
{/* Preview Data */}
|
||||||
{previewData && previewData.headers && previewData.headers.length > 0 ? (
|
{previewData && previewData.headers && previewData.headers.length > 0 ? (
|
||||||
<div className="p-3 border-b border-slate-200">
|
<div className="p-3 border-b border-slate-200">
|
||||||
<h4 className="font-semibold text-slate-800 mb-4">
|
<h4 className="font-semibold text-slate-800 mb-4">Data Preview</h4>
|
||||||
Data Preview
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
<div className="overflow-auto border border-slate-200 rounded-lg max-h-90">
|
<div className="overflow-auto border border-slate-200 rounded-lg max-h-90">
|
||||||
<table className="w-full text-sm min-w-full">
|
<table className="w-full text-sm min-w-full">
|
||||||
|
|
@ -257,7 +261,8 @@ export const ImportPreview: React.FC<ImportPreviewProps> = ({
|
||||||
<div className="flex items-center space-x-2 text-green-700">
|
<div className="flex items-center space-x-2 text-green-700">
|
||||||
<CheckCircle className="w-5 h-5" />
|
<CheckCircle className="w-5 h-5" />
|
||||||
<span className="font-medium">
|
<span className="font-medium">
|
||||||
Import completed successfully! {lastExecutionResult.successCount} of {lastExecutionResult.selectedCount} rows were imported.
|
Import completed successfully! {lastExecutionResult.successCount} of{' '}
|
||||||
|
{lastExecutionResult.selectedCount} rows were imported.
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@ import type { ReactNode, ReactElement } from 'react'
|
||||||
import type { CommonProps } from '@/@types/common'
|
import type { CommonProps } from '@/@types/common'
|
||||||
import { HiArrowLeft, HiCheck } from 'react-icons/hi'
|
import { HiArrowLeft, HiCheck } from 'react-icons/hi'
|
||||||
import { Avatar, Select } from '@/components/ui'
|
import { Avatar, Select } from '@/components/ui'
|
||||||
import i18n, { dateLocales } from '@/locales'
|
|
||||||
import { useStoreActions, useStoreState } from '@/store'
|
import { useStoreActions, useStoreState } from '@/store'
|
||||||
import appConfig from '@/configs/app.config'
|
import appConfig from '@/configs/app.config'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { components } from 'react-select'
|
import { components } from 'react-select'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
import { hasSubdomain } from '@/utils/subdomain'
|
import { hasSubdomain } from '@/utils/subdomain'
|
||||||
|
import { dateLocales } from '@/constants/dateLocales.constant'
|
||||||
|
|
||||||
interface SimpleProps extends CommonProps {
|
interface SimpleProps extends CommonProps {
|
||||||
content?: ReactNode
|
content?: ReactNode
|
||||||
|
|
@ -38,7 +38,6 @@ const Simple = ({ children, content, ...rest }: SimpleProps) => {
|
||||||
|
|
||||||
const onLanguageSelect = (cultureName = appConfig.locale) => {
|
const onLanguageSelect = (cultureName = appConfig.locale) => {
|
||||||
const dispatchLang = () => {
|
const dispatchLang = () => {
|
||||||
i18n.changeLanguage(cultureName)
|
|
||||||
setLang(cultureName)
|
setLang(cultureName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,10 @@ import {
|
||||||
NAV_ITEM_TYPE_TITLE,
|
NAV_ITEM_TYPE_TITLE,
|
||||||
} from '@/constants/navigation.constant'
|
} from '@/constants/navigation.constant'
|
||||||
import { useStoreState } from '@/store'
|
import { useStoreState } from '@/store'
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
import HorizontalMenuDropdownItem from './HorizontalMenuDropdownItem'
|
import HorizontalMenuDropdownItem from './HorizontalMenuDropdownItem'
|
||||||
import HorizontalMenuItem from './HorizontalMenuItem'
|
import HorizontalMenuItem from './HorizontalMenuItem'
|
||||||
import HorizontalMenuIcon from './HorizontalMenuIcon'
|
import HorizontalMenuIcon from './HorizontalMenuIcon'
|
||||||
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
|
|
||||||
type HorizontalMenuContentProps = {
|
type HorizontalMenuContentProps = {
|
||||||
manuVariant: NavMode
|
manuVariant: NavMode
|
||||||
|
|
@ -18,8 +18,6 @@ type HorizontalMenuContentProps = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const HorizontalMenuContent = ({ manuVariant }: HorizontalMenuContentProps) => {
|
const HorizontalMenuContent = ({ manuVariant }: HorizontalMenuContentProps) => {
|
||||||
const { t } = useTranslation()
|
|
||||||
|
|
||||||
const { mainMenu: navigationConfig } = useStoreState((state) => state.abpConfig.menu)
|
const { mainMenu: navigationConfig } = useStoreState((state) => state.abpConfig.menu)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -45,7 +43,7 @@ const HorizontalMenuContent = ({ manuVariant }: HorizontalMenuContentProps) => {
|
||||||
title={
|
title={
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<HorizontalMenuIcon icon={secondarySubNav.icon} />
|
<HorizontalMenuIcon icon={secondarySubNav.icon} />
|
||||||
<span>{t(secondarySubNav.translateKey, secondarySubNav.title)}</span>
|
<span>{secondarySubNav.title}</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -1,53 +1,37 @@
|
||||||
import Dropdown from '@/components/ui/Dropdown'
|
import Dropdown from '@/components/ui/Dropdown'
|
||||||
import HorizontalMenuNavLink from './HorizontalMenuNavLink'
|
import HorizontalMenuNavLink from './HorizontalMenuNavLink'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
|
|
||||||
export type HorizontalMenuItemProps = {
|
export type HorizontalMenuItemProps = {
|
||||||
nav: {
|
nav: {
|
||||||
key: string
|
key: string
|
||||||
title: string
|
title: string
|
||||||
translateKey: string
|
translateKey: string
|
||||||
icon: string
|
icon: string
|
||||||
path: string
|
path: string
|
||||||
isExternalLink?: boolean
|
isExternalLink?: boolean
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const HorizontalMenuDropdownItem = ({ nav }: HorizontalMenuItemProps) => {
|
const HorizontalMenuDropdownItem = ({ nav }: HorizontalMenuItemProps) => {
|
||||||
const { title, translateKey, path, key, isExternalLink, icon } = nav
|
const { title, path, key, isExternalLink, icon } = nav
|
||||||
|
|
||||||
const { t } = useTranslation()
|
return (
|
||||||
|
<Dropdown.Item eventKey={key} className={classNames(path)}>
|
||||||
const itemTitle = t(translateKey, title)
|
{path ? (
|
||||||
|
<HorizontalMenuNavLink
|
||||||
return (
|
path={path}
|
||||||
<Dropdown.Item
|
className={classNames(path)}
|
||||||
eventKey={key}
|
isExternalLink={isExternalLink}
|
||||||
className={
|
icon={icon}
|
||||||
classNames(
|
|
||||||
path
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{path ? (
|
{title}
|
||||||
<HorizontalMenuNavLink
|
</HorizontalMenuNavLink>
|
||||||
path={path}
|
) : (
|
||||||
className={
|
<span>{title}</span>
|
||||||
classNames(
|
)}
|
||||||
path
|
</Dropdown.Item>
|
||||||
)
|
)
|
||||||
}
|
|
||||||
isExternalLink={isExternalLink}
|
|
||||||
icon={icon}
|
|
||||||
>
|
|
||||||
{itemTitle}
|
|
||||||
</HorizontalMenuNavLink>
|
|
||||||
) : (
|
|
||||||
<span>{itemTitle}</span>
|
|
||||||
)}
|
|
||||||
</Dropdown.Item>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default HorizontalMenuDropdownItem
|
export default HorizontalMenuDropdownItem
|
||||||
|
|
|
||||||
|
|
@ -1,54 +1,45 @@
|
||||||
import navigationIcon from '@/configs/navigation-icon.config'
|
import navigationIcon from '@/configs/navigation-icon.config'
|
||||||
import MenuItem from '@/components/ui/MenuItem'
|
import MenuItem from '@/components/ui/MenuItem'
|
||||||
import HorizontalMenuNavLink from './HorizontalMenuNavLink'
|
import HorizontalMenuNavLink from './HorizontalMenuNavLink'
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
import type { NavMode } from '@/@types/theme'
|
import type { NavMode } from '@/@types/theme'
|
||||||
|
|
||||||
export type HorizontalMenuItemProps = {
|
export type HorizontalMenuItemProps = {
|
||||||
nav: {
|
nav: {
|
||||||
key: string
|
key: string
|
||||||
title: string
|
title: string
|
||||||
translateKey: string
|
translateKey: string
|
||||||
icon: string
|
icon: string
|
||||||
path: string
|
path: string
|
||||||
isExternalLink?: boolean
|
isExternalLink?: boolean
|
||||||
}
|
}
|
||||||
isLink?: boolean
|
isLink?: boolean
|
||||||
manuVariant: NavMode
|
manuVariant: NavMode
|
||||||
}
|
}
|
||||||
|
|
||||||
const HorizontalMenuItem = ({
|
const HorizontalMenuItem = ({ nav, isLink, manuVariant }: HorizontalMenuItemProps) => {
|
||||||
nav,
|
const { title, icon, path, isExternalLink } = nav
|
||||||
isLink,
|
|
||||||
manuVariant,
|
|
||||||
}: HorizontalMenuItemProps) => {
|
|
||||||
const { title, translateKey, icon, path, isExternalLink } = nav
|
|
||||||
|
|
||||||
const { t } = useTranslation()
|
const renderIcon = icon && <span className="text-2xl">{navigationIcon[icon]}</span>
|
||||||
|
|
||||||
const itemTitle = t(translateKey, title)
|
return (
|
||||||
|
<>
|
||||||
const renderIcon = icon && <span className="text-2xl">{navigationIcon[icon]}</span>
|
{path && isLink ? (
|
||||||
|
<HorizontalMenuNavLink path={path} isExternalLink={isExternalLink}>
|
||||||
return (
|
<MenuItem variant={manuVariant}>
|
||||||
<>
|
<span className="flex items-center gap-2">
|
||||||
{path && isLink ? (
|
{renderIcon}
|
||||||
<HorizontalMenuNavLink path={path} isExternalLink={isExternalLink}>
|
{title}
|
||||||
<MenuItem variant={manuVariant}>
|
</span>
|
||||||
<span className="flex items-center gap-2">
|
</MenuItem>
|
||||||
{renderIcon}
|
</HorizontalMenuNavLink>
|
||||||
{itemTitle}
|
) : (
|
||||||
</span>
|
<MenuItem variant={manuVariant}>
|
||||||
</MenuItem>
|
{renderIcon}
|
||||||
</HorizontalMenuNavLink>
|
<span>{title}</span>
|
||||||
) : (
|
</MenuItem>
|
||||||
<MenuItem variant={manuVariant}>
|
)}
|
||||||
{renderIcon}
|
</>
|
||||||
<span>{itemTitle}</span>
|
)
|
||||||
</MenuItem>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default HorizontalMenuItem
|
export default HorizontalMenuItem
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,11 @@ import Spinner from '@/components/ui/Spinner'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import withHeaderItem from '@/utils/hoc/withHeaderItem'
|
import withHeaderItem from '@/utils/hoc/withHeaderItem'
|
||||||
import { useStoreState, useStoreActions } from '@/store'
|
import { useStoreState, useStoreActions } from '@/store'
|
||||||
import { dateLocales } from '@/locales'
|
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
// eslint-disable-next-line import/no-named-as-default
|
|
||||||
import i18n from 'i18next'
|
|
||||||
import { HiCheck } from 'react-icons/hi'
|
import { HiCheck } from 'react-icons/hi'
|
||||||
import type { CommonProps } from '@/@types/common'
|
import type { CommonProps } from '@/@types/common'
|
||||||
import appConfig from '@/configs/app.config'
|
import appConfig from '@/configs/app.config'
|
||||||
|
import { dateLocales } from '@/constants/dateLocales.constant'
|
||||||
|
|
||||||
const _LanguageSelector = ({ className }: CommonProps) => {
|
const _LanguageSelector = ({ className }: CommonProps) => {
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
|
|
@ -41,7 +39,6 @@ const _LanguageSelector = ({ className }: CommonProps) => {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
|
|
||||||
const dispatchLang = () => {
|
const dispatchLang = () => {
|
||||||
i18n.changeLanguage(cultureName)
|
|
||||||
setLang(cultureName)
|
setLang(cultureName)
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,128 +1,113 @@
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import {
|
import {
|
||||||
NAV_MODE_THEMED,
|
NAV_MODE_THEMED,
|
||||||
SPLITTED_SIDE_NAV_MINI_WIDTH,
|
SPLITTED_SIDE_NAV_MINI_WIDTH,
|
||||||
SPLITTED_SIDE_NAV_SECONDARY_WIDTH,
|
SPLITTED_SIDE_NAV_SECONDARY_WIDTH,
|
||||||
DIR_LTR,
|
DIR_LTR,
|
||||||
DIR_RTL,
|
DIR_RTL,
|
||||||
NAV_MODE_TRANSPARENT,
|
NAV_MODE_TRANSPARENT,
|
||||||
} from '@/constants/theme.constant'
|
} from '@/constants/theme.constant'
|
||||||
import StackedSideNavMini, { SelectedMenuItem } from './StackedSideNavMini'
|
import StackedSideNavMini, { SelectedMenuItem } from './StackedSideNavMini'
|
||||||
import StackedSideNavSecondary from './StackedSideNavSecondary'
|
import StackedSideNavSecondary from './StackedSideNavSecondary'
|
||||||
import useResponsive from '@/utils/hooks/useResponsive'
|
import useResponsive from '@/utils/hooks/useResponsive'
|
||||||
import isEmpty from 'lodash/isEmpty'
|
import isEmpty from 'lodash/isEmpty'
|
||||||
import { useStoreState } from '@/store'
|
import { useStoreState } from '@/store'
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
|
|
||||||
const stackedSideNavDefaultStyle = {
|
const stackedSideNavDefaultStyle = {
|
||||||
width: SPLITTED_SIDE_NAV_MINI_WIDTH,
|
width: SPLITTED_SIDE_NAV_MINI_WIDTH,
|
||||||
}
|
}
|
||||||
|
|
||||||
const StackedSideNav = () => {
|
const StackedSideNav = () => {
|
||||||
const { t } = useTranslation()
|
const [selectedMenu, setSelectedMenu] = useState<SelectedMenuItem>({})
|
||||||
|
const [activeKeys, setActiveKeys] = useState<string[]>([])
|
||||||
|
|
||||||
const [selectedMenu, setSelectedMenu] = useState<SelectedMenuItem>({})
|
const themeColor = useStoreState((state) => state.theme.themeColor)
|
||||||
const [activeKeys, setActiveKeys] = useState<string[]>([])
|
const primaryColorLevel = useStoreState((state) => state.theme.primaryColorLevel)
|
||||||
|
const navMode = useStoreState((state) => state.theme.navMode)
|
||||||
|
const mode = useStoreState((state) => state.theme.mode)
|
||||||
|
const direction = useStoreState((state) => state.theme.direction)
|
||||||
|
const currentRouteKey = useStoreState((state) => state.base.common.currentRouteKey)
|
||||||
|
const userAuthority = useStoreState((state) => state.auth.user.authority)
|
||||||
|
|
||||||
const themeColor = useStoreState((state) => state.theme.themeColor)
|
const { larger } = useResponsive()
|
||||||
const primaryColorLevel = useStoreState(
|
|
||||||
(state) => state.theme.primaryColorLevel
|
|
||||||
)
|
|
||||||
const navMode = useStoreState((state) => state.theme.navMode)
|
|
||||||
const mode = useStoreState((state) => state.theme.mode)
|
|
||||||
const direction = useStoreState((state) => state.theme.direction)
|
|
||||||
const currentRouteKey = useStoreState(
|
|
||||||
(state) => state.base.common.currentRouteKey
|
|
||||||
)
|
|
||||||
const userAuthority = useStoreState((state) => state.auth.user.authority)
|
|
||||||
|
|
||||||
const { larger } = useResponsive()
|
const navColor = (navType: string, mode: string, ableTheme = true) => {
|
||||||
|
if (navMode === NAV_MODE_THEMED && ableTheme) {
|
||||||
|
return `bg-${themeColor}-${primaryColorLevel} ${navType}-${mode}`
|
||||||
|
}
|
||||||
|
return `${navType}-${mode}`
|
||||||
|
}
|
||||||
|
|
||||||
const navColor = (navType: string, mode: string, ableTheme = true) => {
|
const handleChange = (selected: SelectedMenuItem) => {
|
||||||
if (navMode === NAV_MODE_THEMED && ableTheme) {
|
setSelectedMenu(selected)
|
||||||
return `bg-${themeColor}-${primaryColorLevel} ${navType}-${mode}`
|
}
|
||||||
}
|
|
||||||
return `${navType}-${mode}`
|
const handleCollpase = () => {
|
||||||
|
setSelectedMenu({})
|
||||||
|
setActiveKeys([])
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSetActiveKey = (key: string[]) => {
|
||||||
|
setActiveKeys(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
const stackedSideNavSecondaryDirStyle = () => {
|
||||||
|
let style = {}
|
||||||
|
const marginValue = `${-SPLITTED_SIDE_NAV_SECONDARY_WIDTH}px`
|
||||||
|
if (direction === DIR_LTR) {
|
||||||
|
style = { marginLeft: marginValue }
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleChange = (selected: SelectedMenuItem) => {
|
if (direction === DIR_RTL) {
|
||||||
setSelectedMenu(selected)
|
style = { marginRight: marginValue }
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleCollpase = () => {
|
return style
|
||||||
setSelectedMenu({})
|
}
|
||||||
setActiveKeys([])
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSetActiveKey = (key: string[]) => {
|
return (
|
||||||
setActiveKeys(key)
|
<>
|
||||||
}
|
{larger.md && (
|
||||||
|
<div className={`stacked-side-nav`}>
|
||||||
const stackedSideNavSecondaryDirStyle = () => {
|
<StackedSideNavMini
|
||||||
let style = {}
|
className={`stacked-side-nav-mini ${navColor('stacked-side-nav-mini', navMode)}`}
|
||||||
const marginValue = `${-SPLITTED_SIDE_NAV_SECONDARY_WIDTH}px`
|
style={stackedSideNavDefaultStyle}
|
||||||
if (direction === DIR_LTR) {
|
routeKey={currentRouteKey}
|
||||||
style = { marginLeft: marginValue }
|
activeKeys={activeKeys}
|
||||||
}
|
navMode={navMode}
|
||||||
|
userAuthority={userAuthority as string[]}
|
||||||
if (direction === DIR_RTL) {
|
mode={mode}
|
||||||
style = { marginRight: marginValue }
|
direction={direction}
|
||||||
}
|
onChange={handleChange}
|
||||||
|
onSetActiveKey={handleSetActiveKey}
|
||||||
return style
|
/>
|
||||||
}
|
<div
|
||||||
|
className={`stacked-side-nav-secondary ${navColor(
|
||||||
return (
|
'stacked-side-nav-secondary',
|
||||||
<>
|
mode,
|
||||||
{larger.md && (
|
false,
|
||||||
<div className={`stacked-side-nav`}>
|
)}`}
|
||||||
<StackedSideNavMini
|
style={{
|
||||||
className={`stacked-side-nav-mini ${navColor(
|
width: SPLITTED_SIDE_NAV_SECONDARY_WIDTH,
|
||||||
'stacked-side-nav-mini',
|
...(isEmpty(selectedMenu) ? stackedSideNavSecondaryDirStyle() : {}),
|
||||||
navMode
|
}}
|
||||||
)}`}
|
>
|
||||||
style={stackedSideNavDefaultStyle}
|
{!isEmpty(selectedMenu) && (
|
||||||
routeKey={currentRouteKey}
|
<StackedSideNavSecondary
|
||||||
activeKeys={activeKeys}
|
title={selectedMenu.title as string}
|
||||||
navMode={navMode}
|
menu={selectedMenu.menu}
|
||||||
userAuthority={userAuthority as string[]}
|
routeKey={currentRouteKey}
|
||||||
mode={mode}
|
navMode={NAV_MODE_TRANSPARENT}
|
||||||
direction={direction}
|
direction={direction}
|
||||||
onChange={handleChange}
|
userAuthority={userAuthority as string[]}
|
||||||
onSetActiveKey={handleSetActiveKey}
|
onCollapse={handleCollpase}
|
||||||
/>
|
/>
|
||||||
<div
|
|
||||||
className={`stacked-side-nav-secondary ${navColor(
|
|
||||||
'stacked-side-nav-secondary',
|
|
||||||
mode,
|
|
||||||
false
|
|
||||||
)}`}
|
|
||||||
style={{
|
|
||||||
width: SPLITTED_SIDE_NAV_SECONDARY_WIDTH,
|
|
||||||
...(isEmpty(selectedMenu)
|
|
||||||
? stackedSideNavSecondaryDirStyle()
|
|
||||||
: {}),
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{!isEmpty(selectedMenu) && (
|
|
||||||
<StackedSideNavSecondary
|
|
||||||
title={t(
|
|
||||||
selectedMenu.translateKey as string,
|
|
||||||
selectedMenu.title as string
|
|
||||||
)}
|
|
||||||
menu={selectedMenu.menu}
|
|
||||||
routeKey={currentRouteKey}
|
|
||||||
navMode={NAV_MODE_TRANSPARENT}
|
|
||||||
direction={direction}
|
|
||||||
userAuthority={userAuthority as string[]}
|
|
||||||
onCollapse={handleCollpase}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</>
|
</div>
|
||||||
)
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default StackedSideNav
|
export default StackedSideNav
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import type { Direction } from '@/@types/theme'
|
||||||
import { PermissionCheck } from '@/components/shared'
|
import { PermissionCheck } from '@/components/shared'
|
||||||
import Dropdown from '@/components/ui/Dropdown'
|
import Dropdown from '@/components/ui/Dropdown'
|
||||||
import Menu from '@/components/ui/Menu'
|
import Menu from '@/components/ui/Menu'
|
||||||
import { Trans } from 'react-i18next'
|
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import VerticalMenuIcon from './VerticalMenuIcon'
|
import VerticalMenuIcon from './VerticalMenuIcon'
|
||||||
|
|
||||||
|
|
@ -33,9 +32,7 @@ const DefaultItem = ({ nav, onLinkClick }: DefaultItemProps) => {
|
||||||
label={
|
label={
|
||||||
<>
|
<>
|
||||||
<VerticalMenuIcon icon={nav.icon} />
|
<VerticalMenuIcon icon={nav.icon} />
|
||||||
<span>
|
<span>{nav.title}</span>
|
||||||
<Trans i18nKey={nav.translateKey} defaults={nav.title} />
|
|
||||||
</span>
|
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
eventKey={nav.key}
|
eventKey={nav.key}
|
||||||
|
|
@ -56,16 +53,12 @@ const DefaultItem = ({ nav, onLinkClick }: DefaultItemProps) => {
|
||||||
path: subNav.path,
|
path: subNav.path,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
target={subNav.isExternalLink ? '_blank' : ''}
|
target={subNav.isExternalLink ? '_blank' : ''}
|
||||||
>
|
>
|
||||||
<span>
|
<span>{nav.title}</span>
|
||||||
<Trans i18nKey={subNav.translateKey} defaults={subNav.title} />
|
|
||||||
</span>
|
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<span>
|
<span>{nav.title}</span>
|
||||||
<Trans i18nKey={subNav.translateKey} defaults={subNav.title} />
|
|
||||||
</span>
|
|
||||||
)}
|
)}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</PermissionCheck>
|
</PermissionCheck>
|
||||||
|
|
@ -103,16 +96,12 @@ const CollapsedItem = ({ nav, onLinkClick, direction }: CollapsedItemProps) => {
|
||||||
path: subNav.path,
|
path: subNav.path,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
target={subNav.isExternalLink ? '_blank' : ''}
|
target={subNav.isExternalLink ? '_blank' : ''}
|
||||||
>
|
>
|
||||||
<span>
|
<span>{subNav.title}</span>
|
||||||
<Trans i18nKey={subNav.translateKey} defaults={subNav.title} />
|
|
||||||
</span>
|
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<span>
|
<span>{subNav.title}</span>
|
||||||
<Trans i18nKey={subNav.translateKey} defaults={subNav.title} />
|
|
||||||
</span>
|
|
||||||
)}
|
)}
|
||||||
</Dropdown.Item>
|
</Dropdown.Item>
|
||||||
</PermissionCheck>
|
</PermissionCheck>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import {
|
||||||
} from '@/constants/navigation.constant'
|
} from '@/constants/navigation.constant'
|
||||||
import useMenuActive from '@/utils/hooks/useMenuActive'
|
import useMenuActive from '@/utils/hooks/useMenuActive'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
|
||||||
import { Link, useLocation } from 'react-router-dom'
|
import { Link, useLocation } from 'react-router-dom'
|
||||||
import VerticalCollapsedMenuItem from './VerticalCollapsedMenuItem'
|
import VerticalCollapsedMenuItem from './VerticalCollapsedMenuItem'
|
||||||
import VerticalSingleMenuItem from './VerticalSingleMenuItem'
|
import VerticalSingleMenuItem from './VerticalSingleMenuItem'
|
||||||
|
|
@ -42,9 +41,6 @@ const VerticalMenuContent = (props: VerticalMenuContentProps) => {
|
||||||
onMenuItemClick,
|
onMenuItemClick,
|
||||||
direction = themeConfig.direction,
|
direction = themeConfig.direction,
|
||||||
} = props
|
} = props
|
||||||
|
|
||||||
const { t } = useTranslation()
|
|
||||||
|
|
||||||
const [defaultExpandedKeys, setDefaultExpandedKeys] = useState<string[]>([])
|
const [defaultExpandedKeys, setDefaultExpandedKeys] = useState<string[]>([])
|
||||||
const [defaultActiveKeys, setDefaultActiveKeys] = useState<string[]>([])
|
const [defaultActiveKeys, setDefaultActiveKeys] = useState<string[]>([])
|
||||||
|
|
||||||
|
|
@ -105,9 +101,7 @@ const VerticalMenuContent = (props: VerticalMenuContentProps) => {
|
||||||
label={
|
label={
|
||||||
<>
|
<>
|
||||||
<VerticalMenuIcon icon={nav.icon} />
|
<VerticalMenuIcon icon={nav.icon} />
|
||||||
<span>
|
<span>{nav.title}</span>
|
||||||
<Trans i18nKey={nav.translateKey} defaults={nav.title} />
|
|
||||||
</span>
|
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
eventKey={nav.key}
|
eventKey={nav.key}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import Tooltip from '@/components/ui/Tooltip'
|
||||||
import Menu from '@/components/ui/Menu'
|
import Menu from '@/components/ui/Menu'
|
||||||
import VerticalMenuIcon from './VerticalMenuIcon'
|
import VerticalMenuIcon from './VerticalMenuIcon'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
|
||||||
import type { CommonProps } from '@/@types/common'
|
import type { CommonProps } from '@/@types/common'
|
||||||
import type { Direction } from '@/@types/theme'
|
import type { Direction } from '@/@types/theme'
|
||||||
import type { NavigationTree } from '@/@types/navigation'
|
import type { NavigationTree } from '@/@types/navigation'
|
||||||
|
|
@ -27,10 +26,8 @@ interface DefaultItemProps {
|
||||||
interface VerticalMenuItemProps extends CollapsedItemProps, DefaultItemProps {}
|
interface VerticalMenuItemProps extends CollapsedItemProps, DefaultItemProps {}
|
||||||
|
|
||||||
const CollapsedItem = ({ title, translateKey, children, direction }: CollapsedItemProps) => {
|
const CollapsedItem = ({ title, translateKey, children, direction }: CollapsedItemProps) => {
|
||||||
const { t } = useTranslation()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip title={t(translateKey) || title} placement={direction === 'rtl' ? 'left' : 'right'}>
|
<Tooltip title={title} placement={direction === 'rtl' ? 'left' : 'right'}>
|
||||||
{children}
|
{children}
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)
|
)
|
||||||
|
|
@ -52,14 +49,10 @@ const DefaultItem = (props: DefaultItemProps) => {
|
||||||
path: nav.path,
|
path: nav.path,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
target={nav.isExternalLink ? '_blank' : ''}
|
target={nav.isExternalLink ? '_blank' : ''}
|
||||||
>
|
>
|
||||||
<VerticalMenuIcon icon={nav.icon} />
|
<VerticalMenuIcon icon={nav.icon} />
|
||||||
{!sideCollapsed && (
|
{!sideCollapsed && <span>{nav.title}</span>}
|
||||||
<span>
|
|
||||||
<Trans i18nKey={nav.translateKey} defaults={nav.title} />
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</Link>
|
</Link>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</PermissionCheck>
|
</PermissionCheck>
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,3 @@
|
||||||
// eslint-disable-next-line import/no-named-as-default
|
|
||||||
import i18n from 'i18next'
|
|
||||||
import { initReactI18next } from 'react-i18next'
|
|
||||||
import en from './lang/en.json'
|
|
||||||
import appConfig from '@/configs/app.config'
|
|
||||||
|
|
||||||
const resources = {
|
|
||||||
en: {
|
|
||||||
translation: en,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
i18n.use(initReactI18next).init({
|
|
||||||
resources,
|
|
||||||
fallbackLng: appConfig.locale,
|
|
||||||
lng: appConfig.locale,
|
|
||||||
interpolation: {
|
|
||||||
escapeValue: false,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
export const dateLocales: {
|
export const dateLocales: {
|
||||||
[key: string]: () => Promise<ILocale>
|
[key: string]: () => Promise<ILocale>
|
||||||
} = {
|
} = {
|
||||||
|
|
@ -40,5 +19,3 @@ export const dateLocales: {
|
||||||
tr: () => import('dayjs/locale/tr'),
|
tr: () => import('dayjs/locale/tr'),
|
||||||
zh: () => import('dayjs/locale/zh'),
|
zh: () => import('dayjs/locale/zh'),
|
||||||
}
|
}
|
||||||
|
|
||||||
export default i18n
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
import i18n from './locales'
|
|
||||||
|
|
||||||
export { dateLocales } from './locales'
|
|
||||||
export default i18n
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"nav": {
|
|
||||||
"home": "Home",
|
|
||||||
"singleMenuItem": "Single menu item",
|
|
||||||
"collapseMenu": {
|
|
||||||
"collapseMenu": "Collapse menu item",
|
|
||||||
"item1": "Collapse menu item 1",
|
|
||||||
"item2": "Collapse menu item 2"
|
|
||||||
},
|
|
||||||
"groupMenu": {
|
|
||||||
"groupMenu": "Group menu",
|
|
||||||
"single": "Group single menu item",
|
|
||||||
"collapse": {
|
|
||||||
"collapse": "Group collapse menu",
|
|
||||||
"item1": "Group collapse menu item 1",
|
|
||||||
"item2": "Group collapse menu item 2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { AuditedEntityDto } from '@/proxy/abp'
|
import { AuditedEntityDto } from '@/proxy/abp'
|
||||||
import { PermissionCrudDto } from '@/proxy/form'
|
import { PermissionCrudDto } from '../form/models'
|
||||||
|
|
||||||
export interface BreakDto {
|
export interface BreakDto {
|
||||||
endValue: number
|
endValue: number
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { RouteDto } from '@/proxy/routes'
|
import { RouteDto } from '@/proxy/routes/models'
|
||||||
import { lazy } from 'react'
|
import { lazy } from 'react'
|
||||||
|
|
||||||
// Tüm view bileşenlerini import et (vite özel)
|
// Tüm view bileşenlerini import et (vite özel)
|
||||||
|
|
@ -27,11 +27,11 @@ export function loadComponent(componentPath: string) {
|
||||||
|
|
||||||
// React Router için uygun bir route tipi
|
// React Router için uygun bir route tipi
|
||||||
export interface DynamicReactRoute {
|
export interface DynamicReactRoute {
|
||||||
key: string;
|
key: string
|
||||||
path: string;
|
path: string
|
||||||
getComponent: () => React.LazyExoticComponent<React.ComponentType<any>>;
|
getComponent: () => React.LazyExoticComponent<React.ComponentType<any>>
|
||||||
routeType: string;
|
routeType: string
|
||||||
authority?: string[];
|
authority?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
// API'den gelen route objesini, React Router için uygun hale getirir
|
// API'den gelen route objesini, React Router için uygun hale getirir
|
||||||
|
|
@ -42,5 +42,5 @@ export function mapDynamicRoutes(routes: RouteDto[]): DynamicReactRoute[] {
|
||||||
getComponent: () => loadComponent(route.componentPath),
|
getComponent: () => loadComponent(route.componentPath),
|
||||||
routeType: route.routeType,
|
routeType: route.routeType,
|
||||||
authority: route.authority,
|
authority: route.authority,
|
||||||
}));
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { RouteDto } from '@/proxy/routes'
|
import { RouteDto } from '@/proxy/routes/models'
|
||||||
import React, { createContext, useContext, useEffect, useState } from 'react'
|
import React, { createContext, useContext, useEffect, useState } from 'react'
|
||||||
import { useStoreState } from '@/store/store'
|
import { useStoreState } from '@/store/store'
|
||||||
|
|
||||||
|
|
@ -30,7 +30,7 @@ export const DynamicRoutesProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||||
try {
|
try {
|
||||||
// Get routes from extraProperties instead of API call
|
// Get routes from extraProperties instead of API call
|
||||||
const configRoutes = extraProperties?.routes as RouteDto[]
|
const configRoutes = extraProperties?.routes as RouteDto[]
|
||||||
|
|
||||||
if (configRoutes && Array.isArray(configRoutes)) {
|
if (configRoutes && Array.isArray(configRoutes)) {
|
||||||
setRoutes(configRoutes)
|
setRoutes(configRoutes)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { AxiosError } from 'axios'
|
import { AxiosError } from 'axios'
|
||||||
import { SignUpCredential, SignUpResponse } from '../@types/auth'
|
import { SignUpCredential, SignUpResponse } from '../@types/auth'
|
||||||
import apiService from './api.service'
|
import apiService from './api.service'
|
||||||
import { ProfileDto, UpdateProfileDto } from '../proxy/account'
|
import { ProfileDto, UpdateProfileDto } from '@/proxy/account/models'
|
||||||
|
|
||||||
export const register = (data: SignUpCredential) =>
|
export const register = (data: SignUpCredential) =>
|
||||||
apiService.fetchData<SignUpResponse>({
|
apiService.fetchData<SignUpResponse>({
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { ListResultDto } from '../../proxy'
|
import { ListResultDto } from '../../proxy'
|
||||||
import { ListFormCustomizationRequestDto } from '../../proxy/admin/list-form-customization/models'
|
import { ListFormCustomizationRequestDto } from '../../proxy/admin/list-form-customization/models'
|
||||||
import { ListFormCustomizationDto } from '../../proxy/form'
|
import { ListFormCustomizationDto } from '../../proxy/form/models'
|
||||||
import apiService from '../api.service'
|
import apiService from '../api.service'
|
||||||
|
|
||||||
export const getListFormCustomizations = (input: ListFormCustomizationRequestDto) =>
|
export const getListFormCustomizations = (input: ListFormCustomizationRequestDto) =>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { ListFormJsonRowDto, ListFormWizardDto } from '../../proxy/admin/list-form/models'
|
import { ListFormJsonRowDto, ListFormWizardDto } from '../../proxy/admin/list-form/models'
|
||||||
import { FieldsDefaultValueDto, GridOptionsEditDto } from '../../proxy/form'
|
import { FieldsDefaultValueDto, GridOptionsEditDto } from '../../proxy/form/models'
|
||||||
import apiService from '../api.service'
|
import apiService from '../api.service'
|
||||||
|
|
||||||
export const postListFormWizard = (input: ListFormWizardDto) =>
|
export const postListFormWizard = (input: ListFormWizardDto) =>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
import { AiDto } from '@/proxy/ai/models'
|
||||||
import { PagedAndSortedResultRequestDto, PagedResultDto } from '../proxy'
|
import { PagedAndSortedResultRequestDto, PagedResultDto } from '../proxy'
|
||||||
import { AiDto } from '../proxy/ai'
|
|
||||||
import apiService, { Config } from './api.service'
|
import apiService, { Config } from './api.service'
|
||||||
|
|
||||||
export class AiService {
|
export class AiService {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { AxiosError, Method } from 'axios'
|
import { AxiosError, Method } from 'axios'
|
||||||
import { URLSearchParams } from 'url'
|
import { URLSearchParams } from 'url'
|
||||||
import { GridDto } from '../proxy/form'
|
import { GridDto } from '../proxy/form/models'
|
||||||
import apiService from './api.service'
|
import apiService from './api.service'
|
||||||
|
|
||||||
export const getList = (data: Record<string, string>) => {
|
export const getList = (data: Record<string, string>) => {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { ListResultDto } from '../proxy'
|
|
||||||
import {
|
import {
|
||||||
GetPermissionListResultDto,
|
GetPermissionListResultDto,
|
||||||
IdentityRoleDto,
|
IdentityRoleDto,
|
||||||
|
|
@ -7,7 +6,8 @@ import {
|
||||||
UpdatePermissionsDto,
|
UpdatePermissionsDto,
|
||||||
UserClaimModel,
|
UserClaimModel,
|
||||||
UserInfoViewModel,
|
UserInfoViewModel,
|
||||||
} from '../proxy/admin'
|
} from '@/proxy/admin/models'
|
||||||
|
import { ListResultDto } from '../proxy'
|
||||||
import { AuditLogDto } from '../proxy/auditLog/audit-log'
|
import { AuditLogDto } from '../proxy/auditLog/audit-log'
|
||||||
import apiService from './api.service'
|
import apiService from './api.service'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { GridDto } from '@/proxy/form'
|
import { GridDto } from '@/proxy/form/models'
|
||||||
import {
|
import {
|
||||||
ImportPreviewData,
|
ImportPreviewData,
|
||||||
ListFormImportDto,
|
ListFormImportDto,
|
||||||
|
|
@ -177,7 +177,10 @@ ${headers
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
await this.updateSession(sessionId, { totalRows: rows.length, listFormCode: gridDto?.gridOptions.listFormCode || '' })
|
await this.updateSession(sessionId, {
|
||||||
|
totalRows: rows.length,
|
||||||
|
listFormCode: gridDto?.gridOptions.listFormCode || '',
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sessionId,
|
sessionId,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import {
|
||||||
ListFormCustomizationDto,
|
ListFormCustomizationDto,
|
||||||
ListFormCustomizationForUserDto,
|
ListFormCustomizationForUserDto,
|
||||||
ListFormCustomizationTypeEnum,
|
ListFormCustomizationTypeEnum,
|
||||||
} from '../proxy/form'
|
} from '../proxy/form/models'
|
||||||
import apiService from './api.service'
|
import apiService from './api.service'
|
||||||
|
|
||||||
export const getListFormCustomization = (
|
export const getListFormCustomization = (
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
import { IdentityRoleDto, IdentityUserDto } from '@/proxy/admin/models'
|
||||||
import { ListResultDto, PagedResultDto } from '../proxy'
|
import { ListResultDto, PagedResultDto } from '../proxy'
|
||||||
import { IdentityRoleDto, IdentityUserDto } from '../proxy/admin'
|
|
||||||
import {
|
import {
|
||||||
CreateUpdateOrganizationUnitDto,
|
CreateUpdateOrganizationUnitDto,
|
||||||
OrganizationUnitDto,
|
OrganizationUnitDto,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { RouteDto } from '@/proxy/routes'
|
import { RouteDto } from '@/proxy/routes/models'
|
||||||
import apiService, { Config } from '@/services/api.service'
|
import apiService, { Config } from '@/services/api.service'
|
||||||
|
|
||||||
export class RouteService {
|
export class RouteService {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { AxiosError } from 'axios'
|
import { AxiosError } from 'axios'
|
||||||
import { MainGroupedSettingDto } from '../proxy/settings'
|
|
||||||
import apiService from './api.service'
|
import apiService from './api.service'
|
||||||
|
import { MainGroupedSettingDto } from '@/proxy/settings/models'
|
||||||
|
|
||||||
export const getList = () =>
|
export const getList = () =>
|
||||||
apiService.fetchData<MainGroupedSettingDto[]>({
|
apiService.fetchData<MainGroupedSettingDto[]>({
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,24 @@
|
||||||
// scripts/tenant.ts
|
// scripts/tenant.ts
|
||||||
|
import axios from 'axios'
|
||||||
|
import https from 'https'
|
||||||
|
|
||||||
export type TenantDto = { name: string }
|
export type TenantDto = { name: string }
|
||||||
export type PagedResultDto<T> = { totalCount: number; items: T[] }
|
export type PagedResultDto<T> = { totalCount: number; items: T[] }
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function fetchTenantNames(apiUrl: string): Promise<string[]> {
|
export async function fetchTenantNames(apiUrl: string): Promise<string[]> {
|
||||||
try {
|
try {
|
||||||
const url = `${apiUrl.replace(/\/$/, '')}/api/app/platform-tenant?skipCount=0&maxResultCount=1000`
|
const url = `${apiUrl.replace(/\/$/, '')}/api/app/platform-tenant?skipCount=0&maxResultCount=1000`
|
||||||
|
const isLocalHttps = /^https:\/\/localhost(:\d+)?/i.test(apiUrl)
|
||||||
|
|
||||||
const response = await fetch(url, {
|
const response = await axios.get<PagedResultDto<TenantDto>>(url, {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
'X-Requested-With': 'XMLHttpRequest',
|
'X-Requested-With': 'XMLHttpRequest',
|
||||||
},
|
},
|
||||||
|
httpsAgent: isLocalHttps ? new https.Agent({ rejectUnauthorized: false }) : undefined,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!response.ok) {
|
return (response.data.items ?? []).map((t: TenantDto) => t.name.trim().toLowerCase())
|
||||||
console.error('[vite] Tenant API hatası:', response.status, response.statusText)
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = (await response.json()) as PagedResultDto<TenantDto>
|
|
||||||
return (data.items ?? [])
|
|
||||||
.map((t) =>
|
|
||||||
String(t?.name || '')
|
|
||||||
.trim()
|
|
||||||
.toLowerCase(),
|
|
||||||
)
|
|
||||||
.filter(Boolean)
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('[vite] Tenant listesi alınamadı:', e)
|
console.error('[vite] Tenant listesi alınamadı:', e)
|
||||||
return []
|
return []
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
// eslint-disable-next-line import/no-named-as-default
|
|
||||||
import i18n from 'i18next'
|
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { dateLocales } from '@/locales'
|
|
||||||
import { useStoreState } from '@/store'
|
import { useStoreState } from '@/store'
|
||||||
import { locale } from 'devextreme/localization'
|
import { dateLocales } from '@/constants/dateLocales.constant'
|
||||||
|
|
||||||
function useLocale() {
|
function useLocale() {
|
||||||
const cultureName = useStoreState((state) => state.locale.currentLang)
|
const cultureName = useStoreState((state) => state.locale.currentLang)
|
||||||
|
|
@ -14,10 +11,6 @@ function useLocale() {
|
||||||
)?.twoLetterISOLanguageName
|
)?.twoLetterISOLanguageName
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (cultureName !== i18n.language) {
|
|
||||||
i18n.changeLanguage(cultureName)
|
|
||||||
locale(twoLetterISOLanguageName ?? cultureName)
|
|
||||||
}
|
|
||||||
if (cultureName && twoLetterISOLanguageName && dateLocales[twoLetterISOLanguageName]) {
|
if (cultureName && twoLetterISOLanguageName && dateLocales[twoLetterISOLanguageName]) {
|
||||||
dateLocales[twoLetterISOLanguageName]().then(() => {
|
dateLocales[twoLetterISOLanguageName]().then(() => {
|
||||||
dayjs.locale(cultureName)
|
dayjs.locale(cultureName)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,10 @@
|
||||||
import { ListFormEditTabs } from '@/proxy/admin/list-form/models'
|
import { ListFormEditTabs } from '@/proxy/admin/list-form/models'
|
||||||
import { CommandColumnDto, EditingFormDto, FieldsDefaultValueDto, SubFormDto } from '@/proxy/form'
|
import {
|
||||||
|
CommandColumnDto,
|
||||||
|
EditingFormDto,
|
||||||
|
FieldsDefaultValueDto,
|
||||||
|
SubFormDto,
|
||||||
|
} from '@/proxy/form/models'
|
||||||
import { ExtractNestedValues } from '@/utils/extractNestedValues'
|
import { ExtractNestedValues } from '@/utils/extractNestedValues'
|
||||||
|
|
||||||
export type JsonRowOperation = 'create' | 'update' | 'delete'
|
export type JsonRowOperation = 'create' | 'update' | 'delete'
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,11 @@ import { useEffect, useState } from 'react'
|
||||||
import { MdBarChart, MdList } from 'react-icons/md'
|
import { MdBarChart, MdList } from 'react-icons/md'
|
||||||
import { useLocation, useNavigate } from 'react-router-dom'
|
import { useLocation, useNavigate } from 'react-router-dom'
|
||||||
import Grid from '../list/Grid'
|
import Grid from '../list/Grid'
|
||||||
|
import Chart from '../chart/Chart'
|
||||||
|
import { GridDto, SubFormDto, SubFormTabTypeEnum } from '@/proxy/form/models'
|
||||||
import FormEdit from './FormEdit'
|
import FormEdit from './FormEdit'
|
||||||
import FormNew from './FormNew'
|
import FormNew from './FormNew'
|
||||||
import FormView from './FormView'
|
import FormView from './FormView'
|
||||||
import Chart from '../chart/Chart'
|
|
||||||
import { GridDto, SubFormDto, SubFormTabTypeEnum } from '@/proxy/form/models'
|
|
||||||
|
|
||||||
const SubForms = (props: {
|
const SubForms = (props: {
|
||||||
gridDto: GridDto
|
gridDto: GridDto
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { GridBoxOptionsDto } from '@/proxy/form'
|
import { GridBoxOptionsDto } from '@/proxy/form/models'
|
||||||
import { GridColumnData } from '@/views/list/GridColumnData'
|
import { GridColumnData } from '@/views/list/GridColumnData'
|
||||||
import { Button } from 'devextreme-react/button'
|
import { Button } from 'devextreme-react/button'
|
||||||
import DataGrid from 'devextreme-react/data-grid'
|
import DataGrid from 'devextreme-react/data-grid'
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { TagBoxOptionsDto } from '@/proxy/form'
|
import { TagBoxOptionsDto } from '@/proxy/form/models'
|
||||||
import { GridColumnData } from '@/views/list/GridColumnData'
|
import { GridColumnData } from '@/views/list/GridColumnData'
|
||||||
import TagBox from 'devextreme-react/tag-box'
|
import TagBox from 'devextreme-react/tag-box'
|
||||||
import { ApplyValueMode } from 'devextreme/common'
|
import { ApplyValueMode } from 'devextreme/common'
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { FormItemComponent, SimpleItem } from 'devextreme/ui/form'
|
||||||
import { GridColumnData } from '../list/GridColumnData'
|
import { GridColumnData } from '../list/GridColumnData'
|
||||||
import { Overwrite } from '../../utils/types'
|
import { Overwrite } from '../../utils/types'
|
||||||
import { GridBoxOptionsDto, PlatformEditorTypes, TagBoxOptionsDto } from '../../proxy/form/models'
|
import { GridBoxOptionsDto, PlatformEditorTypes, TagBoxOptionsDto } from '../../proxy/form/models'
|
||||||
import { Meta } from 'easy-peasy'
|
import { Meta } from '@/@types/routes'
|
||||||
|
|
||||||
export type EditorType2 = FormItemComponent | PlatformEditorTypes.dxGridBox
|
export type EditorType2 = FormItemComponent | PlatformEditorTypes.dxGridBox
|
||||||
export type SimpleItemWithColData = Overwrite<
|
export type SimpleItemWithColData = Overwrite<
|
||||||
|
|
|
||||||
|
|
@ -402,8 +402,7 @@ export function PostManagement({
|
||||||
setPostToDelete(null)
|
setPostToDelete(null)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
></ConfirmDialog>
|
||||||
</ConfirmDialog>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
3
ui/src/views/index.ts
Normal file
3
ui/src/views/index.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
import Views from './Views'
|
||||||
|
|
||||||
|
export default Views
|
||||||
Loading…
Reference in a new issue