Optimizasyon değişimleri

This commit is contained in:
Sedat ÖZTÜRK 2026-07-06 12:44:26 +03:00
parent e96498645a
commit 3251c8bda4
184 changed files with 1470 additions and 3008 deletions

View file

@ -44,7 +44,7 @@
"code": "App.SiteManagement.Theme.Style", "code": "App.SiteManagement.Theme.Style",
"nameKey": "App.SiteManagement.Theme.Style", "nameKey": "App.SiteManagement.Theme.Style",
"descriptionKey": "App.SiteManagement.Theme.Style.Description", "descriptionKey": "App.SiteManagement.Theme.Style.Description",
"defaultValue": "dx.material.blue.light.compact", "defaultValue": "dx.material.blue.dark.compact",
"isVisibleToClients": true, "isVisibleToClients": true,
"providers": "U|G|D", "providers": "U|G|D",
"isInherited": false, "isInherited": false,

View file

@ -10254,6 +10254,12 @@
"en": "Active", "en": "Active",
"tr": "Aktif" "tr": "Aktif"
}, },
{
"resourceName": "Platform",
"key": "App.Status.Inactive",
"en": "Inactive",
"tr": "Pasif"
},
{ {
"resourceName": "Platform", "resourceName": "Platform",
"key": "App.DeveloperKit.ComponentEditor.Save", "key": "App.DeveloperKit.ComponentEditor.Save",

View file

@ -13,9 +13,7 @@ interface ComponentCodeEditorProps {
onResetCodeChanges: () => void onResetCodeChanges: () => void
language?: string language?: string
theme?: 'vs-dark' | 'light' theme?: 'vs-dark' | 'light'
parseError?: string | null
onCursorChange?: (componentId: string | null) => void onCursorChange?: (componentId: string | null) => void
onDrop?: (componentDef: ComponentDefinition, position: { line: number; column: number }) => void
onComponentAdded?: (componentDef: ComponentDefinition) => void onComponentAdded?: (componentDef: ComponentDefinition) => void
onComponentSave: () => void onComponentSave: () => void
} }
@ -24,6 +22,7 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
code, code,
onChange, onChange,
onApplyCodeChanges, onApplyCodeChanges,
onResetCodeChanges,
language = 'typescript', language = 'typescript',
theme = 'vs-dark', theme = 'vs-dark',
onCursorChange, onCursorChange,
@ -48,7 +47,6 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
const editorRef = useRef<any>(null) const editorRef = useRef<any>(null)
const containerRef = useRef<HTMLDivElement>(null) const containerRef = useRef<HTMLDivElement>(null)
const cursorChangeTimeout = useRef<number | null>(null)
// Refs to keep latest values accessible inside native DOM listeners // Refs to keep latest values accessible inside native DOM listeners
const localCodeRef = useRef(localCode) const localCodeRef = useRef(localCode)
const dropCallbacksRef = useRef({ onChange, onComponentAdded, onApplyCodeChanges }) const dropCallbacksRef = useRef({ onChange, onComponentAdded, onApplyCodeChanges })
@ -66,14 +64,6 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
dropCallbacksRef.current = { onChange, onComponentAdded, onApplyCodeChanges } dropCallbacksRef.current = { onChange, onComponentAdded, onApplyCodeChanges }
}, [onChange, onComponentAdded, onApplyCodeChanges]) }, [onChange, onComponentAdded, onApplyCodeChanges])
useEffect(() => {
return () => {
if (cursorChangeTimeout.current) {
clearTimeout(cursorChangeTimeout.current)
}
}
}, [])
const findComponentIdAtPosition = ( const findComponentIdAtPosition = (
code: string, code: string,
position: { lineNumber: number; column: number }, position: { lineNumber: number; column: number },
@ -169,7 +159,10 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
if (ch === '(') parenDepth++ if (ch === '(') parenDepth++
else if (ch === ')') { else if (ch === ')') {
parenDepth-- parenDepth--
if (parenDepth <= 0) { insideReturn = false; break } if (parenDepth <= 0) {
insideReturn = false
break
}
} }
} }
} }
@ -178,7 +171,10 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
if (ch === '(') parenDepth++ if (ch === '(') parenDepth++
else if (ch === ')') { else if (ch === ')') {
parenDepth-- parenDepth--
if (parenDepth <= 0) { insideReturn = false; break } if (parenDepth <= 0) {
insideReturn = false
break
}
} }
} }
} }
@ -186,15 +182,11 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
return insideReturn return insideReturn
} }
const handleEditorCursorChange = (_event: any) => { const handleEditorCursorChange = () => {
if (!editorRef.current) return if (!editorRef.current) return
const position = editorRef.current.getPosition() const position = editorRef.current.getPosition()
if (!position) return if (!position) return
// Throttle the cursor change to avoid too many calls
if (cursorChangeTimeout.current) {
clearTimeout(cursorChangeTimeout.current)
}
const id = findComponentIdAtPosition(localCode, position) const id = findComponentIdAtPosition(localCode, position)
if (onCursorChange) onCursorChange(id) if (onCursorChange) onCursorChange(id)
} }
@ -242,12 +234,19 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
let componentDefData: string | undefined let componentDefData: string | undefined
for (const fmt of ['application/json', 'text/plain']) { for (const fmt of ['application/json', 'text/plain']) {
const d = nativeEvent.dataTransfer.getData(fmt) const d = nativeEvent.dataTransfer.getData(fmt)
if (d) { componentDefData = d; break } if (d) {
componentDefData = d
break
}
} }
if (!componentDefData) return if (!componentDefData) return
let componentDef: any let componentDef: any
try { componentDef = JSON.parse(componentDefData) } catch { return } try {
componentDef = JSON.parse(componentDefData)
} catch {
return
}
if (!componentDef?.name) return if (!componentDef?.name) return
// Resolve the drop position inside Monaco // Resolve the drop position inside Monaco
@ -300,8 +299,11 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
const newCode = newLines.join('\n') const newCode = newLines.join('\n')
setLocalCode(newCode) setLocalCode(newCode)
const { onChange: onChg, onComponentAdded: onAdded, onApplyCodeChanges: onApply } = const {
dropCallbacksRef.current onChange: onChg,
onComponentAdded: onAdded,
onApplyCodeChanges: onApply,
} = dropCallbacksRef.current
onChg(newCode) onChg(newCode)
if (onAdded) onAdded(componentDefWithId) if (onAdded) onAdded(componentDefWithId)
setTimeout(() => onApply(newCode), 100) setTimeout(() => onApply(newCode), 100)
@ -346,6 +348,7 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
const handleResetChanges = () => { const handleResetChanges = () => {
setLocalCode(code) setLocalCode(code)
setHasChanges(false) setHasChanges(false)
onResetCodeChanges()
} }
// Drag & Drop handlers for Code Editor // Drag & Drop handlers for Code Editor
@ -561,53 +564,53 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
<div className="bg-gray-800 border-b border-gray-700 p-4 flex items-end justify-between shrink-0"> <div className="bg-gray-800 border-b border-gray-700 p-4 flex items-end justify-between shrink-0">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Button <Button
onClick={handleFormatCode}
loading={isFormatting} loading={isFormatting}
icon={<FaCode className="w-4 h-4" />} icon={<FaCode className="w-4 h-4" />}
variant="default" variant="default"
size="sm" size="sm"
onClick={handleFormatCode}
> >
Formatla Formatla
</Button> </Button>
<Button <Button
onClick={() => setShowSettings(!showSettings)}
icon={<FaCog className="w-4 h-4" />} icon={<FaCog className="w-4 h-4" />}
variant={showSettings ? 'solid' : 'default'} variant={showSettings ? 'solid' : 'default'}
color="blue-600" color="blue-600"
size="sm" size="sm"
onClick={() => setShowSettings(!showSettings)}
> >
Ayarlar Ayarlar
</Button> </Button>
<Button <Button
onClick={handleResetChanges}
icon={<FaTimes className="w-4 h-4" />} icon={<FaTimes className="w-4 h-4" />}
variant="solid" variant="solid"
color="red-600" color="red-600"
size="sm" size="sm"
onClick={handleResetChanges}
> >
Sıfırla Sıfırla
</Button> </Button>
<Button <Button
onClick={handleApplyChanges}
icon={<FaCheck className="w-4 h-4" />} icon={<FaCheck className="w-4 h-4" />}
variant="solid" variant="solid"
color="green-600" color="green-600"
size="sm" size="sm"
onClick={handleApplyChanges}
> >
Uygula Uygula
</Button> </Button>
</div> </div>
<div className="col-span-2 flex items-center justify-end"> <div className="col-span-2 flex items-center justify-end">
<Button <Button
onClick={onComponentSave}
icon={<FaSave className="w-4 h-4" />} icon={<FaSave className="w-4 h-4" />}
variant="solid" variant="solid"
color="yellow-600" color="yellow-600"
size="sm" size="sm"
className="shadow-sm" className="shadow-sm"
onClick={onComponentSave}
> >
Kaydet Kaydet
</Button> </Button>
@ -622,8 +625,8 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
<label className="block text-sm font-medium text-gray-300 mb-2">Tema</label> <label className="block text-sm font-medium text-gray-300 mb-2">Tema</label>
<select <select
value={editorTheme} value={editorTheme}
onChange={(e) => setEditorTheme(e.target.value as 'vs-dark' | 'light')}
className="w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded-md text-white text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded-md text-white text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
onChange={(e) => setEditorTheme(e.target.value as 'vs-dark' | 'light')}
> >
<option value="vs-dark">Koyu</option> <option value="vs-dark">Koyu</option>
<option value="light">ık</option> <option value="light">ık</option>
@ -637,8 +640,8 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
min="10" min="10"
max="24" max="24"
value={fontSize} value={fontSize}
onChange={(e) => setFontSize(parseInt(e.target.value))}
className="w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded-md text-white text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded-md text-white text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
onChange={(e) => setFontSize(parseInt(e.target.value))}
/> />
</div> </div>
@ -648,8 +651,8 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
</label> </label>
<select <select
value={wordWrap} value={wordWrap}
onChange={(e) => setWordWrap(e.target.value as 'on' | 'off')}
className="w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded-md text-white text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" className="w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded-md text-white text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
onChange={(e) => setWordWrap(e.target.value as 'on' | 'off')}
> >
<option value="on">ık</option> <option value="on">ık</option>
<option value="off">Kapalı</option> <option value="off">Kapalı</option>
@ -659,11 +662,11 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
<div> <div>
<label className="block text-sm font-medium text-gray-300 mb-2">Mini Harita</label> <label className="block text-sm font-medium text-gray-300 mb-2">Mini Harita</label>
<Button <Button
onClick={() => setMinimap(!minimap)}
block block
variant={minimap ? 'solid' : 'default'} variant={minimap ? 'solid' : 'default'}
color="blue-600" color="blue-600"
size="sm" size="sm"
onClick={() => setMinimap(!minimap)}
> >
{minimap ? 'Etkin' : 'Devre Dışı'} {minimap ? 'Etkin' : 'Devre Dışı'}
</Button> </Button>
@ -680,8 +683,6 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
language={language} language={language}
theme={editorTheme} theme={editorTheme}
value={localCode} value={localCode}
onChange={handleCodeChange}
onMount={handleEditorDidMount}
options={{ options={{
fontSize: fontSize, fontSize: fontSize,
wordWrap: wordWrap, wordWrap: wordWrap,
@ -748,6 +749,8 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
formatOnPaste: true, formatOnPaste: true,
formatOnType: true, formatOnType: true,
}} }}
onChange={handleCodeChange}
onMount={handleEditorDidMount}
/> />
</div> </div>

View file

