i18n ve Localization düzenlemesi

This commit is contained in:
Sedat ÖZTÜRK 2025-08-12 12:39:09 +03:00
parent 00eb20d55f
commit 012f507cd3
42 changed files with 1462 additions and 678 deletions

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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",

View file

@ -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
} }

View file

@ -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'

View file

@ -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,

View file

@ -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>

View file

@ -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)
} }

View file

@ -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>
} }
> >

View file

@ -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

View file

@ -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

View file

@ -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)
} }

View file

@ -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

View file

@ -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>

View file

@ -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}

View file

@ -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>

View file

@ -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

View file

@ -1,4 +0,0 @@
import i18n from './locales'
export { dateLocales } from './locales'
export default i18n

View file

@ -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"
}
}
}
}

View file

@ -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

View file

@ -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,
})); }))
} }

View file

@ -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 {

View file

@ -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>({

View file

@ -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) =>

View file

@ -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) =>

View file

@ -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 {

View file

@ -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>) => {

View file

@ -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'

View file

@ -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,

View file

@ -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 = (

View file

@ -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,

View file

@ -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 {

View file

@ -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[]>({

View file

@ -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 []

View file

@ -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)

View file

@ -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'

View file

@ -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

View file

@ -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'

View file

@ -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'

View file

@ -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<

View file

@ -402,8 +402,7 @@ export function PostManagement({
setPostToDelete(null) setPostToDelete(null)
} }
}} }}
> ></ConfirmDialog>
</ConfirmDialog>
)} )}
</div> </div>
) )

3
ui/src/views/index.ts Normal file
View file

@ -0,0 +1,3 @@
import Views from './Views'
export default Views