Codex 5.6 Sol Genel Optimizasyon

This commit is contained in:
Sedat ÖZTÜRK 2026-07-13 11:39:13 +03:00
parent e7be51a1be
commit 0ff184fcdf
47 changed files with 595 additions and 331 deletions

View file

@ -13938,6 +13938,12 @@
"en": "Api URL", "en": "Api URL",
"tr": "Api URL" "tr": "Api URL"
}, },
{
"resourceName": "Platform",
"key": "OpenUrl",
"en": "Open URL",
"tr": "URL'yi Aç"
},
{ {
"resourceName": "Platform", "resourceName": "Platform",
"key": "App.Listform.ListformField.ApplicationName", "key": "App.Listform.ListformField.ApplicationName",

View file

@ -350,7 +350,7 @@
{ {
"name": "DynamicEntityComponent", "name": "DynamicEntityComponent",
"routePath": "/admin/dynamic-entity", "routePath": "/admin/dynamic-entity",
"code": "import React, { useEffect, useState } from \"react\";\nimport axios from \"axios\";\n\ninterface DynamicEntityComponentProps {\n title: string;\n}\n\nconst api = axios.create({\n baseURL: \"https://localhost:44344\",\n});\n\nconst DynamicEntityComponent: React.FC<DynamicEntityComponentProps> = ({ title }) => {\n const [data, setData] = useState<Array<{ id: string; name: string }>>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const fetchData = async () => {\n setLoading(true);\n setError(null);\n\n try {\n const res = await api.get(`/api/app/crudendpoint/${title}`);\n const raw = Array.isArray(res.data) ? res.data : res.data?.items ?? [];\n\n const filtered = raw.map((item: any) => ({\n id: item.Id ?? item.id,\n name: item.Name ?? item.name,\n }));\n\n setData(filtered);\n } catch (err: any) {\n setError(err.message || \"Failed to fetch data\");\n } finally {\n setLoading(false);\n }\n };\n\n if (title) fetchData();\n }, [title]);\n\n if (loading) return <div>Loading...</div>;\n if (error) return <div className=\"text-red-600 dark:text-red-400\">Error: {error}</div>;\n if (!data.length) return <div>No records found</div>;\n\n const headers = [\"id\", \"name\", \"actions\"];\n\n return (\n <div className=\"overflow-auto\">\n <table className=\"min-w-full bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 shadow-sm rounded-lg\">\n <thead className=\"bg-slate-100 dark:bg-slate-800\">\n <tr>\n {headers.map((key) => (\n <th\n key={key}\n className=\"text-left px-4 py-2 border-b border-slate-200 dark:border-slate-700 text-sm font-medium text-slate-700 dark:text-slate-200\"\n >\n {key === \"actions\" ? \"Actions\" : key}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {data.map((item, rowIndex) => (\n <tr key={rowIndex} className=\"hover:bg-slate-50 dark:hover:bg-slate-800\">\n <td className=\"px-4 py-2 border-b border-slate-100 dark:border-slate-800 text-sm text-slate-800 dark:text-slate-100\">\n {item.id}\n </td>\n <td className=\"px-4 py-2 border-b border-slate-100 dark:border-slate-800 text-sm text-slate-800 dark:text-slate-100\">\n {item.name}\n </td>\n <td className=\"px-4 py-2 border-b border-slate-100 dark:border-slate-800\">\n <button\n type=\"button\"\n onClick={() => alert(item.name)}\n className=\"bg-blue-600 hover:bg-blue-700 dark:bg-blue-800 dark:hover:bg-blue-900 text-white text-sm px-3 py-1 rounded-lg shadow-sm transition\"\n >\n Show Name\n </button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n};\n\nexport default DynamicEntityComponent;", "code": "import React, { useEffect, useState } from \"react\";\nimport axios from \"axios\";\n\ninterface DynamicEntityComponentProps {\n title: string;\n}\n\nconst api = axios.create({\n baseURL: \"https://localhost:44344\",\n});\n\nconst DynamicEntityComponent: React.FC<DynamicEntityComponentProps> = ({ title }) => {\n const [data, setData] = useState<Array<{ id: string; name: string }>>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const fetchData = async () => {\n setLoading(true);\n setError(null);\n\n try {\n const res = await api.get(`/api/app/crudendpoint/${title}`);\n const raw = Array.isArray(res.data) ? res.data : res.data?.items ?? [];\n\n const filtered = raw.map((item: any) => ({\n id: item.Id ?? item.id,\n name: item.Name ?? item.name,\n }));\n\n setData(filtered);\n } catch (err: any) {\n setError(err.message || \"Failed to fetch data\");\n } finally {\n setLoading(false);\n }\n };\n\n if (title) fetchData();\n }, [title]);\n\n if (loading) return <div>Loading...</div>;\n if (error) return <div className=\"text-red-600 dark:text-red-400\">Error: {error}</div>;\n if (!data.length) return <div>No records found</div>;\n\n const headers = [\"id\", \"name\", \"actions\"];\n\n return (\n <div className=\"overflow-auto\">\n <table className=\"min-w-full bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 shadow-sm rounded-lg\">\n <thead className=\"bg-slate-100 dark:bg-slate-800\">\n <tr>\n {headers.map((key) => (\n <th\n key={key}\n className=\"text-left px-4 py-2 border-b border-slate-200 dark:border-slate-700 text-sm font-medium text-slate-700 dark:text-slate-200\"\n >\n {key === \"actions\" ? \"Actions\" : key}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {data.map((item, rowIndex) => (\n <tr key={item.id ?? rowIndex} className=\"hover:bg-slate-50 dark:hover:bg-slate-800\">\n <td className=\"px-4 py-2 border-b border-slate-100 dark:border-slate-800 text-sm text-slate-800 dark:text-slate-100\">\n {item.id}\n </td>\n <td className=\"px-4 py-2 border-b border-slate-100 dark:border-slate-800 text-sm text-slate-800 dark:text-slate-100\">\n {item.name}\n </td>\n <td className=\"px-4 py-2 border-b border-slate-100 dark:border-slate-800\">\n <Button\n type=\"button\"\n color=\"blue-500\"\n onClick={() => alert(item.name)}\n shape=\"round\"\n size=\"xs\"\n variant=\"solid\"\n id=\"c_mrix4c1a_qrybhk\"\n >\n Show Name\n </Button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n};\n\nexport default DynamicEntityComponent;",
"props": null, "props": null,
"description": null, "description": null,
"isActive": true, "isActive": true,
@ -363,9 +363,7 @@
"props": null, "props": null,
"description": null, "description": null,
"isActive": true, "isActive": true,
"dependencies": [ "dependencies": ["DynamicEntityComponent"]
"DynamicEntityComponent"
]
} }
], ],
"Abouts": [ "Abouts": [
@ -1807,9 +1805,7 @@
{ {
"postContent": "CI/CD pipeline güncellememiz tamamlandı! Deployment süremiz %40 azaldı. Otomasyonun gücü 💪", "postContent": "CI/CD pipeline güncellememiz tamamlandı! Deployment süremiz %40 azaldı. Otomasyonun gücü 💪",
"type": "video", "type": "video",
"urls": [ "urls": ["https://www.w3schools.com/html/mov_bbb.mp4"]
"https://www.w3schools.com/html/mov_bbb.mp4"
]
} }
], ],
"SocialPollOptions": [ "SocialPollOptions": [

View file

@ -1,5 +1,5 @@
{ {
"commit": "351eddf", "commit": "e7be51a",
"releases": [ "releases": [
{ {
"version": "1.1.06", "version": "1.1.06",

View file

@ -6,8 +6,8 @@ import { BrowserRouter } from 'react-router-dom'
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'
import { registerServiceWorker } from './views/version/swRegistration'
import { useEffect } from 'react' import { useEffect } from 'react'
import DevExtremeBoundary from './components/devExtreme/DevExtremeBoundary'
const queryClient = new QueryClient({ const queryClient = new QueryClient({
defaultOptions: { defaultOptions: {
@ -20,7 +20,11 @@ const queryClient = new QueryClient({
function App() { function App() {
useEffect(() => { useEffect(() => {
registerServiceWorker() void import('./views/version/swRegistration')
.then(({ registerServiceWorker }) => registerServiceWorker())
.catch((error: unknown) => {
console.warn('Service worker could not be registered.', error)
})
}, []) }, [])
return ( return (
@ -29,9 +33,11 @@ function App() {
<DynamicRoutesProvider> <DynamicRoutesProvider>
<ComponentProvider> <ComponentProvider>
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
<Theme> <DevExtremeBoundary>
<Layout /> <Theme>
</Theme> <Layout />
</Theme>
</DevExtremeBoundary>
</QueryClientProvider> </QueryClientProvider>
</ComponentProvider> </ComponentProvider>
</DynamicRoutesProvider> </DynamicRoutesProvider>

View file

@ -0,0 +1,56 @@
import Loading from '@/components/shared/Loading'
import { useStoreState } from '@/store'
import { useEffect, useState, type ReactNode } from 'react'
import { useLocation } from 'react-router-dom'
import { configureDevExtreme } from './devExtremeConfig'
interface DevExtremeBoundaryProps {
children: ReactNode
}
const DevExtremeBoundary = ({ children }: DevExtremeBoundaryProps) => {
const { pathname } = useLocation()
const cultureName = useStoreState((state) => state.locale.currentLang) || 'en'
const [configuredCulture, setConfiguredCulture] = useState<string>()
const [error, setError] = useState<Error>()
const requiresDevExtreme = pathname.startsWith('/admin')
useEffect(() => {
if (!requiresDevExtreme || configuredCulture === cultureName) return
let cancelled = false
setError(undefined)
void configureDevExtreme(cultureName)
.then(() => {
if (!cancelled) setConfiguredCulture(cultureName)
})
.catch((reason: unknown) => {
if (!cancelled) {
setError(reason instanceof Error ? reason : new Error(String(reason)))
}
})
return () => {
cancelled = true
}
}, [configuredCulture, cultureName, requiresDevExtreme])
if (!requiresDevExtreme) return children
if (error) {
return <div className="p-4 text-red-600">DevExtreme yüklenemedi: {error.message}</div>
}
if (configuredCulture !== cultureName) {
return (
<div className="flex flex-auto flex-col h-[100vh]">
<Loading loading />
</div>
)
}
return children
}
export default DevExtremeBoundary

View file

@ -0,0 +1,31 @@
let devExtremeModulesPromise:
| Promise<{
config: typeof import('devextreme/core/config').default
locale: typeof import('devextreme/localization').locale
licenseKey: string
}>
| undefined
const loadDevExtremeModules = () => {
devExtremeModulesPromise ??= Promise.all([
import('devextreme/core/config'),
import('devextreme/localization'),
import('@/devextreme-license'),
]).then(([configModule, localizationModule, licenseModule]) => ({
config: configModule.default,
locale: localizationModule.locale,
licenseKey: licenseModule.licenseKey,
}))
return devExtremeModulesPromise
}
export const configureDevExtreme = async (cultureName: string) => {
const { config, locale, licenseKey } = await loadDevExtremeModules()
config({
licenseKey,
defaultCurrency: cultureName.startsWith('tr') ? 'TRY' : 'USD',
})
locale(cultureName)
}

View file

@ -1,16 +1,18 @@
import Header from '@/components/template/Header' import Header from '@/components/template/Header'
import MobileNav from '@/components/template/MobileNav' import MobileNav from '@/components/template/MobileNav'
import Notification from '@/components/template/Notification'
import SideNav from '@/components/template/SideNav' import SideNav from '@/components/template/SideNav'
import SideNavToggle from '@/components/template/SideNavToggle' import SideNavToggle from '@/components/template/SideNavToggle'
import SidePanel from '@/components/template/SidePanel'
import UserDropdown from '@/components/template/UserDropdown' import UserDropdown from '@/components/template/UserDropdown'
import { useStoreState } from '@/store' import { useStoreState } from '@/store'
import LanguageSelector from '../template/LanguageSelector' import LanguageSelector from '../template/LanguageSelector'
import MessengerWidget from '../template/MessengerWidget'
import Search from '../template/Search'
import StackedSideNav from '../template/StackedSideNav' import StackedSideNav from '../template/StackedSideNav'
import AiAssistant from '../template/AiAssistant' import {
DeferredAiAssistant,
DeferredMessengerWidget,
DeferredNotification,
DeferredSearch,
DeferredSidePanel,
} from '../template/DeferredShellActions'
import { DynamicRouter } from '@/routes/dynamicRouter' import { DynamicRouter } from '@/routes/dynamicRouter'
const HeaderActionsStart = () => { const HeaderActionsStart = () => {
@ -18,7 +20,7 @@ const HeaderActionsStart = () => {
<> <>
<MobileNav /> <MobileNav />
<SideNavToggle /> <SideNavToggle />
<Search /> <DeferredSearch />
</> </>
) )
} }
@ -26,11 +28,11 @@ const HeaderActionsStart = () => {
const HeaderActionsEnd = () => { const HeaderActionsEnd = () => {
return ( return (
<> <>
<AiAssistant /> <DeferredAiAssistant />
<Notification /> <DeferredNotification />
<MessengerWidget /> <DeferredMessengerWidget />
<LanguageSelector /> <LanguageSelector />
<SidePanel className="hidden" /> <DeferredSidePanel />
<UserDropdown hoverable={false} /> <UserDropdown hoverable={false} />
</> </>
) )

View file

@ -1,15 +1,17 @@
import Header from '@/components/template/Header' import Header from '@/components/template/Header'
import SidePanel from '@/components/template/SidePanel'
import UserDropdown from '@/components/template/UserDropdown' import UserDropdown from '@/components/template/UserDropdown'
import HeaderLogo from '@/components/template/HeaderLogo' import HeaderLogo from '@/components/template/HeaderLogo'
import SecondaryHeader from '@/components/template/SecondaryHeader' import SecondaryHeader from '@/components/template/SecondaryHeader'
import Notification from '@/components/template/Notification'
import MobileNav from '@/components/template/MobileNav' import MobileNav from '@/components/template/MobileNav'
import View from '@/views/Views' import View from '@/views/Views'
import Search from '@/components/template/Search'
import LanguageSelector from '../template/LanguageSelector' import LanguageSelector from '../template/LanguageSelector'
import MessengerWidget from '../template/MessengerWidget' import {
import AiAssistant from '../template/AiAssistant' DeferredAiAssistant,
DeferredMessengerWidget,
DeferredNotification,
DeferredSearch,
DeferredSidePanel,
} from '../template/DeferredShellActions'
const HeaderActionsStart = () => { const HeaderActionsStart = () => {
return ( return (
@ -23,12 +25,12 @@ const HeaderActionsStart = () => {
const HeaderActionsEnd = () => { const HeaderActionsEnd = () => {
return ( return (
<> <>
<AiAssistant /> <DeferredAiAssistant />
<Search /> <DeferredSearch />
<Notification /> <DeferredNotification />
<MessengerWidget /> <DeferredMessengerWidget />
<LanguageSelector /> <LanguageSelector />
<SidePanel className="hidden" /> <DeferredSidePanel />
<UserDropdown hoverable={false} /> <UserDropdown hoverable={false} />
</> </>
) )

View file

@ -1,4 +1,4 @@
import { useMemo, lazy, Suspense } from 'react' import { Component, useMemo, lazy, Suspense, type ErrorInfo, type ReactNode } from 'react'
import Loading from '@/components/shared/Loading' import Loading from '@/components/shared/Loading'
import { useStoreState } from '@/store' import { useStoreState } from '@/store'
import { import {
@ -36,6 +36,45 @@ const layouts = {
const AuthLayout = lazy(() => import('./AuthLayout')) const AuthLayout = lazy(() => import('./AuthLayout'))
const PublicLayout = lazy(() => import('./PublicLayout')) const PublicLayout = lazy(() => import('./PublicLayout'))
class LayoutChunkErrorBoundary extends Component<
{ children: ReactNode },
{ failed: boolean }
> {
state = { failed: false }
static getDerivedStateFromError() {
return { failed: true }
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
console.error('Application layout could not be loaded.', error, errorInfo)
}
render() {
if (this.state.failed) {
return (
<div className="flex min-h-screen items-center justify-center p-6">
<div className="max-w-md text-center">
<h1 className="mb-2 text-lg font-semibold">Uygulama kabuğu yüklenemedi</h1>
<p className="mb-4 text-sm text-gray-500">
Bağlantınızı kontrol edip uygulamayı yeniden yükleyin.
</p>
<button
type="button"
className="rounded bg-indigo-600 px-4 py-2 text-sm font-medium text-white"
onClick={() => window.location.reload()}
>
Yeniden yükle
</button>
</div>
</div>
)
}
return this.props.children
}
}
const Layout = () => { const Layout = () => {
const location = useLocation() const location = useLocation()
const layoutType = useStoreState((s) => s.theme.layout.type) as LayoutType const layoutType = useStoreState((s) => s.theme.layout.type) as LayoutType
@ -94,15 +133,17 @@ const Layout = () => {
} }
return ( return (
<Suspense <LayoutChunkErrorBoundary>
fallback={ <Suspense
<div className="flex flex-auto flex-col h-[100vh]"> fallback={
<Loading loading /> <div className="flex flex-auto flex-col h-[100vh]">
</div> <Loading loading />
} </div>
> }
<AppLayout /> >
</Suspense> <AppLayout />
</Suspense>
</LayoutChunkErrorBoundary>
) )
} }

View file

@ -1,24 +1,26 @@
import Header from '@/components/template/Header' import Header from '@/components/template/Header'
import MobileNav from '@/components/template/MobileNav' import MobileNav from '@/components/template/MobileNav'
import Notification from '@/components/template/Notification'
import Search from '@/components/template/Search'
import SideNav from '@/components/template/SideNav' import SideNav from '@/components/template/SideNav'
import SideNavToggle from '@/components/template/SideNavToggle' import SideNavToggle from '@/components/template/SideNavToggle'
import SidePanel from '@/components/template/SidePanel'
import UserDropdown from '@/components/template/UserDropdown' import UserDropdown from '@/components/template/UserDropdown'
import View from '@/views/Views' import View from '@/views/Views'
import LanguageSelector from '../template/LanguageSelector' import LanguageSelector from '../template/LanguageSelector'
import MessengerWidget from '../template/MessengerWidget'
import { useStoreState } from '@/store' import { useStoreState } from '@/store'
import StackedSideNav from '../template/StackedSideNav' import StackedSideNav from '../template/StackedSideNav'
import AiAssistant from '../template/AiAssistant' import {
DeferredAiAssistant,
DeferredMessengerWidget,
DeferredNotification,
DeferredSearch,
DeferredSidePanel,
} from '../template/DeferredShellActions'
const HeaderActionsStart = () => { const HeaderActionsStart = () => {
return ( return (
<> <>
<MobileNav /> <MobileNav />
<SideNavToggle /> <SideNavToggle />
<Search /> <DeferredSearch />
</> </>
) )
} }
@ -26,11 +28,11 @@ const HeaderActionsStart = () => {
const HeaderActionsEnd = () => { const HeaderActionsEnd = () => {
return ( return (
<> <>
<AiAssistant /> <DeferredAiAssistant />
<Notification /> <DeferredNotification />
<MessengerWidget /> <DeferredMessengerWidget />
<LanguageSelector /> <LanguageSelector />
<SidePanel className="hidden" /> <DeferredSidePanel />
<UserDropdown hoverable={false} /> <UserDropdown hoverable={false} />
</> </>
) )

View file

@ -1,15 +1,17 @@
import Header from '@/components/template/Header' import Header from '@/components/template/Header'
import SidePanel from '@/components/template/SidePanel'
import UserDropdown from '@/components/template/UserDropdown' import UserDropdown from '@/components/template/UserDropdown'
import HeaderLogo from '@/components/template/HeaderLogo' import HeaderLogo from '@/components/template/HeaderLogo'
import MobileNav from '@/components/template/MobileNav' import MobileNav from '@/components/template/MobileNav'
import HorizontalNav from '@/components/template/HorizontalNav' import HorizontalNav from '@/components/template/HorizontalNav'
import View from '@/views/Views' import View from '@/views/Views'
import Notification from '@/components/template/Notification'
import Search from '@/components/template/Search'
import LanguageSelector from '../template/LanguageSelector' import LanguageSelector from '../template/LanguageSelector'
import MessengerWidget from '../template/MessengerWidget' import {
import AiAssistant from '../template/AiAssistant' DeferredAiAssistant,
DeferredMessengerWidget,
DeferredNotification,
DeferredSearch,
DeferredSidePanel,
} from '../template/DeferredShellActions'
const HeaderActionsStart = () => { const HeaderActionsStart = () => {
return ( return (
@ -23,12 +25,12 @@ const HeaderActionsStart = () => {
const HeaderActionsEnd = () => { const HeaderActionsEnd = () => {
return ( return (
<> <>
<Search /> <DeferredSearch />
<AiAssistant /> <DeferredAiAssistant />
<Notification /> <DeferredNotification />
<MessengerWidget /> <DeferredMessengerWidget />
<LanguageSelector /> <LanguageSelector />
<SidePanel className="hidden" /> <DeferredSidePanel />
<UserDropdown hoverable={false} /> <UserDropdown hoverable={false} />
</> </>
) )

View file

@ -1,20 +1,22 @@
import Header from '@/components/template/Header' import Header from '@/components/template/Header'
import SidePanel from '@/components/template/SidePanel'
import UserDropdown from '@/components/template/UserDropdown' import UserDropdown from '@/components/template/UserDropdown'
import MobileNav from '@/components/template/MobileNav' import MobileNav from '@/components/template/MobileNav'
import StackedSideNav from '@/components/template/StackedSideNav' import StackedSideNav from '@/components/template/StackedSideNav'
import View from '@/views/Views' import View from '@/views/Views'
import Search from '@/components/template/Search'
import Notification from '@/components/template/Notification'
import LanguageSelector from '../template/LanguageSelector' import LanguageSelector from '../template/LanguageSelector'
import MessengerWidget from '../template/MessengerWidget' import {
import AiAssistant from '../template/AiAssistant' DeferredAiAssistant,
DeferredMessengerWidget,
DeferredNotification,
DeferredSearch,
DeferredSidePanel,
} from '../template/DeferredShellActions'
const HeaderActionsStart = () => { const HeaderActionsStart = () => {
return ( return (
<> <>
<MobileNav /> <MobileNav />
<Search /> <DeferredSearch />
</> </>
) )
} }
@ -22,11 +24,11 @@ const HeaderActionsStart = () => {
const HeaderActionsEnd = () => { const HeaderActionsEnd = () => {
return ( return (
<> <>
<AiAssistant /> <DeferredAiAssistant />
<Notification /> <DeferredNotification />
<MessengerWidget /> <DeferredMessengerWidget />
<LanguageSelector /> <LanguageSelector />
<SidePanel className="hidden" /> <DeferredSidePanel />
<UserDropdown hoverable={false} /> <UserDropdown hoverable={false} />
</> </>
) )

View file

@ -0,0 +1,72 @@
import React, { Component, lazy, Suspense, type ErrorInfo, type ReactNode } from 'react'
const Search = lazy(() => import('./Search'))
const AiAssistant = lazy(() => import('./AiAssistant'))
const Notification = lazy(() => import('./Notification'))
const MessengerWidget = lazy(() => import('./MessengerWidget'))
const SidePanel = lazy(() => import('./SidePanel'))
interface OptionalShellActionBoundaryProps {
children: ReactNode
}
interface OptionalShellActionBoundaryState {
failed: boolean
}
class OptionalShellActionBoundary extends Component<
OptionalShellActionBoundaryProps,
OptionalShellActionBoundaryState
> {
state: OptionalShellActionBoundaryState = { failed: false }
static getDerivedStateFromError(): OptionalShellActionBoundaryState {
return { failed: true }
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
console.error('Optional shell action could not be loaded.', error, errorInfo)
}
render() {
return this.state.failed ? null : this.props.children
}
}
const ActionFallback = () => <span aria-hidden className="inline-block h-9 w-9" />
const DeferredAction = ({ children }: { children: ReactNode }) => (
<OptionalShellActionBoundary>
<Suspense fallback={<ActionFallback />}>{children}</Suspense>
</OptionalShellActionBoundary>
)
export const DeferredSearch = () => (
<DeferredAction>
<Search />
</DeferredAction>
)
export const DeferredAiAssistant = () => (
<DeferredAction>
<AiAssistant />
</DeferredAction>
)
export const DeferredNotification = () => (
<DeferredAction>
<Notification />
</DeferredAction>
)
export const DeferredMessengerWidget = () => (
<DeferredAction>
<MessengerWidget />
</DeferredAction>
)
export const DeferredSidePanel = () => (
<DeferredAction>
<SidePanel className="hidden" />
</DeferredAction>
)

View file

@ -1,52 +1,11 @@
import { import type {
CreateUpdateCustomComponentDto, CreateUpdateCustomComponentDto,
CustomComponent, CustomComponent,
CustomComponentDto, CustomComponentDto,
} from '@/proxy/developerKit/models' } from '@/proxy/developerKit/models'
import { developerKitService } from '@/services/developerKit.service' import { developerKitService } from '@/services/developerKit.service'
import { useStoreState } from '@/store/store' import { useStoreState } from '@/store/store'
import React, { createContext, useContext, useState, useEffect, useCallback } from 'react' import React, { createContext, useContext, useState, useEffect, useCallback, useMemo } from 'react'
import {
Alert,
Avatar,
Badge,
Button,
Calendar,
Card,
Checkbox,
ConfigProvider,
DatePicker,
Dialog,
Drawer,
Dropdown,
FormItem,
FormContainer,
Input,
InputGroup,
Menu,
MenuItem,
Notification,
Pagination,
Progress,
Radio,
RangeCalendar,
ScrollBar,
Segment,
Select,
Skeleton,
Spinner,
Steps,
Switcher,
Table,
Tabs,
Tag,
TimeInput,
Timeline,
toast,
Tooltip,
Upload,
} from '../components/ui'
import axios from 'axios'
interface ComponentProps { interface ComponentProps {
[key: string]: unknown [key: string]: unknown
@ -75,6 +34,39 @@ interface ComponentContextType {
const ComponentContext = createContext<ComponentContextType | undefined>(undefined) const ComponentContext = createContext<ComponentContextType | undefined>(undefined)
const HelloWorldComponent: React.ComponentType<unknown> = () =>
React.createElement('div', { className: 'p-6 bg-blue-50 rounded-lg' }, [
React.createElement(
'h1',
{ key: 'title', className: 'text-2xl font-bold text-blue-900 mb-4' },
'Hello World!',
),
React.createElement(
'p',
{ key: 'description', className: 'text-blue-700' },
'Bu manuel kayıtlı bir komponent!',
),
])
const TestListComponent: React.ComponentType<unknown> = () =>
React.createElement('div', { className: 'p-6 bg-green-50 rounded-lg' }, [
React.createElement(
'h1',
{ key: 'title', className: 'text-2xl font-bold text-green-900 mb-4' },
'Test List',
),
React.createElement(
'p',
{ key: 'description', className: 'text-green-700' },
'Bu da test için kayıtlı komponent!',
),
])
const defaultRegisteredComponents: Record<string, React.ComponentType<unknown>> = {
HelloWorld: HelloWorldComponent,
TestList: TestListComponent,
}
// eslint-disable-next-line react-refresh/only-export-components // eslint-disable-next-line react-refresh/only-export-components
export const useComponents = () => { export const useComponents = () => {
const context = useContext(ComponentContext) const context = useContext(ComponentContext)
@ -89,16 +81,13 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
const [components, setComponents] = useState<CustomComponent[]>([]) const [components, setComponents] = useState<CustomComponent[]>([])
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null) const [error, setError] = useState<string | null>(null)
const [registeredComponents, setRegisteredComponents] = useState< const [registeredComponents, setRegisteredComponents] = useState(defaultRegisteredComponents)
Record<string, React.ComponentType<unknown>>
>({})
const [compiledComponents, setCompiledComponents] = useState< const [compiledComponents, setCompiledComponents] = useState<
Record<string, React.ComponentType<ComponentProps>> Record<string, React.ComponentType<ComponentProps>>
>({}) >({})
const refreshComponents = async () => { const refreshComponents = useCallback(async () => {
try { try {
setLoading(true)
setError(null) setError(null)
const customComponents = extraProperties?.customComponents as CustomComponentDto[] const customComponents = extraProperties?.customComponents as CustomComponentDto[]
@ -107,16 +96,14 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
setError(err instanceof Error ? err.message : 'Failed to fetch components') setError(err instanceof Error ? err.message : 'Failed to fetch components')
console.error('Failed to fetch components:', err) console.error('Failed to fetch components:', err)
setComponents([]) setComponents([])
} finally {
setLoading(false)
} }
} }, [extraProperties])
useEffect(() => { useEffect(() => {
refreshComponents() refreshComponents()
}, [extraProperties]) }, [refreshComponents])
const addComponent = async (componentData: CreateUpdateCustomComponentDto) => { const addComponent = useCallback(async (componentData: CreateUpdateCustomComponentDto) => {
try { try {
setLoading(true) setLoading(true)
setError(null) setError(null)
@ -128,9 +115,12 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
} finally { } finally {
setLoading(false) setLoading(false)
} }
} }, [])
const updateComponent = async (id: string, componentData: CreateUpdateCustomComponentDto) => { const updateComponent = useCallback(async (
id: string,
componentData: CreateUpdateCustomComponentDto,
) => {
try { try {
setLoading(true) setLoading(true)
setError(null) setError(null)
@ -144,9 +134,9 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
} finally { } finally {
setLoading(false) setLoading(false)
} }
} }, [])
const deleteComponent = async (id: string) => { const deleteComponent = useCallback(async (id: string) => {
try { try {
setLoading(true) setLoading(true)
setError(null) setError(null)
@ -158,78 +148,36 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
} finally { } finally {
setLoading(false) setLoading(false)
} }
} }, [])
const getComponent = (id: string) => {
return components?.find((comp) => comp.id === id)
}
const getComponentByName = (name: string) => { const componentsById = useMemo(
return components?.find((comp) => comp.name === name) () => new Map(components.map((component) => [component.id, component])),
} [components],
)
const componentsByName = useMemo(
() => new Map(components.map((component) => [component.name, component])),
[components],
)
const activeComponentsByName = useMemo(
() => new Map(components.filter((component) => component.isActive).map((component) => [component.name, component])),
[components],
)
const registerComponent = (name: string, component: React.ComponentType<unknown>) => { const getComponent = useCallback((id: string) => componentsById.get(id), [componentsById])
setRegisteredComponents((prev) => ({
...prev,
[name]: component,
}))
}
// Register some default components on mount const getComponentByName = useCallback(
useEffect(() => { (name: string) => componentsByName.get(name),
// Example components for testing [componentsByName],
const HelloWorldComponent: React.ComponentType<unknown> = () => { )
return React.createElement(
'div', const registerComponent = useCallback(
{ (name: string, component: React.ComponentType<unknown>) => {
className: 'p-6 bg-blue-50 rounded-lg', setRegisteredComponents((previous) =>
}, previous[name] === component ? previous : { ...previous, [name]: component },
[
React.createElement(
'h1',
{
className: 'text-2xl font-bold text-blue-900 mb-4',
},
'Hello World!',
),
React.createElement(
'p',
{
className: 'text-blue-700',
},
'Bu manuel kayıtlı bir komponent!',
),
],
) )
} },
[],
const TestListComponent: React.ComponentType<unknown> = () => { )
return React.createElement(
'div',
{
className: 'p-6 bg-green-50 rounded-lg',
},
[
React.createElement(
'h1',
{
className: 'text-2xl font-bold text-green-900 mb-4',
},
'Test List',
),
React.createElement(
'p',
{
className: 'text-green-700',
},
'Bu da test için kayıtlı komponent!',
),
],
)
}
registerComponent('HelloWorld', HelloWorldComponent)
registerComponent('TestList', TestListComponent)
}, []) // Empty dependency array - only run once
// Component compilation functions (moved from ComponentRegistryProvider) // Component compilation functions (moved from ComponentRegistryProvider)
const extractComponentInfo = useCallback((code: string, defaultName = '') => { const extractComponentInfo = useCallback((code: string, defaultName = '') => {
@ -259,7 +207,10 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
// Compile components when they change // Compile components when they change
useEffect(() => { useEffect(() => {
if (!components || !components?.length) return if (!components.length) {
setCompiledComponents({})
return
}
let cancelled = false let cancelled = false
@ -332,9 +283,54 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
// Babel is several megabytes and is only needed when an active runtime // Babel is several megabytes and is only needed when an active runtime
// component exists. Keep it out of the application startup bundle. // component exists. Keep it out of the application startup bundle.
const Babel = await import('@babel/standalone') const [Babel, ui, { default: axios }] = await Promise.all([
import('@babel/standalone'),
import('../components/ui'),
import('axios'),
])
if (cancelled) return if (cancelled) return
const {
Alert,
Avatar,
Badge,
Button,
Calendar,
Card,
Checkbox,
ConfigProvider,
DatePicker,
Dialog,
Drawer,
Dropdown,
FormItem,
FormContainer,
Input,
InputGroup,
Menu,
MenuItem,
Notification,
Pagination,
Progress,
Radio,
RangeCalendar,
ScrollBar,
Segment,
Select,
Skeleton,
Spinner,
Steps,
Switcher,
Table,
Tabs,
Tag,
TimeInput,
Timeline,
toast,
Tooltip,
Upload,
} = ui
const compiledBundle = Babel.transform(bundledCode, { const compiledBundle = Babel.transform(bundledCode, {
presets: ['react', 'typescript'], presets: ['react', 'typescript'],
filename: 'components-bundle.tsx', filename: 'components-bundle.tsx',
@ -453,7 +449,7 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
return <Component {...props} /> return <Component {...props} />
} }
const component = components.find((c) => c.name === name && c.isActive) const component = activeComponentsByName.get(name)
if (!component) { if (!component) {
console.error(`Component not found: ${name}`) console.error(`Component not found: ${name}`)
return ( return (
@ -465,7 +461,7 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
return null return null
}, },
[components, compiledComponents], [activeComponentsByName, compiledComponents],
) )
const compileAndRender = useCallback((code: string) => { const compileAndRender = useCallback((code: string) => {
@ -476,43 +472,63 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
const isComponentRegistered = useCallback( const isComponentRegistered = useCallback(
(name: string) => { (name: string) => {
return components.some((c) => c.name === name && c.isActive) || !!compiledComponents[name] return activeComponentsByName.has(name) || !!compiledComponents[name]
}, },
[components, compiledComponents], [activeComponentsByName, compiledComponents],
) )
const getRegisteredComponents = useCallback(() => { const getRegisteredComponents = useCallback(() => {
const dbComponents = components?.filter((c) => c.isActive).map((c) => c.name) || [] const dbComponents = [...activeComponentsByName.keys()]
const compiledNames = Object.keys(compiledComponents) const compiledNames = Object.keys(compiledComponents)
return [...new Set([...dbComponents, ...compiledNames])] return [...new Set([...dbComponents, ...compiledNames])]
}, [components, compiledComponents]) }, [activeComponentsByName, compiledComponents])
const getComponentCode = useCallback( const getComponentCode = useCallback(
(name: string) => { (name: string) => {
const component = components.find((c) => c.name === name) const component = componentsByName.get(name)
return component ? component.code : null return component ? component.code : null
}, },
[components], [componentsByName],
) )
const value = { const value = useMemo<ComponentContextType>(
components, () => ({
loading, components,
error, loading,
addComponent, error,
updateComponent, addComponent,
deleteComponent, updateComponent,
getComponent, deleteComponent,
getComponentByName, getComponent,
refreshComponents, getComponentByName,
registeredComponents, refreshComponents,
registerComponent, registeredComponents,
renderComponent, registerComponent,
compileAndRender, renderComponent,
isComponentRegistered, compileAndRender,
getRegisteredComponents, isComponentRegistered,
getComponentCode, getRegisteredComponents,
} getComponentCode,
}),
[
components,
loading,
error,
addComponent,
updateComponent,
deleteComponent,
getComponent,
getComponentByName,
refreshComponents,
registeredComponents,
registerComponent,
renderComponent,
compileAndRender,
isComponentRegistered,
getRegisteredComponents,
getComponentCode,
],
)
return <ComponentContext.Provider value={value}>{children}</ComponentContext.Provider> return <ComponentContext.Provider value={value}>{children}</ComponentContext.Provider>
} }

View file

@ -1,15 +1,38 @@
/* eslint-disable import/default */
import ReactDOM from 'react-dom/client' import ReactDOM from 'react-dom/client'
import App from './App' import App from './App'
import './index.css' import './index.css'
import { UiEvalService } from './services/UiEvalService'
import config from 'devextreme/core/config' type UiEvalServiceModule = typeof import('./services/UiEvalService')
import { licenseKey } from './devextreme-license'
// Lisansı uygulama başlamadan önce kaydediyoruz let uiEvalServicePromise: Promise<UiEvalServiceModule> | undefined
config({ licenseKey }) const loadUiEvalService = () =>
(uiEvalServicePromise ??= import('./services/UiEvalService'))
const lazyUiEvalService = new Proxy<Record<string, (...args: unknown[]) => void>>(
{},
{
get: (_, methodName) => {
if (typeof methodName !== 'string') return undefined
return (...args: unknown[]) => {
void loadUiEvalService()
.then(({ UiEvalService }) => {
const serviceMethod = Reflect.get(UiEvalService, methodName)
if (typeof serviceMethod === 'function') {
Reflect.apply(serviceMethod, UiEvalService, args)
}
})
.catch((error: unknown) => {
console.error(`UiEvalService.${methodName} could not be loaded.`, error)
})
}
},
},
)
const globalWithUiEval = globalThis as typeof globalThis & {
UiEvalService?: typeof lazyUiEvalService
}
globalWithUiEval.UiEvalService ??= lazyUiEvalService
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(<App />) ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(<App />)
UiEvalService.Init()

View file

@ -1,5 +1,3 @@
import { Gantt } from 'devextreme-react'
export const extraFilterControlTypeOptions = [ export const extraFilterControlTypeOptions = [
{ value: 'Select', label: 'Select' }, { value: 'Select', label: 'Select' },
{ value: 'TextBox', label: 'TextBox' }, { value: 'TextBox', label: 'TextBox' },
@ -175,4 +173,4 @@ export const tooltipFormatListOptions = [
{ value: 'thousands', label: 'Thousands' }, { value: 'thousands', label: 'Thousands' },
{ value: 'trillions', label: 'Trillions' }, { value: 'trillions', label: 'Trillions' },
{ value: 'year', label: 'Year' }, { value: 'year', label: 'Year' },
] ]

View file

@ -1,10 +1,10 @@
import { import type {
HorizontalAlignment, HorizontalAlignment,
ScrollMode, ScrollMode,
SelectAllMode, SelectAllMode,
type SingleMultipleOrNone, SingleMultipleOrNone,
} from 'devextreme/common' } from 'devextreme/common'
import { import type {
ApplyFilterMode, ApplyFilterMode,
ColumnChooserMode, ColumnChooserMode,
ColumnResizeMode, ColumnResizeMode,
@ -15,7 +15,7 @@ import {
StartEditAction, StartEditAction,
StateStoreType, StateStoreType,
} from 'devextreme/ui/data_grid_types' } from 'devextreme/ui/data_grid_types'
import { FormItemComponent } from 'devextreme/ui/form' import type { FormItemComponent } from 'devextreme/ui/form'
import { AuditedEntityDto } from '../abp' import { AuditedEntityDto } from '../abp'
import { EditorType2, RowMode } from '../../views/form/types' import { EditorType2, RowMode } from '../../views/form/types'
import { import {
@ -42,9 +42,9 @@ import {
ChartZoomAndPanDto, ChartZoomAndPanDto,
} from '../admin/charts/models' } from '../admin/charts/models'
import { ListViewLayoutType } from '@/views/admin/listForm/edit/types' import { ListViewLayoutType } from '@/views/admin/listForm/edit/types'
import { SeriesType } from 'devextreme/common/charts' import type { SeriesType } from 'devextreme/common/charts'
import { PagerDisplayMode } from 'devextreme/common/grids' import type { PagerDisplayMode } from 'devextreme/common/grids'
import { GanttScaleType } from 'devextreme/ui/gantt' import type { GanttScaleType } from 'devextreme/ui/gantt'
//1 //1
export interface SelectListItem { export interface SelectListItem {

View file

@ -1,20 +1,25 @@
import React, { lazy } from 'react' import React, { lazy } from 'react'
import { RouteDto } from '@/proxy/routes/models' import type { RouteDto } from '@/proxy/routes/models'
import { CustomComponent } from '@/proxy/developerKit/models' import type { CustomComponent } from '@/proxy/developerKit/models'
// Tüm view bileşenlerini import et (vite özel) // Tüm view bileşenlerini import et (vite özel)
// shared klasörü hariç, çünkü bu bileşenler genellikle başka yerlerde statik import ediliyor // shared klasörü hariç, çünkü bu bileşenler genellikle başka yerlerde statik import ediliyor
const modules = import.meta.glob(['../views/**/*.tsx', '!../views/shared/**/*.tsx']) const modules = import.meta.glob(['../views/**/*.tsx', '!../views/shared/**/*.tsx'])
const lazyComponentCache = new Map<string, React.LazyExoticComponent<React.ComponentType<any>>>() // Only physical modules are safe to cache. Runtime components depend on the
// latest ComponentContext render function and must not retain an old closure.
const physicalComponentCache = new Map<
string,
React.LazyExoticComponent<React.ComponentType<any>>
>()
// Fiziksel komponent yükleme (mevcut mantık) // Fiziksel komponent yükleme (mevcut mantık)
function loadPhysicalComponent(componentPath: string) { function loadPhysicalComponent(componentPath: string) {
const cleanedPath = componentPath.replace(/^@\//, '') const cleanedPath = componentPath.replace(/^@\//, '')
const fullPath = `../${cleanedPath}.tsx` const fullPath = `../${cleanedPath}.tsx`
if (lazyComponentCache.has(fullPath)) { if (physicalComponentCache.has(fullPath)) {
return lazyComponentCache.get(fullPath)! return physicalComponentCache.get(fullPath)!
} }
const loader = modules[fullPath] const loader = modules[fullPath]
@ -24,7 +29,7 @@ function loadPhysicalComponent(componentPath: string) {
} }
const LazyComponent = lazy(loader as () => Promise<{ default: React.ComponentType<any> }>) const LazyComponent = lazy(loader as () => Promise<{ default: React.ComponentType<any> }>)
lazyComponentCache.set(fullPath, LazyComponent) physicalComponentCache.set(fullPath, LazyComponent)
return LazyComponent return LazyComponent
} }
@ -35,12 +40,6 @@ function loadDynamicComponent(
renderComponent?: (name: string, props?: any) => React.ReactNode, renderComponent?: (name: string, props?: any) => React.ReactNode,
isComponentRegistered?: (name: string) => boolean, isComponentRegistered?: (name: string) => boolean,
) { ) {
if (lazyComponentCache.has(componentPath)) {
// console.log(`Dynamic component loaded from cache: ${componentName}`)
return lazyComponentCache.get(componentPath)!
}
// Önce manuel registered komponentleri kontrol et // Önce manuel registered komponentleri kontrol et
let DynamicComponent = registeredComponents[componentPath] let DynamicComponent = registeredComponents[componentPath]
@ -61,13 +60,10 @@ function loadDynamicComponent(
throw new Error(`Dynamic component not found: ${componentPath}`) throw new Error(`Dynamic component not found: ${componentPath}`)
} }
// console.log(`Dynamic component loaded: ${componentPath}`) // Do not put this wrapper in a module-level cache. renderComponent changes
// Dinamik komponent için lazy wrapper oluştur // after the asynchronous database bundle compilation finishes. Caching this
const LazyComponent = lazy(() => // function would keep the pre-compilation closure and render an empty page.
Promise.resolve({ default: DynamicComponent as React.ComponentType<any> }), return DynamicComponent as React.ComponentType<any>
)
lazyComponentCache.set(componentPath, LazyComponent)
return LazyComponent
} }
export function loadComponent( export function loadComponent(
@ -103,7 +99,7 @@ export interface DynamicReactRoute {
registeredComponents?: Record<string, React.ComponentType<unknown>>, registeredComponents?: Record<string, React.ComponentType<unknown>>,
renderComponent?: (name: string, props?: any) => React.ReactNode, renderComponent?: (name: string, props?: any) => React.ReactNode,
isComponentRegistered?: (name: string) => boolean, isComponentRegistered?: (name: string) => boolean,
) => React.LazyExoticComponent<React.ComponentType<any>> ) => React.ComponentType<any>
routeType: string routeType: string
authority?: string[] authority?: string[]
componentType: string componentType: string

View file

@ -37,7 +37,7 @@ export const updateSent = (notificationId: string, isSent: boolean) =>
}) })
export const updateReadMany = (notificationIds: string[], isRead: boolean) => export const updateReadMany = (notificationIds: string[], isRead: boolean) =>
apiService.fetchData<number>({ apiService.fetchData<number, string[]>({
method: 'PUT', method: 'PUT',
url: `/api/app/notification/read-many`, url: `/api/app/notification/read-many`,
params: { isRead }, params: { isRead },
@ -45,7 +45,7 @@ export const updateReadMany = (notificationIds: string[], isRead: boolean) =>
}) })
export const updateSentMany = (notificationIds: string[], isSent: boolean) => export const updateSentMany = (notificationIds: string[], isSent: boolean) =>
apiService.fetchData<number>({ apiService.fetchData<number, string[]>({
method: 'PUT', method: 'PUT',
url: `/api/app/notification/sent-many`, url: `/api/app/notification/sent-many`,
params: { isSent }, params: { isSent },

View file

@ -2,8 +2,6 @@ import { useEffect } from 'react'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc' import utc from 'dayjs/plugin/utc'
import timezone from 'dayjs/plugin/timezone' import timezone from 'dayjs/plugin/timezone'
import { locale as dxLocale } from 'devextreme/localization'
import config from 'devextreme/core/config'
import { useStoreState } from '@/store' import { useStoreState } from '@/store'
import { dateLocales } from '@/constants/dateLocales.constant' import { dateLocales } from '@/constants/dateLocales.constant'
@ -26,14 +24,6 @@ function useLocale() {
dayjs.locale(cultureName) dayjs.locale(cultureName)
dayjs.tz.setDefault(timeZone) dayjs.tz.setDefault(timeZone)
// ✅ DevExtreme locale ayarı
dxLocale(cultureName)
// ✅ Para birimi
config({
defaultCurrency: cultureName.startsWith('tr') ? 'TRY' : 'USD',
})
// console.info(`🌍 Locale: ${cultureName}, TZ: ${timeZone}`) // console.info(`🌍 Locale: ${cultureName}, TZ: ${timeZone}`)
}) })
} }

View file

@ -9,7 +9,7 @@ import {
import { ListFormEditTabs } from '@/proxy/admin/list-form/options' import { ListFormEditTabs } from '@/proxy/admin/list-form/options'
import { useStoreState } from '@/store' import { useStoreState } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { ColumnChooserMode, ColumnResizeMode } from 'devextreme/common/grids' import type { ColumnChooserMode, ColumnResizeMode } from 'devextreme/common/grids'
import { Field, FieldProps, Form, Formik } from 'formik' import { Field, FieldProps, Form, Formik } from 'formik'
import * as Yup from 'yup' import * as Yup from 'yup'
import { FormEditProps } from './FormEdit' import { FormEditProps } from './FormEdit'

View file

@ -3,7 +3,7 @@ import { Button, Card, Checkbox, FormContainer, FormItem, Input, Select } from '
import { ListFormEditTabs } from '@/proxy/admin/list-form/options' import { ListFormEditTabs } from '@/proxy/admin/list-form/options'
import { useStoreState } from '@/store' import { useStoreState } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { import type {
GridsEditMode, GridsEditMode,
GridsEditRefreshMode, GridsEditRefreshMode,
NewRowPosition, NewRowPosition,

View file

@ -11,7 +11,7 @@ import {
import { ListFormEditTabs } from '@/proxy/admin/list-form/options' import { ListFormEditTabs } from '@/proxy/admin/list-form/options'
import { useStoreState } from '@/store' import { useStoreState } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { ApplyFilterMode } from 'devextreme/common/grids' import type { ApplyFilterMode } from 'devextreme/common/grids'
import { Field, FieldProps, Form, Formik } from 'formik' import { Field, FieldProps, Form, Formik } from 'formik'
import * as Yup from 'yup' import * as Yup from 'yup'
import { FormEditProps } from './FormEdit' import { FormEditProps } from './FormEdit'

View file

@ -20,7 +20,7 @@ import { useCallback, useEffect, useState } from 'react'
import { getListFormFields } from '@/services/admin/list-form-field.service' import { getListFormFields } from '@/services/admin/list-form-field.service'
import groupBy from 'lodash/groupBy' import groupBy from 'lodash/groupBy'
import { useParams } from 'react-router-dom' import { useParams } from 'react-router-dom'
import { GanttScaleType } from 'devextreme/ui/gantt' import type { GanttScaleType } from 'devextreme/ui/gantt'
import { gantScaleOptions } from './options' import { gantScaleOptions } from './options'
const validationSchema = Yup.object().shape({}) const validationSchema = Yup.object().shape({})

View file

@ -3,8 +3,8 @@ import { Button, Checkbox, FormContainer, FormItem, Input, Select } from '@/comp
import { ListFormEditTabs } from '@/proxy/admin/list-form/options' import { ListFormEditTabs } from '@/proxy/admin/list-form/options'
import { useStoreState } from '@/store' import { useStoreState } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { ScrollMode } from 'devextreme/common' import type { ScrollMode } from 'devextreme/common'
import { PagerDisplayMode } from 'devextreme/common/grids' import type { PagerDisplayMode } from 'devextreme/common/grids'
import { Field, FieldProps, Form, Formik } from 'formik' import { Field, FieldProps, Form, Formik } from 'formik'
import * as Yup from 'yup' import * as Yup from 'yup'
import { FormEditProps } from './FormEdit' import { FormEditProps } from './FormEdit'

View file

@ -3,8 +3,8 @@ import { Button, Checkbox, FormContainer, FormItem, Select } from '@/components/
import { ListFormEditTabs } from '@/proxy/admin/list-form/options' import { ListFormEditTabs } from '@/proxy/admin/list-form/options'
import { useStoreState } from '@/store' import { useStoreState } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { SelectAllMode, SingleMultipleOrNone } from 'devextreme/common' import type { SelectAllMode, SingleMultipleOrNone } from 'devextreme/common'
import { SelectionColumnDisplayMode } from 'devextreme/common/grids' import type { SelectionColumnDisplayMode } from 'devextreme/common/grids'
import { Field, FieldProps, Form, Formik } from 'formik' import { Field, FieldProps, Form, Formik } from 'formik'
import * as Yup from 'yup' import * as Yup from 'yup'
import { FormEditProps } from './FormEdit' import { FormEditProps } from './FormEdit'

View file

@ -3,7 +3,7 @@ import { Button, Checkbox, FormContainer, FormItem, Input, Select } from '@/comp
import { ListFormEditTabs } from '@/proxy/admin/list-form/options' import { ListFormEditTabs } from '@/proxy/admin/list-form/options'
import { useStoreState } from '@/store' import { useStoreState } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { StateStoreType } from 'devextreme/common/grids' import type { StateStoreType } from 'devextreme/common/grids'
import { Field, FieldProps, Form, Formik } from 'formik' import { Field, FieldProps, Form, Formik } from 'formik'
import * as Yup from 'yup' import * as Yup from 'yup'
import { FormEditProps } from './FormEdit' import { FormEditProps } from './FormEdit'

View file

@ -58,6 +58,7 @@ function ComponentCodeLayout() {
try { try {
const componentData = { const componentData = {
name: name.trim(), name: name.trim(),
routePath: id ? (getComponent(id)?.routePath ?? '') : '',
dependencies: JSON.stringify(dependencies), // Serialize dependencies to JSON string dependencies: JSON.stringify(dependencies), // Serialize dependencies to JSON string
code: code.trim(), code: code.trim(),
isActive, isActive,

View file

@ -10,6 +10,7 @@ import {
FaEyeSlash, FaEyeSlash,
FaFilter, FaFilter,
FaCalendarAlt, FaCalendarAlt,
FaExternalLinkAlt,
} from 'react-icons/fa' } from 'react-icons/fa'
import Widget from '@/components/common/Widget' import Widget from '@/components/common/Widget'
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
@ -65,6 +66,11 @@ const ComponentManager: React.FC = () => {
} }
} }
const handleOpenRoute = (routePath: string) => {
const normalizedPath = routePath.startsWith('/') ? routePath : `/${routePath}`
navigate(normalizedPath)
}
return ( return (
<div className="space-y-4"> <div className="space-y-4">
<Helmet <Helmet
@ -241,6 +247,17 @@ const ComponentManager: React.FC = () => {
</Button> </Button>
</div> </div>
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<Button
type="button"
variant="solid"
shape="circle"
color="gray-600"
disabled={!component.isActive || !component.routePath?.trim()}
title={translate('::OpenUrl')}
onClick={() => handleOpenRoute(component.routePath)}
>
<FaExternalLinkAlt className="w-3 h-3" />
</Button>
<Button <Button
type="button" type="button"
variant="solid" variant="solid"
@ -255,7 +272,7 @@ const ComponentManager: React.FC = () => {
'_blank', '_blank',
) )
} }
title={translate('::App.DeveloperKit.Component.Edit')} title={translate('::Edit')}
> >
<FaRegEdit className="w-3 h-3" /> <FaRegEdit className="w-3 h-3" />
</Button> </Button>
@ -272,7 +289,7 @@ const ComponentManager: React.FC = () => {
), ),
) )
} }
title={translate('::App.DeveloperKit.Component.View')} title={translate('::App.Platform.View')}
> >
<FaEye className="w-3 h-3" /> <FaEye className="w-3 h-3" />
</Button> </Button>
@ -282,7 +299,7 @@ const ComponentManager: React.FC = () => {
shape="circle" shape="circle"
color="red-600" color="red-600"
onClick={() => handleDelete(component.id)} onClick={() => handleDelete(component.id)}
title={translate('::App.DeveloperKit.Component.Delete')} title={translate('::Delete')}
> >
<FaTrashAlt className="w-3 h-3" /> <FaTrashAlt className="w-3 h-3" />
</Button> </Button>

View file

@ -3,11 +3,11 @@ import '@/utils/registerDevExtremeEditors'
import { executeEditorScript } from '@/utils/editorScriptRuntime' import { executeEditorScript } from '@/utils/editorScriptRuntime'
import { import {
Form as FormDx, Form as FormDx,
FormRef, type FormRef,
GroupItem as GroupItemDx, GroupItem as GroupItemDx,
SimpleItem as SimpleItemDx, SimpleItem as SimpleItemDx,
} from 'devextreme-react/form' } from 'devextreme-react/form'
import { FieldDataChangedEvent, GroupItem } from 'devextreme/ui/form' import type { FieldDataChangedEvent, GroupItem } from 'devextreme/ui/form'
import { Dispatch, RefObject, useEffect, useRef, useState } from 'react' import { Dispatch, RefObject, useEffect, useRef, useState } from 'react'
import { GridBoxEditorComponent } from './editors/GridBoxEditorComponent' import { GridBoxEditorComponent } from './editors/GridBoxEditorComponent'
import { ImageUploadEditorComponent } from './editors/ImageUploadEditorComponent' import { ImageUploadEditorComponent } from './editors/ImageUploadEditorComponent'

View file

@ -1,7 +1,7 @@
import { Container, Loading } from '@/components/shared' import { Container, Loading } from '@/components/shared'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { DataType } from 'devextreme/common' import type { DataType } from 'devextreme/common'
import { SimpleItem } from 'devextreme/ui/form' import type { SimpleItem } from 'devextreme/ui/form'
import { useEffect, useRef, useState } from 'react' import { useEffect, useRef, useState } from 'react'
import { Helmet } from 'react-helmet' import { Helmet } from 'react-helmet'
import { useParams, useSearchParams } from 'react-router-dom' import { useParams, useSearchParams } from 'react-router-dom'

View file

@ -1,4 +1,4 @@
import { FormItemComponent, SimpleItem } from 'devextreme/ui/form' import type { FormItemComponent, SimpleItem } from 'devextreme/ui/form'
import { Overwrite } from '../../utils/types' import { Overwrite } from '../../utils/types'
import { import {
ColumnFormatDto, ColumnFormatDto,

View file

@ -2,10 +2,10 @@ import { Notification, toast } from '@/components/ui'
import { getList } from '@/services/form.service' import { getList } from '@/services/form.service'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { usePermission } from '@/utils/hooks/usePermission' import { usePermission } from '@/utils/hooks/usePermission'
import { FormRef } from 'devextreme-react/form' import type { FormRef } from 'devextreme-react/form'
import { captionize } from 'devextreme/core/utils/inflector' import { captionize } from 'devextreme/core/utils/inflector'
import CustomStore from 'devextreme/data/custom_store' import CustomStore from 'devextreme/data/custom_store'
import { GroupItem } from 'devextreme/ui/form' import type { GroupItem } from 'devextreme/ui/form'
import { useEffect, useRef, useState } from 'react' import { useEffect, useRef, useState } from 'react'
import { useNavigate, useSearchParams } from 'react-router-dom' import { useNavigate, useSearchParams } from 'react-router-dom'
import { GridColumnData } from '../list/GridColumnData' import { GridColumnData } from '../list/GridColumnData'

View file

@ -7,7 +7,7 @@ import Gantt, {
ContextMenu, ContextMenu,
Editing, Editing,
FilterRow, FilterRow,
GanttRef, type GanttRef,
HeaderFilter, HeaderFilter,
Item, Item,
Sorting, Sorting,
@ -24,7 +24,7 @@ import { layoutTypes } from '../admin/listForm/edit/types'
import WidgetGroup from '@/components/ui/Widget/WidgetGroup' import WidgetGroup from '@/components/ui/Widget/WidgetGroup'
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
import { usePWA } from '@/utils/hooks/usePWA' import { usePWA } from '@/utils/hooks/usePWA'
import { GanttScaleType } from 'devextreme/ui/gantt' import type { GanttScaleType } from 'devextreme/ui/gantt'
import { useListFormColumns } from './useListFormColumns' import { useListFormColumns } from './useListFormColumns'
import CustomStore from 'devextreme/data/custom_store' import CustomStore from 'devextreme/data/custom_store'
import { GridColumnData } from './GridColumnData' import { GridColumnData } from './GridColumnData'

View file

@ -16,8 +16,8 @@ import { Template } from 'devextreme-react/core/template'
import DataGrid, { import DataGrid, {
ColumnChooser, ColumnChooser,
ColumnFixing, ColumnFixing,
DataGridRef, type DataGridRef,
DataGridTypes, type DataGridTypes,
Editing, Editing,
Export, Export,
FilterPanel, FilterPanel,
@ -38,7 +38,7 @@ import DataGrid, {
TotalItem, TotalItem,
} from 'devextreme-react/data-grid' } from 'devextreme-react/data-grid'
import { Item } from 'devextreme-react/toolbar' import { Item } from 'devextreme-react/toolbar'
import { DataType } from 'devextreme/common' import type { DataType } from 'devextreme/common'
import { captionize } from 'devextreme/core/utils/inflector' import { captionize } from 'devextreme/core/utils/inflector'
import CustomStore from 'devextreme/data/custom_store' import CustomStore from 'devextreme/data/custom_store'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useCallback, useEffect, useMemo, useRef, useState } from 'react'

View file

@ -1,4 +1,4 @@
import { DataGridTypes } from 'devextreme-react/data-grid' import type { DataGridTypes } from 'devextreme-react/data-grid'
import { import {
ColumnFormatDto, ColumnFormatDto,
GridBoxOptionsDto, GridBoxOptionsDto,

View file

@ -3,7 +3,7 @@ import {
deleteListFormCustomization, deleteListFormCustomization,
postListFormCustomization, postListFormCustomization,
} from '@/services/list-form-customization.service' } from '@/services/list-form-customization.service'
import { DataGridRef } from 'devextreme-react/data-grid' import type { DataGridRef } from 'devextreme-react/data-grid'
import { Dispatch, MutableRefObject, SetStateAction, useState } from 'react' import { Dispatch, MutableRefObject, SetStateAction, useState } from 'react'
import CreatableSelect from 'react-select/creatable' import CreatableSelect from 'react-select/creatable'
import { ISelectBoxData } from './useFilters' import { ISelectBoxData } from './useFilters'

View file

@ -3,20 +3,25 @@ import { APP_NAME, DX_CLASSNAMES } from '@/constants/app.constant'
import { GridDto, ListFormCustomizationTypeEnum } from '@/proxy/form/models' import { GridDto, ListFormCustomizationTypeEnum } from '@/proxy/form/models'
import { postListFormCustomization } from '@/services/list-form-customization.service' import { postListFormCustomization } from '@/services/list-form-customization.service'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import Chart, { ChartRef, CommonSeriesSettings, Size, Tooltip } from 'devextreme-react/chart' import Chart, {
type ChartRef,
CommonSeriesSettings,
Size,
Tooltip,
} from 'devextreme-react/chart'
import PivotGrid, { import PivotGrid, {
Export, Export,
FieldChooser, FieldChooser,
FieldPanel, FieldPanel,
HeaderFilter, HeaderFilter,
LoadPanel, LoadPanel,
PivotGridRef, type PivotGridRef,
PivotGridTypes, type PivotGridTypes,
Scrolling, Scrolling,
Search, Search,
} from 'devextreme-react/pivot-grid' } from 'devextreme-react/pivot-grid'
import CustomStore from 'devextreme/data/custom_store' import CustomStore from 'devextreme/data/custom_store'
import { Field } from 'devextreme/ui/pivot_grid/data_source' import type { Field } from 'devextreme/ui/pivot_grid/data_source'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { Helmet } from 'react-helmet' import { Helmet } from 'react-helmet'
import { GridColumnData } from './GridColumnData' import { GridColumnData } from './GridColumnData'

View file

@ -13,7 +13,7 @@ import Scheduler, {
Editing, Editing,
Item, Item,
Resource, Resource,
SchedulerRef, type SchedulerRef,
Toolbar, Toolbar,
View, View,
} from 'devextreme-react/scheduler' } from 'devextreme-react/scheduler'
@ -31,7 +31,7 @@ import { Loading } from '@/components/shared'
import { usePermission } from '@/utils/hooks/usePermission' import { usePermission } from '@/utils/hooks/usePermission'
import { RowMode, SimpleItemWithColData } from '../form/types' import { RowMode, SimpleItemWithColData } from '../form/types'
import { captionize } from 'devextreme/core/utils/inflector' import { captionize } from 'devextreme/core/utils/inflector'
import { AppointmentFormOpeningEvent } from 'devextreme/ui/scheduler' import type { AppointmentFormOpeningEvent } from 'devextreme/ui/scheduler'
interface SchedulerViewProps { interface SchedulerViewProps {
listFormCode: string listFormCode: string

View file

@ -29,8 +29,8 @@ import TreeListDx, {
Selection, Selection,
Sorting, Sorting,
Toolbar, Toolbar,
TreeListRef, type TreeListRef,
TreeListTypes, type TreeListTypes,
} from 'devextreme-react/tree-list' } from 'devextreme-react/tree-list'
import { Item } from 'devextreme-react/toolbar' import { Item } from 'devextreme-react/toolbar'
import CustomStore from 'devextreme/data/custom_store' import CustomStore from 'devextreme/data/custom_store'
@ -60,7 +60,7 @@ import { layoutTypes } from '../admin/listForm/edit/types'
import { useListFormCustomDataSource } from './useListFormCustomDataSource' import { useListFormCustomDataSource } from './useListFormCustomDataSource'
import { useListFormColumns } from './useListFormColumns' import { useListFormColumns } from './useListFormColumns'
import { orderListToolbarItems } from './toolbarOrder' import { orderListToolbarItems } from './toolbarOrder'
import { DataType } from 'devextreme/common' import type { DataType } from 'devextreme/common'
import { useStoreState } from '@/store/store' import { useStoreState } from '@/store/store'
import SubForms from '../form/SubForms' import SubForms from '../form/SubForms'
import { ImportDashboard } from '@/components/importManager/ImportDashboard' import { ImportDashboard } from '@/components/importManager/ImportDashboard'

View file

@ -1,5 +1,5 @@
import { DataType } from 'devextreme/common' import type { DataType } from 'devextreme/common'
import { PivotGridDataType } from 'devextreme/ui/pivot_grid/data_source' import type { PivotGridDataType } from 'devextreme/ui/pivot_grid/data_source'
import { MULTIVALUE_DELIMITER } from '../../constants/app.constant' import { MULTIVALUE_DELIMITER } from '../../constants/app.constant'
import { ChartSeriesDto } from '@/proxy/admin/charts/models' import { ChartSeriesDto } from '@/proxy/admin/charts/models'

View file

@ -1,4 +1,4 @@
import { ToolbarItem } from 'devextreme/ui/data_grid_types' import type { ToolbarItem } from 'devextreme/ui/data_grid_types'
const orderedToolbarItemNames = [ const orderedToolbarItemNames = [
'searchPanel', 'searchPanel',

View file

@ -6,10 +6,10 @@ import {
} from '@/proxy/form/models' } from '@/proxy/form/models'
import { getListFormCustomization } from '@/services/list-form-customization.service' import { getListFormCustomization } from '@/services/list-form-customization.service'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { DataGridRef } from 'devextreme-react/data-grid' import type { DataGridRef } from 'devextreme-react/data-grid'
import { PivotGridRef } from 'devextreme-react/pivot-grid' import type { PivotGridRef } from 'devextreme-react/pivot-grid'
import { TreeListRef } from 'devextreme-react/tree-list' import type { TreeListRef } from 'devextreme-react/tree-list'
import { ToolbarItem } from 'devextreme/ui/data_grid_types' import type { ToolbarItem } from 'devextreme/ui/data_grid_types'
import dxDataGrid from 'devextreme/ui/data_grid' import dxDataGrid from 'devextreme/ui/data_grid'
import dxPivotGrid from 'devextreme/ui/pivot_grid' import dxPivotGrid from 'devextreme/ui/pivot_grid'
import dxTreeList from 'devextreme/ui/tree_list' import dxTreeList from 'devextreme/ui/tree_list'
@ -19,7 +19,7 @@ import { setGridPanelColor } from './Utils'
import { usePermission } from '@/utils/hooks/usePermission' import { usePermission } from '@/utils/hooks/usePermission'
import { usePWA } from '@/utils/hooks/usePWA' import { usePWA } from '@/utils/hooks/usePWA'
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
import { GanttRef } from 'devextreme-react/cjs/gantt' import type { GanttRef } from 'devextreme-react/cjs/gantt'
import { useStoreState } from '@/store' import { useStoreState } from '@/store'
import { MULTIVALUE_DELIMITER } from '@/constants/app.constant' import { MULTIVALUE_DELIMITER } from '@/constants/app.constant'
import { createReportQueryString } from '../report/reportRouteParams' import { createReportQueryString } from '../report/reportRouteParams'

View file

@ -1,7 +1,7 @@
import { DataGridTypes } from 'devextreme-react/data-grid' import type { DataGridTypes } from 'devextreme-react/data-grid'
import { DataType, HorizontalEdge, SortOrder, ValidationRule } from 'devextreme/common' import type { DataType, HorizontalEdge, SortOrder, ValidationRule } from 'devextreme/common'
import CustomStore from 'devextreme/data/custom_store' import CustomStore from 'devextreme/data/custom_store'
import { SelectedFilterOperation } from 'devextreme/ui/data_grid' import type { SelectedFilterOperation } from 'devextreme/ui/data_grid'
import { useCallback, useEffect } from 'react' import { useCallback, useEffect } from 'react'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { usePermission } from '@/utils/hooks/usePermission' import { usePermission } from '@/utils/hooks/usePermission'

View file

@ -1,5 +1,5 @@
import { DataGridRef } from 'devextreme-react/data-grid' import type { DataGridRef } from 'devextreme-react/data-grid'
import { PivotGridRef } from 'devextreme-react/pivot-grid' import type { PivotGridRef } from 'devextreme-react/pivot-grid'
import CustomStore from 'devextreme/data/custom_store' import CustomStore from 'devextreme/data/custom_store'
import { MutableRefObject, useCallback } from 'react' import { MutableRefObject, useCallback } from 'react'
import { layoutTypes, ListViewLayoutType } from '@/views/admin/listForm/edit/types' import { layoutTypes, ListViewLayoutType } from '@/views/admin/listForm/edit/types'
@ -8,10 +8,10 @@ import { GridOptionsDto } from '@/proxy/form/models'
import { GridColumnData } from './GridColumnData' import { GridColumnData } from './GridColumnData'
import { dynamicFetch } from '@/services/form.service' import { dynamicFetch } from '@/services/form.service'
import { MULTIVALUE_DELIMITER } from '@/constants/app.constant' import { MULTIVALUE_DELIMITER } from '@/constants/app.constant'
import { TreeListRef } from 'devextreme-react/cjs/tree-list' import type { TreeListRef } from 'devextreme-react/cjs/tree-list'
import { GanttRef } from 'devextreme-react/cjs/gantt' import type { GanttRef } from 'devextreme-react/cjs/gantt'
import { SchedulerRef } from 'devextreme-react/cjs/scheduler' import type { SchedulerRef } from 'devextreme-react/cjs/scheduler'
import { CardViewRef, CardViewTypes } from 'devextreme-react/cjs/card-view' import type { CardViewRef, CardViewTypes } from 'devextreme-react/cjs/card-view'
const filteredGridPanelColor = 'rgba(10, 200, 10, 0.5)' // kullanici tanimli filtre ile filtrelenmis gridin paneline ait renk const filteredGridPanelColor = 'rgba(10, 200, 10, 0.5)' // kullanici tanimli filtre ile filtrelenmis gridin paneline ait renk

View file

@ -3,8 +3,8 @@ import { GridDto, UiCommandButtonPositionTypeEnum, WorkflowDto } from '@/proxy/f
import { dynamicFetch } from '@/services/form.service' import { dynamicFetch } from '@/services/form.service'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { usePermission } from '@/utils/hooks/usePermission' import { usePermission } from '@/utils/hooks/usePermission'
import { DataGridTypes } from 'devextreme-react/data-grid' import type { DataGridTypes } from 'devextreme-react/data-grid'
import { ToolbarItem } from 'devextreme/ui/data_grid_types' import type { ToolbarItem } from 'devextreme/ui/data_grid_types'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import type { ReactNode } from 'react' import type { ReactNode } from 'react'
import { useDialogContext } from '../shared/DialogContext' import { useDialogContext } from '../shared/DialogContext'

View file

@ -1,5 +1,5 @@
import Button from 'devextreme-react/button' import Button from 'devextreme-react/button'
import DataGrid, { DataGridRef } from 'devextreme-react/data-grid' import DataGrid, { type DataGridRef } from 'devextreme-react/data-grid'
import DropDownBox from 'devextreme-react/drop-down-box' import DropDownBox from 'devextreme-react/drop-down-box'
import { ReactElement, useRef } from 'react' import { ReactElement, useRef } from 'react'
import { GridBoxOptionsDto } from '@/proxy/form/models' import { GridBoxOptionsDto } from '@/proxy/form/models'