@ -1,4 +1,4 @@
import { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import TailwindModal from "./TailwindModal"; import TailwindModal from "./TailwindModal";
import { ComponentInfo, HookInfo, PropertyInfo } from "../../proxy/developerKit/componentInfo"; import { ComponentInfo, HookInfo, PropertyInfo } from "../../proxy/developerKit/componentInfo";
import { getComponentDefinition } from "./data/componentDefinitions"; import { getComponentDefinition } from "./data/componentDefinitions";
@ -113,15 +113,6 @@ const PropertyPanel: React.FC<PropertyPanelProps> = ({
setHasHookChanges(true); setHasHookChanges(true);
}; };
// Handle local event changes
const handleLocalEventChange = (eventName: string, value: string) => {
setPendingEvents((prev) => ({
...prev,
[eventName]: value,
}));
setHasChanges(true);
};
// Apply only property/event changes // Apply only property/event changes
const handleApplyPropChanges = () => { const handleApplyPropChanges = () => {
if (!selectedComponent) return; if (!selectedComponent) return;
@ -222,7 +213,7 @@ const PropertyPanel: React.FC<PropertyPanelProps> = ({
if (property.type === "array") { if (property.type === "array") {
try { try {
arrayInputValue = JSON.stringify(value, null, 2); arrayInputValue = JSON.stringify(value, null, 2);
} catch (e) { } catch {
arrayInputValue = ""; arrayInputValue = "";
arrayError = "Array verisi gösterilemiyor."; arrayError = "Array verisi gösterilemiyor.";
} }
@ -365,7 +356,7 @@ const PropertyPanel: React.FC<PropertyPanelProps> = ({
const parsed = JSON.parse(e.target.value); const parsed = JSON.parse(e.target.value);
handleLocalPropertyChange(property.name, parsed); handleLocalPropertyChange(property.name, parsed);
arrayError = ""; arrayError = "";
} catch (err) { } catch {
arrayError = "Geçersiz JSON formatı"; arrayError = "Geçersiz JSON formatı";
} }
}} }}

View file

@ -1,4 +1,4 @@
import { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { searchTailwindClasses, TAILWIND_CLASSES } from './data/tailwindClasses'; import { searchTailwindClasses, TAILWIND_CLASSES } from './data/tailwindClasses';
import { Button } from '../ui'; import { Button } from '../ui';
import { FaTimes } from 'react-icons/fa'; import { FaTimes } from 'react-icons/fa';
@ -40,12 +40,6 @@ const TailwindModal: React.FC<TailwindModalProps> = ({
// Don't close modal - let user select multiple classes // Don't close modal - let user select multiple classes
}; };
const handleAddToCurrentValue = (className: string) => {
const newValue = currentValue ? `${currentValue} ${className}` : className;
onSelectClass(newValue);
// Don't close modal - let user continue selecting
};
if (!isOpen) return null; if (!isOpen) return null;
return ( return (

View file

@ -1,3 +1,5 @@
import React from 'react';
declare interface Window { declare interface Window {
ReactDOM?: { ReactDOM?: {
render: (element: React.ReactNode, container: Element) => void; render: (element: React.ReactNode, container: Element) => void;

View file

@ -1,3 +1,4 @@
import React from "react";
import classNames from "classnames"; import classNames from "classnames";
interface InfoSectionProps { interface InfoSectionProps {

View file

@ -1,4 +1,4 @@
import { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import classNames from "classnames"; import classNames from "classnames";
import { iconList } from "./iconList"; import { iconList } from "./iconList";

View file

@ -1,6 +1,5 @@
import classNames from "classnames"; import classNames from "classnames";
import Widget, { type colorType } from "./Widget"; import Widget, { type colorType } from "./Widget";
import { useNavigate } from "react-router-dom";
import { WidgetEditDto, WidgetGroupDto } from "../../types/common"; import { WidgetEditDto, WidgetGroupDto } from "../../types/common";
export default function WidgetGroup({ export default function WidgetGroup({
@ -8,8 +7,6 @@ export default function WidgetGroup({
}: { }: {
widgetGroups: WidgetGroupDto[]; widgetGroups: WidgetGroupDto[];
}) { }) {
const navigate = useNavigate();
return ( return (
<div> <div>
{widgetGroups.map((group, gIdx) => ( {widgetGroups.map((group, gIdx) => (

View file

@ -1,4 +1,4 @@
import { cloneElement } from 'react' import React, { cloneElement } from 'react'
import Avatar from '@/components/ui/Avatar' import Avatar from '@/components/ui/Avatar'
import Logo from '@/components/template/Logo' import Logo from '@/components/template/Logo'
import { APP_NAME } from '@/constants/app.constant' import { APP_NAME } from '@/constants/app.constant'

View file

@ -1,44 +1,10 @@
import React from 'react' import type { PropsWithChildren } from 'react'
import { FaTachometerAlt, FaDatabase, FaBolt, FaServer, FaPuzzlePiece } from 'react-icons/fa'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { useLocation, useNavigate } from 'react-router-dom'
import { ROUTES_ENUM } from '@/routes/route.constant'
import { Container } from '../shared' import { Container } from '../shared'
interface DeveloperLayoutProps { const DeveloperLayout = ({ children }: PropsWithChildren) => {
children: React.ReactNode
}
const DeveloperLayout: React.FC<DeveloperLayoutProps> = ({ children }) => {
const { translate } = useLocalization()
const location = useLocation()
const navigate = useNavigate()
const navigation = [
{
id: 'entities',
label: translate('::App.DeveloperKit.Entity'),
icon: FaDatabase,
path: ROUTES_ENUM.protected.saas.developerKit.entities,
},
{
id: 'endpoints',
label: translate('::App.DeveloperKit.CrudEndpoints'),
icon: FaServer,
path: ROUTES_ENUM.protected.saas.developerKit.endpoints,
},
{
id: 'components',
label: translate('::App.DeveloperKit.Components'),
icon: FaPuzzlePiece,
path: ROUTES_ENUM.protected.saas.developerKit.components,
},
]
return ( return (
<Container> <Container>
<div className="flex flex-col lg:flex-row gap-8"> <div className="flex flex-col lg:flex-row gap-8">
{/* Main Content */}
<div className="flex-1">{children}</div> <div className="flex-1">{children}</div>
</div> </div>
</Container> </Container>

View file

@ -23,7 +23,6 @@ export const BillingControls: React.FC<BillingControlsProps> = ({
setGlobalBillingCycle, setGlobalBillingCycle,
setGlobalPeriod, setGlobalPeriod,
onCartClick, onCartClick,
onNavigate,
cartItemsCount, cartItemsCount,
cartState, cartState,
}) => { }) => {

View file

@ -10,7 +10,7 @@ interface OrderSuccessProps {
onBackToShop: () => void onBackToShop: () => void
} }
export const OrderSuccess: React.FC<OrderSuccessProps> = ({ orderId, onBackToShop }) => { export const OrderSuccess: React.FC<OrderSuccessProps> = ({ orderId }) => {
const navigate = useNavigate() const navigate = useNavigate()
const { translate } = useLocalization() const { translate } = useLocalization()

View file

@ -1,6 +1,6 @@
import React, { useState } from 'react' import React, { useState } from 'react'
import { FaPlus, FaMinus } from 'react-icons/fa' import { FaPlus, FaMinus } from 'react-icons/fa'
import { BillingCycle, Product, ProductDto } from '@/proxy/order/models' import { BillingCycle, ProductDto } from '@/proxy/order/models'
import { CartState } from '@/utils/cartUtils' import { CartState } from '@/utils/cartUtils'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { Button } from '@/components/ui' import { Button } from '@/components/ui'

View file

@ -4,14 +4,14 @@ import { Link } from 'react-router-dom'
import type { CommonProps } from '@/proxy/common' import type { CommonProps } from '@/proxy/common'
import type { ComponentPropsWithoutRef } from 'react' import type { ComponentPropsWithoutRef } from 'react'
interface ActionLink extends CommonProps, ComponentPropsWithoutRef<'a'> { interface ActionLinkProps extends CommonProps, ComponentPropsWithoutRef<'a'> {
themeColor?: boolean themeColor?: boolean
to?: string to?: string
href?: string href?: string
reloadDocument?: boolean reloadDocument?: boolean
} }
const ActionLink = (props: ActionLink) => { const ActionLink = (props: ActionLinkProps) => {
const { const {
children, children,
className, className,

View file

@ -1,5 +1,4 @@
import { MigrateLogEntry } from '@/proxy/setup/models' import { MigrateLogEntry } from '@/proxy/setup/models'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { useEffect, useRef, useState } from 'react' import { useEffect, useRef, useState } from 'react'
import { createRoot } from 'react-dom/client' import { createRoot } from 'react-dom/client'
import { Button } from '@/components/ui' import { Button } from '@/components/ui'

View file

@ -1,4 +1,4 @@
import { forwardRef } from 'react' import React, { forwardRef } from 'react'
import classNames from 'classnames' import classNames from 'classnames'
import useThemeClass from '@/utils/hooks/useThemeClass' import useThemeClass from '@/utils/hooks/useThemeClass'
import { FaCheckCircle } from 'react-icons/fa' import { FaCheckCircle } from 'react-icons/fa'

View file

@ -179,29 +179,53 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
useEffect(() => { useEffect(() => {
// Example components for testing // Example components for testing
const HelloWorldComponent: React.ComponentType<unknown> = () => { const HelloWorldComponent: React.ComponentType<unknown> = () => {
return React.createElement('div', { return React.createElement(
className: 'p-6 bg-blue-50 rounded-lg' 'div',
}, [ {
React.createElement('h1', { className: 'p-6 bg-blue-50 rounded-lg',
className: 'text-2xl font-bold text-blue-900 mb-4' },
}, 'Hello World!'), [
React.createElement('p', { React.createElement(
className: 'text-blue-700' 'h1',
}, 'Bu manuel kayıtlı bir komponent!') {
]) 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> = () => { const TestListComponent: React.ComponentType<unknown> = () => {
return React.createElement('div', { return React.createElement(
className: 'p-6 bg-green-50 rounded-lg' 'div',
}, [ {
React.createElement('h1', { className: 'p-6 bg-green-50 rounded-lg',
className: 'text-2xl font-bold text-green-900 mb-4' },
}, 'Test List'), [
React.createElement('p', { React.createElement(
className: 'text-green-700' 'h1',
}, 'Bu da test için kayıtlı komponent!') {
]) 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('HelloWorld', HelloWorldComponent)
@ -269,8 +293,8 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
const componentDefinitions = componentInfos const componentDefinitions = componentInfos
.map((info) => { .map((info) => {
const componentVariables = componentInfos const componentVariables = componentInfos
.filter(other => other.name !== info.name) .filter((other) => other.name !== info.name)
.map(other => `const ${other.name} = ${other.name}_Component;`) .map((other) => `const ${other.name} = ${other.name}_Component;`)
.join('\n ') .join('\n ')
return ` return `
@ -314,12 +338,90 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
} }
const componentsFactory = new Function( const componentsFactory = new Function(
'React', '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', 'axios', 'React',
'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',
'axios',
`return ${compiledBundle}`, `return ${compiledBundle}`,
) )
const compiledComponentsRegistry = componentsFactory( const compiledComponentsRegistry = componentsFactory(
React, 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, axios, React,
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,
axios,
) )
setCompiledComponents(compiledComponentsRegistry) setCompiledComponents(compiledComponentsRegistry)
@ -352,14 +454,11 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
[components, compiledComponents], [components, compiledComponents],
) )
const compileAndRender = useCallback( const compileAndRender = useCallback((code: string) => {
(code: string, props: ComponentProps = {}) => {
if (!code?.trim()) return null if (!code?.trim()) return null
// Simplified version - can be extended later // Simplified version - can be extended later
return <div>Code compilation not implemented yet</div> return <div>Code compilation not implemented yet</div>
}, }, [])
[],
)
const isComponentRegistered = useCallback( const isComponentRegistered = useCallback(
(name: string) => { (name: string) => {

View file

@ -1,4 +1,4 @@
import React, { createContext, useContext } from 'react' import { createContext, useContext } from 'react'
interface DemoContextValue { interface DemoContextValue {
openDemo: () => void openDemo: () => void

View file

@ -1,5 +1,5 @@
// ScrollContext.tsx // ScrollContext.tsx
import React, { createContext, useContext } from 'react' import { createContext, useContext } from 'react'
export const ScrollContext = createContext<boolean>(false) export const ScrollContext = createContext<boolean>(false)

View file

@ -1,5 +1,5 @@
import React, { lazy } from 'react'
import { RouteDto } from '@/proxy/routes/models' import { RouteDto } from '@/proxy/routes/models'
import { lazy } from 'react'
// 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

View file

@ -50,7 +50,7 @@ export const deleteListFormJsonRow = (id: string, field: string, index: number)
url: `/api/admin/list-form-json-row/${id}?field=${field}&index=${index}`, url: `/api/admin/list-form-json-row/${id}?field=${field}&index=${index}`,
}) })
export const getListFormSelectQueryByCode = (listFormCode?: string, op: number = -1) => export const getListFormSelectQueryByCode = (listFormCode?: string) =>
apiService.fetchData<string>({ apiService.fetchData<string>({
method: 'GET', method: 'GET',
url: `/api/admin/list-form-query-preview/form-select-query`, url: `/api/admin/list-form-query-preview/form-select-query`,

View file

@ -56,7 +56,7 @@ class NoteService {
}) })
} }
async downloadFile(savedFileName: string, fileName: string, fileType: string) { async downloadFile(savedFileName: string, fileName: string) {
const response = await apiService.fetchData<NoteFileDto>({ const response = await apiService.fetchData<NoteFileDto>({
url: `/api/app/note/download?savedFileName=${savedFileName}`, url: `/api/app/note/download?savedFileName=${savedFileName}`,
method: 'GET', method: 'GET',

View file

@ -1,5 +1,5 @@
import { InstallmentOptionDto, OrderDto, PaymentMethodDto, ProductDto } from '@/proxy/order/models' import { InstallmentOptionDto, OrderDto, PaymentMethodDto, ProductDto } from '@/proxy/order/models'
import apiService, { Config } from '@/services/api.service' import apiService from '@/services/api.service'
import axios from 'axios' import axios from 'axios'
export class OrderService { export class OrderService {

View file

@ -111,7 +111,7 @@ platformApiService.interceptors.response.use(
signOut() signOut()
error.silent = true error.silent = true
} }
} catch (error2) { } catch {
await revokeTokens({ await revokeTokens({
token: auth.session.token, token: auth.session.token,
refreshToken: auth.session.refreshToken, refreshToken: auth.session.refreshToken,

View file

@ -1,663 +0,0 @@
import { DepartmentDto, EmployeeDto } from '@/proxy/intranet/models'
export interface Address {
// Adres
country: string
state: string
city: string
street: string
postalCode: string
}
export interface HrCostCenter {
// İnsan Kaynakları Masraf Merkezi
id: string
code: string
name: string
description?: string
parentCostCenterId?: string
parentCostCenter?: HrCostCenter
subCostCenters: HrCostCenter[]
responsibleEmployeeId?: string
responsibleEmployee?: EmployeeDto
departmentId?: string
department?: DepartmentDto
costCenterType: CostCenterType
budgetedAmount: number
actualAmount: number
currency: string
fiscalYear: string
isActive: boolean
creationTime: Date
lastModificationTime: Date
}
export interface HrPerformanceEvaluation {
// İnsan Kaynakları Performans Değerlendirmesi
id: string
employeeId: string
employee?: EmployeeDto
evaluatorId: string
evaluator?: EmployeeDto
evaluationPeriod: string
evaluationType: EvaluationTypeEnum
overallRating: number
goals: HrPerformanceGoal[]
competencies: HrCompetencyRating[]
strengths: string[]
areasForImprovement: string[]
developmentPlan: string[]
comments?: string
status: EvaluationStatusEnum
dueDate: Date
completedDate?: Date
creationTime: Date
lastModificationTime: Date
}
export interface HrPerformanceGoal {
// İnsan Kaynakları Performans Hedefi
id: string
evaluationId: string
goalDescription: string
targetValue?: string
actualValue?: string
weight: number
rating: number
comments?: string
}
export interface HrCompetencyRating {
// İnsan Kaynakları Yeterlilik Değerlendirmesi
id: string
evaluationId: string
competencyName: string
expectedLevel: number
actualLevel: number
rating: number
comments?: string
}
export interface HrTraining {
// İnsan Kaynakları Eğitimi
id: string
trainingCode: string
title: string
description?: string
trainingType: TrainingTypeEnum
provider: string
startDate: Date
endDate: Date
duration: number
location?: string
isOnline: boolean
maxParticipants?: number
cost: number
currency: string
status: TrainingStatusEnum
participants: HrTrainingParticipant[]
materials: string[]
creationTime: Date
lastModificationTime: Date
}
export interface HrTrainingParticipant {
// İnsan Kaynakları Eğitim Katılımcısı
id: string
trainingId: string
employeeId: string
employee?: EmployeeDto
enrollmentDate: Date
completionDate?: Date
status: ParticipationStatusEnum
score?: number
feedback?: string
certificateIssued: boolean
}
export interface HrWorkSchedule {
// İnsan Kaynakları Çalışma Programı
id: string
scheduleCode: string
name: string
description?: string
workingDays: HrWorkingDay[]
totalHoursPerWeek: number
isFlexible: boolean
isActive: boolean
}
export interface HrWorkingDay {
// İnsan Kaynakları Çalışma Günü
dayOfWeek: number // 0-6 (Sunday-Saturday)
isWorkingDay: boolean
startTime?: string
endTime?: string
breakDuration?: number // minutes
}
export interface HrDisciplinaryAction {
// İnsan Kaynakları Disiplin Cezası
id: string
employeeId: string
employee?: EmployeeDto
actionType: DisciplinaryActionTypeEnum
reason: string
description: string
actionDate: Date
issuedBy: string
severity: DisciplinarySeverityEnum
status: DisciplinaryStatusEnum
expiryDate?: Date
attachments: string[]
creationTime: Date
lastModificationTime: Date
}
export interface HrEmergencyContact {
// İnsan Kaynakları Acil Durum İletişim
name: string
relationship: string
phoneNumber: string
email?: string
address?: Address
}
export interface HrEmploymentType {
// İnsan Kaynakları İstihdam Türü
id: string
name: string
count?: number
creationTime: Date
lastModificationTime: Date
}
export interface HrPayroll {
// İnsan Kaynakları Maaş Bordrosu
id: string
employeeId: string
employee?: EmployeeDto
period: string
baseSalary: number
allowances: HrPayrollAllowance[] // İnsan Kaynakları Maaş Ek Ödemeleri
deductions: HrPayrollDeduction[] // İnsan Kaynakları Maaş Kesintileri
overtime: number
bonus: number
grossSalary: number
netSalary: number
tax: number
socialSecurity: number
status: PayrollStatusEnum
paymentDate?: Date
creationTime: Date
lastModificationTime: Date
}
export interface HrPayrollAllowance {
// İnsan Kaynakları Maaş Ek Ödemesi
id: string
name: string
amount: number
taxable: boolean
}
export interface HrPayrollDeduction {
// İnsan Kaynakları Maaş Kesintisi
id: string
name: string
amount: number
mandatory: boolean
}
export interface HrBadge {
// İnsan Kaynakları Rozeti
id: string
code: string
name: string
description: string
icon: string
color: string
backgroundColor: string
category: BadgeCategoryEnum
criteria: string
points: number
rarity: BadgeRarityEnum
isActive: boolean
creationTime: Date
lastModificationTime: Date
}
export interface HrOrganizationChart {
// İnsan Kaynakları Organizasyon Şeması
id: string
employeeId: string
employee?: EmployeeDto
parentId?: string
parent?: HrOrganizationChart
children?: HrOrganizationChart[]
level: number
position: string
isActive: boolean
}
export interface HrEmployeeBadge {
// İnsan Kaynakları Çalışan Rozeti
id: string
employeeId: string
employee?: EmployeeDto
badgeId: string
badge?: HrBadge
earnedDate: Date
expiryDate?: Date
reason?: string
notes?: string
isActive: boolean
creationTime: Date
lastModificationTime: Date
}
export interface HrEvaluation360Template {
// İnsan Kaynakları 360 Derece Değerlendirme Şablonu
id: string
name: string
description: string
isActive: boolean
questionGroups: HrQuestionGroup[]
applicablePositions: string[] // JobPosition ID'leri
applicableDepartments: string[] // Department ID'leri
assessorTypes: AssessorTypeEnum[] // Değerlendiriciler
creationTime: Date
lastModificationTime: Date
}
export interface HrQuestionGroup {
// İnsan Kaynakları Soru Grubu
id: string
templateId: string
groupName: string
description?: string
weight: number // Bu grubun toplam puandaki ağırlığı (%)
order: number
questions: HrEvaluationQuestion[]
}
export interface HrEvaluationQuestion {
// İnsan Kaynakları Değerlendirme Sorusu
id: string
groupId: string
questionText: string
questionType: QuestionTypeEnum
isRequired: boolean
weight: number // Bu sorunun grup içindeki ağırlığı (%)
order: number
options?: HrQuestionOption[] // Çoktan seçmeli sorular için
minRating?: number
maxRating?: number
ratingLabels?: string[] // Rating için etiketler (örn: ["Zayıf", "Orta", "İyi", "Mükemmel"])
}
export interface HrQuestionOption {
// İnsan Kaynakları Soru Seçeneği
id: string
questionId: string
optionText: string
value: number
order: number
}
export interface HrEvaluation360 {
// İnsan Kaynakları 360 Derece Değerlendirme Kampanyası
id: string
name: string
description: string
templateId: string
template?: HrEvaluation360Template
evaluationPeriod: string
startDate: Date
endDate: Date
status: CampaignStatusEnum
departmentId?: string // Hedef departman
targetEmployees: string[] // Değerlendirilecek Employee ID'leri
settings: HrEvaluation360Settings
creationTime: Date
lastModificationTime: Date
}
export interface HrEvaluation360Settings {
// İnsan Kaynakları 360 Derece Değerlendirme Ayarları
allowSelfEvaluation: boolean
requireManagerEvaluation: boolean
minPeerEvaluations: number
minSubordinateEvaluations: number
allowAnonymousFeedback: boolean
sendReminderEmails: boolean
reminderIntervalDays: number
}
export interface HrEvaluation360Participant {
// İnsan Kaynakları 360 Derece Değerlendirme Katılımcısı
id: string
campaignId: string
evaluatedEmployeeId: string // Değerlendirilen kişi
evaluatedEmployee?: EmployeeDto
evaluatorId: string // Değerlendiren kişi
evaluator?: EmployeeDto
evaluatorType: AssessorTypeEnum
status: ParticipantStatusEnum
invitedDate: Date
startedDate?: Date
completedDate?: Date
responses: HrEvaluation360Response[]
overallScore?: number
notes?: string
}
export interface HrEvaluation360Response {
// İnsan Kaynakları 360 Derece Değerlendirme Cevabı
id: string
participantId: string
questionId: string
question?: HrEvaluationQuestion
responseValue: string | number // Cevap değeri
responseText?: string // Metin cevaplar için
score: number // Hesaplanan puan
submittedDate: Date
}
export interface HrEvaluation360Result {
// İnsan Kaynakları 360 Derece Değerlendirme Sonucu
id: string
campaignId: string
employeeId: string
employee?: EmployeeDto
participants: HrEvaluation360Participant[] // Bu sonuca katkıda bulunan değerlendiriciler
overallScore: number
maxPossibleScore: number
scorePercentage: number
groupScores: HrGroupScore[]
assessorTypeScores: HrAssessorTypeScore[]
strengths: string[]
developmentAreas: string[]
actionPlan: string[]
managerComments?: string
hrComments?: string
status: ResultStatusEnum
generatedDate: Date
approvedBy?: string
approvedDate?: Date
}
export interface HrGroupScore {
// İnsan Kaynakları Grup Puanı
groupId: string
groupName: string
score: number
maxScore: number
percentage: number
responseCount: number
}
export interface HrAssessorTypeScore {
// İnsan Kaynakları Değerlendirici Türü Puanı
assessorType: AssessorTypeEnum
assessorCount: number
averageScore: number
maxScore: number
percentage: number
}
export enum PayrollStatusEnum {
// Maaş Durumu
Draft = 'DRAFT', // Taslak
Calculated = 'CALCULATED', // Hesaplandı
Approved = 'APPROVED', // Onaylandı
Paid = 'PAID', // Ödendi
Cancelled = 'CANCELLED', // İptal edildi
}
export enum GoalStatusEnum {
// Hedef Durumu
NotStarted = 'NOT_STARTED', // Başlanmadı
InProgress = 'IN_PROGRESS', // Devam Ediyor
Completed = 'COMPLETED', // Tamamlandı
Overdue = 'OVERDUE', // Geçmiş
Cancelled = 'CANCELLED', // İptal edildi
}
export enum BadgeCategoryEnum {
// Rozet Kategorisi
Performance = 'PERFORMANCE', // Performans
Leadership = 'LEADERSHIP', // Liderlik
Innovation = 'INNOVATION', // Yenilik
Teamwork = 'TEAMWORK', // Takım Çalışması
Customer = 'CUSTOMER', // Müşteri
Safety = 'SAFETY', // Güvenlik
Attendance = 'ATTENDANCE', // Devamsızlık
Training = 'TRAINING', // Eğitim
Project = 'PROJECT', // Proje
Special = 'SPECIAL', // Özel
}
export enum BadgeRarityEnum {
// Rozet Nadirliği
Common = 'COMMON', // Orta
Uncommon = 'UNCOMMON', // Yaygın olmayan
Rare = 'RARE', // Nadir
Epic = 'EPIC', // Epik
Legendary = 'LEGENDARY', // Efsanevi
}
export enum ResultStatusEnum {
// Sonuç Durumu
Pending = 'PENDING', // Beklemede
InReview = 'IN_REVIEW', // İnceleniyor
Approved = 'APPROVED', // Onaylandı
Published = 'PUBLISHED', // Yayınlandı
}
export enum GenderEnum {
// Cinsiyet
Male = 'MALE', // Erkek
Female = 'FEMALE', // Kadın
Other = 'OTHER', // Diğer
}
export enum MaritalStatusEnum {
// Medeni Durum
Single = 'SINGLE', // Bekar
Married = 'MARRIED', // Evli
Divorced = 'DIVORCED', // Boşanmış
Widowed = 'WIDOWED', // Dul
}
export enum CostCenterType {
// Masraf Merkezi Türü
Revenue = 'REVENUE', // Gelir
Standard = 'STANDARD', // Standart
Discretionary = 'DISCRETIONARY', // İsteğe bağlı
Investment = 'INVESTMENT', // Yatırım
Service = 'SERVICE', // Hizmet
Production = 'PRODUCTION', // Üretim
Support = 'SUPPORT', // Destek
Administrative = 'ADMINISTRATIVE', // İdari
}
export enum EmploymentTypeEnum {
// İstihdam Türü
FullTime = 'FULL_TIME', // Tam Zamanlı
PartTime = 'PART_TIME', // Yarı Zamanlı
Contract = 'CONTRACT', // Sözleşmeli
Intern = 'INTERN', // Stajyer
Temporary = 'TEMPORARY', // Geçici
Consultant = 'CONSULTANT', // Danışman
}
export enum EmployeeStatusEnum {
// Çalışan Durumu
Active = 'ACTIVE', // Aktif
Inactive = 'INACTIVE', // Pasif
OnLeave = 'ON_LEAVE', // İzinli
Suspended = 'SUSPENDED', // Askıya Alındı
Terminated = 'TERMINATED', // İşten Ayrıldı
}
export enum JobLevelEnum {
// İş Seviyesi
Entry = 'ENTRY', // Giriş
Junior = 'JUNIOR', // Junior
Mid = 'MID', // Orta
Senior = 'SENIOR', // Kıdemli
Lead = 'LEAD', // Lider
Manager = 'MANAGER', // Yönetici
Director = 'DIRECTOR', // Direktör
Executive = 'EXECUTIVE', // İcra
}
export enum LeaveTypeEnum {
// İzin Türü
Annual = 'Annual', // Yıllık
Sick = 'Sick', // Hastalık
Maternity = 'Maternity', // Doğum
Paternity = 'Paternity', // Babalık
Personal = 'Personal', // Kişisel
Emergency = 'Emergency', // Acil
Study = 'Study', // Eğitim
Unpaid = 'Unpaid', // Ücretsiz
}
export enum LeaveStatusEnum {
// İzin Durumu
Pending = 'Pending', // Beklemede
Approved = 'Approved', // Onaylandı
Rejected = 'Rejected', // Reddedildi
Cancelled = 'Cancelled', // İptal edildi
}
export enum EvaluationStatusEnum {
// Değerlendirme Durumu
NotStarted = 'NOT_STARTED', // Başlanmadı
InProgress = 'IN_PROGRESS', // Devam Ediyor
PendingReview = 'PENDING_REVIEW', // İnceleme Bekliyor
Completed = 'COMPLETED', // Tamamlandı
Overdue = 'OVERDUE', // Geçmiş
}
export enum TrainingTypeEnum {
// Eğitim Türü
Technical = 'TECHNICAL', // Teknik
Soft_Skills = 'SOFT_SKILLS', // Yumuşak Beceriler
Leadership = 'LEADERSHIP', // Liderlik
Compliance = 'COMPLIANCE', // Uyum
Safety = 'SAFETY', // Güvenlik
Product = 'PRODUCT', // Ürün
Process = 'PROCESS', // Süreç
}
export enum TrainingStatusEnum {
// Eğitim Durumu
Planned = 'PLANNED', // Planlandı
Open = 'OPEN', // Açık
InProgress = 'IN_PROGRESS', // Devam Ediyor
Completed = 'COMPLETED', // Tamamlandı
Cancelled = 'CANCELLED', // İptal Edildi
}
export enum ParticipationStatusEnum {
// Katılım Durumu
Enrolled = 'ENROLLED', // Kayıtlı
InProgress = 'IN_PROGRESS', // Devam Ediyor
Completed = 'COMPLETED', // Tamamlandı
Failed = 'FAILED', // Başarısız
Withdrawn = 'WITHDRAWN', // Çekildi
}
export enum DisciplinaryActionTypeEnum {
// Disiplin Cezası Türü
Verbal_Warning = 'VERBAL_WARNING', // Sözlü Uyarı
Written_Warning = 'WRITTEN_WARNING', // Yazılı Uyarı
Final_Warning = 'FINAL_WARNING', // Son Uyarı
Suspension = 'SUSPENSION', // Askıya Alma
Termination = 'TERMINATION', // İşten Çıkarma
Demotion = 'DEMOTION', // Aşağı Alma
}
export enum DisciplinarySeverityEnum {
// Disiplin Cezası Şiddeti
Minor = 'MINOR', // Hafif
Major = 'MAJOR', // Ağır
Severe = 'SEVERE', // Ciddi
}
export enum DisciplinaryStatusEnum {
// Disiplin Cezası Durumu
Active = 'ACTIVE', // Aktif
Resolved = 'RESOLVED', // Çözüldü
Expired = 'EXPIRED', // Süresi Dolmuş
Appealed = 'APPEALED', // İtiraz Edilmiş
}
export enum AssessorTypeEnum {
// Değerlendirici Türü
Self = 'SELF', // Kendi
Manager = 'MANAGER', // Yönetici
Peer = 'PEER', // Meslektaş
Subordinate = 'SUBORDINATE', // Ast
Customer = 'CUSTOMER', // Müşteri
OtherDepartment = 'OTHER_DEPARTMENT', // Diğer Departman
HRUpperManagement = 'HR_UPPER_MANAGEMENT', // İK/Üst Yönetim
External = 'EXTERNAL', // Dış paydaş değerlendirmesi (mevcut)
}
export enum EvaluationTypeEnum {
// Değerlendirme Türü
Annual = 'ANNUAL', // Yıllık
Quarterly = 'QUARTERLY', // Çeyrek
Probation = 'PROBATION', // Deneme Süresi
Project = 'PROJECT', // Proje
Competency = 'COMPETENCY', // Yeterlilik
Leadership = 'LEADERSHIP', // Liderlik
Degree360 = 'DEGREE_360', // 360° Derece değerlendirme
}
export enum CampaignStatusEnum {
// Kampanya Durumu
Draft = 'DRAFT', // Taslak
Active = 'ACTIVE', // Aktif
Completed = 'COMPLETED', // Tamamlandı
Cancelled = 'CANCELLED', // İptal Edildi
}
export enum ParticipantStatusEnum {
// Katılımcı Durumu
Invited = 'INVITED', // Davet Edildi
Started = 'STARTED', // Başladı
Completed = 'COMPLETED', // Tamamlandı
Expired = 'EXPIRED', // Süresi Dolmuş
Declined = 'DECLINED', // Reddedildi
}
export enum QuestionTypeEnum {
// Soru Türü
Rating = 'RATING', // 1-5 puan verme
MultipleChoice = 'MULTIPLE_CHOICE', // Çoktan seçmeli
Text = 'TEXT', // Metin cevap
YesNo = 'YES_NO', // Evet/Hayır
Scale = 'SCALE', // Ölçek (1-10 gibi)
}
export const getQuestionTypeText = (type: QuestionTypeEnum) => {
switch (type) {
case QuestionTypeEnum.Rating:
return 'Puanlama'
case QuestionTypeEnum.MultipleChoice:
return 'Çoktan Seçmeli'
case QuestionTypeEnum.Text:
return 'Metin'
case QuestionTypeEnum.YesNo:
return 'Evet/Hayır'
case QuestionTypeEnum.Scale:
return 'Ölçek'
default:
return 'Bilinmeyen'
}
}

View file

@ -11,7 +11,7 @@ function deepParseJson(jsonString: Json): Json {
} }
try { try {
return deepParseJson(JSON.parse(jsonString)) return deepParseJson(JSON.parse(jsonString))
} catch (err) { } catch {
return jsonString return jsonString
} }
} else if (Array.isArray(jsonString)) { } else if (Array.isArray(jsonString)) {

View file

@ -7,12 +7,8 @@ import { NotificationDto } from '@/proxy/notification/models'
import { getList } from '@/services/notification.service' import { getList } from '@/services/notification.service'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { Dictionary } from 'lodash'
import forOwn from 'lodash/forOwn'
import groupBy from 'lodash/groupBy' import groupBy from 'lodash/groupBy'
import has from 'lodash/has' import { useCallback, useEffect, useState } from 'react'
import merge from 'lodash/merge'
import { useEffect, useState } from 'react'
import Log from './components/Log' import Log from './components/Log'
import LogFilter from './components/LogFilter' import LogFilter from './components/LogFilter'
import { Helmet } from 'react-helmet' import { Helmet } from 'react-helmet'
@ -21,12 +17,13 @@ import { DIR_RTL } from '@/constants/theme.constant'
import { useStoreState } from '@/store' import { useStoreState } from '@/store'
const itemsPerPage = 10 const itemsPerPage = 10
type NotificationGroups = Record<string, NotificationDto[]>
const ActivityLog = () => { const ActivityLog = () => {
const { translate } = useLocalization() const { translate } = useLocalization()
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const [notifications, setNotifications] = useState<Dictionary<NotificationDto[]>>({}) const [notifications, setNotifications] = useState<NotificationGroups>({})
const [page, setPage] = useState(0) const [page, setPage] = useState(0)
const [hasMore, setHasMore] = useState(false) const [hasMore, setHasMore] = useState(false)
const [isFilterDrawerOpen, setIsFilterDrawerOpen] = useState(false) const [isFilterDrawerOpen, setIsFilterDrawerOpen] = useState(false)
@ -41,8 +38,9 @@ const ActivityLog = () => {
NotificationChannels.WhatsApp, NotificationChannels.WhatsApp,
]) ])
const fetchData = async (isLoadmore: boolean = false) => { const fetchData = useCallback(async (isLoadmore: boolean = false) => {
setLoading(true) setLoading(true)
try {
const response = await getList({ const response = await getList({
maxResultCount: itemsPerPage, maxResultCount: itemsPerPage,
skipCount: page * itemsPerPage, skipCount: page * itemsPerPage,
@ -57,22 +55,26 @@ const ActivityLog = () => {
const logs = groupBy(items, (a) => dayjs(a.creationTime).format('YYYY-MM-DD')) const logs = groupBy(items, (a) => dayjs(a.creationTime).format('YYYY-MM-DD'))
if (isLoadmore) { if (isLoadmore) {
forOwn(notifications, function (value, key) { setNotifications((prev) => {
if (has(logs, key)) { const next: NotificationGroups = { ...prev }
notifications[key] = [...notifications[key], ...logs[key]]
delete logs[key] for (const [key, value] of Object.entries(logs)) {
next[key] = [...(next[key] ?? []), ...value]
} }
return next
}) })
setNotifications(merge(notifications, logs))
} else { } else {
setNotifications(logs) setNotifications(logs)
} }
} finally {
setLoading(false) setLoading(false)
} }
}, [filter, page])
useEffect(() => { useEffect(() => {
fetchData(page > 0) fetchData(page > 0)
}, [page, filter]) }, [fetchData, page])
const handleFilterChange = (value: string[]) => { const handleFilterChange = (value: string[]) => {
setPage(0) setPage(0)
@ -111,13 +113,13 @@ const ActivityLog = () => {
<Log <Log
notifications={notifications} notifications={notifications}
isLoading={loading} isLoading={loading}
onLoadMore={() => setPage((prev) => prev + 1)}
loadable={hasMore} loadable={hasMore}
onLoadMore={() => setPage((prev) => prev + 1)}
></Log> ></Log>
</div> </div>
<div className="hidden lg:block"> <div className="hidden lg:block">
<LogFilter filter={filter} onFilterChange={handleFilterChange} useAffix className="dark:bg-gray-800" /> <LogFilter useAffix filter={filter} className="dark:bg-gray-800" onFilterChange={handleFilterChange} />
</div> </div>
</div> </div>
</div> </div>
@ -132,9 +134,9 @@ const ActivityLog = () => {
> >
<LogFilter <LogFilter
filter={filter} filter={filter}
onFilterChange={handleFilterChange}
useAffix={false} useAffix={false}
className="border-none p-0 dark:bg-gray-800" className="border-none p-0 dark:bg-gray-800"
onFilterChange={handleFilterChange}
/> />
</Drawer> </Drawer>
</AdaptableCard> </AdaptableCard>

View file

@ -5,7 +5,6 @@ import { AVATAR_URL } from '@/constants/app.constant'
import { NotificationDto } from '@/proxy/notification/models' import { NotificationDto } from '@/proxy/notification/models'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { Dictionary } from 'lodash'
import isEmpty from 'lodash/isEmpty' import isEmpty from 'lodash/isEmpty'
import keys from 'lodash/keys' import keys from 'lodash/keys'
import Event from './Event' import Event from './Event'
@ -18,7 +17,7 @@ const Log = ({
isLoading, isLoading,
loadable, loadable,
}: { }: {
notifications: Dictionary<NotificationDto[]> notifications: Record<string, NotificationDto[]>
onLoadMore: () => void onLoadMore: () => void
isLoading: boolean isLoading: boolean
loadable: boolean loadable: boolean
@ -38,7 +37,7 @@ const Log = ({
{isEmpty(notifications[group]) ? ( {isEmpty(notifications[group]) ? (
<Timeline.Item className="dark:text-gray-400">Bildirim yok</Timeline.Item> <Timeline.Item className="dark:text-gray-400">Bildirim yok</Timeline.Item>
) : ( ) : (
notifications[group].map((notification, i) => ( notifications[group].map((notification) => (
<Timeline.Item <Timeline.Item
key={notification.id} key={notification.id}
media={ media={
@ -57,7 +56,7 @@ const Log = ({
))} ))}
<div className="text-center"> <div className="text-center">
{loadable ? ( {loadable ? (
<Button size="sm" loading={isLoading} onClick={onLoadMore} variant='solid'> <Button size="sm" loading={isLoading} variant='solid' onClick={onLoadMore}>
{translate('::Abp.Identity.ActivityLogs.LoadMore')} {translate('::Abp.Identity.ActivityLogs.LoadMore')}
</Button> </Button>
) : ( ) : (

View file

@ -1,4 +1,4 @@
import { useState, useEffect, useCallback, useRef } from 'react' import { useState, useEffect, useCallback, useRef, type MouseEvent } from 'react'
import { Helmet } from 'react-helmet' import { Helmet } from 'react-helmet'
import { Button, Input, Select, toast, Notification, Spinner } from '@/components/ui' import { Button, Input, Select, toast, Notification, Spinner } from '@/components/ui'
import { useStoreState } from '@/store' import { useStoreState } from '@/store'
@ -251,7 +251,7 @@ const FileManager = () => {
}) })
} }
const handleItemDoubleClick = (item: FileItemType, event?: React.MouseEvent) => { const handleItemDoubleClick = (item: FileItemType, event?: MouseEvent) => {
// Prevent text selection and other default behaviors // Prevent text selection and other default behaviors
if (event) { if (event) {
event.preventDefault() event.preventDefault()
@ -409,7 +409,7 @@ const FileManager = () => {
if (hasFiles) { if (hasFiles) {
toast.push( toast.push(
<Notification title="Security Warning" type="warning"> <Notification title="Security Warning" type="warning">
Folder '{item.name}' contains files and cannot be deleted for security reasons. Folder {item.name} contains files and cannot be deleted for security reasons.
</Notification>, </Notification>,
) )
return return
@ -491,6 +491,8 @@ const FileManager = () => {
return () => { return () => {
document.removeEventListener('keydown', handleKeyDown) document.removeEventListener('keydown', handleKeyDown)
} }
// Keyboard shortcuts should bind once per selection/list state snapshot.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedItems, filteredItems]) }, [selectedItems, filteredItems])
// Bulk operations // Bulk operations
@ -710,7 +712,7 @@ const FileManager = () => {
setLoading(false) setLoading(false)
} }
} }
} catch (error) { } catch {
toast.push( toast.push(
<Notification title="Error" type="danger"> <Notification title="Error" type="danger">
Invalid clipboard data Invalid clipboard data
@ -738,18 +740,18 @@ const FileManager = () => {
<Button <Button
variant="plain" variant="plain"
icon={<FaArrowUp />} icon={<FaArrowUp />}
onClick={goUpOneLevel}
size="sm" size="sm"
disabled={breadcrumbItems.length <= 1} disabled={breadcrumbItems.length <= 1}
className="text-gray-600 hover:text-blue-600 flex-shrink-0" className="text-gray-600 hover:text-blue-600 flex-shrink-0"
title="Go up one level" title="Go up one level"
onClick={goUpOneLevel}
/> />
<Button <Button
variant="solid" variant="solid"
icon={<FaCloudUploadAlt />} icon={<FaCloudUploadAlt />}
onClick={() => setUploadModalOpen(true)}
size="sm" size="sm"
className="flex-shrink-0" className="flex-shrink-0"
onClick={() => setUploadModalOpen(true)}
> >
<span className="hidden sm:inline">{translate('::FileManager.UploadFiles')}</span> <span className="hidden sm:inline">{translate('::FileManager.UploadFiles')}</span>
<span className="sm:hidden">{translate('::FileManager.Upload')}</span> <span className="sm:hidden">{translate('::FileManager.Upload')}</span>
@ -757,9 +759,9 @@ const FileManager = () => {
<Button <Button
variant="default" variant="default"
icon={<FaFolder />} icon={<FaFolder />}
onClick={() => setCreateFolderModalOpen(true)}
size="sm" size="sm"
className="flex-shrink-0" className="flex-shrink-0"
onClick={() => setCreateFolderModalOpen(true)}
> >
<span className="hidden sm:inline">{translate('::FileManager.CreateFolder')}</span> <span className="hidden sm:inline">{translate('::FileManager.CreateFolder')}</span>
<span className="sm:hidden">{translate('::FileManager.Create')}</span> <span className="sm:hidden">{translate('::FileManager.Create')}</span>
@ -769,33 +771,37 @@ const FileManager = () => {
<Button <Button
variant="plain" variant="plain"
icon={<FaCopy />} icon={<FaCopy />}
onClick={copySelectedItems}
disabled={selectedItems.length === 0} disabled={selectedItems.length === 0}
size="sm" size="sm"
className="text-gray-600 hover:text-blue-600 disabled:opacity-50 flex-shrink-0" className="text-gray-600 hover:text-blue-600 disabled:opacity-50 flex-shrink-0"
title={translate('::FileManager.CopySelectedItems')} title={translate('::FileManager.CopySelectedItems')}
onClick={copySelectedItems}
/> />
<Button <Button
variant="plain" variant="plain"
icon={<FaCut />} icon={<FaCut />}
onClick={cutSelectedItems}
disabled={selectedItems.length === 0} disabled={selectedItems.length === 0}
size="sm" size="sm"
className="text-gray-600 hover:text-orange-600 disabled:opacity-50 flex-shrink-0" className="text-gray-600 hover:text-orange-600 disabled:opacity-50 flex-shrink-0"
title={translate('::FileManager.CutSelectedItems')} title={translate('::FileManager.CutSelectedItems')}
onClick={cutSelectedItems}
/> />
<Button <Button
variant="plain" variant="plain"
icon={<FaPaste />} icon={<FaPaste />}
onClick={pasteItems}
disabled={!hasClipboardData} disabled={!hasClipboardData}
size="sm" size="sm"
className="text-gray-600 hover:text-green-600 disabled:opacity-50 flex-shrink-0" className="text-gray-600 hover:text-green-600 disabled:opacity-50 flex-shrink-0"
title={translate('::FileManager.PasteSelectedItems')} title={translate('::FileManager.PasteSelectedItems')}
onClick={pasteItems}
/> />
<Button <Button
variant="plain" variant="plain"
icon={<FaEdit />} icon={<FaEdit />}
size="sm"
disabled={selectedItems.length !== 1}
className="text-gray-600 hover:text-blue-600 flex-shrink-0"
title={translate('::FileManager.RenameSelectedItem')}
onClick={() => { onClick={() => {
if (selectedItems.length === 1) { if (selectedItems.length === 1) {
const itemToRename = filteredItems.find((item) => item.id === selectedItems[0]) const itemToRename = filteredItems.find((item) => item.id === selectedItems[0])
@ -810,15 +816,21 @@ const FileManager = () => {
} }
} }
}} }}
size="sm"
disabled={selectedItems.length !== 1}
className="text-gray-600 hover:text-blue-600 flex-shrink-0"
title={translate('::FileManager.RenameSelectedItem')}
></Button> ></Button>
<Button <Button
variant="plain" variant="plain"
icon={<FaDownload />} icon={<FaDownload />}
size="sm"
disabled={
selectedItems.length !== 1 ||
(() => {
const selectedItem = filteredItems.find((item) => item.id === selectedItems[0])
return selectedItem?.type !== 'file'
})()
}
className="text-gray-600 hover:text-green-600 flex-shrink-0"
title={translate('::FileManager.DownloadSelectedFile')}
onClick={() => { onClick={() => {
if (selectedItems.length === 1) { if (selectedItems.length === 1) {
const itemToDownload = filteredItems.find((item) => item.id === selectedItems[0]) const itemToDownload = filteredItems.find((item) => item.id === selectedItems[0])
@ -833,26 +845,16 @@ const FileManager = () => {
} }
} }
}} }}
size="sm"
disabled={
selectedItems.length !== 1 ||
(() => {
const selectedItem = filteredItems.find((item) => item.id === selectedItems[0])
return selectedItem?.type !== 'file'
})()
}
className="text-gray-600 hover:text-green-600 flex-shrink-0"
title={translate('::FileManager.DownloadSelectedFile')}
></Button> ></Button>
<Button <Button
variant="plain" variant="plain"
icon={<FaTrash />} icon={<FaTrash />}
onClick={deleteSelectedItems}
size="sm" size="sm"
disabled={selectedItems.length === 0} disabled={selectedItems.length === 0}
className="text-gray-600 hover:text-red-600 flex-shrink-0" className="text-gray-600 hover:text-red-600 flex-shrink-0"
title={translate('::FileManager.DeleteSelectedItems')} title={translate('::FileManager.DeleteSelectedItems')}
onClick={deleteSelectedItems}
> >
<span>{translate('::Delete')}</span> {selectedItems.length > 0 && `(${selectedItems.length})`} <span>{translate('::Delete')}</span> {selectedItems.length > 0 && `(${selectedItems.length})`}
</Button> </Button>
@ -869,11 +871,6 @@ const FileManager = () => {
<FaSquare /> <FaSquare />
) )
} }
onClick={
selectedItems.length === filteredItems.filter((item) => !item.isReadOnly).length
? deselectAllItems
: selectAllItems
}
size="sm" size="sm"
className="text-gray-600 hover:text-blue-600 flex-shrink-0" className="text-gray-600 hover:text-blue-600 flex-shrink-0"
title={ title={
@ -881,6 +878,11 @@ const FileManager = () => {
? 'Deselect all selectable items' ? 'Deselect all selectable items'
: 'Select all selectable items' : 'Select all selectable items'
} }
onClick={
selectedItems.length === filteredItems.filter((item) => !item.isReadOnly).length
? deselectAllItems
: selectAllItems
}
> >
<span className="hidden lg:inline"> <span className="hidden lg:inline">
{selectedItems.length === filteredItems.filter((item) => !item.isReadOnly).length {selectedItems.length === filteredItems.filter((item) => !item.isReadOnly).length
@ -904,9 +906,9 @@ const FileManager = () => {
size="sm" size="sm"
placeholder={translate('::FileManager.SearchFiles')} placeholder={translate('::FileManager.SearchFiles')}
value={filters.searchTerm} value={filters.searchTerm}
onChange={(e) => setFilters((prev) => ({ ...prev, searchTerm: e.target.value }))}
prefix={<FaSearch className="text-gray-400" />} prefix={<FaSearch className="text-gray-400" />}
className="w-full sm:w-36 md:w-48" className="w-full sm:w-36 md:w-48"
onChange={(e) => setFilters((prev) => ({ ...prev, searchTerm: e.target.value }))}
/> />
</div> </div>
@ -954,15 +956,15 @@ const FileManager = () => {
size="sm" size="sm"
icon={<FaTh />} icon={<FaTh />}
variant={viewMode === 'grid' ? 'solid' : 'default'} variant={viewMode === 'grid' ? 'solid' : 'default'}
onClick={() => setViewMode('grid')}
title="Grid view" title="Grid view"
onClick={() => setViewMode('grid')}
/> />
<Button <Button
size="sm" size="sm"
icon={<FaList />} icon={<FaList />}
variant={viewMode === 'list' ? 'solid' : 'default'} variant={viewMode === 'list' ? 'solid' : 'default'}
onClick={() => setViewMode('list')}
title="List view" title="List view"
onClick={() => setViewMode('list')}
/> />
</div> </div>
</div> </div>
@ -1131,40 +1133,40 @@ const FileManager = () => {
{/* Modals */} {/* Modals */}
<FileUploadModal <FileUploadModal
isOpen={uploadModalOpen} isOpen={uploadModalOpen}
onClose={() => setUploadModalOpen(false)}
onUpload={handleUploadFiles}
currentFolderId={currentFolderId} currentFolderId={currentFolderId}
loading={uploading} loading={uploading}
onClose={() => setUploadModalOpen(false)}
onUpload={handleUploadFiles}
/> />
<CreateFolderModal <CreateFolderModal
isOpen={createFolderModalOpen} isOpen={createFolderModalOpen}
onClose={() => setCreateFolderModalOpen(false)}
onCreate={handleCreateFolder}
loading={creating} loading={creating}
currentFolderId={currentFolderId} currentFolderId={currentFolderId}
onClose={() => setCreateFolderModalOpen(false)}
onCreate={handleCreateFolder}
/> />
<RenameItemModal <RenameItemModal
isOpen={renameModalOpen} isOpen={renameModalOpen}
item={itemToRename}
loading={renaming}
onClose={() => { onClose={() => {
setRenameModalOpen(false) setRenameModalOpen(false)
setItemToRename(undefined) setItemToRename(undefined)
}} }}
onRename={handleRenameItem} onRename={handleRenameItem}
item={itemToRename}
loading={renaming}
/> />
<DeleteConfirmModal <DeleteConfirmModal
isOpen={deleteModalOpen} isOpen={deleteModalOpen}
items={itemsToDelete}
loading={deleting}
onClose={() => { onClose={() => {
setDeleteModalOpen(false) setDeleteModalOpen(false)
setItemsToDelete([]) setItemsToDelete([])
}} }}
onDelete={handleDeleteItems} onDelete={handleDeleteItems}
items={itemsToDelete}
loading={deleting}
/> />
</Container> </Container>
) )

View file

@ -27,7 +27,6 @@ const Breadcrumb = forwardRef<HTMLDivElement, BreadcrumbProps>((props, ref) => {
<FaFolder className="h-4 w-4 mr-1" /> <FaFolder className="h-4 w-4 mr-1" />
) )
} }
onClick={() => onNavigate(item)}
className={classNames( className={classNames(
'flex items-center px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors', 'flex items-center px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors',
index === items.length - 1 index === items.length - 1
@ -35,6 +34,7 @@ const Breadcrumb = forwardRef<HTMLDivElement, BreadcrumbProps>((props, ref) => {
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100', : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100',
)} )}
disabled={index === items.length - 1} disabled={index === items.length - 1}
onClick={() => onNavigate(item)}
> >
<span className="truncate max-w-32">{item.name}</span> <span className="truncate max-w-32">{item.name}</span>
</Button> </Button>

View file

@ -1,4 +1,4 @@
import { forwardRef, useState, useEffect } from 'react' import { forwardRef, useState, useEffect, type ChangeEvent, type MouseEvent } from 'react'
import classNames from 'classnames' import classNames from 'classnames'
import { import {
FaFolder, FaFolder,
@ -16,7 +16,6 @@ import {
FaLink, FaLink,
} from 'react-icons/fa' } from 'react-icons/fa'
import { toast, Notification } from '@/components/ui' import { toast, Notification } from '@/components/ui'
// import { Dropdown } from '@/components/ui' // Artık kullanmıyoruz
import type { FileItem as FileItemType, FileActionMenuItem } from '@/types/fileManagement' import type { FileItem as FileItemType, FileActionMenuItem } from '@/types/fileManagement'
import { FILE_URL } from '@/constants/app.constant' import { FILE_URL } from '@/constants/app.constant'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
@ -26,7 +25,7 @@ export interface FileItemProps {
selected?: boolean selected?: boolean
viewMode?: 'grid' | 'list' viewMode?: 'grid' | 'list'
onSelect?: (item: FileItemType) => void onSelect?: (item: FileItemType) => void
onDoubleClick?: (item: FileItemType, event?: React.MouseEvent) => void onDoubleClick?: (item: FileItemType, event?: MouseEvent) => void
onCreateFolder?: (parentItem: FileItemType) => void onCreateFolder?: (parentItem: FileItemType) => void
onRename?: (item: FileItemType) => void onRename?: (item: FileItemType) => void
onMove?: (item: FileItemType) => void onMove?: (item: FileItemType) => void
@ -141,11 +140,11 @@ const FileItem = forwardRef<HTMLDivElement, FileItemProps>((props, ref) => {
onSelect?.(item) onSelect?.(item)
} }
const handleDoubleClick = (e: React.MouseEvent) => { const handleDoubleClick = (e: MouseEvent) => {
onDoubleClick?.(item, e) onDoubleClick?.(item, e)
} }
const handleContextMenu = (e: React.MouseEvent) => { const handleContextMenu = (e: MouseEvent) => {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
@ -171,12 +170,12 @@ const FileItem = forwardRef<HTMLDivElement, FileItemProps>((props, ref) => {
} }
}, [dropdownOpen]) }, [dropdownOpen])
const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleCheckboxChange = (e: ChangeEvent<HTMLInputElement>) => {
e.stopPropagation() // Prevent item selection when clicking checkbox e.stopPropagation() // Prevent item selection when clicking checkbox
onToggleSelect?.(item) onToggleSelect?.(item)
} }
const handleCheckboxClick = (e: React.MouseEvent) => { const handleCheckboxClick = (e: MouseEvent) => {
e.stopPropagation() // Prevent item selection when clicking checkbox e.stopPropagation() // Prevent item selection when clicking checkbox
} }
@ -216,7 +215,7 @@ const FileItem = forwardRef<HTMLDivElement, FileItemProps>((props, ref) => {
() => { () => {
toast.push( toast.push(
<Notification type="success" title="Başarılı"> <Notification type="success" title="Başarılı">
Dosya URL'si panoya kopyalandı Dosya URL&apos;si panoya kopyalandı
</Notification>, </Notification>,
) )
}, },
@ -367,9 +366,9 @@ const FileItem = forwardRef<HTMLDivElement, FileItemProps>((props, ref) => {
<input <input
type="checkbox" type="checkbox"
checked={selected} checked={selected}
className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
onChange={handleCheckboxChange} onChange={handleCheckboxChange}
onClick={handleCheckboxClick} onClick={handleCheckboxClick}
className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
/> />
) : ( ) : (
<div className="w-4 h-4" /> // Boş alan bırak <div className="w-4 h-4" /> // Boş alan bırak
@ -464,9 +463,9 @@ const FileItem = forwardRef<HTMLDivElement, FileItemProps>((props, ref) => {
<input <input
type="checkbox" type="checkbox"
checked={selected} checked={selected}
className="w-4 h-4 text-blue-600 bg-white border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600 shadow-sm"
onChange={handleCheckboxChange} onChange={handleCheckboxChange}
onClick={handleCheckboxClick} onClick={handleCheckboxClick}
className="w-4 h-4 text-blue-600 bg-white border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600 shadow-sm"
/> />
</div> </div>
)} )}

View file

@ -1,6 +1,5 @@
import { forwardRef, useState, useEffect } from 'react' import { forwardRef, useState, useEffect, type FormEvent } from 'react'
import { Dialog, Button, Input, FormItem } from '@/components/ui' import { Dialog, Button, Input, FormItem } from '@/components/ui'
import { FaTimes } from 'react-icons/fa'
import type { FileItem } from '@/types/fileManagement' import type { FileItem } from '@/types/fileManagement'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
@ -20,7 +19,7 @@ export const CreateFolderModal = forwardRef<HTMLDivElement, CreateFolderModalPro
const [error, setError] = useState('') const [error, setError] = useState('')
const { translate } = useLocalization() const { translate } = useLocalization()
const handleSubmit = async (e: React.FormEvent) => { const handleSubmit = async (e: FormEvent) => {
e.preventDefault() e.preventDefault()
if (!folderName.trim()) { if (!folderName.trim()) {
@ -33,7 +32,7 @@ export const CreateFolderModal = forwardRef<HTMLDivElement, CreateFolderModalPro
setFolderName('') setFolderName('')
setError('') setError('')
onClose() onClose()
} catch (err) { } catch {
setError('Failed to create folder') setError('Failed to create folder')
} }
} }
@ -47,27 +46,27 @@ export const CreateFolderModal = forwardRef<HTMLDivElement, CreateFolderModalPro
return ( return (
<Dialog isOpen={isOpen} onClose={handleClose}> <Dialog isOpen={isOpen} onClose={handleClose}>
<div ref={ref}> <div ref={ref}>
<form onSubmit={handleSubmit} className="py-6"> <form className="py-6" onSubmit={handleSubmit}>
<FormItem label={translate('::FileManager.FolderName')} invalid={!!error} errorMessage={error}> <FormItem label={translate('::FileManager.FolderName')} invalid={!!error} errorMessage={error}>
<Input <Input
value={folderName}
onChange={(e) => setFolderName(e.target.value)}
autoFocus autoFocus
value={folderName}
className="mt-2" className="mt-2"
onChange={(e) => setFolderName(e.target.value)}
/> />
</FormItem> </FormItem>
</form> </form>
<div className="flex justify-end space-x-2 pt-4 border-t"> <div className="flex justify-end space-x-2 pt-4 border-t">
<Button size='sm' variant="default" onClick={handleClose} disabled={loading}> <Button size='sm' variant="default" disabled={loading} onClick={handleClose}>
{translate('::Cancel')} {translate('::Cancel')}
</Button> </Button>
<Button <Button
size='sm' size='sm'
variant="solid" variant="solid"
onClick={handleSubmit}
loading={loading} loading={loading}
disabled={!folderName.trim()} disabled={!folderName.trim()}
onClick={handleSubmit}
> >
{translate('::FileManager.CreateFolder')} {translate('::FileManager.CreateFolder')}
</Button> </Button>
@ -102,7 +101,7 @@ export const RenameItemModal = forwardRef<HTMLDivElement, RenameItemModalProps>(
} }
}, [item]) }, [item])
const handleSubmit = async (e: React.FormEvent) => { const handleSubmit = async (e: FormEvent) => {
e.preventDefault() e.preventDefault()
if (!newName.trim()) { if (!newName.trim()) {
@ -119,7 +118,7 @@ export const RenameItemModal = forwardRef<HTMLDivElement, RenameItemModalProps>(
await onRename(newName.trim()) await onRename(newName.trim())
setError('') setError('')
onClose() onClose()
} catch (err) { } catch {
setError(`Failed to rename ${item?.type}`) setError(`Failed to rename ${item?.type}`)
} }
} }
@ -141,31 +140,31 @@ export const RenameItemModal = forwardRef<HTMLDivElement, RenameItemModalProps>(
</h3> </h3>
</div> </div>
<form onSubmit={handleSubmit} className="py-6"> <form className="py-6" onSubmit={handleSubmit}>
<FormItem <FormItem
label={translate(`::FileManager.${item.type === 'folder' ? 'FolderName' : 'FileName'}`)} label={translate(`::FileManager.${item.type === 'folder' ? 'FolderName' : 'FileName'}`)}
invalid={!!error} invalid={!!error}
errorMessage={error} errorMessage={error}
> >
<Input <Input
value={newName}
onChange={(e) => setNewName(e.target.value)}
placeholder={`Enter ${translate(`::FileManager.${item.type === 'folder' ? 'FolderName' : 'FileName'}`)}`}
autoFocus autoFocus
value={newName}
placeholder={`Enter ${translate(`::FileManager.${item.type === 'folder' ? 'FolderName' : 'FileName'}`)}`}
onChange={(e) => setNewName(e.target.value)}
/> />
</FormItem> </FormItem>
</form> </form>
<div className="flex justify-end space-x-2 pt-4 border-t"> <div className="flex justify-end space-x-2 pt-4 border-t">
<Button size='sm' variant="default" onClick={handleClose} disabled={loading}> <Button size='sm' variant="default" disabled={loading} onClick={handleClose}>
{translate('::Cancel')} {translate('::Cancel')}
</Button> </Button>
<Button <Button
size='sm' size='sm'
variant="solid" variant="solid"
onClick={handleSubmit}
loading={loading} loading={loading}
disabled={!newName.trim()} disabled={!newName.trim()}
onClick={handleSubmit}
> >
{translate('::App.Listform.ListformField.Rename')} {translate('::App.Listform.ListformField.Rename')}
</Button> </Button>
@ -195,7 +194,7 @@ export const DeleteConfirmModal = forwardRef<HTMLDivElement, DeleteConfirmModalP
try { try {
await onDelete() await onDelete()
onClose() onClose()
} catch (err) { } catch {
// Error handling is done in parent component // Error handling is done in parent component
} }
} }
@ -240,14 +239,14 @@ export const DeleteConfirmModal = forwardRef<HTMLDivElement, DeleteConfirmModalP
</div> </div>
<div className="flex justify-end space-x-2 pt-4 border-t"> <div className="flex justify-end space-x-2 pt-4 border-t">
<Button size='sm' variant="default" onClick={onClose} disabled={loading}> <Button size='sm' variant="default" disabled={loading} onClick={onClose}>
{translate('::Cancel')} {translate('::Cancel')}
</Button> </Button>
<Button <Button
size='sm' size='sm'
variant="solid" variant="solid"
onClick={handleDelete}
loading={loading} loading={loading}
onClick={handleDelete}
> >
{translate('::Delete')} {translate('::Delete')}
</Button> </Button>

View file

@ -1,4 +1,11 @@
import { forwardRef, useState, useCallback, useRef } from 'react' import {
forwardRef,
useState,
useCallback,
useRef,
type ChangeEvent,
type DragEvent,
} from 'react'
import { Dialog, Button, Progress } from '@/components/ui' import { Dialog, Button, Progress } from '@/components/ui'
import { FaCloudUploadAlt, FaTimes } from 'react-icons/fa' import { FaCloudUploadAlt, FaTimes } from 'react-icons/fa'
import classNames from 'classnames' import classNames from 'classnames'
@ -22,7 +29,7 @@ interface UploadFileWithProgress {
} }
const FileUploadModal = forwardRef<HTMLDivElement, FileUploadModalProps>((props, ref) => { const FileUploadModal = forwardRef<HTMLDivElement, FileUploadModalProps>((props, ref) => {
const { isOpen, onClose, onUpload, currentFolderId, loading = false, className } = props const { isOpen, onClose, onUpload, className } = props
const [uploadFiles, setUploadFiles] = useState<UploadFileWithProgress[]>([]) const [uploadFiles, setUploadFiles] = useState<UploadFileWithProgress[]>([])
const [isDragOver, setIsDragOver] = useState(false) const [isDragOver, setIsDragOver] = useState(false)
@ -53,24 +60,24 @@ const FileUploadModal = forwardRef<HTMLDivElement, FileUploadModalProps>((props,
setUploadFiles((prev) => [...prev, ...newFiles]) setUploadFiles((prev) => [...prev, ...newFiles])
}, []) }, [])
const handleFileInputChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleFileInputChange = (e: ChangeEvent<HTMLInputElement>) => {
if (e.target.files) { if (e.target.files) {
handleFilesSelect(e.target.files) handleFilesSelect(e.target.files)
} }
} }
const handleDragOver = useCallback((e: React.DragEvent) => { const handleDragOver = useCallback((e: DragEvent) => {
e.preventDefault() e.preventDefault()
setIsDragOver(true) setIsDragOver(true)
}, []) }, [])
const handleDragLeave = useCallback((e: React.DragEvent) => { const handleDragLeave = useCallback((e: DragEvent) => {
e.preventDefault() e.preventDefault()
setIsDragOver(false) setIsDragOver(false)
}, []) }, [])
const handleDrop = useCallback( const handleDrop = useCallback(
(e: React.DragEvent) => { (e: DragEvent) => {
e.preventDefault() e.preventDefault()
setIsDragOver(false) setIsDragOver(false)
@ -216,10 +223,6 @@ const FileUploadModal = forwardRef<HTMLDivElement, FileUploadModalProps>((props,
} }
} }
const clearCompletedFiles = () => {
setUploadFiles((prev) => prev.filter((f) => f.status !== 'completed'))
}
const clearErrorFiles = () => { const clearErrorFiles = () => {
setUploadFiles((prev) => prev.filter((f) => f.status !== 'error')) setUploadFiles((prev) => prev.filter((f) => f.status !== 'error'))
} }
@ -231,7 +234,7 @@ const FileUploadModal = forwardRef<HTMLDivElement, FileUploadModalProps>((props,
const hasError = errorFiles > 0 const hasError = errorFiles > 0
return ( return (
<Dialog isOpen={isOpen} onClose={handleClose} className={className}> <Dialog isOpen={isOpen} className={className} onClose={handleClose}>
<div ref={ref}> <div ref={ref}>
<div className="flex items-center justify-between pb-2 border-b"> <div className="flex items-center justify-between pb-2 border-b">
<h3 className="text-lg font-semibold">Upload Files</h3> <h3 className="text-lg font-semibold">Upload Files</h3>
@ -251,11 +254,11 @@ const FileUploadModal = forwardRef<HTMLDivElement, FileUploadModalProps>((props,
> >
<input <input
ref={fileInputRef} ref={fileInputRef}
type="file"
multiple multiple
type="file"
className="absolute inset-0 w-full h-full opacity-0 cursor-pointer" className="absolute inset-0 w-full h-full opacity-0 cursor-pointer"
onChange={handleFileInputChange}
disabled={uploading} disabled={uploading}
onChange={handleFileInputChange}
/> />
<FaCloudUploadAlt className="mx-auto h-12 w-12 text-gray-400 mb-4" /> <FaCloudUploadAlt className="mx-auto h-12 w-12 text-gray-400 mb-4" />
@ -318,9 +321,9 @@ const FileUploadModal = forwardRef<HTMLDivElement, FileUploadModalProps>((props,
variant="plain" variant="plain"
size="sm" size="sm"
icon={<FaTimes />} icon={<FaTimes />}
onClick={() => removeFile(file.id)}
disabled={uploading} disabled={uploading}
className="ml-2 flex-shrink-0" className="ml-2 flex-shrink-0"
onClick={() => removeFile(file.id)}
/> />
)} )}
</div> </div>
@ -349,21 +352,21 @@ const FileUploadModal = forwardRef<HTMLDivElement, FileUploadModalProps>((props,
{hasError && !uploading && ( {hasError && !uploading && (
<Button <Button
variant="plain" variant="plain"
onClick={clearErrorFiles}
className="text-red-600 hover:text-red-700" className="text-red-600 hover:text-red-700"
onClick={clearErrorFiles}
> >
Clear Errors Clear Errors
</Button> </Button>
)} )}
<Button size="sm" variant="default" onClick={handleClose} disabled={uploading}> <Button size="sm" variant="default" disabled={uploading} onClick={handleClose}>
{uploading ? 'Uploading...' : 'Close'} {uploading ? 'Uploading...' : 'Close'}
</Button> </Button>
<Button <Button
size="sm" size="sm"
variant="solid" variant="solid"
onClick={handleUpload}
disabled={pendingFiles === 0 || uploading} disabled={pendingFiles === 0 || uploading}
loading={uploading} loading={uploading}
onClick={handleUpload}
> >
{uploading ? 'Uploading...' : `Upload ${pendingFiles} File(s)`} {uploading ? 'Uploading...' : `Upload ${pendingFiles} File(s)`}
</Button> </Button>

View file

@ -1,4 +1,15 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import {
type Dispatch,
type MutableRefObject,
type SetStateAction,
type WheelEvent,
type MouseEvent as ReactMouseEvent,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react'
import { import {
FaSitemap, FaSitemap,
FaBriefcase, FaBriefcase,
@ -19,11 +30,10 @@ import {
OrgChartUserDto, OrgChartUserDto,
} from '@/services/orgChart.service' } from '@/services/orgChart.service'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { APP_NAME } from '@/constants/app.constant' import { AVATAR_URL, APP_NAME } from '@/constants/app.constant'
import Loading from '@/components/shared/Loading' import Loading from '@/components/shared/Loading'
import { useCurrentMenuIcon } from '@/utils/hooks/useCurrentMenuIcon' import { useCurrentMenuIcon } from '@/utils/hooks/useCurrentMenuIcon'
import { Avatar, Button } from '@/components/ui' import { Avatar, Button } from '@/components/ui'
import { AVATAR_URL } from '@/constants/app.constant'
import { useStoreState } from '@/store' import { useStoreState } from '@/store'
import UserProfileCard from '@/views/intranet/SocialWall/UserProfileCard' import UserProfileCard from '@/views/intranet/SocialWall/UserProfileCard'
@ -436,9 +446,9 @@ function OrgChartNode({
tenantId?: string tenantId?: string
zoom: number zoom: number
positions: PositionMap positions: PositionMap
setPositions: React.Dispatch<React.SetStateAction<PositionMap>> setPositions: Dispatch<SetStateAction<PositionMap>>
nodeRefs: React.MutableRefObject<NodeRefMap> nodeRefs: MutableRefObject<NodeRefMap>
cardRefs: React.MutableRefObject<CardRefMap> cardRefs: MutableRefObject<CardRefMap>
requestRepaint: () => void requestRepaint: () => void
applySelfTransform?: boolean applySelfTransform?: boolean
}) { }) {
@ -451,9 +461,8 @@ function OrgChartNode({
const levelColor = LEVEL_COLORS[depth % LEVEL_COLORS.length] const levelColor = LEVEL_COLORS[depth % LEVEL_COLORS.length]
const borderColor = levelColor.border const borderColor = levelColor.border
const headerBg = levelColor.header const headerBg = levelColor.header
const badgeBg = levelColor.badge
const handleDragStart = (e: React.MouseEvent<HTMLDivElement>) => { const handleDragStart = (e: ReactMouseEvent<HTMLDivElement>) => {
const target = e.target as HTMLElement const target = e.target as HTMLElement
if (target.closest('[data-stop-drag="true"]')) { if (target.closest('[data-stop-drag="true"]')) {
return return
@ -508,12 +517,12 @@ function OrgChartNode({
ref={(el) => { ref={(el) => {
cardRefs.current[node.id] = el cardRefs.current[node.id] = el
}} }}
onMouseDown={handleDragStart}
data-card="" data-card=""
data-depth={depth} data-depth={depth}
data-users-visible={showUsers ? 'true' : 'false'} data-users-visible={showUsers ? 'true' : 'false'}
className={`relative bg-white border ${borderColor} rounded-xl shadow-sm w-36 sm:w-44 md:w-52 hover:shadow-md transition-shadow`} className={`relative bg-white border ${borderColor} rounded-xl shadow-sm w-36 sm:w-44 md:w-52 hover:shadow-md transition-shadow`}
style={{ cursor: dragging ? 'grabbing' : 'grab' }} style={{ cursor: dragging ? 'grabbing' : 'grab' }}
onMouseDown={handleDragStart}
> >
{/* Header bar */} {/* Header bar */}
<div <div
@ -534,10 +543,6 @@ function OrgChartNode({
{hasChildren && ( {hasChildren && (
<Button <Button
data-stop-drag="true" data-stop-drag="true"
onClick={() => {
setCollapsed((c) => !c)
requestRepaint()
}}
variant="plain" variant="plain"
shape="circle" shape="circle"
icon={ icon={
@ -548,6 +553,10 @@ function OrgChartNode({
) )
} }
className="ml-1 !h-5 !w-5 flex-shrink-0 !px-0 text-white opacity-70 transition-opacity hover:opacity-100" className="ml-1 !h-5 !w-5 flex-shrink-0 !px-0 text-white opacity-70 transition-opacity hover:opacity-100"
onClick={() => {
setCollapsed((c) => !c)
requestRepaint()
}}
></Button> ></Button>
)} )}
</div> </div>
@ -590,7 +599,7 @@ function OrgChartNode({
{/* Children */} {/* Children */}
{hasChildren && !collapsed && ( {hasChildren && !collapsed && (
<div className="mt-6 sm:mt-8 md:mt-10 flex items-start gap-4 sm:gap-6 md:gap-10"> <div className="mt-6 sm:mt-8 md:mt-10 flex items-start gap-4 sm:gap-6 md:gap-10">
{node.children.map((child, idx) => { {node.children.map((child) => {
const childPosition = positions[child.id] ?? { x: 0, y: 0 } const childPosition = positions[child.id] ?? { x: 0, y: 0 }
return ( return (
@ -639,7 +648,7 @@ function OrgChartTree({
tenantId?: string tenantId?: string
zoom: number zoom: number
positions: PositionMap positions: PositionMap
setPositions: React.Dispatch<React.SetStateAction<PositionMap>> setPositions: Dispatch<SetStateAction<PositionMap>>
edges: EdgeLink[] edges: EdgeLink[]
}) { }) {
const containerRef = useRef<HTMLDivElement>(null) const containerRef = useRef<HTMLDivElement>(null)
@ -836,7 +845,7 @@ const OrgChart = () => {
setPositions({}) setPositions({})
}, [mode]) }, [mode])
const handleWheelZoom = (e: React.WheelEvent<HTMLDivElement>) => { const handleWheelZoom = (e: WheelEvent<HTMLDivElement>) => {
if (!e.ctrlKey) { if (!e.ctrlKey) {
return return
} }
@ -882,7 +891,6 @@ const OrgChart = () => {
<div className="flex flex-wrap items-center gap-2"> <div className="flex flex-wrap items-center gap-2">
<div className="flex items-center bg-slate-100 dark:bg-gray-800 rounded-lg p-1 gap-1"> <div className="flex items-center bg-slate-100 dark:bg-gray-800 rounded-lg p-1 gap-1">
<Button <Button
onClick={() => setMode('department')}
variant="plain" variant="plain"
shape="none" shape="none"
icon={<FaBuilding className="h-3.5 w-3.5 flex-shrink-0" />} icon={<FaBuilding className="h-3.5 w-3.5 flex-shrink-0" />}
@ -892,13 +900,13 @@ const OrgChart = () => {
? '!bg-blue-600 !text-white shadow-sm ring-1 ring-blue-300/70 dark:ring-blue-400/70' ? '!bg-blue-600 !text-white shadow-sm ring-1 ring-blue-300/70 dark:ring-blue-400/70'
: '!bg-transparent text-slate-600 hover:!bg-white hover:text-slate-800 dark:text-gray-300 dark:hover:!bg-gray-700 dark:hover:text-white' : '!bg-transparent text-slate-600 hover:!bg-white hover:text-slate-800 dark:text-gray-300 dark:hover:!bg-gray-700 dark:hover:text-white'
}`} }`}
onClick={() => setMode('department')}
> >
<span className="hidden sm:inline"> <span className="hidden sm:inline">
{translate('::App.Hr.Department') || 'Departman'} {translate('::App.Hr.Department') || 'Departman'}
</span> </span>
</Button> </Button>
<Button <Button
onClick={() => setMode('jobPosition')}
variant="plain" variant="plain"
shape="none" shape="none"
icon={<FaBriefcase className="h-3.5 w-3.5 flex-shrink-0" />} icon={<FaBriefcase className="h-3.5 w-3.5 flex-shrink-0" />}
@ -908,6 +916,7 @@ const OrgChart = () => {
? '!bg-purple-600 !text-white shadow-sm ring-1 ring-purple-300/70 dark:ring-purple-400/70' ? '!bg-purple-600 !text-white shadow-sm ring-1 ring-purple-300/70 dark:ring-purple-400/70'
: '!bg-transparent text-slate-600 hover:!bg-white hover:text-slate-800 dark:text-gray-300 dark:hover:!bg-gray-700 dark:hover:text-white' : '!bg-transparent text-slate-600 hover:!bg-white hover:text-slate-800 dark:text-gray-300 dark:hover:!bg-gray-700 dark:hover:text-white'
}`} }`}
onClick={() => setMode('jobPosition')}
> >
<span className="hidden sm:inline"> <span className="hidden sm:inline">
{translate('::App.Hr.JobPosition') || 'Pozisyon'} {translate('::App.Hr.JobPosition') || 'Pozisyon'}
@ -920,8 +929,8 @@ const OrgChart = () => {
<input <input
type="checkbox" type="checkbox"
checked={showUsers} checked={showUsers}
onChange={(e) => setShowUsers(e.target.checked)}
className="h-4 w-4 rounded border-slate-300 dark:border-gray-600 text-blue-600 focus:ring-blue-500" className="h-4 w-4 rounded border-slate-300 dark:border-gray-600 text-blue-600 focus:ring-blue-500"
onChange={(e) => setShowUsers(e.target.checked)}
/> />
<span className="hidden sm:inline"> <span className="hidden sm:inline">
{translate('::App.Definitions.OrgChart.ShowUsers') || 'Kullanıcılar'} {translate('::App.Definitions.OrgChart.ShowUsers') || 'Kullanıcılar'}
@ -931,42 +940,42 @@ const OrgChart = () => {
<div className="flex items-center bg-slate-100 dark:bg-gray-800 rounded-lg p-1 gap-1"> <div className="flex items-center bg-slate-100 dark:bg-gray-800 rounded-lg p-1 gap-1">
<Button <Button
onClick={handleZoomOut}
variant="plain" variant="plain"
shape="none" shape="none"
icon={<FaSearchMinus className="h-3.5 w-3.5" />} icon={<FaSearchMinus className="h-3.5 w-3.5" />}
className="!h-7 !w-7 !rounded-md !px-0 text-slate-600 hover:!bg-white hover:text-slate-800 dark:text-gray-300 dark:hover:!bg-gray-700 dark:hover:text-white sm:!h-8 sm:!w-8" className="!h-7 !w-7 !rounded-md !px-0 text-slate-600 hover:!bg-white hover:text-slate-800 dark:text-gray-300 dark:hover:!bg-gray-700 dark:hover:text-white sm:!h-8 sm:!w-8"
title="Zoom Out" title="Zoom Out"
onClick={handleZoomOut}
/> />
<span className="text-xs font-medium text-slate-600 dark:text-gray-300 px-1 min-w-[36px] sm:min-w-[46px] text-center"> <span className="text-xs font-medium text-slate-600 dark:text-gray-300 px-1 min-w-[36px] sm:min-w-[46px] text-center">
{Math.round(zoom * 100)}% {Math.round(zoom * 100)}%
</span> </span>
<Button <Button
onClick={handleZoomIn}
variant="plain" variant="plain"
shape="none" shape="none"
icon={<FaSearchPlus className="h-3.5 w-3.5" />} icon={<FaSearchPlus className="h-3.5 w-3.5" />}
className="!h-7 !w-7 !rounded-md !px-0 text-slate-600 hover:!bg-white hover:text-slate-800 dark:text-gray-300 dark:hover:!bg-gray-700 dark:hover:text-white sm:!h-8 sm:!w-8" className="!h-7 !w-7 !rounded-md !px-0 text-slate-600 hover:!bg-white hover:text-slate-800 dark:text-gray-300 dark:hover:!bg-gray-700 dark:hover:text-white sm:!h-8 sm:!w-8"
title="Zoom In" title="Zoom In"
onClick={handleZoomIn}
/> />
<Button <Button
onClick={handleZoomReset}
variant="plain" variant="plain"
shape="none" shape="none"
icon={<FaUndo className="h-3.5 w-3.5" />} icon={<FaUndo className="h-3.5 w-3.5" />}
className="!h-7 !w-7 !rounded-md !px-0 text-slate-600 hover:!bg-white hover:text-slate-800 dark:text-gray-300 dark:hover:!bg-gray-700 dark:hover:text-white sm:!h-8 sm:!w-8" className="!h-7 !w-7 !rounded-md !px-0 text-slate-600 hover:!bg-white hover:text-slate-800 dark:text-gray-300 dark:hover:!bg-gray-700 dark:hover:text-white sm:!h-8 sm:!w-8"
title="Reset Zoom" title="Reset Zoom"
onClick={handleZoomReset}
/> />
</div> </div>
<Button <Button
onClick={handleExportJpg}
disabled={exporting || loading} disabled={exporting || loading}
variant="plain" variant="plain"
shape="none" shape="none"
icon={<FaFileImage className="h-3.5 w-3.5 flex-shrink-0" />} icon={<FaFileImage className="h-3.5 w-3.5 flex-shrink-0" />}
className="!inline-flex !h-auto !items-center !justify-center gap-1.5 !rounded-lg bg-slate-100 !p-1.5 text-xs font-medium text-slate-600 transition-colors hover:!bg-slate-200 disabled:opacity-50 dark:bg-gray-800 dark:text-gray-300 dark:hover:!bg-gray-700 sm:!p-2 sm:text-sm" className="!inline-flex !h-auto !items-center !justify-center gap-1.5 !rounded-lg bg-slate-100 !p-1.5 text-xs font-medium text-slate-600 transition-colors hover:!bg-slate-200 disabled:opacity-50 dark:bg-gray-800 dark:text-gray-300 dark:hover:!bg-gray-700 sm:!p-2 sm:text-sm"
title="JPG olarak indir" title="JPG olarak indir"
onClick={handleExportJpg}
> >
<span className="hidden sm:inline">{exporting ? 'İşleniyor…' : 'Export'}</span> <span className="hidden sm:inline">{exporting ? 'İşleniyor…' : 'Export'}</span>
</Button> </Button>

View file

@ -1,4 +1,4 @@
import { Card, Checkbox, FormContainer, FormItem, Input, Select, Button } from '@/components/ui' import { Checkbox, FormContainer, FormItem, Input, Select, Button } from '@/components/ui'
import { SelectBoxOption } from '@/types/shared' import { SelectBoxOption } from '@/types/shared'
import { Field, FieldProps, Form, Formik } from 'formik' import { Field, FieldProps, Form, Formik } from 'formik'
import { object } from 'yup' import { object } from 'yup'
@ -26,7 +26,7 @@ function ChartTabAnimation(props: FormEditProps) {
await props.onSubmit(ListFormEditTabs.ChartAnimationForm, values, formikHelpers) await props.onSubmit(ListFormEditTabs.ChartAnimationForm, values, formikHelpers)
}} }}
> >
{({ touched, errors, resetForm, isSubmitting, values }) => ( {({ touched, errors, isSubmitting, values }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<FormItem <FormItem
@ -79,7 +79,7 @@ function ChartTabAnimation(props: FormEditProps) {
<Field type="number" name="animationDto.maxPointCountSupported" component={Input} /> <Field type="number" name="animationDto.maxPointCountSupported" component={Input} />
</FormItem> </FormItem>
<div className="mt-4"> <div className="mt-4">
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</div> </div>

View file

@ -68,7 +68,7 @@ function ChartTabAnnotations(props: FormEditProps) {
) )
}} }}
> >
{({ touched, errors, resetForm, isSubmitting, values }) => ( {({ touched, errors, isSubmitting, values }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<Tabs defaultValue="annotations_general"> <Tabs defaultValue="annotations_general">
@ -121,7 +121,7 @@ function ChartTabAnnotations(props: FormEditProps) {
size="sm" size="sm"
title="Edit" title="Edit"
icon={<FaEdit />} icon={<FaEdit />}
onClick={async (e) => { onClick={async () => {
setJsonRowOpModalData({ setJsonRowOpModalData({
tabName: ListFormEditTabs.ChartAnnotations.GeneralJsonRow, tabName: ListFormEditTabs.ChartAnnotations.GeneralJsonRow,
operation: 'update', operation: 'update',
@ -660,7 +660,7 @@ function ChartTabAnnotations(props: FormEditProps) {
</TabContent> </TabContent>
</Tabs> </Tabs>
<div className="mt-4"> <div className="mt-4">
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</div> </div>

View file

@ -60,7 +60,7 @@ function ChartTabAxis(props: FormEditProps) {
await props.onSubmit(ListFormEditTabs.ChartAxis.CommonAxisForm, values, formikHelpers) await props.onSubmit(ListFormEditTabs.ChartAxis.CommonAxisForm, values, formikHelpers)
}} }}
> >
{({ touched, errors, resetForm, isSubmitting, values }) => ( {({ touched, errors, isSubmitting, values }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<Tabs defaultValue="axis_value"> <Tabs defaultValue="axis_value">
@ -114,7 +114,7 @@ function ChartTabAxis(props: FormEditProps) {
size="sm" size="sm"
title="Edit" title="Edit"
icon={<FaEdit />} icon={<FaEdit />}
onClick={async (e) => { onClick={async () => {
setJsonRowOpModalData({ setJsonRowOpModalData({
tabName: ListFormEditTabs.ChartAxis.ValueAxisJsonRow, tabName: ListFormEditTabs.ChartAxis.ValueAxisJsonRow,
operation: 'update', operation: 'update',
@ -541,7 +541,7 @@ function ChartTabAxis(props: FormEditProps) {
</TabContent> </TabContent>
</Tabs> </Tabs>
<div className="mt-4"> <div className="mt-4">
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</div> </div>

View file

@ -13,7 +13,7 @@ import TabList from '@/components/ui/Tabs/TabList'
import TabNav from '@/components/ui/Tabs/TabNav' import TabNav from '@/components/ui/Tabs/TabNav'
import { IdentityRoleDto } from '@/proxy/admin/models' import { IdentityRoleDto } from '@/proxy/admin/models'
import { SelectBoxOption } from '@/types/shared' import { SelectBoxOption } from '@/types/shared'
import { Field, FieldProps, Form, Formik, FormikErrors, FormikTouched } from 'formik' import { Field, FieldProps, Form, Formik } from 'formik'
import { FormEditProps } from '../../listForm/edit/FormEdit' import { FormEditProps } from '../../listForm/edit/FormEdit'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { useStoreState } from '@/store/store' import { useStoreState } from '@/store/store'
@ -53,7 +53,7 @@ function ChartTabCommonSettings(props: FormEditProps) {
await props.onSubmit(ListFormEditTabs.ChartCommon, values, formikHelpers) await props.onSubmit(ListFormEditTabs.ChartCommon, values, formikHelpers)
}} }}
> >
{({ touched, errors, resetForm, isSubmitting, values }) => ( {({ touched, errors, isSubmitting, values }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<Tabs defaultValue="commonSettings_general"> <Tabs defaultValue="commonSettings_general">
@ -716,7 +716,7 @@ function ChartTabCommonSettings(props: FormEditProps) {
</TabContent> </TabContent>
</Tabs> </Tabs>
<div className="mt-4"> <div className="mt-4">
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</div> </div>

View file

@ -26,7 +26,7 @@ function ChartTabCrosshair(props: FormEditProps) {
await props.onSubmit(ListFormEditTabs.ChartCrosshairForm, values, formikHelpers) await props.onSubmit(ListFormEditTabs.ChartCrosshairForm, values, formikHelpers)
}} }}
> >
{({ touched, errors, resetForm, isSubmitting, values }) => ( {({ touched, errors, isSubmitting, values }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-3"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-3">
@ -336,7 +336,7 @@ function ChartTabCrosshair(props: FormEditProps) {
</Card> </Card>
</div> </div>
<div className="mt-4"> <div className="mt-4">
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</div> </div>

View file

@ -1,4 +1,4 @@
import { Button, Card, Checkbox, FormContainer, FormItem, Input } from '@/components/ui' import { Button, Checkbox, FormContainer, FormItem, Input } from '@/components/ui'
import { Field, FieldProps, Form, Formik } from 'formik' import { Field, FieldProps, Form, Formik } from 'formik'
import { FormEditProps } from '../../listForm/edit/FormEdit' import { FormEditProps } from '../../listForm/edit/FormEdit'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
@ -24,7 +24,7 @@ function ChartTabExport(props: FormEditProps) {
await props.onSubmit(ListFormEditTabs.ChartExportForm, values, formikHelpers) await props.onSubmit(ListFormEditTabs.ChartExportForm, values, formikHelpers)
}} }}
> >
{({ touched, errors, resetForm, isSubmitting, values }) => ( {({ touched, errors, isSubmitting }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<FormItem label="Enabled"> <FormItem label="Enabled">
@ -65,7 +65,7 @@ function ChartTabExport(props: FormEditProps) {
</FormItem> </FormItem>
<div className="mt-4"> <div className="mt-4">
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</div> </div>

View file

@ -5,12 +5,8 @@ import {
FormContainer, FormContainer,
FormItem, FormItem,
Input, Input,
Select, Select
Tabs,
} from '@/components/ui' } from '@/components/ui'
import TabContent from '@/components/ui/Tabs/TabContent'
import TabList from '@/components/ui/Tabs/TabList'
import TabNav from '@/components/ui/Tabs/TabNav'
import { SelectBoxOption } from '@/types/shared' import { SelectBoxOption } from '@/types/shared'
import { Field, FieldProps, Form, Formik } from 'formik' import { Field, FieldProps, Form, Formik } from 'formik'
import { FormEditProps } from '../../listForm/edit/FormEdit' import { FormEditProps } from '../../listForm/edit/FormEdit'
@ -42,7 +38,7 @@ function ChartTabLegend(props: FormEditProps) {
await props.onSubmit(ListFormEditTabs.ChartLegendForm, values, formikHelpers) await props.onSubmit(ListFormEditTabs.ChartLegendForm, values, formikHelpers)
}} }}
> >
{({ touched, errors, resetForm, isSubmitting, values }) => ( {({ touched, errors, isSubmitting, values }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<div className="grid grid-cols-1 md:grid-cols-2 gap-3"> <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
@ -216,7 +212,7 @@ function ChartTabLegend(props: FormEditProps) {
</Card> </Card>
</div> </div>
<div className="mt-4"> <div className="mt-4">
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</div> </div>

View file

@ -43,7 +43,7 @@ function ChartTabPanes(props: FormEditProps) {
) )
}} }}
> >
{({ touched, errors, resetForm, isSubmitting, values }) => ( {({ touched, errors, isSubmitting }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<Card className="my-2"> <Card className="my-2">
@ -110,7 +110,7 @@ function ChartTabPanes(props: FormEditProps) {
size="sm" size="sm"
title="Edit" title="Edit"
icon={<FaEdit />} icon={<FaEdit />}
onClick={async (e) => { onClick={async () => {
setJsonRowOpModalData({ setJsonRowOpModalData({
tabName: ListFormEditTabs.ChartPanes.PanesJsonRow, tabName: ListFormEditTabs.ChartPanes.PanesJsonRow,
operation: 'update', operation: 'update',
@ -155,7 +155,7 @@ function ChartTabPanes(props: FormEditProps) {
setData={setJsonRowOpModalData} setData={setJsonRowOpModalData}
/> />
<div className="mt-4"> <div className="mt-4">
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</div> </div>

View file

@ -34,7 +34,7 @@ import {
chartSeriesSelectionModeOptions, chartSeriesSelectionModeOptions,
chartSeriesDashStyleOptions, chartSeriesDashStyleOptions,
} from './options' } from './options'
import { useEffect, useState } from 'react' import { useCallback, useEffect, useMemo, useState } from 'react'
import { JsonRowDialogData } from './json-row-operations/types' import { JsonRowDialogData } from './json-row-operations/types'
import JsonRowOpDialogSeries from './json-row-operations/JsonRowOpDialogSeries' import JsonRowOpDialogSeries from './json-row-operations/JsonRowOpDialogSeries'
import CreatableSelect from 'react-select/creatable' import CreatableSelect from 'react-select/creatable'
@ -52,25 +52,22 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
const [fieldList, setFieldList] = useState<SelectBoxOption[]>([]) const [fieldList, setFieldList] = useState<SelectBoxOption[]>([])
const listFormValues = useStoreState((s) => s.admin.lists.values) const listFormValues = useStoreState((s) => s.admin.lists.values)
if (!listFormValues) {
return null
}
const valueAxisList = () => { const valueAxisList = useMemo(() => {
return listFormValues?.valueAxisDto.map((key: ChartValueAxisDto) => ({ return (listFormValues?.valueAxisDto ?? []).map((key: ChartValueAxisDto) => ({
value: key.name, value: key.name,
label: key.name, label: key.name,
})) }))
} }, [listFormValues?.valueAxisDto])
const valuePaneList = () => { const valuePaneList = useMemo(() => {
return listFormValues?.panesDto.map((key: ChartPanesDto) => ({ return (listFormValues?.panesDto ?? []).map((key: ChartPanesDto) => ({
value: key.name, value: key.name,
label: key.name, label: key.name,
})) }))
} }, [listFormValues?.panesDto])
const getFields = async () => { const getFields = useCallback(async () => {
if (!props.listFormCode) { if (!props.listFormCode) {
return return
} }
@ -101,13 +98,17 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
}, },
) )
} }
} }, [props.listFormCode])
useEffect(() => { useEffect(() => {
if (props.listFormCode) { if (props.listFormCode) {
getFields() getFields()
} }
}, [props.listFormCode]) }, [getFields, props.listFormCode])
if (!listFormValues) {
return null
}
return ( return (
<Formik <Formik
@ -121,7 +122,7 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
) )
}} }}
> >
{({ touched, errors, resetForm, isSubmitting, values }) => ( {({ touched, errors, isSubmitting, values }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<Tabs defaultValue="series_general"> <Tabs defaultValue="series_general">
@ -176,7 +177,7 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
size="sm" size="sm"
title="Edit" title="Edit"
icon={<FaEdit />} icon={<FaEdit />}
onClick={async (e) => { onClick={async () => {
setJsonRowOpModalData({ setJsonRowOpModalData({
tabName: ListFormEditTabs.ChartSeries.GeneralJsonRow, tabName: ListFormEditTabs.ChartSeries.GeneralJsonRow,
operation: 'update', operation: 'update',
@ -346,9 +347,9 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
(option) => (option) =>
option.value === values.commonSeriesSettingsDto.argumentField, option.value === values.commonSeriesSettingsDto.argumentField,
)} )}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
menuPlacement="auto" menuPlacement="auto"
maxMenuHeight={150} maxMenuHeight={150}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
/> />
)} )}
</Field> </Field>
@ -362,7 +363,7 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
} }
errorMessage={errors.commonSeriesSettingsDto?.valueField} errorMessage={errors.commonSeriesSettingsDto?.valueField}
> >
<Field type="text" name="valueField"> <Field type="text" name="commonSeriesSettingsDto.valueField">
{({ field, form }: FieldProps<SelectBoxOption>) => ( {({ field, form }: FieldProps<SelectBoxOption>) => (
<Select <Select
componentAs={CreatableSelect} componentAs={CreatableSelect}
@ -374,9 +375,9 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
(option) => (option) =>
option.value === values.commonSeriesSettingsDto.valueField, option.value === values.commonSeriesSettingsDto.valueField,
)} )}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
menuPlacement="auto" menuPlacement="auto"
maxMenuHeight={150} maxMenuHeight={150}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
/> />
)} )}
</Field> </Field>
@ -398,9 +399,9 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
<Select <Select
field={field} field={field}
form={form} form={form}
options={valueAxisList()} options={valueAxisList}
isClearable={true} isClearable={true}
value={valueAxisList()?.find( value={valueAxisList.find(
(option) => option.value === values.commonSeriesSettingsDto.axis, (option) => option.value === values.commonSeriesSettingsDto.axis,
)} )}
onChange={(option) => form.setFieldValue(field.name, option?.value)} onChange={(option) => form.setFieldValue(field.name, option?.value)}
@ -424,9 +425,9 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
<Select <Select
field={field} field={field}
form={form} form={form}
options={valuePaneList()} options={valuePaneList}
isClearable={true} isClearable={true}
value={valuePaneList()?.find( value={valuePaneList.find(
(option) => option.value === values.commonSeriesSettingsDto.pane, (option) => option.value === values.commonSeriesSettingsDto.pane,
)} )}
onChange={(option) => form.setFieldValue(field.name, option?.value)} onChange={(option) => form.setFieldValue(field.name, option?.value)}
@ -523,7 +524,7 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
</TabContent> </TabContent>
</Tabs> </Tabs>
<div className="mt-4"> <div className="mt-4">
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</div> </div>

View file

@ -26,7 +26,7 @@ const ChartTabZoomAndPan = (props: FormEditProps) => {
await props.onSubmit(ListFormEditTabs.ChartZoomForm, values, formikHelpers) await props.onSubmit(ListFormEditTabs.ChartZoomForm, values, formikHelpers)
}} }}
> >
{({ touched, errors, resetForm, isSubmitting, values }) => ( {({ touched, errors, isSubmitting, values }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<div className="grid grid-cols-1 md:grid-cols-2 gap-3"> <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
@ -176,7 +176,7 @@ const ChartTabZoomAndPan = (props: FormEditProps) => {
</Card> </Card>
</div> </div>
<div className="mt-4"> <div className="mt-4">
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</div> </div>

View file

@ -294,7 +294,7 @@ function FormCustomization({
/> />
</FormItem> </FormItem>
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -1,4 +1,4 @@
import { Alert, Badge, Notification, Tabs, toast } from '@/components/ui' import { Badge, Notification, Tabs, toast } from '@/components/ui'
import TabContent from '@/components/ui/Tabs/TabContent' import TabContent from '@/components/ui/Tabs/TabContent'
import TabList from '@/components/ui/Tabs/TabList' import TabList from '@/components/ui/Tabs/TabList'
import TabNav from '@/components/ui/Tabs/TabNav' import TabNav from '@/components/ui/Tabs/TabNav'
@ -7,7 +7,7 @@ import { SelectBoxOption } from '@/types/shared'
import { useStoreActions, useStoreState } from '@/store' import { useStoreActions, useStoreState } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { FormikHelpers } from 'formik' import { FormikHelpers } from 'formik'
import { useEffect, useState } from 'react' import { useCallback, useEffect, useState } from 'react'
import { Helmet } from 'react-helmet' import { Helmet } from 'react-helmet'
import { Link, useParams } from 'react-router-dom' import { Link, useParams } from 'react-router-dom'
import FormCustomization from './FormCustomization' import FormCustomization from './FormCustomization'
@ -27,8 +27,7 @@ import FormTabSubForm from './FormTabSubForm'
import FormFields from './form-fields/FormFields' import FormFields from './form-fields/FormFields'
import { putListForms } from '@/services/admin/list-form.service' import { putListForms } from '@/services/admin/list-form.service'
import { getRoles, getUsers } from '@/services/identity.service' import { getRoles, getUsers } from '@/services/identity.service'
import { GridOptionsEditDto, ListFormCustomizationDto } from '@/proxy/form/models' import { SelectCommandTypeEnum, GridOptionsEditDto, ListFormCustomizationDto } from '@/proxy/form/models'
import { SelectCommandTypeEnum } from '@/proxy/form/models'
import { IdentityRoleDto, IdentityUserDto } from '@/proxy/admin/models' import { IdentityRoleDto, IdentityUserDto } from '@/proxy/admin/models'
import { getListFormCustomizations } from '@/services/admin/list-form-customization.service' import { getListFormCustomizations } from '@/services/admin/list-form-customization.service'
import { sqlObjectManagerService } from '@/services/sql-query-manager.service' import { sqlObjectManagerService } from '@/services/sql-query-manager.service'
@ -95,7 +94,7 @@ const FormEdit = () => {
} }
}, [languages]) }, [languages])
const getRoleList = async () => { const getRoleList = useCallback(async () => {
const response = await getRoles() const response = await getRoles()
if (response.data?.items) { if (response.data?.items) {
setRoleList( setRoleList(
@ -105,9 +104,9 @@ const FormEdit = () => {
})), })),
) )
} }
} }, [])
const getUserList = async () => { const getUserList = useCallback(async () => {
const response = await getUsers(0, 1000) const response = await getUsers(0, 1000)
if (response.data?.items) { if (response.data?.items) {
setUserList( setUserList(
@ -117,17 +116,17 @@ const FormEdit = () => {
})), })),
) )
} }
} }, [])
const getCustomizations = async () => { const getCustomizations = useCallback(async () => {
if (!listFormCode) { if (!listFormCode) {
return return
} }
const resp = await getListFormCustomizations({ listFormCode, maxResultCount: 1000 }) const resp = await getListFormCustomizations({ listFormCode, maxResultCount: 1000 })
setCustomizations(resp?.data?.items) setCustomizations(resp?.data?.items)
} }, [listFormCode])
const refreshData = async () => { const refreshData = useCallback(async () => {
if (!listFormCode) { if (!listFormCode) {
return return
} }
@ -135,7 +134,7 @@ const FormEdit = () => {
await getCustomizations() await getCustomizations()
await getRoleList() await getRoleList()
await getUserList() await getUserList()
} }, [getCustomizations, getListFormValues, getRoleList, getUserList, listFormCode])
const listFormType = listFormValues?.listFormType || 'List' const listFormType = listFormValues?.listFormType || 'List'
const [activeFormType, setActiveFormType] = useState<string>(listFormType) const [activeFormType, setActiveFormType] = useState<string>(listFormType)
@ -144,7 +143,7 @@ const FormEdit = () => {
//LİST FORM ve LİST FORM FİELDS AİT BİLGİLER //LİST FORM ve LİST FORM FİELDS AİT BİLGİLER
useEffect(() => { useEffect(() => {
refreshData() refreshData()
}, [listFormCode]) }, [refreshData])
useEffect(() => { useEffect(() => {
const loadWorkflowColumns = async () => { const loadWorkflowColumns = async () => {
@ -378,9 +377,9 @@ const FormEdit = () => {
<TabContent value="details" className="px-2"> <TabContent value="details" className="px-2">
<FormTabDetails <FormTabDetails
onSubmit={onSubmit}
roleList={roleList} roleList={roleList}
userList={userList} userList={userList}
onSubmit={onSubmit}
onFormTypeChange={setActiveFormType} onFormTypeChange={setActiveFormType}
/> />
</TabContent> </TabContent>
@ -442,7 +441,7 @@ const FormEdit = () => {
<FormTabSubForm /> <FormTabSubForm />
</TabContent> </TabContent>
<TabContent value="widget" className="px-2"> <TabContent value="widget" className="px-2">
<FormTabWidgets listFormCode={listFormCode} /> <FormTabWidgets />
</TabContent> </TabContent>
<TabContent value="workflow" className="px-2"> <TabContent value="workflow" className="px-2">
<FormTabWorkflow <FormTabWorkflow
@ -478,7 +477,7 @@ const FormEdit = () => {
<ChartTabCommonSettings onSubmit={onSubmit} /> <ChartTabCommonSettings onSubmit={onSubmit} />
</TabContent> </TabContent>
<TabContent value="series" className="px-2"> <TabContent value="series" className="px-2">
<ChartTabSeries onSubmit={onSubmit} listFormCode={listFormCode} /> <ChartTabSeries listFormCode={listFormCode} onSubmit={onSubmit} />
</TabContent> </TabContent>
<TabContent value="panes" className="px-2"> <TabContent value="panes" className="px-2">
<ChartTabPanes onSubmit={onSubmit} /> <ChartTabPanes onSubmit={onSubmit} />

View file

@ -1,13 +1,10 @@
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
import { import {
Button, Button,
Card,
Checkbox, Checkbox,
FormContainer, FormContainer,
FormItem, FormItem,
Input,
Select, Select,
Tabs,
} from '@/components/ui' } from '@/components/ui'
import { ListFormEditTabs } from '@/proxy/admin/list-form/options' import { ListFormEditTabs } from '@/proxy/admin/list-form/options'
import { useStoreState } from '@/store' import { useStoreState } from '@/store'
@ -310,7 +307,7 @@ function FormTabColumns(props: FormEditProps) {
</div> </div>
</div> </div>
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit" className="my-2"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit" className="my-2">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -78,7 +78,7 @@ function FormTabCommands() {
size="sm" size="sm"
title="Edit" title="Edit"
icon={<FaEdit />} icon={<FaEdit />}
onClick={async (e) => { onClick={async () => {
setJsonRowOpModalData({ setJsonRowOpModalData({
tabName: ListFormEditTabs.CommandColumnsJsonRow, tabName: ListFormEditTabs.CommandColumnsJsonRow,
operation: 'update', operation: 'update',

View file

@ -263,10 +263,10 @@ function FormTabDatabaseDataSource(props: FormEditProps) {
: [] : []
return ( return (
<Select <Select
isClearable
componentAs={CreatableSelect} componentAs={CreatableSelect}
field={field} field={field}
form={form} form={form}
isClearable
isLoading={isLoadingDbObjects} isLoading={isLoadingDbObjects}
options={grouped} options={grouped}
placeholder={ placeholder={
@ -346,10 +346,10 @@ function FormTabDatabaseDataSource(props: FormEditProps) {
<Field type="text" autoComplete="off" name="keyFieldName"> <Field type="text" autoComplete="off" name="keyFieldName">
{({ field, form }: FieldProps<string>) => ( {({ field, form }: FieldProps<string>) => (
<Select <Select
isClearable
componentAs={CreatableSelect} componentAs={CreatableSelect}
field={field} field={field}
form={form} form={form}
isClearable
isLoading={isLoadingColumns} isLoading={isLoadingColumns}
placeholder={ placeholder={
isLoadingColumns isLoadingColumns
@ -387,7 +387,7 @@ function FormTabDatabaseDataSource(props: FormEditProps) {
</FormItem> </FormItem>
</Card> </Card>
<Button size="sm" block variant="solid" loading={isSubmitting}> <Button block size="sm" variant="solid" loading={isSubmitting}>
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -48,7 +48,7 @@ function FormTabDatabaseDelete({
await onSubmit(ListFormEditTabs.Database.Delete.DeleteForm, values, formikHelpers) await onSubmit(ListFormEditTabs.Database.Delete.DeleteForm, values, formikHelpers)
}} }}
> >
{({ touched, errors, values, isSubmitting }) => ( {({ touched, errors, isSubmitting }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<Card className="my-2"> <Card className="my-2">
@ -116,7 +116,7 @@ function FormTabDatabaseDelete({
</FormItem> </FormItem>
</div> </div>
<Button size="sm" block variant="solid" loading={isSubmitting}> <Button block size="sm" variant="solid" loading={isSubmitting}>
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</Card> </Card>

View file

@ -48,7 +48,7 @@ function FormTabDatabaseInsert({
await onSubmit(ListFormEditTabs.Database.Insert.InsertForm, values, formikHelpers) await onSubmit(ListFormEditTabs.Database.Insert.InsertForm, values, formikHelpers)
}} }}
> >
{({ touched, errors, values, isSubmitting }) => ( {({ touched, errors, isSubmitting }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<Card className="my-2"> <Card className="my-2">
@ -114,7 +114,7 @@ function FormTabDatabaseInsert({
/> />
</FormItem> </FormItem>
</div> </div>
<Button size="sm" block variant="solid" loading={isSubmitting}> <Button block size="sm" variant="solid" loading={isSubmitting}>
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</Card> </Card>

View file

@ -48,7 +48,7 @@ function FormTabDatabaseSelect({
await onSubmit(ListFormEditTabs.Database.Select.SelectForm, values, formikHelpers) await onSubmit(ListFormEditTabs.Database.Select.SelectForm, values, formikHelpers)
}} }}
> >
{({ touched, errors, values, isSubmitting }) => ( {({ touched, errors, isSubmitting }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<Card className="my-2"> <Card className="my-2">
@ -65,7 +65,7 @@ function FormTabDatabaseSelect({
component={Input} component={Input}
/> />
</FormItem> </FormItem>
<Button size="sm" block variant="solid" loading={isSubmitting}> <Button block size="sm" variant="solid" loading={isSubmitting}>
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</Card> </Card>

View file

@ -48,7 +48,7 @@ function FormTabDatabaseUpdate({
await onSubmit(ListFormEditTabs.Database.Update.UpdateForm, values, formikHelpers) await onSubmit(ListFormEditTabs.Database.Update.UpdateForm, values, formikHelpers)
}} }}
> >
{({ touched, errors, values, isSubmitting }) => ( {({ touched, errors, isSubmitting }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<Card className="my-2"> <Card className="my-2">
@ -114,7 +114,7 @@ function FormTabDatabaseUpdate({
/> />
</FormItem> </FormItem>
</div> </div>
<Button size="sm" block variant="solid" loading={isSubmitting}> <Button block size="sm" variant="solid" loading={isSubmitting}>
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</Card> </Card>

View file

@ -1,4 +1,3 @@
import { Container } from '@/components/shared'
import { Button, Card, Checkbox, FormContainer, FormItem, Input, Select } from '@/components/ui' import { Button, Card, Checkbox, FormContainer, FormItem, Input, Select } from '@/components/ui'
import { ListFormEditTabs } from '@/proxy/admin/list-form/options' import { ListFormEditTabs } from '@/proxy/admin/list-form/options'
import { LanguageInfo } from '@/proxy/config/models' import { LanguageInfo } from '@/proxy/config/models'
@ -47,9 +46,6 @@ function FormTabDetails(
const languages = useStoreState((state) => state.abpConfig.config?.localization.languages) const languages = useStoreState((state) => state.abpConfig.config?.localization.languages)
const listFormValues = useStoreState((s) => s.admin.lists.values) const listFormValues = useStoreState((s) => s.admin.lists.values)
if (!listFormValues) {
return null
}
useEffect(() => { useEffect(() => {
if (languages) { if (languages) {
@ -62,6 +58,10 @@ function FormTabDetails(
} }
}, [languages]) }, [languages])
if (!listFormValues) {
return null
}
return ( return (
<Formik <Formik
initialValues={listFormValues} initialValues={listFormValues}
@ -437,7 +437,7 @@ function FormTabDetails(
</Card> </Card>
</div> </div>
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -454,7 +454,7 @@ function FormTabEdit(props: FormEditProps & { listFormCode: string }) {
)} )}
</Card> </Card>
</div> </div>
<Button size="sm" block variant="solid" loading={isSubmitting}> <Button block size="sm" variant="solid" loading={isSubmitting}>
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -1,7 +1,6 @@
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
import { import {
Button, Button,
Card,
Checkbox, Checkbox,
FormContainer, FormContainer,
FormItem, FormItem,
@ -18,15 +17,10 @@ import * as Yup from 'yup'
import { FormEditProps } from './FormEdit' import { FormEditProps } from './FormEdit'
import { import {
applyFilterOptions, applyFilterOptions,
overflowWrapOptions,
sortModeOptions,
whiteSpaceOptions,
} from './options' } from './options'
import TabList from '@/components/ui/Tabs/TabList' import TabList from '@/components/ui/Tabs/TabList'
import TabNav from '@/components/ui/Tabs/TabNav' import TabNav from '@/components/ui/Tabs/TabNav'
import TabContent from '@/components/ui/Tabs/TabContent' import TabContent from '@/components/ui/Tabs/TabContent'
import { GridOptionsSortModeEnum } from '@/proxy/form/models'
import { SelectBoxOption } from '@/types/shared'
const validationSchema = Yup.object().shape({}) const validationSchema = Yup.object().shape({})
@ -304,7 +298,7 @@ function FormTabFilters(props: FormEditProps) {
</TabContent> </TabContent>
</Tabs> </Tabs>
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -16,9 +16,9 @@ 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'
import { SelectBoxOption } from '@/types/shared' import { SelectBoxOption } from '@/types/shared'
import { useEffect, useState } from 'react' 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' import groupBy from 'lodash/groupBy'
import { useParams } from 'react-router-dom' import { useParams } from 'react-router-dom'
import { GanttScaleType } from 'devextreme/ui/gantt' import { GanttScaleType } from 'devextreme/ui/gantt'
import { gantScaleOptions } from './options' import { gantScaleOptions } from './options'
@ -30,7 +30,7 @@ function FormTabGantt(props: FormEditProps) {
const { translate } = useLocalization() const { translate } = useLocalization()
const [fieldList, setFieldList] = useState<SelectBoxOption[]>([]) const [fieldList, setFieldList] = useState<SelectBoxOption[]>([])
const getFields = async () => { const getFields = useCallback(async () => {
if (!listFormCode) { if (!listFormCode) {
return return
} }
@ -61,11 +61,11 @@ function FormTabGantt(props: FormEditProps) {
}, },
) )
} }
} }, [listFormCode])
useEffect(() => { useEffect(() => {
getFields() getFields()
}, [listFormCode]) }, [getFields])
const listFormValues = useStoreState((s) => s.admin.lists.values) const listFormValues = useStoreState((s) => s.admin.lists.values)
if (!listFormValues) { if (!listFormValues) {
@ -471,7 +471,7 @@ function FormTabGantt(props: FormEditProps) {
</Card> </Card>
</div> </div>
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit" className="my-2"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit" className="my-2">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -26,7 +26,7 @@ function FormTabGroup(props: FormEditProps) {
await props.onSubmit(ListFormEditTabs.GroupForm, values, formikHelpers) await props.onSubmit(ListFormEditTabs.GroupForm, values, formikHelpers)
}} }}
> >
{({ touched, errors, isSubmitting, values }) => ( {({ touched, errors, isSubmitting }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<FormItem <FormItem
@ -54,7 +54,7 @@ function FormTabGroup(props: FormEditProps) {
/> />
</FormItem> </FormItem>
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -235,7 +235,7 @@ function FormTabPager(props: FormEditProps) {
</div> </div>
</div> </div>
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -26,11 +26,9 @@ function FormTabPermissions(props: FormEditProps) {
const { translate } = useLocalization() const { translate } = useLocalization()
const listFormValues = useStoreState((s) => s.admin.lists.values) const listFormValues = useStoreState((s) => s.admin.lists.values)
if (!listFormValues) {
return null
}
const getPermissionList = async () => { useEffect(() => {
const loadPermissions = async () => {
const response = await getPermissionsList() const response = await getPermissionsList()
if (response.data) { if (response.data) {
setPermissions( setPermissions(
@ -42,11 +40,12 @@ function FormTabPermissions(props: FormEditProps) {
} }
} }
useEffect(() => { loadPermissions()
if (permissions) { }, [])
getPermissionList()
if (!listFormValues) {
return null
} }
}, [permissions])
return ( return (
<Container className="grid xl:grid-cols-2"> <Container className="grid xl:grid-cols-2">
@ -239,7 +238,7 @@ function FormTabPermissions(props: FormEditProps) {
</FormItem> </FormItem>
)} )}
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -186,7 +186,7 @@ function FormTabColumns(props: FormEditProps) {
</div> </div>
</div> </div>
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit" className="my-2"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit" className="my-2">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -98,7 +98,7 @@ function FormTabRow(props: FormEditProps) {
</Field> </Field>
</FormItem> </FormItem>
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -16,9 +16,9 @@ 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'
import { SelectBoxOption } from '@/types/shared' import { SelectBoxOption } from '@/types/shared'
import { useEffect, useState } from 'react' 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' import groupBy from 'lodash/groupBy'
import { useParams } from 'react-router-dom' import { useParams } from 'react-router-dom'
import { firstDayOfWeekOptions, schedulerViewOptions } from './options' import { firstDayOfWeekOptions, schedulerViewOptions } from './options'
@ -29,7 +29,7 @@ function FormTabScheduler(props: FormEditProps) {
const { translate } = useLocalization() const { translate } = useLocalization()
const [fieldList, setFieldList] = useState<SelectBoxOption[]>([]) const [fieldList, setFieldList] = useState<SelectBoxOption[]>([])
const getFields = async () => { const getFields = useCallback(async () => {
if (!listFormCode) { if (!listFormCode) {
return return
} }
@ -60,11 +60,11 @@ function FormTabScheduler(props: FormEditProps) {
}, },
) )
} }
} }, [listFormCode])
useEffect(() => { useEffect(() => {
getFields() getFields()
}, [listFormCode]) }, [getFields])
const listFormValues = useStoreState((s) => s.admin.lists.values) const listFormValues = useStoreState((s) => s.admin.lists.values)
if (!listFormValues) { if (!listFormValues) {
@ -363,7 +363,7 @@ function FormTabScheduler(props: FormEditProps) {
</FormItem> </FormItem>
</Card> </Card>
</div> </div>
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit" className="my-2"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit" className="my-2">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button>{' '} </Button>{' '}
</FormContainer> </FormContainer>

View file

@ -26,7 +26,7 @@ function FormTabSearch(props: FormEditProps) {
await props.onSubmit(ListFormEditTabs.SearchForm, values, formikHelpers) await props.onSubmit(ListFormEditTabs.SearchForm, values, formikHelpers)
}} }}
> >
{({ touched, errors, isSubmitting, values }) => ( {({ touched, errors, isSubmitting }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<FormItem <FormItem
@ -55,7 +55,7 @@ function FormTabSearch(props: FormEditProps) {
/> />
</FormItem> </FormItem>
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -128,7 +128,7 @@ function FormTabSelect(props: FormEditProps) {
/> />
</FormItem> </FormItem>
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -1,32 +1,20 @@
import { Container } from '@/components/shared' import { Container } from '@/components/shared'
import { import {
Button, Button,
Card,
Checkbox,
FormContainer, FormContainer,
FormItem, FormItem,
Input,
Select, Select,
Tabs,
} from '@/components/ui' } from '@/components/ui'
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 { 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'
import { import {
applyFilterOptions,
overflowWrapOptions,
sortModeOptions, sortModeOptions,
whiteSpaceOptions,
} from './options' } from './options'
import TabList from '@/components/ui/Tabs/TabList'
import TabNav from '@/components/ui/Tabs/TabNav'
import TabContent from '@/components/ui/Tabs/TabContent'
import { GridOptionsSortModeEnum } from '@/proxy/form/models' import { GridOptionsSortModeEnum } from '@/proxy/form/models'
import { SelectBoxOption } from '@/types/shared'
const validationSchema = Yup.object().shape({}) const validationSchema = Yup.object().shape({})
@ -74,7 +62,7 @@ function FormTabSorting(props: FormEditProps) {
</Field> </Field>
</FormItem> </FormItem>
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -97,7 +97,7 @@ function FormTabState(props: FormEditProps) {
/> />
</FormItem> </FormItem>
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -7,7 +7,6 @@ import {
Input, Input,
Select, Select,
toast, toast,
Card,
} from '@/components/ui' } from '@/components/ui'
import { ListFormEditTabs } from '@/proxy/admin/list-form/options' import { ListFormEditTabs } from '@/proxy/admin/list-form/options'
import { useStoreState } from '@/store' import { useStoreState } from '@/store'
@ -16,9 +15,9 @@ 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'
import { SelectBoxOption } from '@/types/shared' import { SelectBoxOption } from '@/types/shared'
import { useEffect, useState } from 'react' 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' import groupBy from 'lodash/groupBy'
import { useParams } from 'react-router-dom' import { useParams } from 'react-router-dom'
const validationSchema = Yup.object().shape({}) const validationSchema = Yup.object().shape({})
@ -28,7 +27,7 @@ function FormTabTree(props: FormEditProps) {
const { translate } = useLocalization() const { translate } = useLocalization()
const [fieldList, setFieldList] = useState<SelectBoxOption[]>([]) const [fieldList, setFieldList] = useState<SelectBoxOption[]>([])
const getFields = async () => { const getFields = useCallback(async () => {
if (!listFormCode) { if (!listFormCode) {
return return
} }
@ -59,11 +58,11 @@ function FormTabTree(props: FormEditProps) {
}, },
) )
} }
} }, [listFormCode])
useEffect(() => { useEffect(() => {
getFields() getFields()
}, [listFormCode]) }, [getFields])
const listFormValues = useStoreState((s) => s.admin.lists.values) const listFormValues = useStoreState((s) => s.admin.lists.values)
if (!listFormValues) { if (!listFormValues) {
@ -185,7 +184,7 @@ function FormTabTree(props: FormEditProps) {
component={Checkbox} component={Checkbox}
/> />
</FormItem> </FormItem>
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit" className="my-2"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit" className="my-2">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -13,7 +13,7 @@ import { FaEdit, FaFileMedical, FaTrash } from 'react-icons/fa'
import { JsonRowDialogData } from './json-row-operations/types' import { JsonRowDialogData } from './json-row-operations/types'
import JsonRowOpDialogWidget from './json-row-operations/JsonRowOpDialogWidget' import JsonRowOpDialogWidget from './json-row-operations/JsonRowOpDialogWidget'
function FormTabWidgets(props: { listFormCode: string }) { function FormTabWidgets() {
const [isJsonRowOpDialogOpen, setIsJsonRowOpDialogOpen] = useState(false) const [isJsonRowOpDialogOpen, setIsJsonRowOpDialogOpen] = useState(false)
const [jsonRowOpModalData, setJsonRowOpModalData] = useState<JsonRowDialogData>() const [jsonRowOpModalData, setJsonRowOpModalData] = useState<JsonRowDialogData>()
const { translate } = useLocalization() const { translate } = useLocalization()

View file

@ -12,7 +12,7 @@ import { workflowService, type WorkflowCriteriaDto } from '@/services/workflow.s
import { WorkflowDesigner } from '../workflow/WorkflowDesigner' import { WorkflowDesigner } from '../workflow/WorkflowDesigner'
import { SelectBoxOption } from '@/types/shared' import { SelectBoxOption } from '@/types/shared'
import { Field, FieldProps, Form, Formik } from 'formik' import { Field, FieldProps, Form, Formik } from 'formik'
import { Button, Card, Checkbox, FormContainer, FormItem, Input, Select } from '@/components/ui' import { Button, Card, Checkbox, FormContainer, FormItem, Select } from '@/components/ui'
import { ListFormEditTabs } from '@/proxy/admin/list-form/options' import { ListFormEditTabs } from '@/proxy/admin/list-form/options'
import { bool, object, string } from 'yup' import { bool, object, string } from 'yup'
import { useStoreState } from '@/store/store' import { useStoreState } from '@/store/store'
@ -450,7 +450,7 @@ export function FormTabWorkflow(
</FormItem> </FormItem>
</div> </div>
<Button size="sm" block variant="solid" type="submit" loading={isSubmitting}> <Button block size="sm" variant="solid" type="submit" loading={isSubmitting}>
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</Card> </Card>

View file

@ -22,12 +22,10 @@ import { FormFieldEditProps } from './FormFields'
import FormFieldTabPivotSetting from './FormFieldTabPivotSetting' import FormFieldTabPivotSetting from './FormFieldTabPivotSetting'
function FormFieldEdit({ function FormFieldEdit({
listFormCode,
item, item,
onSubmit, onSubmit,
fields fields,
}: { }: {
listFormCode: string
item: ColumnFormatEditDto | null item: ColumnFormatEditDto | null
fields: ColumnFormatEditDto[] fields: ColumnFormatEditDto[]
} & FormFieldEditProps) { } & FormFieldEditProps) {
@ -77,111 +75,57 @@ function FormFieldEdit({
</TabList> </TabList>
<div className="pt-4"> <div className="pt-4">
<TabContent value="details"> <TabContent value="details">
<FormFieldTabDetails <FormFieldTabDetails initialValues={item} onSubmit={onSubmit} />
listFormCode={listFormCode}
initialValues={item}
onSubmit={onSubmit}
/>
</TabContent> </TabContent>
<TabContent value="options"> <TabContent value="options">
<FormFieldTabOptions <FormFieldTabOptions initialValues={item} onSubmit={onSubmit} />
listFormCode={listFormCode}
initialValues={item}
onSubmit={onSubmit}
/>
</TabContent> </TabContent>
<TabContent value="permissions"> <TabContent value="permissions">
<FormFieldTabPermissions <FormFieldTabPermissions initialValues={item} onSubmit={onSubmit} />
listFormCode={listFormCode}
initialValues={item}
onSubmit={onSubmit}
/>
</TabContent> </TabContent>
<TabContent value="customization"> <TabContent value="customization">
<FormFieldTabCustomization <FormFieldTabCustomization initialValues={item} onSubmit={onSubmit} />
listFormCode={listFormCode}
initialValues={item}
onSubmit={onSubmit}
/>
</TabContent> </TabContent>
<TabContent value="filtering"> <TabContent value="filtering">
<FormFieldTabFiltering <FormFieldTabFiltering initialValues={item} onSubmit={onSubmit} />
listFormCode={listFormCode}
initialValues={item}
onSubmit={onSubmit}
/>
</TabContent> </TabContent>
<TabContent value="headering"> <TabContent value="headering">
<FormFieldTabHeadering <FormFieldTabHeadering initialValues={item} onSubmit={onSubmit} />
listFormCode={listFormCode}
initialValues={item}
onSubmit={onSubmit}
/>
</TabContent> </TabContent>
<TabContent value="grouping"> <TabContent value="grouping">
<FormFieldTabGrouping <FormFieldTabGrouping initialValues={item} onSubmit={onSubmit} />
listFormCode={listFormCode}
initialValues={item}
onSubmit={onSubmit}
/>
</TabContent> </TabContent>
<TabContent value="groupSummary"> <TabContent value="groupSummary">
<FormFieldTabGroupSummary <FormFieldTabGroupSummary
listFormCode={listFormCode}
initialValues={item} initialValues={item}
onSubmit={onSubmit}
fields={fields} fields={fields}
onSubmit={onSubmit}
/> />
</TabContent> </TabContent>
<TabContent value="totalSummary"> <TabContent value="totalSummary">
<FormFieldTabTotalSummary <FormFieldTabTotalSummary
listFormCode={listFormCode}
initialValues={item} initialValues={item}
onSubmit={onSubmit}
fields={fields} fields={fields}
onSubmit={onSubmit}
/> />
</TabContent> </TabContent>
<TabContent value="joinOptions"> <TabContent value="joinOptions">
<FormFieldTabJoinOptions <FormFieldTabJoinOptions initialValues={item} onSubmit={onSubmit} />
listFormCode={listFormCode}
initialValues={item}
onSubmit={onSubmit}
/>
</TabContent> </TabContent>
<TabContent value="lookup"> <TabContent value="lookup">
<FormFieldTabLookup <FormFieldTabLookup initialValues={item} onSubmit={onSubmit} />
listFormCode={listFormCode}
initialValues={item}
onSubmit={onSubmit}
/>
</TabContent> </TabContent>
<TabContent value="cssOptions"> <TabContent value="cssOptions">
<FormFieldTabCssOptions <FormFieldTabCssOptions initialValues={item} onSubmit={onSubmit} />
listFormCode={listFormCode}
initialValues={item}
onSubmit={onSubmit}
/>
</TabContent> </TabContent>
<TabContent value="validationRules"> <TabContent value="validationRules">
<FormFieldTabValidationRules <FormFieldTabValidationRules initialValues={item} onSubmit={onSubmit} />
listFormCode={listFormCode}
initialValues={item}
onSubmit={onSubmit}
/>
</TabContent> </TabContent>
<TabContent value="conditionalFormatting"> <TabContent value="conditionalFormatting">
<FormFieldTabConditionalFormatting <FormFieldTabConditionalFormatting initialValues={item} onSubmit={onSubmit} />
listFormCode={listFormCode}
initialValues={item}
onSubmit={onSubmit}
/>
</TabContent> </TabContent>
<TabContent value="pivotSetting"> <TabContent value="pivotSetting">
<FormFieldTabPivotSetting <FormFieldTabPivotSetting initialValues={item} onSubmit={onSubmit} />
listFormCode={listFormCode}
initialValues={item}
onSubmit={onSubmit}
/>
</TabContent> </TabContent>
</div> </div>
</Tabs> </Tabs>

View file

@ -46,11 +46,9 @@ const schema = object().shape({
}) })
function FormFieldTabConditionalFormatting({ function FormFieldTabConditionalFormatting({
listFormCode,
initialValues, initialValues,
onSubmit, onSubmit,
}: { }: {
listFormCode: string
initialValues: ColumnFormatEditDto initialValues: ColumnFormatEditDto
} & FormFieldEditProps) { } & FormFieldEditProps) {
const { translate } = useLocalization() const { translate } = useLocalization()
@ -219,7 +217,7 @@ function FormFieldTabConditionalFormatting({
} }
}} }}
> >
{({ touched, errors, resetForm, values }) => ( {({ touched, errors, values }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<FormItem <FormItem
@ -316,7 +314,7 @@ function FormFieldTabConditionalFormatting({
/> />
</FormItem> </FormItem>
<Button size="sm" block variant="solid" loading={isLoading} type="submit"> <Button block size="sm" variant="solid" loading={isLoading} type="submit">
{isLoading ? translate('::Saving') : translate('::Save')} {isLoading ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -12,11 +12,9 @@ const schema = object().shape({
}) })
function FormFieldTabCssOptions({ function FormFieldTabCssOptions({
listFormCode,
initialValues, initialValues,
onSubmit, onSubmit,
}: { }: {
listFormCode: string
initialValues: ColumnFormatEditDto initialValues: ColumnFormatEditDto
} & FormFieldEditProps) { } & FormFieldEditProps) {
const { translate } = useLocalization() const { translate } = useLocalization()
@ -31,7 +29,7 @@ function FormFieldTabCssOptions({
await onSubmit(ListFormFieldEditTabs.CssOptionsForm, values, formikHelpers) await onSubmit(ListFormFieldEditTabs.CssOptionsForm, values, formikHelpers)
}} }}
> >
{({ touched, errors, isSubmitting, values }) => ( {({ touched, errors, isSubmitting }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<FormItem <FormItem
@ -63,7 +61,7 @@ function FormFieldTabCssOptions({
/> />
</FormItem> </FormItem>
<Button size="sm" className="mt-1" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" className="mt-1" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -20,11 +20,9 @@ const schema = object().shape({
}) })
function FormFieldTabCustomization({ function FormFieldTabCustomization({
listFormCode,
initialValues, initialValues,
onSubmit, onSubmit,
}: { }: {
listFormCode: string
initialValues: ColumnFormatEditDto initialValues: ColumnFormatEditDto
} & FormFieldEditProps) { } & FormFieldEditProps) {
const { translate } = useLocalization() const { translate } = useLocalization()
@ -39,7 +37,7 @@ function FormFieldTabCustomization({
await onSubmit(ListFormFieldEditTabs.CustomizationForm, values, formikHelpers) await onSubmit(ListFormFieldEditTabs.CustomizationForm, values, formikHelpers)
}} }}
> >
{({ touched, errors, isSubmitting, values }) => ( {({ isSubmitting, values }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<FormItem label={translate('::ListForms.ListFormFieldEdit.CustomizationFixed')}> <FormItem label={translate('::ListForms.ListFormFieldEdit.CustomizationFixed')}>
@ -70,7 +68,7 @@ function FormFieldTabCustomization({
</Field> </Field>
</FormItem> </FormItem>
<Button size="sm" className="mt-1" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" className="mt-1" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -23,11 +23,9 @@ const schema = object().shape({
}) })
function FormFieldTabDetails({ function FormFieldTabDetails({
listFormCode,
initialValues, initialValues,
onSubmit, onSubmit,
}: { }: {
listFormCode: string
initialValues: ColumnFormatEditDto initialValues: ColumnFormatEditDto
} & FormFieldEditProps) { } & FormFieldEditProps) {
const { translate } = useLocalization() const { translate } = useLocalization()
@ -156,7 +154,7 @@ function FormFieldTabDetails({
onClose={() => setIsEditorOptionsDialogOpen(false)} onClose={() => setIsEditorOptionsDialogOpen(false)}
onApply={(val) => setFieldValue('editorOptions', val)} onApply={(val) => setFieldValue('editorOptions', val)}
/> />
<Button size="sm" className="mt-1" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" className="mt-1" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</Form> </Form>

View file

@ -17,11 +17,9 @@ const schema = object().shape({
}) })
function FormFieldTabFiltering({ function FormFieldTabFiltering({
listFormCode,
initialValues, initialValues,
onSubmit, onSubmit,
}: { }: {
listFormCode: string
initialValues: ColumnFormatEditDto initialValues: ColumnFormatEditDto
} & FormFieldEditProps) { } & FormFieldEditProps) {
const { translate } = useLocalization() const { translate } = useLocalization()
@ -36,7 +34,7 @@ function FormFieldTabFiltering({
await onSubmit(ListFormFieldEditTabs.FilteringForm, values, formikHelpers) await onSubmit(ListFormFieldEditTabs.FilteringForm, values, formikHelpers)
}} }}
> >
{({ touched, errors, isSubmitting, values }) => ( {({ touched, errors, isSubmitting }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<FormItem <FormItem
@ -84,7 +82,7 @@ function FormFieldTabFiltering({
/> />
</FormItem> </FormItem>
<Button size="sm" className="mt-1" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" className="mt-1" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -23,12 +23,10 @@ const schema = object().shape({
}) })
function FormFieldTabGroupSummary({ function FormFieldTabGroupSummary({
listFormCode,
initialValues, initialValues,
onSubmit, onSubmit,
fields, fields,
}: { }: {
listFormCode: string
initialValues: ColumnFormatEditDto initialValues: ColumnFormatEditDto
fields: ColumnFormatEditDto[] fields: ColumnFormatEditDto[]
} & FormFieldEditProps) { } & FormFieldEditProps) {
@ -176,7 +174,7 @@ function FormFieldTabGroupSummary({
/> />
</FormItem> </FormItem>
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -17,11 +17,9 @@ const schema = object().shape({
}) })
function FormFieldTabGrouping({ function FormFieldTabGrouping({
listFormCode,
initialValues, initialValues,
onSubmit, onSubmit,
}: { }: {
listFormCode: string
initialValues: ColumnFormatEditDto initialValues: ColumnFormatEditDto
} & FormFieldEditProps) { } & FormFieldEditProps) {
const { translate } = useLocalization() const { translate } = useLocalization()
@ -36,7 +34,7 @@ function FormFieldTabGrouping({
await onSubmit(ListFormFieldEditTabs.GroupingForm, values, formikHelpers) await onSubmit(ListFormFieldEditTabs.GroupingForm, values, formikHelpers)
}} }}
> >
{({ touched, errors, isSubmitting, values }) => ( {({ touched, errors, isSubmitting }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<FormItem label={translate('::ListForms.ListFormFieldEdit.GroupingAllowGrouping')}> <FormItem label={translate('::ListForms.ListFormFieldEdit.GroupingAllowGrouping')}>
@ -61,7 +59,7 @@ function FormFieldTabGrouping({
/> />
</FormItem> </FormItem>
<Button size="sm" className="mt-1" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" className="mt-1" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -17,11 +17,9 @@ const schema = object().shape({
}) })
function FormFieldTabHeadering({ function FormFieldTabHeadering({
listFormCode,
initialValues, initialValues,
onSubmit, onSubmit,
}: { }: {
listFormCode: string
initialValues: ColumnFormatEditDto initialValues: ColumnFormatEditDto
} & FormFieldEditProps) { } & FormFieldEditProps) {
const { translate } = useLocalization() const { translate } = useLocalization()
@ -36,7 +34,7 @@ function FormFieldTabHeadering({
await onSubmit(ListFormFieldEditTabs.HeaderingForm, values, formikHelpers) await onSubmit(ListFormFieldEditTabs.HeaderingForm, values, formikHelpers)
}} }}
> >
{({ touched, errors, isSubmitting, values }) => ( {({ touched, errors, isSubmitting }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<FormItem <FormItem
@ -65,7 +63,7 @@ function FormFieldTabHeadering({
/> />
</FormItem> </FormItem>
<Button size="sm" className="mt-1" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" className="mt-1" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -1,5 +1,4 @@
import { Container } from '@/components/shared' import { Button, Card, FormItem, Input, Select } from '@/components/ui'
import { Button, Card, FormContainer, FormItem, Input, Select } from '@/components/ui'
import { import {
ColumnFormatEditDto, ColumnFormatEditDto,
GridColumnJoinConditionEnum, GridColumnJoinConditionEnum,
@ -29,11 +28,9 @@ const schema = object().shape({
}) })
function FormFieldTabJoinOptions({ function FormFieldTabJoinOptions({
listFormCode,
initialValues, initialValues,
onSubmit, onSubmit,
}: { }: {
listFormCode: string
initialValues: ColumnFormatEditDto initialValues: ColumnFormatEditDto
} & FormFieldEditProps) { } & FormFieldEditProps) {
const { translate } = useLocalization() const { translate } = useLocalization()
@ -234,7 +231,7 @@ function FormFieldTabJoinOptions({
</FormItem> </FormItem>
</Card> </Card>
</div> </div>
<Button size="sm" className="mt-1" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" className="mt-1" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</Form> </Form>

View file

@ -1,5 +1,4 @@
import { Container } from '@/components/shared' import { Button, Card, FormItem, Input, Select } from '@/components/ui'
import { Button, Card, Checkbox, FormContainer, FormItem, Input, Select } from '@/components/ui'
import { ColumnFormatEditDto, ListFormFieldEditTabs } from '@/proxy/admin/list-form-field/models' import { ColumnFormatEditDto, ListFormFieldEditTabs } from '@/proxy/admin/list-form-field/models'
import type { DatabaseColumnDto, SqlObjectExplorerDto } from '@/proxy/sql-query-manager/models' import type { DatabaseColumnDto, SqlObjectExplorerDto } from '@/proxy/sql-query-manager/models'
import { sqlObjectManagerService } from '@/services/sql-query-manager.service' import { sqlObjectManagerService } from '@/services/sql-query-manager.service'
@ -70,11 +69,11 @@ function TablePickerModal({
{step === 'columns' && ( {step === 'columns' && (
<Button <Button
type="button" type="button"
onClick={() => setStep('table')}
variant="plain" variant="plain"
shape="circle" shape="circle"
icon={<FaArrowLeft className="text-xs" />} icon={<FaArrowLeft className="text-xs" />}
className="!h-6 !w-6 !px-0 text-gray-400 transition-colors hover:!bg-transparent hover:text-indigo-500" className="!h-6 !w-6 !px-0 text-gray-400 transition-colors hover:!bg-transparent hover:text-indigo-500"
onClick={() => setStep('table')}
/> />
)} )}
<span className="text-sm font-semibold text-gray-700 dark:text-gray-200"> <span className="text-sm font-semibold text-gray-700 dark:text-gray-200">
@ -85,11 +84,11 @@ function TablePickerModal({
</div> </div>
<Button <Button
type="button" type="button"
onClick={onClose}
variant="plain" variant="plain"
shape="circle" shape="circle"
icon={<FaTimes />} icon={<FaTimes />}
className="!h-7 !w-7 !px-0 text-gray-400 hover:!bg-transparent hover:text-gray-600 dark:hover:text-gray-200" className="!h-7 !w-7 !px-0 text-gray-400 hover:!bg-transparent hover:text-gray-600 dark:hover:text-gray-200"
onClick={onClose}
/> />
</div> </div>
@ -100,9 +99,9 @@ function TablePickerModal({
<input <input
autoFocus autoFocus
value={tableSearch} value={tableSearch}
onChange={(e) => setTableSearch(e.target.value)}
placeholder={translate('::Search') || 'Ara...'} placeholder={translate('::Search') || 'Ara...'}
className="w-full text-xs px-2 py-1.5 rounded border border-gray-200 dark:border-gray-600 bg-gray-50 dark:bg-gray-800 text-gray-700 dark:text-gray-200 focus:outline-none focus:border-indigo-400" className="w-full text-xs px-2 py-1.5 rounded border border-gray-200 dark:border-gray-600 bg-gray-50 dark:bg-gray-800 text-gray-700 dark:text-gray-200 focus:outline-none focus:border-indigo-400"
onChange={(e) => setTableSearch(e.target.value)}
/> />
</div> </div>
<div className="overflow-y-auto flex-1 p-2"> <div className="overflow-y-auto flex-1 p-2">
@ -117,6 +116,9 @@ function TablePickerModal({
<Button <Button
key={t.fullName} key={t.fullName}
type="button" type="button"
variant="plain"
shape="none"
className="w-full !h-auto !justify-start !rounded !px-3 !py-2 text-left font-mono text-xs text-gray-700 transition-colors hover:!bg-indigo-50 dark:text-gray-200 dark:hover:!bg-indigo-900/30"
onClick={async () => { onClick={async () => {
setPickerTable(t) setPickerTable(t)
setStep('columns') setStep('columns')
@ -137,9 +139,6 @@ function TablePickerModal({
setIsLoadingColumns(false) setIsLoadingColumns(false)
} }
}} }}
variant="plain"
shape="none"
className="w-full !h-auto !justify-start !rounded !px-3 !py-2 text-left font-mono text-xs text-gray-700 transition-colors hover:!bg-indigo-50 dark:text-gray-200 dark:hover:!bg-indigo-900/30"
> >
<span className="text-gray-400 mr-1">{t.schemaName}.</span> <span className="text-gray-400 mr-1">{t.schemaName}.</span>
{t.tableName} {t.tableName}
@ -165,8 +164,8 @@ function TablePickerModal({
</label> </label>
<select <select
value={keyCol} value={keyCol}
onChange={(e) => setKeyCol(e.target.value)}
className="w-full text-xs h-8 px-2 rounded border border-gray-200 dark:border-gray-600 bg-gray-50 dark:bg-gray-700 text-gray-700 dark:text-gray-200 focus:outline-none focus:border-indigo-400" className="w-full text-xs h-8 px-2 rounded border border-gray-200 dark:border-gray-600 bg-gray-50 dark:bg-gray-700 text-gray-700 dark:text-gray-200 focus:outline-none focus:border-indigo-400"
onChange={(e) => setKeyCol(e.target.value)}
> >
<option value="">-- Seçiniz --</option> <option value="">-- Seçiniz --</option>
{pickerColumns.map((c) => ( {pickerColumns.map((c) => (
@ -182,8 +181,8 @@ function TablePickerModal({
</label> </label>
<select <select
value={nameCol} value={nameCol}
onChange={(e) => setNameCol(e.target.value)}
className="w-full text-xs h-8 px-2 rounded border border-gray-200 dark:border-gray-600 bg-gray-50 dark:bg-gray-700 text-gray-700 dark:text-gray-200 focus:outline-none focus:border-indigo-400" className="w-full text-xs h-8 px-2 rounded border border-gray-200 dark:border-gray-600 bg-gray-50 dark:bg-gray-700 text-gray-700 dark:text-gray-200 focus:outline-none focus:border-indigo-400"
onChange={(e) => setNameCol(e.target.value)}
> >
<option value="">-- Seçiniz --</option> <option value="">-- Seçiniz --</option>
{pickerColumns.map((c) => ( {pickerColumns.map((c) => (
@ -204,8 +203,10 @@ function TablePickerModal({
</div> </div>
)} )}
<Button <Button
block
type="button" type="button"
disabled={!keyCol || !nameCol} disabled={!keyCol || !nameCol}
variant="solid"
onClick={() => { onClick={() => {
onSelect( onSelect(
buildLookupQuery({ buildLookupQuery({
@ -216,8 +217,6 @@ function TablePickerModal({
}), }),
) )
}} }}
block
variant="solid"
> >
{translate('::OK')} {translate('::OK')}
</Button> </Button>
@ -248,11 +247,9 @@ function getNormalizedInitialValues(initialValues: ColumnFormatEditDto) {
} }
function FormFieldTabLookup({ function FormFieldTabLookup({
listFormCode,
initialValues, initialValues,
onSubmit, onSubmit,
}: { }: {
listFormCode: string
initialValues: ColumnFormatEditDto initialValues: ColumnFormatEditDto
} & FormFieldEditProps) { } & FormFieldEditProps) {
const { translate } = useLocalization() const { translate } = useLocalization()
@ -317,11 +314,11 @@ function FormFieldTabLookup({
extra={ extra={
<Button <Button
type="button" type="button"
onClick={openTablePicker}
variant="plain" variant="plain"
shape="none" shape="none"
icon={<FaPlus className="text-[8px]" />} icon={<FaPlus className="text-[8px]" />}
className="ml-2 !h-auto !items-center gap-1 !rounded border border-indigo-200 bg-indigo-50 !px-1.5 !py-0.5 text-[10px] font-medium text-indigo-600 transition-colors hover:!bg-indigo-100 dark:border-indigo-700 dark:bg-indigo-900/20 dark:text-indigo-400 dark:hover:!bg-indigo-800/40" className="ml-2 !h-auto !items-center gap-1 !rounded border border-indigo-200 bg-indigo-50 !px-1.5 !py-0.5 text-[10px] font-medium text-indigo-600 transition-colors hover:!bg-indigo-100 dark:border-indigo-700 dark:bg-indigo-900/20 dark:text-indigo-400 dark:hover:!bg-indigo-800/40"
onClick={openTablePicker}
> >
{translate('::ListForms.Wizard.Step3.GenerateFromTable') || 'Tablodan Oluştur'} {translate('::ListForms.Wizard.Step3.GenerateFromTable') || 'Tablodan Oluştur'}
</Button> </Button>
@ -465,7 +462,7 @@ function FormFieldTabLookup({
</FormItem> </FormItem>
</Card> </Card>
</div> </div>
<Button size="sm" className="mt-1" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" className="mt-1" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</Form> </Form>

View file

@ -1,5 +1,4 @@
import { Container } from '@/components/shared' import { Button, Card, Checkbox, FormItem, Input, Select } from '@/components/ui'
import { Button, Card, Checkbox, FormContainer, FormItem, Input, Select } from '@/components/ui'
import { ColumnFormatEditDto, ListFormFieldEditTabs } from '@/proxy/admin/list-form-field/models' import { ColumnFormatEditDto, ListFormFieldEditTabs } from '@/proxy/admin/list-form-field/models'
import { SelectBoxOption } from '@/types/shared' import { SelectBoxOption } from '@/types/shared'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
@ -22,11 +21,9 @@ const schema = object().shape({
}) })
function FormFieldTabOptions({ function FormFieldTabOptions({
listFormCode,
initialValues, initialValues,
onSubmit, onSubmit,
}: { }: {
listFormCode: string
initialValues: ColumnFormatEditDto initialValues: ColumnFormatEditDto
} & FormFieldEditProps) { } & FormFieldEditProps) {
const { translate } = useLocalization() const { translate } = useLocalization()
@ -113,7 +110,7 @@ function FormFieldTabOptions({
</Card> </Card>
</div> </div>
<Button size="sm" className="mt-1" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" className="mt-1" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</Form> </Form>

View file

@ -21,11 +21,9 @@ const schema = object().shape({
}) })
function FormFieldTabPermissions({ function FormFieldTabPermissions({
listFormCode,
initialValues, initialValues,
onSubmit, onSubmit,
}: { }: {
listFormCode: string
initialValues: ColumnFormatEditDto initialValues: ColumnFormatEditDto
} & FormFieldEditProps) { } & FormFieldEditProps) {
const { translate } = useLocalization() const { translate } = useLocalization()
@ -159,7 +157,7 @@ function FormFieldTabPermissions({
<Field name="permissionDto.i" component={Checkbox} /> <Field name="permissionDto.i" component={Checkbox} />
</FormItem> </FormItem>
<Button size="sm" className="mt-1" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" className="mt-1" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -1,5 +1,4 @@
import { Container } from '@/components/shared' import { Button, Card, Checkbox, FormItem, Select } from '@/components/ui'
import { Button, Card, Checkbox, FormContainer, FormItem, Input, Select } from '@/components/ui'
import { ColumnFormatEditDto, ListFormFieldEditTabs } from '@/proxy/admin/list-form-field/models' import { ColumnFormatEditDto, ListFormFieldEditTabs } from '@/proxy/admin/list-form-field/models'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { Field, FieldProps, Form, Formik } from 'formik' import { Field, FieldProps, Form, Formik } from 'formik'
@ -28,11 +27,9 @@ const schema = object().shape({
}) })
function FormFieldTabPivotSetting({ function FormFieldTabPivotSetting({
listFormCode,
initialValues, initialValues,
onSubmit, onSubmit,
}: { }: {
listFormCode: string
initialValues: ColumnFormatEditDto initialValues: ColumnFormatEditDto
} & FormFieldEditProps) { } & FormFieldEditProps) {
const { translate } = useLocalization() const { translate } = useLocalization()
@ -214,7 +211,7 @@ function FormFieldTabPivotSetting({
</FormItem> </FormItem>
</Card> </Card>
</div> </div>
<Button size="sm" className="mt-1" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" className="mt-1" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</Form> </Form>

View file

@ -8,7 +8,6 @@ import { columnSummaryTypeListOptions } from '../options'
import { FormFieldEditProps } from './FormFields' import { FormFieldEditProps } from './FormFields'
import { tooltipFormatListOptions } from '@/proxy/admin/list-form/options' import { tooltipFormatListOptions } from '@/proxy/admin/list-form/options'
import { SelectBoxOption } from '@/types/shared' import { SelectBoxOption } from '@/types/shared'
import { useState } from 'react'
const schema = object().shape({ const schema = object().shape({
columnTotalSummaryDto: object() columnTotalSummaryDto: object()
@ -24,12 +23,10 @@ const schema = object().shape({
}) })
function FormFieldTabTotalSummary({ function FormFieldTabTotalSummary({
listFormCode,
initialValues, initialValues,
onSubmit, onSubmit,
fields, fields,
}: { }: {
listFormCode: string
initialValues: ColumnFormatEditDto initialValues: ColumnFormatEditDto
fields: ColumnFormatEditDto[] fields: ColumnFormatEditDto[]
} & FormFieldEditProps) { } & FormFieldEditProps) {
@ -177,7 +174,7 @@ function FormFieldTabTotalSummary({
/> />
</FormItem> </FormItem>
<Button size="sm" className="mt-1" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" className="mt-1" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -60,11 +60,9 @@ const schema = object().shape({
}) })
function FormFieldTabValidationRules({ function FormFieldTabValidationRules({
listFormCode,
initialValues, initialValues,
onSubmit, onSubmit,
}: { }: {
listFormCode: string
initialValues: ColumnFormatEditDto initialValues: ColumnFormatEditDto
} & FormFieldEditProps) { } & FormFieldEditProps) {
const { translate } = useLocalization() const { translate } = useLocalization()
@ -229,7 +227,7 @@ function FormFieldTabValidationRules({
} }
}} }}
> >
{({ touched, errors, resetForm, values }) => ( {({ touched, errors, values }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<FormItem <FormItem
@ -355,7 +353,7 @@ function FormFieldTabValidationRules({
<Field name="trim" placeholder="Trim" component={Checkbox} /> <Field name="trim" placeholder="Trim" component={Checkbox} />
</FormItem> </FormItem>
<Button size="sm" className="mt-1" block variant="solid" loading={isLoading} type="submit"> <Button block size="sm" className="mt-1" variant="solid" loading={isLoading} type="submit">
{isLoading ? translate('::Saving') : translate('::Save')} {isLoading ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -35,7 +35,7 @@ import { useLocalization } from '@/utils/hooks/useLocalization'
import setNull from '@/utils/setNull' import setNull from '@/utils/setNull'
import classNames from 'classnames' import classNames from 'classnames'
import { Field, FieldProps, Form, Formik, FormikHelpers } from 'formik' import { Field, FieldProps, Form, Formik, FormikHelpers } from 'formik'
import { useEffect, useState } from 'react' import { useCallback, useEffect, useState } from 'react'
import { FaFileMedical, FaCopy, FaEyeSlash, FaMinus, FaTimes, FaTable } from 'react-icons/fa' import { FaFileMedical, FaCopy, FaEyeSlash, FaMinus, FaTimes, FaTable } from 'react-icons/fa'
import { number, object, string } from 'yup' import { number, object, string } from 'yup'
import FormFieldEdit from './FormFieldEdit' import FormFieldEdit from './FormFieldEdit'
@ -219,7 +219,7 @@ function FormFields({
await getFields() await getFields()
} }
const getFields = async (cultureName?: string, roleId?: string, userId?: string) => { const getFields = useCallback(async (cultureName?: string, roleId?: string, userId?: string) => {
if (!listFormCode) { if (!listFormCode) {
return return
} }
@ -254,11 +254,11 @@ function FormFields({
}, },
) )
} }
} }, [listFormCode])
useEffect(() => { useEffect(() => {
getFields() getFields()
}, [listFormCode]) }, [getFields])
useEffect(() => { useEffect(() => {
if (!fields || !row) { if (!fields || !row) {
@ -266,10 +266,10 @@ function FormFields({
} }
const newRow = fields.find((f) => f.id === row.id) const newRow = fields.find((f) => f.id === row.id)
if (newRow) { if (newRow && newRow !== row) {
setRow(newRow) setRow(newRow)
} }
}, [fields]) }, [fields, row])
const onSubmit = async ( const onSubmit = async (
editType: string, editType: string,
@ -390,7 +390,7 @@ function FormFields({
</Field> </Field>
</FormItem> </FormItem>
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? '...' : translate('::ListForms.ListFormField.Filter')} {isSubmitting ? '...' : translate('::ListForms.ListFormField.Filter')}
</Button> </Button>
</FormContainer> </FormContainer>
@ -454,14 +454,14 @@ function FormFields({
<TBody> <TBody>
{fields.map((field) => ( {fields.map((field) => (
<Tr <Tr
key={field.id}
className={classNames( className={classNames(
'cursor-pointer', 'cursor-pointer',
field.id === row?.id ? 'bg-sozsoft-active dark:bg-gray-600' : '', field.id === row?.id ? 'bg-sozsoft-active dark:bg-gray-600' : '',
)} )}
onClick={(e: any) => { onClick={() => {
setRow(field) setRow(field)
}} }}
key={field.id}
> >
<Td className="flex items-center !p-0"> <Td className="flex items-center !p-0">
<Button <Button
@ -505,7 +505,7 @@ function FormFields({
</Table> </Table>
</div> </div>
<div className="2xl:col-span-3 lg:col-span-3 xl:col-span-2"> <div className="2xl:col-span-3 lg:col-span-3 xl:col-span-2">
<FormFieldEdit listFormCode={listFormCode} item={row} onSubmit={onSubmit} fields={fields} /> <FormFieldEdit item={row} fields={fields} onSubmit={onSubmit} />
</div> </div>
</div> </div>
</AdaptableCard> </AdaptableCard>
@ -684,7 +684,7 @@ function FormFields({
</Field> </Field>
</FormItem> </FormItem>
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>
@ -793,7 +793,7 @@ function FormFields({
} }
}} }}
> >
{({ touched, errors, resetForm, isSubmitting, values }) => ( {({ touched, errors, isSubmitting, values }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<FormItem <FormItem
@ -1023,7 +1023,7 @@ function FormFields({
<Field name="copiedFields.pivotSetting" component={Checkbox} className="mr-1" /> <Field name="copiedFields.pivotSetting" component={Checkbox} className="mr-1" />
</FormItem> </FormItem>
</div> </div>
<Button size="sm" block variant="solid" loading={isSubmitting} type="submit"> <Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::Saving') : translate('::Save')} {isSubmitting ? translate('::Saving') : translate('::Save')}
</Button> </Button>
</FormContainer> </FormContainer>

View file

@ -1,7 +1,7 @@
import { Button, Dialog } from '@/components/ui' import { Button, Dialog } from '@/components/ui'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { useEffect, useMemo, useState } from 'react' import { useEffect, useMemo, useState } from 'react'
import { FaCheck, FaCode, FaPlus, FaSlidersH, FaTimes, FaTrash } from 'react-icons/fa' import { FaCheck, FaCode, FaPlus, FaTimes, FaTrash } from 'react-icons/fa'
type CustomOption = { type CustomOption = {
id: string id: string
@ -295,51 +295,52 @@ function EditorOptionsBuilderDialog({
<Button <Button
type="button" type="button"
size="sm" size="sm"
onClick={clearOptions}
title="editorOptions alanını boşaltır. Backend'e boş string kaydedilir." title="editorOptions alanını boşaltır. Backend'e boş string kaydedilir."
onClick={clearOptions}
> >
NULL / Empty NULL / Empty
</Button> </Button>
<Button <Button
type="button" type="button"
size="sm" size="sm"
onClick={() => addPreset({ disabled: true })}
title='{"disabled": true} ekler.' title='{"disabled": true} ekler.'
onClick={() => addPreset({ disabled: true })}
> >
disabled disabled
</Button> </Button>
<Button <Button
type="button" type="button"
size="sm" size="sm"
onClick={() => addPreset({ tooltip: { enabled: true } })}
title='{"tooltip": {"enabled": true}} ekler.' title='{"tooltip": {"enabled": true}} ekler.'
onClick={() => addPreset({ tooltip: { enabled: true } })}
> >
Tooltip Tooltip
</Button> </Button>
<Button <Button
type="button" type="button"
size="sm" size="sm"
onClick={() => addPreset({ format: { type: 'fixedPoint', precision: 2 } })}
title="Ondalık format precision 2 ekler." title="Ondalık format precision 2 ekler."
onClick={() => addPreset({ format: { type: 'fixedPoint', precision: 2 } })}
> >
fixedPoint precision 2 fixedPoint precision 2
</Button> </Button>
<Button <Button
type="button" type="button"
size="sm" size="sm"
title="Pasif ve precision 2 fixedPoint formatını birlikte ekler."
onClick={() => onClick={() =>
addPreset({ addPreset({
disabled: true, disabled: true,
format: { type: 'fixedPoint', precision: 2 }, format: { type: 'fixedPoint', precision: 2 },
}) })
} }
title="Pasif ve precision 2 fixedPoint formatını birlikte ekler."
> >
disabled fixedPoint 2 disabled fixedPoint 2
</Button> </Button>
<Button <Button
type="button" type="button"
size="sm" size="sm"
title="Precision 1, mask behavior, spin buttons ve pasif ayarını ekler."
onClick={() => onClick={() =>
addPreset({ addPreset({
format: { type: 'fixedPoint', precision: 1 }, format: { type: 'fixedPoint', precision: 1 },
@ -348,13 +349,13 @@ function EditorOptionsBuilderDialog({
disabled: true, disabled: true,
}) })
} }
title="Precision 1, mask behavior, spin buttons ve pasif ayarını ekler."
> >
disabled fixedPoint 1 disabled fixedPoint 1
</Button> </Button>
<Button <Button
type="button" type="button"
size="sm" size="sm"
title="NumberBox için precision 2, mask behavior ve spin buttons ekler."
onClick={() => onClick={() =>
addPreset({ addPreset({
format: { type: 'fixedPoint', precision: 2 }, format: { type: 'fixedPoint', precision: 2 },
@ -362,34 +363,34 @@ function EditorOptionsBuilderDialog({
showSpinButtons: true, showSpinButtons: true,
}) })
} }
title="NumberBox için precision 2, mask behavior ve spin buttons ekler."
> >
numberSpin precision 2 numberSpin precision 2
</Button> </Button>
<Button <Button
type="button" type="button"
size="sm" size="sm"
onClick={() => addPreset({ format: 'dd/MM/yyyy', displayFormat: 'dd/MM/yyyy' })}
title="DateBox için gün/ay/yıl formatını ekler." title="DateBox için gün/ay/yıl formatını ekler."
onClick={() => addPreset({ format: 'dd/MM/yyyy', displayFormat: 'dd/MM/yyyy' })}
> >
date dd/MM/yyyy date dd/MM/yyyy
</Button> </Button>
<Button <Button
type="button" type="button"
size="sm" size="sm"
title="DateBox için gün/ay/yıl saat:dakika formatını ekler."
onClick={() => onClick={() =>
addPreset({ addPreset({
format: 'dd/MM/yyyy HH:mm', format: 'dd/MM/yyyy HH:mm',
displayFormat: 'dd/MM/yyyy HH:mm', displayFormat: 'dd/MM/yyyy HH:mm',
}) })
} }
title="DateBox için gün/ay/yıl saat:dakika formatını ekler."
> >
dateTime dd/MM/yyyy HH:mm dateTime dd/MM/yyyy HH:mm
</Button> </Button>
<Button <Button
type="button" type="button"
size="sm" size="sm"
title="Telefon maskesi, yer tutucu ve Türkçe hata mesajı ekler."
onClick={() => onClick={() =>
addPreset({ addPreset({
format: 'phoneGlobal', format: 'phoneGlobal',
@ -400,13 +401,13 @@ function EditorOptionsBuilderDialog({
placeholder: '(555) 123-4567', placeholder: '(555) 123-4567',
}) })
} }
title="Telefon maskesi, yer tutucu ve Türkçe hata mesajı ekler."
> >
phoneGlobal mask phoneGlobal mask
</Button> </Button>
<Button <Button
type="button" type="button"
size="sm" size="sm"
title="Saat seçimi için dxDateBox time picker ayarları ekler."
onClick={() => onClick={() =>
addPreset({ addPreset({
type: 'time', type: 'time',
@ -417,32 +418,31 @@ function EditorOptionsBuilderDialog({
width: '100%', width: '100%',
}) })
} }
title="Saat seçimi için dxDateBox time picker ayarları ekler."
> >
time picker time picker
</Button> </Button>
<Button <Button
type="button" type="button"
size="sm" size="sm"
onClick={() => addPreset({ width: 80, height: 80, multiple: true })}
title="ImageUpload için 80x80 ve multiple ayarlarını ekler." title="ImageUpload için 80x80 ve multiple ayarlarını ekler."
onClick={() => addPreset({ width: 80, height: 80, multiple: true })}
> >
multi image multi image
</Button> </Button>
<Button type="button" size="sm" onClick={() => addPreset({ height: 60 })} title='{"height": 60} ekler.'> <Button type="button" size="sm" title='{"height": 60} ekler.' onClick={() => addPreset({ height: 60 })}>
Height 60 Height 60
</Button> </Button>
<Button type="button" size="sm" onClick={() => addPreset({ height: 100 })} title='{"height": 100} ekler.'> <Button type="button" size="sm" title='{"height": 100} ekler.' onClick={() => addPreset({ height: 100 })}>
Height 100 Height 100
</Button> </Button>
<Button type="button" size="sm" onClick={() => addPreset({ height: 200 })} title='{"height": 200} ekler.'> <Button type="button" size="sm" title='{"height": 200} ekler.' onClick={() => addPreset({ height: 200 })}>
Height 200 Height 200
</Button> </Button>
<Button <Button
type="button" type="button"
size="sm" size="sm"
onClick={() => addPreset(buildHtmlEditorOptions())}
title="HtmlEditor toolbar, image upload ve media resizing ayarlarını ekler." title="HtmlEditor toolbar, image upload ve media resizing ayarlarını ekler."
onClick={() => addPreset(buildHtmlEditorOptions())}
> >
htmlEditor toolbar htmlEditor toolbar
</Button> </Button>
@ -451,12 +451,12 @@ function EditorOptionsBuilderDialog({
return ( return (
<Dialog <Dialog
preventScroll
isOpen={isOpen} isOpen={isOpen}
width={1320} width={1320}
height="88vh" height="88vh"
contentClassName="flex flex-col" contentClassName="flex flex-col"
style={{ overlay: { zIndex: 1300 } }} style={{ overlay: { zIndex: 1300 } }}
preventScroll
onClose={onClose} onClose={onClose}
onRequestClose={onClose} onRequestClose={onClose}
> >
@ -545,9 +545,9 @@ function EditorOptionsBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={toInputValue(options.width)} value={toInputValue(options.width)}
onChange={(event) => setOptionValue('width', event.target.value)}
placeholder="100% veya 240" placeholder="100% veya 240"
title="Örnek: 100%, 240, 80" title="Örnek: 100%, 240, 80"
onChange={(event) => setOptionValue('width', event.target.value)}
/> />
</label> </label>
<label className="text-xs text-gray-500"> <label className="text-xs text-gray-500">
@ -555,15 +555,15 @@ function EditorOptionsBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={toInputValue(options.height)} value={toInputValue(options.height)}
placeholder="200"
type="number"
title="Editor yüksekliği. Örnek: 60, 100, 200"
onChange={(event) => onChange={(event) =>
setOptionValue( setOptionValue(
'height', 'height',
event.target.value ? Number(event.target.value) : undefined, event.target.value ? Number(event.target.value) : undefined,
) )
} }
placeholder="200"
type="number"
title="Editor yüksekliği. Örnek: 60, 100, 200"
/> />
</label> </label>
<label className="text-xs text-gray-500"> <label className="text-xs text-gray-500">
@ -571,9 +571,9 @@ function EditorOptionsBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={toInputValue(options.placeholder)} value={toInputValue(options.placeholder)}
onChange={(event) => setOptionValue('placeholder', event.target.value)}
placeholder="Placeholder" placeholder="Placeholder"
title="Editor boşken görünecek metin." title="Editor boşken görünecek metin."
onChange={(event) => setOptionValue('placeholder', event.target.value)}
/> />
</label> </label>
</div> </div>
@ -592,9 +592,9 @@ function EditorOptionsBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={toInputValue(options.label)} value={toInputValue(options.label)}
onChange={(event) => setOptionValue('label', event.target.value)}
placeholder="Alan etiketi" placeholder="Alan etiketi"
title="Editor içi label metni." title="Editor içi label metni."
onChange={(event) => setOptionValue('label', event.target.value)}
/> />
</label> </label>
<label className="text-xs text-gray-500"> <label className="text-xs text-gray-500">
@ -602,8 +602,8 @@ function EditorOptionsBuilderDialog({
<select <select
className={baseInputClass} className={baseInputClass}
value={toSelectValue(options.labelMode)} value={toSelectValue(options.labelMode)}
onChange={(event) => setOptionValue('labelMode', event.target.value)}
title="Label gösterim modu." title="Label gösterim modu."
onChange={(event) => setOptionValue('labelMode', event.target.value)}
> >
<option value="">Seç</option> <option value="">Seç</option>
<option value="static">static</option> <option value="static">static</option>
@ -617,8 +617,8 @@ function EditorOptionsBuilderDialog({
<select <select
className={baseInputClass} className={baseInputClass}
value={toSelectValue(options.stylingMode)} value={toSelectValue(options.stylingMode)}
onChange={(event) => setOptionValue('stylingMode', event.target.value)}
title="DevExtreme editor görünüm stili." title="DevExtreme editor görünüm stili."
onChange={(event) => setOptionValue('stylingMode', event.target.value)}
> >
<option value="">Seç</option> <option value="">Seç</option>
<option value="outlined">outlined</option> <option value="outlined">outlined</option>
@ -631,9 +631,9 @@ function EditorOptionsBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={toInputValue(options.hint)} value={toInputValue(options.hint)}
onChange={(event) => setOptionValue('hint', event.target.value)}
placeholder="Tooltip/hint metni" placeholder="Tooltip/hint metni"
title="Editor üzerine gelince gösterilecek hint." title="Editor üzerine gelince gösterilecek hint."
onChange={(event) => setOptionValue('hint', event.target.value)}
/> />
</label> </label>
<label className="text-xs text-gray-500"> <label className="text-xs text-gray-500">
@ -641,9 +641,9 @@ function EditorOptionsBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={toInputValue(options.valueChangeEvent)} value={toInputValue(options.valueChangeEvent)}
onChange={(event) => setOptionValue('valueChangeEvent', event.target.value)}
placeholder="change veya input" placeholder="change veya input"
title="Değer değişimini tetikleyecek DOM event adı. Örnek: change, input, keyup." title="Değer değişimini tetikleyecek DOM event adı. Örnek: change, input, keyup."
onChange={(event) => setOptionValue('valueChangeEvent', event.target.value)}
/> />
</label> </label>
<label className="text-xs text-gray-500"> <label className="text-xs text-gray-500">
@ -651,11 +651,11 @@ function EditorOptionsBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={toInputValue(getByPath(options, 'inputAttr.aria-label'))} value={toInputValue(getByPath(options, 'inputAttr.aria-label'))}
placeholder="Erişilebilir ad"
title="Input için aria-label."
onChange={(event) => onChange={(event) =>
setOptionPathValue('inputAttr.aria-label', event.target.value) setOptionPathValue('inputAttr.aria-label', event.target.value)
} }
placeholder="Erişilebilir ad"
title="Input için aria-label."
/> />
</label> </label>
</div> </div>
@ -674,8 +674,8 @@ function EditorOptionsBuilderDialog({
<select <select
className={baseInputClass} className={baseInputClass}
value={toSelectValue(options.mode)} value={toSelectValue(options.mode)}
onChange={(event) => setOptionValue('mode', event.target.value)}
title="Input mode. TextBox/NumberBox için kullanılabilir." title="Input mode. TextBox/NumberBox için kullanılabilir."
onChange={(event) => setOptionValue('mode', event.target.value)}
> >
<option value="">Seç</option> <option value="">Seç</option>
<option value="text">text</option> <option value="text">text</option>
@ -692,15 +692,15 @@ function EditorOptionsBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={toInputValue(options.maxLength)} value={toInputValue(options.maxLength)}
placeholder="50"
type="number"
title="Maksimum karakter sayısı."
onChange={(event) => onChange={(event) =>
setOptionValue( setOptionValue(
'maxLength', 'maxLength',
event.target.value ? Number(event.target.value) : undefined, event.target.value ? Number(event.target.value) : undefined,
) )
} }
placeholder="50"
type="number"
title="Maksimum karakter sayısı."
/> />
</label> </label>
<label className="text-xs text-gray-500"> <label className="text-xs text-gray-500">
@ -708,9 +708,9 @@ function EditorOptionsBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={toInputValue(options.mask)} value={toInputValue(options.mask)}
onChange={(event) => setOptionValue('mask', event.target.value)}
placeholder="(000) 000-0000" placeholder="(000) 000-0000"
title="TextBox mask değeri." title="TextBox mask değeri."
onChange={(event) => setOptionValue('mask', event.target.value)}
/> />
</label> </label>
<label className="text-xs text-gray-500"> <label className="text-xs text-gray-500">
@ -718,9 +718,9 @@ function EditorOptionsBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={toInputValue(options.maskInvalidMessage)} value={toInputValue(options.maskInvalidMessage)}
onChange={(event) => setOptionValue('maskInvalidMessage', event.target.value)}
placeholder="Geçerli değer girin" placeholder="Geçerli değer girin"
title="Mask geçersiz olduğunda gösterilecek mesaj." title="Mask geçersiz olduğunda gösterilecek mesaj."
onChange={(event) => setOptionValue('maskInvalidMessage', event.target.value)}
/> />
</label> </label>
<label className="text-xs text-gray-500"> <label className="text-xs text-gray-500">
@ -728,8 +728,8 @@ function EditorOptionsBuilderDialog({
<select <select
className={baseInputClass} className={baseInputClass}
value={toSelectValue(options.showMaskMode)} value={toSelectValue(options.showMaskMode)}
onChange={(event) => setOptionValue('showMaskMode', event.target.value)}
title="Mask ne zaman gösterilsin?" title="Mask ne zaman gösterilsin?"
onChange={(event) => setOptionValue('showMaskMode', event.target.value)}
> >
<option value="">Seç</option> <option value="">Seç</option>
<option value="always">always</option> <option value="always">always</option>
@ -741,9 +741,9 @@ function EditorOptionsBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={toInputValue(getByPath(options, 'maskRules.X'))} value={toInputValue(getByPath(options, 'maskRules.X'))}
onChange={(event) => setOptionPathValue('maskRules.X', event.target.value)}
placeholder="[0-9]" placeholder="[0-9]"
title="Custom mask rule. Örnek: X -> [0-9]" title="Custom mask rule. Örnek: X -> [0-9]"
onChange={(event) => setOptionPathValue('maskRules.X', event.target.value)}
/> />
</label> </label>
</div> </div>
@ -763,15 +763,15 @@ function EditorOptionsBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={toInputValue(options[key])} value={toInputValue(options[key])}
placeholder={key === 'step' ? '1' : '0'}
type="number"
title={`${key} numeric option.`}
onChange={(event) => onChange={(event) =>
setOptionValue( setOptionValue(
key, key,
event.target.value ? Number(event.target.value) : undefined, event.target.value ? Number(event.target.value) : undefined,
) )
} }
placeholder={key === 'step' ? '1' : '0'}
type="number"
title={`${key} numeric option.`}
/> />
</label> </label>
))} ))}
@ -780,8 +780,8 @@ function EditorOptionsBuilderDialog({
<select <select
className={baseInputClass} className={baseInputClass}
value={toSelectValue(getByPath(options, 'format.type'))} value={toSelectValue(getByPath(options, 'format.type'))}
onChange={(event) => setOptionPathValue('format.type', event.target.value)}
title="NumberBox format type." title="NumberBox format type."
onChange={(event) => setOptionPathValue('format.type', event.target.value)}
> >
<option value="">Seç</option> <option value="">Seç</option>
<option value="fixedPoint">fixedPoint</option> <option value="fixedPoint">fixedPoint</option>
@ -795,15 +795,15 @@ function EditorOptionsBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={toInputValue(getByPath(options, 'format.precision'))} value={toInputValue(getByPath(options, 'format.precision'))}
placeholder="2"
type="number"
title="Ondalık hassasiyeti."
onChange={(event) => onChange={(event) =>
setOptionPathValue( setOptionPathValue(
'format.precision', 'format.precision',
event.target.value ? Number(event.target.value) : undefined, event.target.value ? Number(event.target.value) : undefined,
) )
} }
placeholder="2"
type="number"
title="Ondalık hassasiyeti."
/> />
</label> </label>
</div> </div>
@ -822,8 +822,8 @@ function EditorOptionsBuilderDialog({
<select <select
className={baseInputClass} className={baseInputClass}
value={toSelectValue(options.type)} value={toSelectValue(options.type)}
onChange={(event) => setOptionValue('type', event.target.value)}
title="DateBox type." title="DateBox type."
onChange={(event) => setOptionValue('type', event.target.value)}
> >
<option value="">Seç</option> <option value="">Seç</option>
<option value="date">date</option> <option value="date">date</option>
@ -836,8 +836,8 @@ function EditorOptionsBuilderDialog({
<select <select
className={baseInputClass} className={baseInputClass}
value={toSelectValue(options.pickerType)} value={toSelectValue(options.pickerType)}
onChange={(event) => setOptionValue('pickerType', event.target.value)}
title="DateBox picker type." title="DateBox picker type."
onChange={(event) => setOptionValue('pickerType', event.target.value)}
> >
<option value="">Seç</option> <option value="">Seç</option>
<option value="calendar">calendar</option> <option value="calendar">calendar</option>
@ -851,9 +851,9 @@ function EditorOptionsBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={toInputValue(options.displayFormat)} value={toInputValue(options.displayFormat)}
onChange={(event) => setOptionValue('displayFormat', event.target.value)}
placeholder="dd/MM/yyyy veya HH:mm" placeholder="dd/MM/yyyy veya HH:mm"
title="DateBox display format." title="DateBox display format."
onChange={(event) => setOptionValue('displayFormat', event.target.value)}
/> />
</label> </label>
<label className="text-xs text-gray-500"> <label className="text-xs text-gray-500">
@ -861,11 +861,11 @@ function EditorOptionsBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={toInputValue(options.dateSerializationFormat)} value={toInputValue(options.dateSerializationFormat)}
placeholder="yyyy-MM-ddTHH:mm:ss"
title="Kaydedilecek date serialization format."
onChange={(event) => onChange={(event) =>
setOptionValue('dateSerializationFormat', event.target.value) setOptionValue('dateSerializationFormat', event.target.value)
} }
placeholder="yyyy-MM-ddTHH:mm:ss"
title="Kaydedilecek date serialization format."
/> />
</label> </label>
<label className="text-xs text-gray-500"> <label className="text-xs text-gray-500">
@ -873,15 +873,15 @@ function EditorOptionsBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={toInputValue(options.interval)} value={toInputValue(options.interval)}
placeholder="5"
type="number"
title="Time list aralığı dakika cinsinden."
onChange={(event) => onChange={(event) =>
setOptionValue( setOptionValue(
'interval', 'interval',
event.target.value ? Number(event.target.value) : undefined, event.target.value ? Number(event.target.value) : undefined,
) )
} }
placeholder="5"
type="number"
title="Time list aralığı dakika cinsinden."
/> />
</label> </label>
<label className="text-xs text-gray-500"> <label className="text-xs text-gray-500">
@ -889,9 +889,9 @@ function EditorOptionsBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={toInputValue(options.invalidDateMessage)} value={toInputValue(options.invalidDateMessage)}
onChange={(event) => setOptionValue('invalidDateMessage', event.target.value)}
placeholder="Geçerli tarih/saat girin" placeholder="Geçerli tarih/saat girin"
title="Geçersiz tarih mesajı." title="Geçersiz tarih mesajı."
onChange={(event) => setOptionValue('invalidDateMessage', event.target.value)}
/> />
</label> </label>
</div> </div>
@ -932,6 +932,8 @@ function EditorOptionsBuilderDialog({
<input <input
className={`${baseInputClass} col-span-4`} className={`${baseInputClass} col-span-4`}
value={option.path} value={option.path}
placeholder="path.to.option"
title="Nokta ile nested path yaz. Örnek: toolbar.multiline"
onChange={(event) => onChange={(event) =>
setCustomOptions((current) => setCustomOptions((current) =>
current.map((item) => current.map((item) =>
@ -939,8 +941,6 @@ function EditorOptionsBuilderDialog({
), ),
) )
} }
placeholder="path.to.option"
title="Nokta ile nested path yaz. Örnek: toolbar.multiline"
/> />
<select <select
className={`${baseInputClass} col-span-2`} className={`${baseInputClass} col-span-2`}
@ -963,6 +963,8 @@ function EditorOptionsBuilderDialog({
<input <input
className={`${baseInputClass} col-span-5`} className={`${baseInputClass} col-span-5`}
value={option.value} value={option.value}
placeholder={option.type === 'boolean' ? 'true / false' : 'value'}
title="Tip JSON ise object/array yazabilirsin. Tip boolean ise true veya false yaz."
onChange={(event) => onChange={(event) =>
setCustomOptions((current) => setCustomOptions((current) =>
current.map((item) => current.map((item) =>
@ -970,8 +972,6 @@ function EditorOptionsBuilderDialog({
), ),
) )
} }
placeholder={option.type === 'boolean' ? 'true / false' : 'value'}
title="Tip JSON ise object/array yazabilirsin. Tip boolean ise true veya false yaz."
/> />
<Button <Button
type="button" type="button"

View file

@ -3,7 +3,7 @@ import { SelectBoxOption } from '@/types/shared'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import Editor from '@monaco-editor/react' import Editor from '@monaco-editor/react'
import { useEffect, useMemo, useState } from 'react' import { useEffect, useMemo, useState } from 'react'
import { FaBolt, FaCheck, FaCode, FaMagic, FaPlus, FaTimes, FaTrash } from 'react-icons/fa' import { FaCheck, FaCode, FaMagic, FaPlus, FaTimes, FaTrash } from 'react-icons/fa'
type CopyMapping = { type CopyMapping = {
id: string id: string
@ -597,12 +597,6 @@ function EditorScriptBuilderDialog({
setAmountTotalField((current) => current || findField('TotalAmount')) setAmountTotalField((current) => current || findField('TotalAmount'))
} }
const fillTimeDefaults = () => {
setTimeStartField((current) => current || findField('StartTime'))
setTimeEndField((current) => current || findField('EndTime'))
setTimeTargetField((current) => current || findField('TotalHours'))
}
const resetBuilderSelections = () => { const resetBuilderSelections = () => {
setCopyMappings([]) setCopyMappings([])
setDaysStartField('') setDaysStartField('')
@ -834,12 +828,12 @@ function EditorScriptBuilderDialog({
return ( return (
<Dialog <Dialog
preventScroll
isOpen={isOpen} isOpen={isOpen}
width={1100} width={1100}
height="82vh" height="82vh"
contentClassName="flex flex-col" contentClassName="flex flex-col"
style={{ overlay: { zIndex: 1300 } }} style={{ overlay: { zIndex: 1300 } }}
preventScroll
onClose={onClose} onClose={onClose}
onRequestClose={onClose} onRequestClose={onClose}
> >
@ -898,6 +892,8 @@ function EditorScriptBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={mapping.source} value={mapping.source}
placeholder="Örn: unitPrice veya Customer.Name"
title="Seçilen kayıttaki kolon/path. Örnek: Quantity, UnitPrice, Customer.Name"
onChange={(event) => onChange={(event) =>
setCopyMappings((current) => setCopyMappings((current) =>
current.map((item) => current.map((item) =>
@ -907,8 +903,6 @@ function EditorScriptBuilderDialog({
), ),
) )
} }
placeholder="Örn: unitPrice veya Customer.Name"
title="Seçilen kayıttaki kolon/path. Örnek: Quantity, UnitPrice, Customer.Name"
/> />
</label> </label>
<div className="col-span-12 md:col-span-5"> <div className="col-span-12 md:col-span-5">
@ -1012,11 +1006,11 @@ function EditorScriptBuilderDialog({
action.operator === 'empty' || action.operator === 'empty' ||
action.operator === 'notEmpty' action.operator === 'notEmpty'
} }
placeholder="Örn: Aktif, 1000"
title="Koşulda kullanılacak sabit değer. Örnek: Aktif, 0, True"
onChange={(event) => onChange={(event) =>
updateConditionalAction(action.id, { value: event.target.value }) updateConditionalAction(action.id, { value: event.target.value })
} }
placeholder="Örn: Aktif, 1000"
title="Koşulda kullanılacak sabit değer. Örnek: Aktif, 0, True"
/> />
</label> </label>
<div className={actionIconCellClass}> <div className={actionIconCellClass}>
@ -1054,7 +1048,7 @@ function EditorScriptBuilderDialog({
<option value="confirm">Onay iste</option> <option value="confirm">Onay iste</option>
<option value="calculate">Formül hesapla</option> <option value="calculate">Formül hesapla</option>
<option value="setReadOnly">ReadOnly ayarla</option> <option value="setReadOnly">ReadOnly ayarla</option>
<option value="apiToField">API sonucunu field'a yaz</option> <option value="apiToField">API sonucunu field&apos;a yaz</option>
</select> </select>
</label> </label>
@ -1077,11 +1071,11 @@ function EditorScriptBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={action.textValue} value={action.textValue}
placeholder="text, {Field} or {selected.Name}"
title="Sabit metin veya token yaz. Örnek: {Name}, {value}, {selected.DisplayName}"
onChange={(event) => onChange={(event) =>
updateConditionalAction(action.id, { textValue: event.target.value }) updateConditionalAction(action.id, { textValue: event.target.value })
} }
placeholder="text, {Field} or {selected.Name}"
title="Sabit metin veya token yaz. Örnek: {Name}, {value}, {selected.DisplayName}"
/> />
</label> </label>
)} )}
@ -1129,11 +1123,11 @@ function EditorScriptBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={action.apiUrl} value={action.apiUrl}
placeholder="/api/path/{Id}"
title="Token kullanabilirsin: /api/orders/{OrderId}, /api/x/{selected.Id}, /api/y/{value}"
onChange={(event) => onChange={(event) =>
updateConditionalAction(action.id, { apiUrl: event.target.value }) updateConditionalAction(action.id, { apiUrl: event.target.value })
} }
placeholder="/api/path/{Id}"
title="Token kullanabilirsin: /api/orders/{OrderId}, /api/x/{selected.Id}, /api/y/{value}"
/> />
</label> </label>
<label className={`${fieldLabelClass} col-span-12 md:col-span-3`}> <label className={`${fieldLabelClass} col-span-12 md:col-span-3`}>
@ -1141,13 +1135,13 @@ function EditorScriptBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={action.responsePath} value={action.responsePath}
placeholder="data.value"
title="API JSON cevabından okunacak path. Boş bırakırsan tüm JSON hedef field'a yazılır."
onChange={(event) => onChange={(event) =>
updateConditionalAction(action.id, { updateConditionalAction(action.id, {
responsePath: event.target.value, responsePath: event.target.value,
}) })
} }
placeholder="data.value"
title="API JSON cevabından okunacak path. Boş bırakırsan tüm JSON hedef field'a yazılır."
/> />
</label> </label>
</> </>
@ -1160,13 +1154,13 @@ function EditorScriptBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={action.textValue} value={action.textValue}
placeholder="/report?id={Id}&type={selected.Type}"
title="Açılacak URL. Token destekler: {Id}, {value}, {selected.Type}"
onChange={(event) => onChange={(event) =>
updateConditionalAction(action.id, { updateConditionalAction(action.id, {
textValue: event.target.value, textValue: event.target.value,
}) })
} }
placeholder="/report?id={Id}&type={selected.Type}"
title="Açılacak URL. Token destekler: {Id}, {value}, {selected.Type}"
/> />
</label> </label>
<label className={`${fieldLabelClass} col-span-12 md:col-span-2`}> <label className={`${fieldLabelClass} col-span-12 md:col-span-2`}>
@ -1194,11 +1188,11 @@ function EditorScriptBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={action.message} value={action.message}
placeholder="{Field} tokenları ile mesaj"
title="Alert/confirm mesajı. Token destekler: {Name}, {value}, {selected.Name}"
onChange={(event) => onChange={(event) =>
updateConditionalAction(action.id, { message: event.target.value }) updateConditionalAction(action.id, { message: event.target.value })
} }
placeholder="{Field} tokenları ile mesaj"
title="Alert/confirm mesajı. Token destekler: {Name}, {value}, {selected.Name}"
/> />
</label> </label>
)} )}
@ -1209,11 +1203,11 @@ function EditorScriptBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={action.formula} value={action.formula}
placeholder="Number(data.Quantity || 0) * Number(data.UnitPrice || 0)"
title="JavaScript expression yaz. data=formData, selected=selectedItem, value=e.value olarak kullanılır."
onChange={(event) => onChange={(event) =>
updateConditionalAction(action.id, { formula: event.target.value }) updateConditionalAction(action.id, { formula: event.target.value })
} }
placeholder="Number(data.Quantity || 0) * Number(data.UnitPrice || 0)"
title="JavaScript expression yaz. data=formData, selected=selectedItem, value=e.value olarak kullanılır."
/> />
</label> </label>
)} )}
@ -1292,9 +1286,9 @@ function EditorScriptBuilderDialog({
<input <input
className={baseInputClass} className={baseInputClass}
value={serviceCall} value={serviceCall}
onChange={(event) => setServiceCall(event.target.value)}
placeholder="UiEvalService.ApiGenerateBackgroundWorkers();" placeholder="UiEvalService.ApiGenerateBackgroundWorkers();"
title="Global servis çağrısı. Örnek: UiEvalService.ApiGenerateBackgroundWorkers();" title="Global servis çağrısı. Örnek: UiEvalService.ApiGenerateBackgroundWorkers();"
onChange={(event) => setServiceCall(event.target.value)}
/> />
</div> </div>
</section> </section>
@ -1340,7 +1334,6 @@ function EditorScriptBuilderDialog({
language="typescript" language="typescript"
theme="vs-dark" theme="vs-dark"
value={scriptEditorValue} value={scriptEditorValue}
onChange={(nextValue) => setScriptEditorValue(nextValue || '')}
options={{ options={{
automaticLayout: true, automaticLayout: true,
fontSize: 12, fontSize: 12,
@ -1349,6 +1342,7 @@ function EditorScriptBuilderDialog({
tabSize: 2, tabSize: 2,
wordWrap: 'on', wordWrap: 'on',
}} }}
onChange={(nextValue) => setScriptEditorValue(nextValue || '')}
/> />
</div> </div>
</section> </section>

View file

@ -88,10 +88,10 @@ function JsonRowOpDialogAnnotation({
id="annotationOperation" id="annotationOperation"
isOpen={isOpen} isOpen={isOpen}
preventScroll={true} preventScroll={true}
onClose={handleClose}
onRequestClose={handleClose}
width={900} width={900}
height="90vh" height="90vh"
onClose={handleClose}
onRequestClose={handleClose}
> >
{(data.operation === 'create' || data.operation === 'update') && ( {(data.operation === 'create' || data.operation === 'update') && (
<Formik <Formik

View file

@ -16,7 +16,7 @@ import { useStoreActions } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { Field, FieldArray, FieldProps, Form, Formik } from 'formik' import { Field, FieldArray, FieldProps, Form, Formik } from 'formik'
import groupBy from 'lodash/groupBy' import groupBy from 'lodash/groupBy'
import { Dispatch, SetStateAction, useEffect, useState } from 'react' import { Dispatch, SetStateAction, useCallback, useEffect, useState } from 'react'
import { FaBolt, FaCalendarMinus, FaCalendarPlus, FaSlidersH, FaTag } from 'react-icons/fa' import { FaBolt, FaCalendarMinus, FaCalendarPlus, FaSlidersH, FaTag } from 'react-icons/fa'
import { number, object, string } from 'yup' import { number, object, string } from 'yup'
import { import {
@ -82,7 +82,7 @@ function JsonRowOpDialogEditForm({
const [scriptBuilderIndex, setScriptBuilderIndex] = useState<number | null>(null) const [scriptBuilderIndex, setScriptBuilderIndex] = useState<number | null>(null)
const [isHelperOpen, setIsHelperOpen] = useState(false) const [isHelperOpen, setIsHelperOpen] = useState(false)
const getFields = async () => { const getFields = useCallback(async () => {
if (!listFormCode) { if (!listFormCode) {
return return
} }
@ -113,7 +113,7 @@ function JsonRowOpDialogEditForm({
}, },
) )
} }
} }, [listFormCode])
const handleClose = async (e?: any) => { const handleClose = async (e?: any) => {
if (e) { if (e) {
@ -133,7 +133,7 @@ function JsonRowOpDialogEditForm({
if (isOpen && data) { if (isOpen && data) {
getFields() getFields()
} }
}, [isOpen, data]) }, [isOpen, data, getFields])
if (!data || !fieldList?.length) { if (!data || !fieldList?.length) {
return null return null
@ -279,10 +279,10 @@ function JsonRowOpDialogEditForm({
<Dialog <Dialog
isOpen={isHelperOpen} isOpen={isHelperOpen}
onClose={() => setIsHelperOpen(false)}
onRequestClose={() => setIsHelperOpen(false)}
preventScroll={true} preventScroll={true}
width={1000} width={1000}
onClose={() => setIsHelperOpen(false)}
onRequestClose={() => setIsHelperOpen(false)}
> >
<h5 className="mb-4">Helper</h5> <h5 className="mb-4">Helper</h5>
@ -396,11 +396,11 @@ function JsonRowOpDialogEditForm({
) )
: null : null
} }
menuPlacement="auto"
maxMenuHeight={150}
onChange={(option) => onChange={(option) =>
form.setFieldValue(field.name, option?.value) form.setFieldValue(field.name, option?.value)
} }
menuPlacement="auto"
maxMenuHeight={150}
/> />
)} )}
</Field> </Field>
@ -422,12 +422,12 @@ function JsonRowOpDialogEditForm({
(option) => (option) =>
option.value === values.items?.at(index)?.editorType2, option.value === values.items?.at(index)?.editorType2,
)} )}
onChange={(option) =>
form.setFieldValue(field.name, option?.value)
}
className="flex-1" className="flex-1"
menuPlacement="auto" menuPlacement="auto"
maxMenuHeight={150} maxMenuHeight={150}
onChange={(option) =>
form.setFieldValue(field.name, option?.value)
}
/> />
)} )}
</Field> </Field>

View file

@ -10,10 +10,10 @@ import {
} from '@/components/ui' } from '@/components/ui'
import { ListFormJsonRowDto } from '@/proxy/admin/list-form/models' import { ListFormJsonRowDto } from '@/proxy/admin/list-form/models'
import { SelectBoxOption } from '@/types/shared' import { SelectBoxOption } from '@/types/shared'
import { useStoreActions, useStoreState } from '@/store' import { useStoreActions } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { Field, FieldProps, Form, Formik } from 'formik' import { Field, FieldProps, Form, Formik } from 'formik'
import { Dispatch, SetStateAction, useEffect, useState } from 'react' import { Dispatch, SetStateAction, useCallback, useEffect, useState } from 'react'
import { object, string } from 'yup' import { object, string } from 'yup'
import { JsonRowDialogData } from './types' import { JsonRowDialogData } from './types'
import { import {
@ -22,10 +22,10 @@ import {
postListFormJsonRow, postListFormJsonRow,
putListFormJsonRow, putListFormJsonRow,
} from '@/services/admin/list-form.service' } from '@/services/admin/list-form.service'
import { cascadeFilterOperator, colSpanOptions } from '../options' import { cascadeFilterOperator } from '../options'
import CreatableSelect from 'react-select/creatable' import CreatableSelect from 'react-select/creatable'
import { getListFormFields } from '@/services/admin/list-form-field.service' import { getListFormFields } from '@/services/admin/list-form-field.service'
import { groupBy } from 'lodash' import groupBy from 'lodash/groupBy'
import { extraFilterControlTypeOptions } from '@/proxy/admin/list-form/options' import { extraFilterControlTypeOptions } from '@/proxy/admin/list-form/options'
const schema = object().shape({ const schema = object().shape({
@ -73,7 +73,7 @@ function JsonRowOpDialogExtraFilter({
setIsOpen(false) setIsOpen(false)
} }
const getFields = async () => { const getFields = useCallback(async () => {
if (!listFormCode) { if (!listFormCode) {
return return
} }
@ -104,13 +104,13 @@ function JsonRowOpDialogExtraFilter({
}, },
) )
} }
} }, [listFormCode])
useEffect(() => { useEffect(() => {
if (isOpen && data) { if (isOpen && data) {
getFields() getFields()
} }
}, [isOpen, data]) }, [isOpen, data, getFields])
if (!data || !fieldList?.length) { if (!data || !fieldList?.length) {
return null return null
@ -121,9 +121,9 @@ function JsonRowOpDialogExtraFilter({
id="extraFilterOperation" id="extraFilterOperation"
isOpen={isOpen} isOpen={isOpen}
preventScroll={true} preventScroll={true}
width={data.operation === 'create' || data.operation === 'update' ? 'sm' : '450px'}
onClose={handleClose} onClose={handleClose}
onRequestClose={handleClose} onRequestClose={handleClose}
width={data.operation === 'create' || data.operation === 'update' ? 'sm' : '450px'}
> >
{(data.operation === 'create' || data.operation === 'update') && ( {(data.operation === 'create' || data.operation === 'update') && (
<> <>

View file

@ -5,15 +5,13 @@ import {
FormItem, FormItem,
Input, Input,
Notification, Notification,
Select,
Tabs,
toast, toast,
} from '@/components/ui' } from '@/components/ui'
import { ListFormJsonRowDto } from '@/proxy/admin/list-form/models' import { ListFormJsonRowDto } from '@/proxy/admin/list-form/models'
import { useStoreActions } from '@/store' import { useStoreActions } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { Field, FieldProps, Form, Formik } from 'formik' import { Field, FieldProps, Form, Formik } from 'formik'
import { Dispatch, SetStateAction, useEffect, useState } from 'react' import { Dispatch, SetStateAction } from 'react'
import { number, object, string } from 'yup' import { number, object, string } from 'yup'
import { JsonRowDialogData } from './types' import { JsonRowDialogData } from './types'
import { import {
@ -114,7 +112,7 @@ function JsonRowOpDialogPane({
} }
}} }}
> >
{({ touched, errors, values, isSubmitting }) => ( {({ touched, errors, isSubmitting }) => (
<Form> <Form>
<FormContainer size="sm"> <FormContainer size="sm">
<div className="h-full overflow-y-auto p-2"> <div className="h-full overflow-y-auto p-2">

View file

@ -14,7 +14,7 @@ import { SelectBoxOption } from '@/types/shared'
import { useStoreActions, useStoreState } from '@/store' import { useStoreActions, useStoreState } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { Field, FieldProps, Form, Formik } from 'formik' import { Field, FieldProps, Form, Formik } from 'formik'
import { Dispatch, SetStateAction, useEffect, useState } from 'react' import { Dispatch, SetStateAction } from 'react'
import { boolean, number, object, string } from 'yup' import { boolean, number, object, string } from 'yup'
import { JsonRowDialogData } from './types' import { JsonRowDialogData } from './types'
import { import {
@ -30,7 +30,6 @@ import {
columnSummaryTypeListOptions, columnSummaryTypeListOptions,
} from '../options' } from '../options'
import { ChartPanesDto, ChartValueAxisDto } from '@/proxy/admin/charts/models' import { ChartPanesDto, ChartValueAxisDto } from '@/proxy/admin/charts/models'
import CreatableSelect from 'react-select/creatable'
import { tooltipFormatListOptions } from '@/proxy/admin/list-form/options' import { tooltipFormatListOptions } from '@/proxy/admin/list-form/options'
const schema = object().shape({ const schema = object().shape({
@ -129,10 +128,10 @@ function JsonRowOpDialogSeries({
id="paneOperation" id="paneOperation"
isOpen={isOpen} isOpen={isOpen}
preventScroll={true} preventScroll={true}
onClose={handleClose}
onRequestClose={handleClose}
width={900} width={900}
height="90vh" height="90vh"
onClose={handleClose}
onRequestClose={handleClose}
> >
{(data.operation === 'create' || data.operation === 'update') && ( {(data.operation === 'create' || data.operation === 'update') && (
<Formik <Formik
@ -282,9 +281,9 @@ function JsonRowOpDialogSeries({
value={fieldList?.find( value={fieldList?.find(
(option) => option.value === values.argumentField, (option) => option.value === values.argumentField,
)} )}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
menuPlacement="auto" menuPlacement="auto"
maxMenuHeight={150} maxMenuHeight={150}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
/> />
)} )}
</Field> </Field>
@ -303,9 +302,9 @@ function JsonRowOpDialogSeries({
isClearable={true} isClearable={true}
options={fieldList} options={fieldList}
value={fieldList?.find((option) => option.value === values.valueField)} value={fieldList?.find((option) => option.value === values.valueField)}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
menuPlacement="auto" menuPlacement="auto"
maxMenuHeight={150} maxMenuHeight={150}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
/> />
)} )}
</Field> </Field>

View file

@ -122,7 +122,7 @@ function JsonRowOpDialogSubForm({
} }
loadData() loadData()
}, [isOpen, listFormValues?.listFormCode]) }, [isOpen, listFormValues?.listFormCode, translate])
useEffect(() => { useEffect(() => {
if (isOpen) { if (isOpen) {

View file

@ -12,10 +12,10 @@ import {
import SqlEditor from '@/views/developerKit/SqlEditor' import SqlEditor from '@/views/developerKit/SqlEditor'
import { ListFormJsonRowDto } from '@/proxy/admin/list-form/models' import { ListFormJsonRowDto } from '@/proxy/admin/list-form/models'
import { SelectBoxOption } from '@/types/shared' import { SelectBoxOption } from '@/types/shared'
import { useStoreActions, useStoreState } from '@/store' import { useStoreActions } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { Field, FieldProps, Form, Formik } from 'formik' import { Field, FieldProps, Form, Formik } from 'formik'
import { Dispatch, SetStateAction, useEffect, useState } from 'react' import { Dispatch, SetStateAction } from 'react'
import { number, object, string } from 'yup' import { number, object, string } from 'yup'
import { JsonRowDialogData } from './types' import { JsonRowDialogData } from './types'
import { import {
@ -77,10 +77,10 @@ function JsonRowOpDialogWidget({
id="widgetOperation" id="widgetOperation"
isOpen={isOpen} isOpen={isOpen}
preventScroll={true} preventScroll={true}
onClose={handleClose}
onRequestClose={handleClose}
width={data.operation === 'create' || data.operation === 'update' ? 900 : 450} width={data.operation === 'create' || data.operation === 'update' ? 900 : 450}
height="90vh" height="90vh"
onClose={handleClose}
onRequestClose={handleClose}
> >
{(data.operation === 'create' || data.operation === 'update') && ( {(data.operation === 'create' || data.operation === 'update') && (
<Formik <Formik
@ -243,13 +243,9 @@ function JsonRowOpDialogWidget({
<div className="space-y-3"> <div className="space-y-3">
<div> <div>
<code className="text-xs bg-gray-800 p-1 rounded block mt-1"> <code className="text-xs bg-gray-800 p-1 rounded block mt-1">
SELECT 'Aktif' as title, COUNT(Id) as value, {
<br /> "SELECT 'Aktif' as title, COUNT(Id) as value, 'blue' as color, 'FaChartBar' as icon, 'Aktif kayıtlar' as subTitle FROM YourTable WHERE IsActive = 1"
&nbsp;&nbsp;'blue' as color, 'FaChartBar' as icon, }
<br />
&nbsp;&nbsp;'Aktif kayıtlar' as subTitle
<br />
FROM YourTable WHERE IsActive = 1
</code> </code>
</div> </div>
</div> </div>
@ -269,8 +265,8 @@ function JsonRowOpDialogWidget({
> >
<SqlEditor <SqlEditor
value={values.sqlQuery || ''} value={values.sqlQuery || ''}
onChange={(value) => setFieldValue('sqlQuery', value || '')}
height="35vh" height="35vh"
onChange={(value) => setFieldValue('sqlQuery', value || '')}
/> />
</div> </div>
</FormItem> </FormItem>

View file

@ -10,7 +10,6 @@ import { useLocation, useNavigate } from 'react-router-dom'
import * as Yup from 'yup' import * as Yup from 'yup'
import { getMenus } from '@/services/menu.service' import { getMenus } from '@/services/menu.service'
import { getPermissions } from '@/services/identity.service' import { getPermissions } from '@/services/identity.service'
import { DbTypeEnum, SelectCommandTypeEnum } from '@/proxy/form/models'
import { getDataSources } from '@/services/data-source.service' import { getDataSources } from '@/services/data-source.service'
import { sqlObjectManagerService } from '@/services/sql-query-manager.service' import { sqlObjectManagerService } from '@/services/sql-query-manager.service'
import type { SqlObjectExplorerDto, DatabaseColumnDto } from '@/proxy/sql-query-manager/models' import type { SqlObjectExplorerDto, DatabaseColumnDto } from '@/proxy/sql-query-manager/models'
@ -32,13 +31,15 @@ import { Container } from '@/components/shared'
import { sqlDataTypeToDbType } from '../edit/options' import { sqlDataTypeToDbType } from '../edit/options'
import { useStoreActions } from '@/store/store' import { useStoreActions } from '@/store/store'
import { deleteWizardFile, getWizardFile, postListFormWizard } from '@/services/wizard.service' import { deleteWizardFile, getWizardFile, postListFormWizard } from '@/services/wizard.service'
import { UiLookupDataSourceTypeEnum } from '@/proxy/form/models'
import { ListFormWizardDto } from '@/proxy/admin/wizard/models' import { ListFormWizardDto } from '@/proxy/admin/wizard/models'
import { import {
ListFormWorkflowCriteriaDto, ListFormWorkflowCriteriaDto,
SubFormDto, SubFormDto,
WidgetEditDto, WidgetEditDto,
WorkflowDto, WorkflowDto,
UiLookupDataSourceTypeEnum,
DbTypeEnum,
SelectCommandTypeEnum,
} from '@/proxy/form/models' } from '@/proxy/form/models'
// ─── Formik initial values & validation ────────────────────────────────────── // ─── Formik initial values & validation ──────────────────────────────────────
@ -271,7 +272,9 @@ const Wizard = () => {
setSelectCommandColumns(cols) setSelectCommandColumns(cols)
const colNames = new Set(cols.map((c) => c.columnName.toLowerCase())) const colNames = new Set(cols.map((c) => c.columnName.toLowerCase()))
const hasTenantColumn = colNames.has('tenantid') const hasTenantColumn = colNames.has('tenantid')
const selectableColumns = cols.filter((c) => isAutoSelectedColumn(c.columnName, hasTenantColumn)) const selectableColumns = cols.filter((c) =>
isAutoSelectedColumn(c.columnName, hasTenantColumn),
)
setSelectedColumns(new Set(selectableColumns.map((c) => c.columnName))) setSelectedColumns(new Set(selectableColumns.map((c) => c.columnName)))
setEditingGroups([]) setEditingGroups([])
// Auto-check isTenant / isBranch based on column presence // Auto-check isTenant / isBranch based on column presence
@ -297,7 +300,11 @@ const Wizard = () => {
const toggleColumn = (col: string) => const toggleColumn = (col: string) =>
setSelectedColumns((prev) => { setSelectedColumns((prev) => {
const next = new Set(prev) const next = new Set(prev)
next.has(col) ? next.delete(col) : next.add(col) if (next.has(col)) {
next.delete(col)
} else {
next.add(col)
}
return next return next
}) })
@ -548,7 +555,8 @@ const Wizard = () => {
const previousSpacedLabel = toSpacedLabel(formik?.values.wizardName ?? '') const previousSpacedLabel = toSpacedLabel(formik?.values.wizardName ?? '')
const derived = deriveListFormCode(name) const derived = deriveListFormCode(name)
const setAutoText = (field: keyof Pick< const setAutoText = (
field: keyof Pick<
ListFormWizardDto, ListFormWizardDto,
| 'languageTextMenuEn' | 'languageTextMenuEn'
| 'languageTextMenuTr' | 'languageTextMenuTr'
@ -556,7 +564,8 @@ const Wizard = () => {
| 'languageTextTitleTr' | 'languageTextTitleTr'
| 'languageTextDescEn' | 'languageTextDescEn'
| 'languageTextDescTr' | 'languageTextDescTr'
>) => { >,
) => {
const current = formik?.values[field] const current = formik?.values[field]
if (!current || current === previousSpacedLabel) { if (!current || current === previousSpacedLabel) {
formik?.setFieldValue(field, spacedLabel) formik?.setFieldValue(field, spacedLabel)
@ -789,7 +798,7 @@ const Wizard = () => {
setSubmitting(false) setSubmitting(false)
}} }}
> >
{({ touched, errors, isSubmitting, values }) => ( {({ touched, errors, values }) => (
<Form onKeyDown={preventEnterSubmit}> <Form onKeyDown={preventEnterSubmit}>
<FormContainer size={currentStep >= 2 ? undefined : 'sm'}> <FormContainer size={currentStep >= 2 ? undefined : 'sm'}>
{/* ─── Step 1: Basic Info ─────────────────────────────── */} {/* ─── Step 1: Basic Info ─────────────────────────────── */}
@ -856,7 +865,6 @@ const Wizard = () => {
groups={editingGroups} groups={editingGroups}
onGroupsChange={setEditingGroups} onGroupsChange={setEditingGroups}
dbObjects={dbObjects} dbObjects={dbObjects}
isLoadingDbObjects={isLoadingDbObjects}
dsCode={currentDataSource} dsCode={currentDataSource}
translate={translate} translate={translate}
onBack={() => setCurrentStep(1)} onBack={() => setCurrentStep(1)}

View file

@ -321,7 +321,8 @@ function MenuTreeInline({
const toggle = (code: string) => const toggle = (code: string) =>
setExpanded((prev) => { setExpanded((prev) => {
const n = new Set(prev) const n = new Set(prev)
n.has(code) ? n.delete(code) : n.add(code) if (n.has(code)) n.delete(code)
else n.add(code)
return n return n
}) })

View file

@ -64,7 +64,6 @@ export interface WizardStep3Props {
groups: WizardGroup[] groups: WizardGroup[]
onGroupsChange: (groups: WizardGroup[]) => void onGroupsChange: (groups: WizardGroup[]) => void
dbObjects: SqlObjectExplorerDto | null dbObjects: SqlObjectExplorerDto | null
isLoadingDbObjects: boolean
dsCode: string dsCode: string
translate: (key: string) => string translate: (key: string) => string
onBack: () => void onBack: () => void
@ -794,7 +793,6 @@ const WizardStep3 = ({
groups, groups,
onGroupsChange, onGroupsChange,
dbObjects, dbObjects,
isLoadingDbObjects: _isLoadingDbObjects,
dsCode, dsCode,
translate, translate,
onBack, onBack,

Some files were not shown because too many files have changed in this diff Show more