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",
"tr": "Api URL"
},
{
"resourceName": "Platform",
"key": "OpenUrl",
"en": "Open URL",
"tr": "URL'yi Aç"
},
{
"resourceName": "Platform",
"key": "App.Listform.ListformField.ApplicationName",

View file

@ -350,7 +350,7 @@
{
"name": "DynamicEntityComponent",
"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,
"description": null,
"isActive": true,
@ -363,9 +363,7 @@
"props": null,
"description": null,
"isActive": true,
"dependencies": [
"DynamicEntityComponent"
]
"dependencies": ["DynamicEntityComponent"]
}
],
"Abouts": [
@ -1807,9 +1805,7 @@
{
"postContent": "CI/CD pipeline güncellememiz tamamlandı! Deployment süremiz %40 azaldı. Otomasyonun gücü 💪",
"type": "video",
"urls": [
"https://www.w3schools.com/html/mov_bbb.mp4"
]
"urls": ["https://www.w3schools.com/html/mov_bbb.mp4"]
}
],
"SocialPollOptions": [

View file

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

View file

@ -6,8 +6,8 @@ import { BrowserRouter } from 'react-router-dom'
import { store } from './store'
import { DynamicRoutesProvider } from './routes/dynamicRoutesContext'
import { ComponentProvider } from './contexts/ComponentContext'
import { registerServiceWorker } from './views/version/swRegistration'
import { useEffect } from 'react'
import DevExtremeBoundary from './components/devExtreme/DevExtremeBoundary'
const queryClient = new QueryClient({
defaultOptions: {
@ -20,7 +20,11 @@ const queryClient = new QueryClient({
function App() {
useEffect(() => {
registerServiceWorker()
void import('./views/version/swRegistration')
.then(({ registerServiceWorker }) => registerServiceWorker())
.catch((error: unknown) => {
console.warn('Service worker could not be registered.', error)
})
}, [])
return (
@ -29,9 +33,11 @@ function App() {
<DynamicRoutesProvider>
<ComponentProvider>
<QueryClientProvider client={queryClient}>
<Theme>
<Layout />
</Theme>
<DevExtremeBoundary>
<Theme>
<Layout />
</Theme>
</DevExtremeBoundary>
</QueryClientProvider>
</ComponentProvider>
</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 MobileNav from '@/components/template/MobileNav'
import Notification from '@/components/template/Notification'
import SideNav from '@/components/template/SideNav'
import SideNavToggle from '@/components/template/SideNavToggle'
import SidePanel from '@/components/template/SidePanel'
import UserDropdown from '@/components/template/UserDropdown'
import { useStoreState } from '@/store'
import LanguageSelector from '../template/LanguageSelector'
import MessengerWidget from '../template/MessengerWidget'
import Search from '../template/Search'
import StackedSideNav from '../template/StackedSideNav'
import AiAssistant from '../template/AiAssistant'
import {
DeferredAiAssistant,
DeferredMessengerWidget,
DeferredNotification,
DeferredSearch,
DeferredSidePanel,
} from '../template/DeferredShellActions'
import { DynamicRouter } from '@/routes/dynamicRouter'
const HeaderActionsStart = () => {
@ -18,7 +20,7 @@ const HeaderActionsStart = () => {
<>
<MobileNav />
<SideNavToggle />
<Search />
<DeferredSearch />
</>
)
}
@ -26,11 +28,11 @@ const HeaderActionsStart = () => {
const HeaderActionsEnd = () => {
return (
<>
<AiAssistant />
<Notification />
<MessengerWidget />
<DeferredAiAssistant />
<DeferredNotification />
<DeferredMessengerWidget />
<LanguageSelector />
<SidePanel className="hidden" />
<DeferredSidePanel />
<UserDropdown hoverable={false} />
</>
)

View file

@ -1,15 +1,17 @@
import Header from '@/components/template/Header'
import SidePanel from '@/components/template/SidePanel'
import UserDropdown from '@/components/template/UserDropdown'
import HeaderLogo from '@/components/template/HeaderLogo'
import SecondaryHeader from '@/components/template/SecondaryHeader'
import Notification from '@/components/template/Notification'
import MobileNav from '@/components/template/MobileNav'
import View from '@/views/Views'
import Search from '@/components/template/Search'
import LanguageSelector from '../template/LanguageSelector'
import MessengerWidget from '../template/MessengerWidget'
import AiAssistant from '../template/AiAssistant'
import {
DeferredAiAssistant,
DeferredMessengerWidget,
DeferredNotification,
DeferredSearch,
DeferredSidePanel,
} from '../template/DeferredShellActions'
const HeaderActionsStart = () => {
return (
@ -23,12 +25,12 @@ const HeaderActionsStart = () => {
const HeaderActionsEnd = () => {
return (
<>
<AiAssistant />
<Search />
<Notification />
<MessengerWidget />
<DeferredAiAssistant />
<DeferredSearch />
<DeferredNotification />
<DeferredMessengerWidget />
<LanguageSelector />
<SidePanel className="hidden" />
<DeferredSidePanel />
<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 { useStoreState } from '@/store'
import {
@ -36,6 +36,45 @@ const layouts = {
const AuthLayout = lazy(() => import('./AuthLayout'))
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 location = useLocation()
const layoutType = useStoreState((s) => s.theme.layout.type) as LayoutType
@ -94,15 +133,17 @@ const Layout = () => {
}
return (
<Suspense
fallback={
<div className="flex flex-auto flex-col h-[100vh]">
<Loading loading />
</div>
}
>
<AppLayout />
</Suspense>
<LayoutChunkErrorBoundary>
<Suspense
fallback={
<div className="flex flex-auto flex-col h-[100vh]">
<Loading loading />
</div>
}
>
<AppLayout />
</Suspense>
</LayoutChunkErrorBoundary>
)
}

View file

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

View file

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

View file

@ -1,20 +1,22 @@
import Header from '@/components/template/Header'
import SidePanel from '@/components/template/SidePanel'
import UserDropdown from '@/components/template/UserDropdown'
import MobileNav from '@/components/template/MobileNav'
import StackedSideNav from '@/components/template/StackedSideNav'
import View from '@/views/Views'
import Search from '@/components/template/Search'
import Notification from '@/components/template/Notification'
import LanguageSelector from '../template/LanguageSelector'
import MessengerWidget from '../template/MessengerWidget'
import AiAssistant from '../template/AiAssistant'
import {
DeferredAiAssistant,
DeferredMessengerWidget,
DeferredNotification,
DeferredSearch,
DeferredSidePanel,
} from '../template/DeferredShellActions'
const HeaderActionsStart = () => {
return (
<>
<MobileNav />
<Search />
<DeferredSearch />
</>
)
}
@ -22,11 +24,11 @@ const HeaderActionsStart = () => {
const HeaderActionsEnd = () => {
return (
<>
<AiAssistant />
<Notification />
<MessengerWidget />
<DeferredAiAssistant />
<DeferredNotification />
<DeferredMessengerWidget />
<LanguageSelector />
<SidePanel className="hidden" />
<DeferredSidePanel />
<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,
CustomComponent,
CustomComponentDto,
} from '@/proxy/developerKit/models'
import { developerKitService } from '@/services/developerKit.service'
import { useStoreState } from '@/store/store'
import React, { createContext, useContext, useState, useEffect, useCallback } 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'
import React, { createContext, useContext, useState, useEffect, useCallback, useMemo } from 'react'
interface ComponentProps {
[key: string]: unknown
@ -75,6 +34,39 @@ interface ComponentContextType {
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
export const useComponents = () => {
const context = useContext(ComponentContext)
@ -89,16 +81,13 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
const [components, setComponents] = useState<CustomComponent[]>([])
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const [registeredComponents, setRegisteredComponents] = useState<
Record<string, React.ComponentType<unknown>>
>({})
const [registeredComponents, setRegisteredComponents] = useState(defaultRegisteredComponents)
const [compiledComponents, setCompiledComponents] = useState<
Record<string, React.ComponentType<ComponentProps>>
>({})
const refreshComponents = async () => {
const refreshComponents = useCallback(async () => {
try {
setLoading(true)
setError(null)
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')
console.error('Failed to fetch components:', err)
setComponents([])
} finally {
setLoading(false)
}
}
}, [extraProperties])
useEffect(() => {
refreshComponents()
}, [extraProperties])
}, [refreshComponents])
const addComponent = async (componentData: CreateUpdateCustomComponentDto) => {
const addComponent = useCallback(async (componentData: CreateUpdateCustomComponentDto) => {
try {
setLoading(true)
setError(null)
@ -128,9 +115,12 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
} finally {
setLoading(false)
}
}
}, [])
const updateComponent = async (id: string, componentData: CreateUpdateCustomComponentDto) => {
const updateComponent = useCallback(async (
id: string,
componentData: CreateUpdateCustomComponentDto,
) => {
try {
setLoading(true)
setError(null)
@ -144,9 +134,9 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
} finally {
setLoading(false)
}
}
}, [])
const deleteComponent = async (id: string) => {
const deleteComponent = useCallback(async (id: string) => {
try {
setLoading(true)
setError(null)
@ -158,78 +148,36 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
} finally {
setLoading(false)
}
}
const getComponent = (id: string) => {
return components?.find((comp) => comp.id === id)
}
}, [])
const getComponentByName = (name: string) => {
return components?.find((comp) => comp.name === name)
}
const componentsById = useMemo(
() => 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>) => {
setRegisteredComponents((prev) => ({
...prev,
[name]: component,
}))
}
const getComponent = useCallback((id: string) => componentsById.get(id), [componentsById])
// Register some default components on mount
useEffect(() => {
// Example components for testing
const HelloWorldComponent: React.ComponentType<unknown> = () => {
return React.createElement(
'div',
{
className: 'p-6 bg-blue-50 rounded-lg',
},
[
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 getComponentByName = useCallback(
(name: string) => componentsByName.get(name),
[componentsByName],
)
const registerComponent = useCallback(
(name: string, component: React.ComponentType<unknown>) => {
setRegisteredComponents((previous) =>
previous[name] === component ? previous : { ...previous, [name]: component },
)
}
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)
const extractComponentInfo = useCallback((code: string, defaultName = '') => {
@ -259,7 +207,10 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
// Compile components when they change
useEffect(() => {
if (!components || !components?.length) return
if (!components.length) {
setCompiledComponents({})
return
}
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
// 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
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, {
presets: ['react', 'typescript'],
filename: 'components-bundle.tsx',
@ -453,7 +449,7 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
return <Component {...props} />
}
const component = components.find((c) => c.name === name && c.isActive)
const component = activeComponentsByName.get(name)
if (!component) {
console.error(`Component not found: ${name}`)
return (
@ -465,7 +461,7 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
return null
},
[components, compiledComponents],
[activeComponentsByName, compiledComponents],
)
const compileAndRender = useCallback((code: string) => {
@ -476,43 +472,63 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
const isComponentRegistered = useCallback(
(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 dbComponents = components?.filter((c) => c.isActive).map((c) => c.name) || []
const dbComponents = [...activeComponentsByName.keys()]
const compiledNames = Object.keys(compiledComponents)
return [...new Set([...dbComponents, ...compiledNames])]
}, [components, compiledComponents])
}, [activeComponentsByName, compiledComponents])
const getComponentCode = useCallback(
(name: string) => {
const component = components.find((c) => c.name === name)
const component = componentsByName.get(name)
return component ? component.code : null
},
[components],
[componentsByName],
)
const value = {
components,
loading,
error,
addComponent,
updateComponent,
deleteComponent,
getComponent,
getComponentByName,
refreshComponents,
registeredComponents,
registerComponent,
renderComponent,
compileAndRender,
isComponentRegistered,
getRegisteredComponents,
getComponentCode,
}
const value = useMemo<ComponentContextType>(
() => ({
components,
loading,
error,
addComponent,
updateComponent,
deleteComponent,
getComponent,
getComponentByName,
refreshComponents,
registeredComponents,
registerComponent,
renderComponent,
compileAndRender,
isComponentRegistered,
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>
}

View file

@ -1,15 +1,38 @@
/* eslint-disable import/default */
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'
import { UiEvalService } from './services/UiEvalService'
import config from 'devextreme/core/config'
import { licenseKey } from './devextreme-license'
type UiEvalServiceModule = typeof import('./services/UiEvalService')
// Lisansı uygulama başlamadan önce kaydediyoruz
config({ licenseKey })
let uiEvalServicePromise: Promise<UiEvalServiceModule> | undefined
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 />)
UiEvalService.Init()

View file

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

View file

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

View file

@ -1,20 +1,25 @@
import React, { lazy } from 'react'
import { RouteDto } from '@/proxy/routes/models'
import { CustomComponent } from '@/proxy/developerKit/models'
import type { RouteDto } from '@/proxy/routes/models'
import type { CustomComponent } from '@/proxy/developerKit/models'
// Tüm view bileşenlerini import et (vite özel)
// 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 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)
function loadPhysicalComponent(componentPath: string) {
const cleanedPath = componentPath.replace(/^@\//, '')
const fullPath = `../${cleanedPath}.tsx`
if (lazyComponentCache.has(fullPath)) {
return lazyComponentCache.get(fullPath)!
if (physicalComponentCache.has(fullPath)) {
return physicalComponentCache.get(fullPath)!
}
const loader = modules[fullPath]
@ -24,7 +29,7 @@ function loadPhysicalComponent(componentPath: string) {
}
const LazyComponent = lazy(loader as () => Promise<{ default: React.ComponentType<any> }>)
lazyComponentCache.set(fullPath, LazyComponent)
physicalComponentCache.set(fullPath, LazyComponent)
return LazyComponent
}
@ -35,12 +40,6 @@ function loadDynamicComponent(
renderComponent?: (name: string, props?: any) => React.ReactNode,
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
let DynamicComponent = registeredComponents[componentPath]
@ -61,13 +60,10 @@ function loadDynamicComponent(
throw new Error(`Dynamic component not found: ${componentPath}`)
}
// console.log(`Dynamic component loaded: ${componentPath}`)
// Dinamik komponent için lazy wrapper oluştur
const LazyComponent = lazy(() =>
Promise.resolve({ default: DynamicComponent as React.ComponentType<any> }),
)
lazyComponentCache.set(componentPath, LazyComponent)
return LazyComponent
// Do not put this wrapper in a module-level cache. renderComponent changes
// after the asynchronous database bundle compilation finishes. Caching this
// function would keep the pre-compilation closure and render an empty page.
return DynamicComponent as React.ComponentType<any>
}
export function loadComponent(
@ -103,7 +99,7 @@ export interface DynamicReactRoute {
registeredComponents?: Record<string, React.ComponentType<unknown>>,
renderComponent?: (name: string, props?: any) => React.ReactNode,
isComponentRegistered?: (name: string) => boolean,
) => React.LazyExoticComponent<React.ComponentType<any>>
) => React.ComponentType<any>
routeType: string
authority?: string[]
componentType: string

View file

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

View file

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

View file

@ -9,7 +9,7 @@ import {
import { ListFormEditTabs } from '@/proxy/admin/list-form/options'
import { useStoreState } from '@/store'
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 * as Yup from 'yup'
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 { useStoreState } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization'
import {
import type {
GridsEditMode,
GridsEditRefreshMode,
NewRowPosition,

View file

@ -11,7 +11,7 @@ import {
import { ListFormEditTabs } from '@/proxy/admin/list-form/options'
import { useStoreState } from '@/store'
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 * as Yup from 'yup'
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 groupBy from 'lodash/groupBy'
import { useParams } from 'react-router-dom'
import { GanttScaleType } from 'devextreme/ui/gantt'
import type { GanttScaleType } from 'devextreme/ui/gantt'
import { gantScaleOptions } from './options'
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 { useStoreState } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { ScrollMode } from 'devextreme/common'
import { PagerDisplayMode } from 'devextreme/common/grids'
import type { ScrollMode } from 'devextreme/common'
import type { PagerDisplayMode } from 'devextreme/common/grids'
import { Field, FieldProps, Form, Formik } from 'formik'
import * as Yup from 'yup'
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 { useStoreState } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { SelectAllMode, SingleMultipleOrNone } from 'devextreme/common'
import { SelectionColumnDisplayMode } from 'devextreme/common/grids'
import type { SelectAllMode, SingleMultipleOrNone } from 'devextreme/common'
import type { SelectionColumnDisplayMode } from 'devextreme/common/grids'
import { Field, FieldProps, Form, Formik } from 'formik'
import * as Yup from 'yup'
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 { useStoreState } from '@/store'
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 * as Yup from 'yup'
import { FormEditProps } from './FormEdit'

View file

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

View file

@ -10,6 +10,7 @@ import {
FaEyeSlash,
FaFilter,
FaCalendarAlt,
FaExternalLinkAlt,
} from 'react-icons/fa'
import Widget from '@/components/common/Widget'
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 (
<div className="space-y-4">
<Helmet
@ -241,6 +247,17 @@ const ComponentManager: React.FC = () => {
</Button>
</div>
<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
type="button"
variant="solid"
@ -255,7 +272,7 @@ const ComponentManager: React.FC = () => {
'_blank',
)
}
title={translate('::App.DeveloperKit.Component.Edit')}
title={translate('::Edit')}
>
<FaRegEdit className="w-3 h-3" />
</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" />
</Button>
@ -282,7 +299,7 @@ const ComponentManager: React.FC = () => {
shape="circle"
color="red-600"
onClick={() => handleDelete(component.id)}
title={translate('::App.DeveloperKit.Component.Delete')}
title={translate('::Delete')}
>
<FaTrashAlt className="w-3 h-3" />
</Button>

View file

@ -3,11 +3,11 @@ import '@/utils/registerDevExtremeEditors'
import { executeEditorScript } from '@/utils/editorScriptRuntime'
import {
Form as FormDx,
FormRef,
type FormRef,
GroupItem as GroupItemDx,
SimpleItem as SimpleItemDx,
} 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 { GridBoxEditorComponent } from './editors/GridBoxEditorComponent'
import { ImageUploadEditorComponent } from './editors/ImageUploadEditorComponent'

View file

@ -1,7 +1,7 @@
import { Container, Loading } from '@/components/shared'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { DataType } from 'devextreme/common'
import { SimpleItem } from 'devextreme/ui/form'
import type { DataType } from 'devextreme/common'
import type { SimpleItem } from 'devextreme/ui/form'
import { useEffect, useRef, useState } from 'react'
import { Helmet } from 'react-helmet'
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 {
ColumnFormatDto,

View file

@ -2,10 +2,10 @@ import { Notification, toast } from '@/components/ui'
import { getList } from '@/services/form.service'
import { useLocalization } from '@/utils/hooks/useLocalization'
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 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 { useNavigate, useSearchParams } from 'react-router-dom'
import { GridColumnData } from '../list/GridColumnData'

View file

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

View file

@ -16,8 +16,8 @@ import { Template } from 'devextreme-react/core/template'
import DataGrid, {
ColumnChooser,
ColumnFixing,
DataGridRef,
DataGridTypes,
type DataGridRef,
type DataGridTypes,
Editing,
Export,
FilterPanel,
@ -38,7 +38,7 @@ import DataGrid, {
TotalItem,
} from 'devextreme-react/data-grid'
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 CustomStore from 'devextreme/data/custom_store'
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 {
ColumnFormatDto,
GridBoxOptionsDto,

View file

@ -3,7 +3,7 @@ import {
deleteListFormCustomization,
postListFormCustomization,
} 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 CreatableSelect from 'react-select/creatable'
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 { postListFormCustomization } from '@/services/list-form-customization.service'
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, {
Export,
FieldChooser,
FieldPanel,
HeaderFilter,
LoadPanel,
PivotGridRef,
PivotGridTypes,
type PivotGridRef,
type PivotGridTypes,
Scrolling,
Search,
} from 'devextreme-react/pivot-grid'
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 { Helmet } from 'react-helmet'
import { GridColumnData } from './GridColumnData'

View file

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

View file

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

View file

@ -1,5 +1,5 @@
import { DataType } from 'devextreme/common'
import { PivotGridDataType } from 'devextreme/ui/pivot_grid/data_source'
import type { DataType } from 'devextreme/common'
import type { PivotGridDataType } from 'devextreme/ui/pivot_grid/data_source'
import { MULTIVALUE_DELIMITER } from '../../constants/app.constant'
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 = [
'searchPanel',

View file

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

View file

@ -1,7 +1,7 @@
import { DataGridTypes } from 'devextreme-react/data-grid'
import { DataType, HorizontalEdge, SortOrder, ValidationRule } from 'devextreme/common'
import type { DataGridTypes } from 'devextreme-react/data-grid'
import type { DataType, HorizontalEdge, SortOrder, ValidationRule } from 'devextreme/common'
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 { useLocalization } from '@/utils/hooks/useLocalization'
import { usePermission } from '@/utils/hooks/usePermission'

View file

@ -1,5 +1,5 @@
import { DataGridRef } from 'devextreme-react/data-grid'
import { PivotGridRef } from 'devextreme-react/pivot-grid'
import type { DataGridRef } from 'devextreme-react/data-grid'
import type { PivotGridRef } from 'devextreme-react/pivot-grid'
import CustomStore from 'devextreme/data/custom_store'
import { MutableRefObject, useCallback } from 'react'
import { layoutTypes, ListViewLayoutType } from '@/views/admin/listForm/edit/types'
@ -8,10 +8,10 @@ import { GridOptionsDto } from '@/proxy/form/models'
import { GridColumnData } from './GridColumnData'
import { dynamicFetch } from '@/services/form.service'
import { MULTIVALUE_DELIMITER } from '@/constants/app.constant'
import { TreeListRef } from 'devextreme-react/cjs/tree-list'
import { GanttRef } from 'devextreme-react/cjs/gantt'
import { SchedulerRef } from 'devextreme-react/cjs/scheduler'
import { CardViewRef, CardViewTypes } from 'devextreme-react/cjs/card-view'
import type { TreeListRef } from 'devextreme-react/cjs/tree-list'
import type { GanttRef } from 'devextreme-react/cjs/gantt'
import type { SchedulerRef } from 'devextreme-react/cjs/scheduler'
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

View file

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

View file

@ -1,5 +1,5 @@
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 { ReactElement, useRef } from 'react'
import { GridBoxOptionsDto } from '@/proxy/form/models'