Optimizasyon değişimleri
This commit is contained in:
parent
e96498645a
commit
bab639ce63
184 changed files with 1470 additions and 3008 deletions
|
|
@ -44,7 +44,7 @@
|
|||
"code": "App.SiteManagement.Theme.Style",
|
||||
"nameKey": "App.SiteManagement.Theme.Style",
|
||||
"descriptionKey": "App.SiteManagement.Theme.Style.Description",
|
||||
"defaultValue": "dx.material.blue.light.compact",
|
||||
"defaultValue": "dx.material.blue.dark.compact",
|
||||
"isVisibleToClients": true,
|
||||
"providers": "U|G|D",
|
||||
"isInherited": false,
|
||||
|
|
|
|||
|
|
@ -10254,6 +10254,12 @@
|
|||
"en": "Active",
|
||||
"tr": "Aktif"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Status.Inactive",
|
||||
"en": "Inactive",
|
||||
"tr": "Pasif"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.DeveloperKit.ComponentEditor.Save",
|
||||
|
|
|
|||
|
|
@ -13,9 +13,7 @@ interface ComponentCodeEditorProps {
|
|||
onResetCodeChanges: () => void
|
||||
language?: string
|
||||
theme?: 'vs-dark' | 'light'
|
||||
parseError?: string | null
|
||||
onCursorChange?: (componentId: string | null) => void
|
||||
onDrop?: (componentDef: ComponentDefinition, position: { line: number; column: number }) => void
|
||||
onComponentAdded?: (componentDef: ComponentDefinition) => void
|
||||
onComponentSave: () => void
|
||||
}
|
||||
|
|
@ -24,6 +22,7 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
|
|||
code,
|
||||
onChange,
|
||||
onApplyCodeChanges,
|
||||
onResetCodeChanges,
|
||||
language = 'typescript',
|
||||
theme = 'vs-dark',
|
||||
onCursorChange,
|
||||
|
|
@ -48,7 +47,6 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
|
|||
|
||||
const editorRef = useRef<any>(null)
|
||||
const containerRef = useRef<HTMLDivElement>(null)
|
||||
const cursorChangeTimeout = useRef<number | null>(null)
|
||||
// Refs to keep latest values accessible inside native DOM listeners
|
||||
const localCodeRef = useRef(localCode)
|
||||
const dropCallbacksRef = useRef({ onChange, onComponentAdded, onApplyCodeChanges })
|
||||
|
|
@ -66,14 +64,6 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
|
|||
dropCallbacksRef.current = { onChange, onComponentAdded, onApplyCodeChanges }
|
||||
}, [onChange, onComponentAdded, onApplyCodeChanges])
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (cursorChangeTimeout.current) {
|
||||
clearTimeout(cursorChangeTimeout.current)
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
const findComponentIdAtPosition = (
|
||||
code: string,
|
||||
position: { lineNumber: number; column: number },
|
||||
|
|
@ -169,7 +159,10 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
|
|||
if (ch === '(') parenDepth++
|
||||
else if (ch === ')') {
|
||||
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++
|
||||
else if (ch === ')') {
|
||||
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
|
||||
}
|
||||
|
||||
const handleEditorCursorChange = (_event: any) => {
|
||||
const handleEditorCursorChange = () => {
|
||||
if (!editorRef.current) return
|
||||
const position = editorRef.current.getPosition()
|
||||
if (!position) return
|
||||
|
||||
// Throttle the cursor change to avoid too many calls
|
||||
if (cursorChangeTimeout.current) {
|
||||
clearTimeout(cursorChangeTimeout.current)
|
||||
}
|
||||
const id = findComponentIdAtPosition(localCode, position)
|
||||
if (onCursorChange) onCursorChange(id)
|
||||
}
|
||||
|
|
@ -242,12 +234,19 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
|
|||
let componentDefData: string | undefined
|
||||
for (const fmt of ['application/json', 'text/plain']) {
|
||||
const d = nativeEvent.dataTransfer.getData(fmt)
|
||||
if (d) { componentDefData = d; break }
|
||||
if (d) {
|
||||
componentDefData = d
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!componentDefData) return
|
||||
|
||||
let componentDef: any
|
||||
try { componentDef = JSON.parse(componentDefData) } catch { return }
|
||||
try {
|
||||
componentDef = JSON.parse(componentDefData)
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
if (!componentDef?.name) return
|
||||
|
||||
// Resolve the drop position inside Monaco
|
||||
|
|
@ -300,8 +299,11 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
|
|||
const newCode = newLines.join('\n')
|
||||
|
||||
setLocalCode(newCode)
|
||||
const { onChange: onChg, onComponentAdded: onAdded, onApplyCodeChanges: onApply } =
|
||||
dropCallbacksRef.current
|
||||
const {
|
||||
onChange: onChg,
|
||||
onComponentAdded: onAdded,
|
||||
onApplyCodeChanges: onApply,
|
||||
} = dropCallbacksRef.current
|
||||
onChg(newCode)
|
||||
if (onAdded) onAdded(componentDefWithId)
|
||||
setTimeout(() => onApply(newCode), 100)
|
||||
|
|
@ -346,6 +348,7 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
|
|||
const handleResetChanges = () => {
|
||||
setLocalCode(code)
|
||||
setHasChanges(false)
|
||||
onResetCodeChanges()
|
||||
}
|
||||
|
||||
// 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="flex items-center gap-2">
|
||||
<Button
|
||||
onClick={handleFormatCode}
|
||||
loading={isFormatting}
|
||||
icon={<FaCode className="w-4 h-4" />}
|
||||
variant="default"
|
||||
size="sm"
|
||||
onClick={handleFormatCode}
|
||||
>
|
||||
Formatla
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={() => setShowSettings(!showSettings)}
|
||||
icon={<FaCog className="w-4 h-4" />}
|
||||
variant={showSettings ? 'solid' : 'default'}
|
||||
color="blue-600"
|
||||
size="sm"
|
||||
onClick={() => setShowSettings(!showSettings)}
|
||||
>
|
||||
Ayarlar
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={handleResetChanges}
|
||||
icon={<FaTimes className="w-4 h-4" />}
|
||||
variant="solid"
|
||||
color="red-600"
|
||||
size="sm"
|
||||
onClick={handleResetChanges}
|
||||
>
|
||||
Sıfırla
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={handleApplyChanges}
|
||||
icon={<FaCheck className="w-4 h-4" />}
|
||||
variant="solid"
|
||||
color="green-600"
|
||||
size="sm"
|
||||
onClick={handleApplyChanges}
|
||||
>
|
||||
Uygula
|
||||
</Button>
|
||||
</div>
|
||||
<div className="col-span-2 flex items-center justify-end">
|
||||
<Button
|
||||
onClick={onComponentSave}
|
||||
icon={<FaSave className="w-4 h-4" />}
|
||||
variant="solid"
|
||||
color="yellow-600"
|
||||
size="sm"
|
||||
className="shadow-sm"
|
||||
onClick={onComponentSave}
|
||||
>
|
||||
Kaydet
|
||||
</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>
|
||||
<select
|
||||
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"
|
||||
onChange={(e) => setEditorTheme(e.target.value as 'vs-dark' | 'light')}
|
||||
>
|
||||
<option value="vs-dark">Koyu</option>
|
||||
<option value="light">Açık</option>
|
||||
|
|
@ -637,8 +640,8 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
|
|||
min="10"
|
||||
max="24"
|
||||
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"
|
||||
onChange={(e) => setFontSize(parseInt(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
@ -648,8 +651,8 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
|
|||
</label>
|
||||
<select
|
||||
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"
|
||||
onChange={(e) => setWordWrap(e.target.value as 'on' | 'off')}
|
||||
>
|
||||
<option value="on">Açık</option>
|
||||
<option value="off">Kapalı</option>
|
||||
|
|
@ -659,11 +662,11 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
|
|||
<div>
|
||||
<label className="block text-sm font-medium text-gray-300 mb-2">Mini Harita</label>
|
||||
<Button
|
||||
onClick={() => setMinimap(!minimap)}
|
||||
block
|
||||
variant={minimap ? 'solid' : 'default'}
|
||||
color="blue-600"
|
||||
size="sm"
|
||||
onClick={() => setMinimap(!minimap)}
|
||||
>
|
||||
{minimap ? 'Etkin' : 'Devre Dışı'}
|
||||
</Button>
|
||||
|
|
@ -680,8 +683,6 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
|
|||
language={language}
|
||||
theme={editorTheme}
|
||||
value={localCode}
|
||||
onChange={handleCodeChange}
|
||||
onMount={handleEditorDidMount}
|
||||
options={{
|
||||
fontSize: fontSize,
|
||||
wordWrap: wordWrap,
|
||||
|
|
@ -748,6 +749,8 @@ export const ComponentCodeEditor: React.FC<ComponentCodeEditorProps> = ({
|
|||
formatOnPaste: true,
|
||||
formatOnType: true,
|
||||
}}
|
||||
onChange={handleCodeChange}
|
||||
onMount={handleEditorDidMount}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import TailwindModal from "./TailwindModal";
|
||||
import { ComponentInfo, HookInfo, PropertyInfo } from "../../proxy/developerKit/componentInfo";
|
||||
import { getComponentDefinition } from "./data/componentDefinitions";
|
||||
|
|
@ -113,15 +113,6 @@ const PropertyPanel: React.FC<PropertyPanelProps> = ({
|
|||
setHasHookChanges(true);
|
||||
};
|
||||
|
||||
// Handle local event changes
|
||||
const handleLocalEventChange = (eventName: string, value: string) => {
|
||||
setPendingEvents((prev) => ({
|
||||
...prev,
|
||||
[eventName]: value,
|
||||
}));
|
||||
setHasChanges(true);
|
||||
};
|
||||
|
||||
// Apply only property/event changes
|
||||
const handleApplyPropChanges = () => {
|
||||
if (!selectedComponent) return;
|
||||
|
|
@ -222,7 +213,7 @@ const PropertyPanel: React.FC<PropertyPanelProps> = ({
|
|||
if (property.type === "array") {
|
||||
try {
|
||||
arrayInputValue = JSON.stringify(value, null, 2);
|
||||
} catch (e) {
|
||||
} catch {
|
||||
arrayInputValue = "";
|
||||
arrayError = "Array verisi gösterilemiyor.";
|
||||
}
|
||||
|
|
@ -365,7 +356,7 @@ const PropertyPanel: React.FC<PropertyPanelProps> = ({
|
|||
const parsed = JSON.parse(e.target.value);
|
||||
handleLocalPropertyChange(property.name, parsed);
|
||||
arrayError = "";
|
||||
} catch (err) {
|
||||
} catch {
|
||||
arrayError = "Geçersiz JSON formatı";
|
||||
}
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { searchTailwindClasses, TAILWIND_CLASSES } from './data/tailwindClasses';
|
||||
import { Button } from '../ui';
|
||||
import { FaTimes } from 'react-icons/fa';
|
||||
|
|
@ -40,12 +40,6 @@ const TailwindModal: React.FC<TailwindModalProps> = ({
|
|||
// 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;
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import React from 'react';
|
||||
|
||||
declare interface Window {
|
||||
ReactDOM?: {
|
||||
render: (element: React.ReactNode, container: Element) => void;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import React from "react";
|
||||
import classNames from "classnames";
|
||||
|
||||
interface InfoSectionProps {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import classNames from "classnames";
|
||||
import { iconList } from "./iconList";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import classNames from "classnames";
|
||||
import Widget, { type colorType } from "./Widget";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { WidgetEditDto, WidgetGroupDto } from "../../types/common";
|
||||
|
||||
export default function WidgetGroup({
|
||||
|
|
@ -8,8 +7,6 @@ export default function WidgetGroup({
|
|||
}: {
|
||||
widgetGroups: WidgetGroupDto[];
|
||||
}) {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<div>
|
||||
{widgetGroups.map((group, gIdx) => (
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { cloneElement } from 'react'
|
||||
import React, { cloneElement } from 'react'
|
||||
import Avatar from '@/components/ui/Avatar'
|
||||
import Logo from '@/components/template/Logo'
|
||||
import { APP_NAME } from '@/constants/app.constant'
|
||||
|
|
|
|||
|
|
@ -1,44 +1,10 @@
|
|||
import React 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 type { PropsWithChildren } from 'react'
|
||||
import { Container } from '../shared'
|
||||
|
||||
interface DeveloperLayoutProps {
|
||||
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,
|
||||
},
|
||||
]
|
||||
|
||||
const DeveloperLayout = ({ children }: PropsWithChildren) => {
|
||||
return (
|
||||
<Container>
|
||||
<div className="flex flex-col lg:flex-row gap-8">
|
||||
{/* Main Content */}
|
||||
<div className="flex-1">{children}</div>
|
||||
</div>
|
||||
</Container>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ export const BillingControls: React.FC<BillingControlsProps> = ({
|
|||
setGlobalBillingCycle,
|
||||
setGlobalPeriod,
|
||||
onCartClick,
|
||||
onNavigate,
|
||||
cartItemsCount,
|
||||
cartState,
|
||||
}) => {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ interface OrderSuccessProps {
|
|||
onBackToShop: () => void
|
||||
}
|
||||
|
||||
export const OrderSuccess: React.FC<OrderSuccessProps> = ({ orderId, onBackToShop }) => {
|
||||
export const OrderSuccess: React.FC<OrderSuccessProps> = ({ orderId }) => {
|
||||
const navigate = useNavigate()
|
||||
const { translate } = useLocalization()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState } from 'react'
|
||||
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 { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { Button } from '@/components/ui'
|
||||
|
|
|
|||
|
|
@ -4,14 +4,14 @@ import { Link } from 'react-router-dom'
|
|||
import type { CommonProps } from '@/proxy/common'
|
||||
import type { ComponentPropsWithoutRef } from 'react'
|
||||
|
||||
interface ActionLink extends CommonProps, ComponentPropsWithoutRef<'a'> {
|
||||
interface ActionLinkProps extends CommonProps, ComponentPropsWithoutRef<'a'> {
|
||||
themeColor?: boolean
|
||||
to?: string
|
||||
href?: string
|
||||
reloadDocument?: boolean
|
||||
}
|
||||
|
||||
const ActionLink = (props: ActionLink) => {
|
||||
const ActionLink = (props: ActionLinkProps) => {
|
||||
const {
|
||||
children,
|
||||
className,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { MigrateLogEntry } from '@/proxy/setup/models'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { Button } from '@/components/ui'
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { forwardRef } from 'react'
|
||||
import React, { forwardRef } from 'react'
|
||||
import classNames from 'classnames'
|
||||
import useThemeClass from '@/utils/hooks/useThemeClass'
|
||||
import { FaCheckCircle } from 'react-icons/fa'
|
||||
|
|
|
|||
|
|
@ -179,34 +179,58 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
|
|||
useEffect(() => {
|
||||
// Example components for testing
|
||||
const HelloWorldComponent: React.ComponentType<unknown> = () => {
|
||||
return React.createElement('div', {
|
||||
className: 'p-6 bg-blue-50 rounded-lg'
|
||||
}, [
|
||||
React.createElement('h1', {
|
||||
className: 'text-2xl font-bold text-blue-900 mb-4'
|
||||
}, 'Hello World!'),
|
||||
React.createElement('p', {
|
||||
className: 'text-blue-700'
|
||||
}, 'Bu manuel kayıtlı bir komponent!')
|
||||
])
|
||||
return React.createElement(
|
||||
'div',
|
||||
{
|
||||
className: 'p-6 bg-blue-50 rounded-lg',
|
||||
},
|
||||
[
|
||||
React.createElement(
|
||||
'h1',
|
||||
{
|
||||
className: 'text-2xl font-bold text-blue-900 mb-4',
|
||||
},
|
||||
'Hello World!',
|
||||
),
|
||||
React.createElement(
|
||||
'p',
|
||||
{
|
||||
className: 'text-blue-700',
|
||||
},
|
||||
'Bu manuel kayıtlı bir komponent!',
|
||||
),
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
const TestListComponent: React.ComponentType<unknown> = () => {
|
||||
return React.createElement('div', {
|
||||
className: 'p-6 bg-green-50 rounded-lg'
|
||||
}, [
|
||||
React.createElement('h1', {
|
||||
className: 'text-2xl font-bold text-green-900 mb-4'
|
||||
}, 'Test List'),
|
||||
React.createElement('p', {
|
||||
className: 'text-green-700'
|
||||
}, 'Bu da test için kayıtlı komponent!')
|
||||
])
|
||||
return React.createElement(
|
||||
'div',
|
||||
{
|
||||
className: 'p-6 bg-green-50 rounded-lg',
|
||||
},
|
||||
[
|
||||
React.createElement(
|
||||
'h1',
|
||||
{
|
||||
className: 'text-2xl font-bold text-green-900 mb-4',
|
||||
},
|
||||
'Test List',
|
||||
),
|
||||
React.createElement(
|
||||
'p',
|
||||
{
|
||||
className: 'text-green-700',
|
||||
},
|
||||
'Bu da test için kayıtlı komponent!',
|
||||
),
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
registerComponent('HelloWorld', HelloWorldComponent)
|
||||
registerComponent('TestList', TestListComponent)
|
||||
}, []) // Empty dependency array - only run once
|
||||
}, []) // Empty dependency array - only run once
|
||||
|
||||
// Component compilation functions (moved from ComponentRegistryProvider)
|
||||
const extractComponentInfo = useCallback((code: string, defaultName = '') => {
|
||||
|
|
@ -269,8 +293,8 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
|
|||
const componentDefinitions = componentInfos
|
||||
.map((info) => {
|
||||
const componentVariables = componentInfos
|
||||
.filter(other => other.name !== info.name)
|
||||
.map(other => `const ${other.name} = ${other.name}_Component;`)
|
||||
.filter((other) => other.name !== info.name)
|
||||
.map((other) => `const ${other.name} = ${other.name}_Component;`)
|
||||
.join('\n ')
|
||||
|
||||
return `
|
||||
|
|
@ -314,12 +338,90 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
|
|||
}
|
||||
|
||||
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}`,
|
||||
)
|
||||
|
||||
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)
|
||||
|
|
@ -352,14 +454,11 @@ export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ chi
|
|||
[components, compiledComponents],
|
||||
)
|
||||
|
||||
const compileAndRender = useCallback(
|
||||
(code: string, props: ComponentProps = {}) => {
|
||||
if (!code?.trim()) return null
|
||||
// Simplified version - can be extended later
|
||||
return <div>Code compilation not implemented yet</div>
|
||||
},
|
||||
[],
|
||||
)
|
||||
const compileAndRender = useCallback((code: string) => {
|
||||
if (!code?.trim()) return null
|
||||
// Simplified version - can be extended later
|
||||
return <div>Code compilation not implemented yet</div>
|
||||
}, [])
|
||||
|
||||
const isComponentRegistered = useCallback(
|
||||
(name: string) => {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { createContext, useContext } from 'react'
|
||||
import { createContext, useContext } from 'react'
|
||||
|
||||
interface DemoContextValue {
|
||||
openDemo: () => void
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// ScrollContext.tsx
|
||||
import React, { createContext, useContext } from 'react'
|
||||
import { createContext, useContext } from 'react'
|
||||
|
||||
export const ScrollContext = createContext<boolean>(false)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { lazy } from 'react'
|
||||
import { RouteDto } from '@/proxy/routes/models'
|
||||
import { lazy } from 'react'
|
||||
|
||||
// Tüm view bileşenlerini import et (vite özel)
|
||||
// shared klasörü hariç, çünkü bu bileşenler genellikle başka yerlerde statik import ediliyor
|
||||
|
|
|
|||
|
|
@ -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}`,
|
||||
})
|
||||
|
||||
export const getListFormSelectQueryByCode = (listFormCode?: string, op: number = -1) =>
|
||||
export const getListFormSelectQueryByCode = (listFormCode?: string) =>
|
||||
apiService.fetchData<string>({
|
||||
method: 'GET',
|
||||
url: `/api/admin/list-form-query-preview/form-select-query`,
|
||||
|
|
|
|||
|
|
@ -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>({
|
||||
url: `/api/app/note/download?savedFileName=${savedFileName}`,
|
||||
method: 'GET',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
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'
|
||||
|
||||
export class OrderService {
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ platformApiService.interceptors.response.use(
|
|||
signOut()
|
||||
error.silent = true
|
||||
}
|
||||
} catch (error2) {
|
||||
} catch {
|
||||
await revokeTokens({
|
||||
token: auth.session.token,
|
||||
refreshToken: auth.session.refreshToken,
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ function deepParseJson(jsonString: Json): Json {
|
|||
}
|
||||
try {
|
||||
return deepParseJson(JSON.parse(jsonString))
|
||||
} catch (err) {
|
||||
} catch {
|
||||
return jsonString
|
||||
}
|
||||
} else if (Array.isArray(jsonString)) {
|
||||
|
|
|
|||
|
|
@ -7,12 +7,8 @@ import { NotificationDto } from '@/proxy/notification/models'
|
|||
import { getList } from '@/services/notification.service'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import dayjs from 'dayjs'
|
||||
import { Dictionary } from 'lodash'
|
||||
import forOwn from 'lodash/forOwn'
|
||||
import groupBy from 'lodash/groupBy'
|
||||
import has from 'lodash/has'
|
||||
import merge from 'lodash/merge'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import Log from './components/Log'
|
||||
import LogFilter from './components/LogFilter'
|
||||
import { Helmet } from 'react-helmet'
|
||||
|
|
@ -21,12 +17,13 @@ import { DIR_RTL } from '@/constants/theme.constant'
|
|||
import { useStoreState } from '@/store'
|
||||
|
||||
const itemsPerPage = 10
|
||||
type NotificationGroups = Record<string, NotificationDto[]>
|
||||
|
||||
const ActivityLog = () => {
|
||||
const { translate } = useLocalization()
|
||||
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [notifications, setNotifications] = useState<Dictionary<NotificationDto[]>>({})
|
||||
const [notifications, setNotifications] = useState<NotificationGroups>({})
|
||||
const [page, setPage] = useState(0)
|
||||
const [hasMore, setHasMore] = useState(false)
|
||||
const [isFilterDrawerOpen, setIsFilterDrawerOpen] = useState(false)
|
||||
|
|
@ -41,38 +38,43 @@ const ActivityLog = () => {
|
|||
NotificationChannels.WhatsApp,
|
||||
])
|
||||
|
||||
const fetchData = async (isLoadmore: boolean = false) => {
|
||||
const fetchData = useCallback(async (isLoadmore: boolean = false) => {
|
||||
setLoading(true)
|
||||
const response = await getList({
|
||||
maxResultCount: itemsPerPage,
|
||||
skipCount: page * itemsPerPage,
|
||||
sorting: 'CreationTime DESC',
|
||||
channels: filter,
|
||||
isListRequest: true,
|
||||
})
|
||||
const items = response.data?.items ?? []
|
||||
|
||||
const currentItemCount = page * itemsPerPage + items.length
|
||||
setHasMore((response.data?.totalCount ?? 0) > currentItemCount)
|
||||
const logs = groupBy(items, (a) => dayjs(a.creationTime).format('YYYY-MM-DD'))
|
||||
|
||||
if (isLoadmore) {
|
||||
forOwn(notifications, function (value, key) {
|
||||
if (has(logs, key)) {
|
||||
notifications[key] = [...notifications[key], ...logs[key]]
|
||||
delete logs[key]
|
||||
}
|
||||
try {
|
||||
const response = await getList({
|
||||
maxResultCount: itemsPerPage,
|
||||
skipCount: page * itemsPerPage,
|
||||
sorting: 'CreationTime DESC',
|
||||
channels: filter,
|
||||
isListRequest: true,
|
||||
})
|
||||
setNotifications(merge(notifications, logs))
|
||||
} else {
|
||||
setNotifications(logs)
|
||||
const items = response.data?.items ?? []
|
||||
|
||||
const currentItemCount = page * itemsPerPage + items.length
|
||||
setHasMore((response.data?.totalCount ?? 0) > currentItemCount)
|
||||
const logs = groupBy(items, (a) => dayjs(a.creationTime).format('YYYY-MM-DD'))
|
||||
|
||||
if (isLoadmore) {
|
||||
setNotifications((prev) => {
|
||||
const next: NotificationGroups = { ...prev }
|
||||
|
||||
for (const [key, value] of Object.entries(logs)) {
|
||||
next[key] = [...(next[key] ?? []), ...value]
|
||||
}
|
||||
|
||||
return next
|
||||
})
|
||||
} else {
|
||||
setNotifications(logs)
|
||||
}
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
setLoading(false)
|
||||
}
|
||||
}, [filter, page])
|
||||
|
||||
useEffect(() => {
|
||||
fetchData(page > 0)
|
||||
}, [page, filter])
|
||||
}, [fetchData, page])
|
||||
|
||||
const handleFilterChange = (value: string[]) => {
|
||||
setPage(0)
|
||||
|
|
@ -111,13 +113,13 @@ const ActivityLog = () => {
|
|||
<Log
|
||||
notifications={notifications}
|
||||
isLoading={loading}
|
||||
onLoadMore={() => setPage((prev) => prev + 1)}
|
||||
loadable={hasMore}
|
||||
onLoadMore={() => setPage((prev) => prev + 1)}
|
||||
></Log>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
|
|
@ -132,9 +134,9 @@ const ActivityLog = () => {
|
|||
>
|
||||
<LogFilter
|
||||
filter={filter}
|
||||
onFilterChange={handleFilterChange}
|
||||
useAffix={false}
|
||||
className="border-none p-0 dark:bg-gray-800"
|
||||
onFilterChange={handleFilterChange}
|
||||
/>
|
||||
</Drawer>
|
||||
</AdaptableCard>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import { AVATAR_URL } from '@/constants/app.constant'
|
|||
import { NotificationDto } from '@/proxy/notification/models'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import dayjs from 'dayjs'
|
||||
import { Dictionary } from 'lodash'
|
||||
import isEmpty from 'lodash/isEmpty'
|
||||
import keys from 'lodash/keys'
|
||||
import Event from './Event'
|
||||
|
|
@ -18,7 +17,7 @@ const Log = ({
|
|||
isLoading,
|
||||
loadable,
|
||||
}: {
|
||||
notifications: Dictionary<NotificationDto[]>
|
||||
notifications: Record<string, NotificationDto[]>
|
||||
onLoadMore: () => void
|
||||
isLoading: boolean
|
||||
loadable: boolean
|
||||
|
|
@ -38,7 +37,7 @@ const Log = ({
|
|||
{isEmpty(notifications[group]) ? (
|
||||
<Timeline.Item className="dark:text-gray-400">Bildirim yok</Timeline.Item>
|
||||
) : (
|
||||
notifications[group].map((notification, i) => (
|
||||
notifications[group].map((notification) => (
|
||||
<Timeline.Item
|
||||
key={notification.id}
|
||||
media={
|
||||
|
|
@ -57,7 +56,7 @@ const Log = ({
|
|||
))}
|
||||
<div className="text-center">
|
||||
{loadable ? (
|
||||
<Button size="sm" loading={isLoading} onClick={onLoadMore} variant='solid'>
|
||||
<Button size="sm" loading={isLoading} variant='solid' onClick={onLoadMore}>
|
||||
{translate('::Abp.Identity.ActivityLogs.LoadMore')}
|
||||
</Button>
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -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 { Button, Input, Select, toast, Notification, Spinner } from '@/components/ui'
|
||||
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
|
||||
if (event) {
|
||||
event.preventDefault()
|
||||
|
|
@ -409,7 +409,7 @@ const FileManager = () => {
|
|||
if (hasFiles) {
|
||||
toast.push(
|
||||
<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>,
|
||||
)
|
||||
return
|
||||
|
|
@ -491,6 +491,8 @@ const FileManager = () => {
|
|||
return () => {
|
||||
document.removeEventListener('keydown', handleKeyDown)
|
||||
}
|
||||
// Keyboard shortcuts should bind once per selection/list state snapshot.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [selectedItems, filteredItems])
|
||||
|
||||
// Bulk operations
|
||||
|
|
@ -710,7 +712,7 @@ const FileManager = () => {
|
|||
setLoading(false)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
} catch {
|
||||
toast.push(
|
||||
<Notification title="Error" type="danger">
|
||||
Invalid clipboard data
|
||||
|
|
@ -738,18 +740,18 @@ const FileManager = () => {
|
|||
<Button
|
||||
variant="plain"
|
||||
icon={<FaArrowUp />}
|
||||
onClick={goUpOneLevel}
|
||||
size="sm"
|
||||
disabled={breadcrumbItems.length <= 1}
|
||||
className="text-gray-600 hover:text-blue-600 flex-shrink-0"
|
||||
title="Go up one level"
|
||||
onClick={goUpOneLevel}
|
||||
/>
|
||||
<Button
|
||||
variant="solid"
|
||||
icon={<FaCloudUploadAlt />}
|
||||
onClick={() => setUploadModalOpen(true)}
|
||||
size="sm"
|
||||
className="flex-shrink-0"
|
||||
onClick={() => setUploadModalOpen(true)}
|
||||
>
|
||||
<span className="hidden sm:inline">{translate('::FileManager.UploadFiles')}</span>
|
||||
<span className="sm:hidden">{translate('::FileManager.Upload')}</span>
|
||||
|
|
@ -757,9 +759,9 @@ const FileManager = () => {
|
|||
<Button
|
||||
variant="default"
|
||||
icon={<FaFolder />}
|
||||
onClick={() => setCreateFolderModalOpen(true)}
|
||||
size="sm"
|
||||
className="flex-shrink-0"
|
||||
onClick={() => setCreateFolderModalOpen(true)}
|
||||
>
|
||||
<span className="hidden sm:inline">{translate('::FileManager.CreateFolder')}</span>
|
||||
<span className="sm:hidden">{translate('::FileManager.Create')}</span>
|
||||
|
|
@ -769,33 +771,37 @@ const FileManager = () => {
|
|||
<Button
|
||||
variant="plain"
|
||||
icon={<FaCopy />}
|
||||
onClick={copySelectedItems}
|
||||
disabled={selectedItems.length === 0}
|
||||
size="sm"
|
||||
className="text-gray-600 hover:text-blue-600 disabled:opacity-50 flex-shrink-0"
|
||||
title={translate('::FileManager.CopySelectedItems')}
|
||||
onClick={copySelectedItems}
|
||||
/>
|
||||
<Button
|
||||
variant="plain"
|
||||
icon={<FaCut />}
|
||||
onClick={cutSelectedItems}
|
||||
disabled={selectedItems.length === 0}
|
||||
size="sm"
|
||||
className="text-gray-600 hover:text-orange-600 disabled:opacity-50 flex-shrink-0"
|
||||
title={translate('::FileManager.CutSelectedItems')}
|
||||
onClick={cutSelectedItems}
|
||||
/>
|
||||
<Button
|
||||
variant="plain"
|
||||
icon={<FaPaste />}
|
||||
onClick={pasteItems}
|
||||
disabled={!hasClipboardData}
|
||||
size="sm"
|
||||
className="text-gray-600 hover:text-green-600 disabled:opacity-50 flex-shrink-0"
|
||||
title={translate('::FileManager.PasteSelectedItems')}
|
||||
onClick={pasteItems}
|
||||
/>
|
||||
<Button
|
||||
variant="plain"
|
||||
icon={<FaEdit />}
|
||||
size="sm"
|
||||
disabled={selectedItems.length !== 1}
|
||||
className="text-gray-600 hover:text-blue-600 flex-shrink-0"
|
||||
title={translate('::FileManager.RenameSelectedItem')}
|
||||
onClick={() => {
|
||||
if (selectedItems.length === 1) {
|
||||
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
|
||||
variant="plain"
|
||||
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={() => {
|
||||
if (selectedItems.length === 1) {
|
||||
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
|
||||
variant="plain"
|
||||
icon={<FaTrash />}
|
||||
onClick={deleteSelectedItems}
|
||||
size="sm"
|
||||
disabled={selectedItems.length === 0}
|
||||
className="text-gray-600 hover:text-red-600 flex-shrink-0"
|
||||
title={translate('::FileManager.DeleteSelectedItems')}
|
||||
onClick={deleteSelectedItems}
|
||||
>
|
||||
<span>{translate('::Delete')}</span> {selectedItems.length > 0 && `(${selectedItems.length})`}
|
||||
</Button>
|
||||
|
|
@ -869,11 +871,6 @@ const FileManager = () => {
|
|||
<FaSquare />
|
||||
)
|
||||
}
|
||||
onClick={
|
||||
selectedItems.length === filteredItems.filter((item) => !item.isReadOnly).length
|
||||
? deselectAllItems
|
||||
: selectAllItems
|
||||
}
|
||||
size="sm"
|
||||
className="text-gray-600 hover:text-blue-600 flex-shrink-0"
|
||||
title={
|
||||
|
|
@ -881,6 +878,11 @@ const FileManager = () => {
|
|||
? 'Deselect all selectable items'
|
||||
: 'Select all selectable items'
|
||||
}
|
||||
onClick={
|
||||
selectedItems.length === filteredItems.filter((item) => !item.isReadOnly).length
|
||||
? deselectAllItems
|
||||
: selectAllItems
|
||||
}
|
||||
>
|
||||
<span className="hidden lg:inline">
|
||||
{selectedItems.length === filteredItems.filter((item) => !item.isReadOnly).length
|
||||
|
|
@ -904,9 +906,9 @@ const FileManager = () => {
|
|||
size="sm"
|
||||
placeholder={translate('::FileManager.SearchFiles')}
|
||||
value={filters.searchTerm}
|
||||
onChange={(e) => setFilters((prev) => ({ ...prev, searchTerm: e.target.value }))}
|
||||
prefix={<FaSearch className="text-gray-400" />}
|
||||
className="w-full sm:w-36 md:w-48"
|
||||
onChange={(e) => setFilters((prev) => ({ ...prev, searchTerm: e.target.value }))}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
@ -954,15 +956,15 @@ const FileManager = () => {
|
|||
size="sm"
|
||||
icon={<FaTh />}
|
||||
variant={viewMode === 'grid' ? 'solid' : 'default'}
|
||||
onClick={() => setViewMode('grid')}
|
||||
title="Grid view"
|
||||
onClick={() => setViewMode('grid')}
|
||||
/>
|
||||
<Button
|
||||
size="sm"
|
||||
icon={<FaList />}
|
||||
variant={viewMode === 'list' ? 'solid' : 'default'}
|
||||
onClick={() => setViewMode('list')}
|
||||
title="List view"
|
||||
onClick={() => setViewMode('list')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1131,40 +1133,40 @@ const FileManager = () => {
|
|||
{/* Modals */}
|
||||
<FileUploadModal
|
||||
isOpen={uploadModalOpen}
|
||||
onClose={() => setUploadModalOpen(false)}
|
||||
onUpload={handleUploadFiles}
|
||||
currentFolderId={currentFolderId}
|
||||
loading={uploading}
|
||||
onClose={() => setUploadModalOpen(false)}
|
||||
onUpload={handleUploadFiles}
|
||||
/>
|
||||
|
||||
<CreateFolderModal
|
||||
isOpen={createFolderModalOpen}
|
||||
onClose={() => setCreateFolderModalOpen(false)}
|
||||
onCreate={handleCreateFolder}
|
||||
loading={creating}
|
||||
currentFolderId={currentFolderId}
|
||||
onClose={() => setCreateFolderModalOpen(false)}
|
||||
onCreate={handleCreateFolder}
|
||||
/>
|
||||
|
||||
<RenameItemModal
|
||||
isOpen={renameModalOpen}
|
||||
item={itemToRename}
|
||||
loading={renaming}
|
||||
onClose={() => {
|
||||
setRenameModalOpen(false)
|
||||
setItemToRename(undefined)
|
||||
}}
|
||||
onRename={handleRenameItem}
|
||||
item={itemToRename}
|
||||
loading={renaming}
|
||||
/>
|
||||
|
||||
<DeleteConfirmModal
|
||||
isOpen={deleteModalOpen}
|
||||
items={itemsToDelete}
|
||||
loading={deleting}
|
||||
onClose={() => {
|
||||
setDeleteModalOpen(false)
|
||||
setItemsToDelete([])
|
||||
}}
|
||||
onDelete={handleDeleteItems}
|
||||
items={itemsToDelete}
|
||||
loading={deleting}
|
||||
/>
|
||||
</Container>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ const Breadcrumb = forwardRef<HTMLDivElement, BreadcrumbProps>((props, ref) => {
|
|||
<FaFolder className="h-4 w-4 mr-1" />
|
||||
)
|
||||
}
|
||||
onClick={() => onNavigate(item)}
|
||||
className={classNames(
|
||||
'flex items-center px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors',
|
||||
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',
|
||||
)}
|
||||
disabled={index === items.length - 1}
|
||||
onClick={() => onNavigate(item)}
|
||||
>
|
||||
<span className="truncate max-w-32">{item.name}</span>
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
FaFolder,
|
||||
|
|
@ -16,7 +16,6 @@ import {
|
|||
FaLink,
|
||||
} from 'react-icons/fa'
|
||||
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 { FILE_URL } from '@/constants/app.constant'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
|
@ -26,7 +25,7 @@ export interface FileItemProps {
|
|||
selected?: boolean
|
||||
viewMode?: 'grid' | 'list'
|
||||
onSelect?: (item: FileItemType) => void
|
||||
onDoubleClick?: (item: FileItemType, event?: React.MouseEvent) => void
|
||||
onDoubleClick?: (item: FileItemType, event?: MouseEvent) => void
|
||||
onCreateFolder?: (parentItem: FileItemType) => void
|
||||
onRename?: (item: FileItemType) => void
|
||||
onMove?: (item: FileItemType) => void
|
||||
|
|
@ -141,11 +140,11 @@ const FileItem = forwardRef<HTMLDivElement, FileItemProps>((props, ref) => {
|
|||
onSelect?.(item)
|
||||
}
|
||||
|
||||
const handleDoubleClick = (e: React.MouseEvent) => {
|
||||
const handleDoubleClick = (e: MouseEvent) => {
|
||||
onDoubleClick?.(item, e)
|
||||
}
|
||||
|
||||
const handleContextMenu = (e: React.MouseEvent) => {
|
||||
const handleContextMenu = (e: MouseEvent) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
|
||||
|
|
@ -171,12 +170,12 @@ const FileItem = forwardRef<HTMLDivElement, FileItemProps>((props, ref) => {
|
|||
}
|
||||
}, [dropdownOpen])
|
||||
|
||||
const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const handleCheckboxChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
e.stopPropagation() // Prevent item selection when clicking checkbox
|
||||
onToggleSelect?.(item)
|
||||
}
|
||||
|
||||
const handleCheckboxClick = (e: React.MouseEvent) => {
|
||||
const handleCheckboxClick = (e: MouseEvent) => {
|
||||
e.stopPropagation() // Prevent item selection when clicking checkbox
|
||||
}
|
||||
|
||||
|
|
@ -216,7 +215,7 @@ const FileItem = forwardRef<HTMLDivElement, FileItemProps>((props, ref) => {
|
|||
() => {
|
||||
toast.push(
|
||||
<Notification type="success" title="Başarılı">
|
||||
Dosya URL'si panoya kopyalandı
|
||||
Dosya URL'si panoya kopyalandı
|
||||
</Notification>,
|
||||
)
|
||||
},
|
||||
|
|
@ -367,9 +366,9 @@ const FileItem = forwardRef<HTMLDivElement, FileItemProps>((props, ref) => {
|
|||
<input
|
||||
type="checkbox"
|
||||
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}
|
||||
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
|
||||
|
|
@ -464,9 +463,9 @@ const FileItem = forwardRef<HTMLDivElement, FileItemProps>((props, ref) => {
|
|||
<input
|
||||
type="checkbox"
|
||||
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}
|
||||
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>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -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 { FaTimes } from 'react-icons/fa'
|
||||
import type { FileItem } from '@/types/fileManagement'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
||||
|
|
@ -20,7 +19,7 @@ export const CreateFolderModal = forwardRef<HTMLDivElement, CreateFolderModalPro
|
|||
const [error, setError] = useState('')
|
||||
const { translate } = useLocalization()
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
const handleSubmit = async (e: FormEvent) => {
|
||||
e.preventDefault()
|
||||
|
||||
if (!folderName.trim()) {
|
||||
|
|
@ -33,7 +32,7 @@ export const CreateFolderModal = forwardRef<HTMLDivElement, CreateFolderModalPro
|
|||
setFolderName('')
|
||||
setError('')
|
||||
onClose()
|
||||
} catch (err) {
|
||||
} catch {
|
||||
setError('Failed to create folder')
|
||||
}
|
||||
}
|
||||
|
|
@ -47,27 +46,27 @@ export const CreateFolderModal = forwardRef<HTMLDivElement, CreateFolderModalPro
|
|||
return (
|
||||
<Dialog isOpen={isOpen} onClose={handleClose}>
|
||||
<div ref={ref}>
|
||||
<form onSubmit={handleSubmit} className="py-6">
|
||||
<form className="py-6" onSubmit={handleSubmit}>
|
||||
<FormItem label={translate('::FileManager.FolderName')} invalid={!!error} errorMessage={error}>
|
||||
<Input
|
||||
value={folderName}
|
||||
onChange={(e) => setFolderName(e.target.value)}
|
||||
autoFocus
|
||||
value={folderName}
|
||||
className="mt-2"
|
||||
onChange={(e) => setFolderName(e.target.value)}
|
||||
/>
|
||||
</FormItem>
|
||||
</form>
|
||||
|
||||
<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')}
|
||||
</Button>
|
||||
<Button
|
||||
size='sm'
|
||||
variant="solid"
|
||||
onClick={handleSubmit}
|
||||
loading={loading}
|
||||
disabled={!folderName.trim()}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
{translate('::FileManager.CreateFolder')}
|
||||
</Button>
|
||||
|
|
@ -102,7 +101,7 @@ export const RenameItemModal = forwardRef<HTMLDivElement, RenameItemModalProps>(
|
|||
}
|
||||
}, [item])
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
const handleSubmit = async (e: FormEvent) => {
|
||||
e.preventDefault()
|
||||
|
||||
if (!newName.trim()) {
|
||||
|
|
@ -119,7 +118,7 @@ export const RenameItemModal = forwardRef<HTMLDivElement, RenameItemModalProps>(
|
|||
await onRename(newName.trim())
|
||||
setError('')
|
||||
onClose()
|
||||
} catch (err) {
|
||||
} catch {
|
||||
setError(`Failed to rename ${item?.type}`)
|
||||
}
|
||||
}
|
||||
|
|
@ -141,31 +140,31 @@ export const RenameItemModal = forwardRef<HTMLDivElement, RenameItemModalProps>(
|
|||
</h3>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="py-6">
|
||||
<form className="py-6" onSubmit={handleSubmit}>
|
||||
<FormItem
|
||||
label={translate(`::FileManager.${item.type === 'folder' ? 'FolderName' : 'FileName'}`)}
|
||||
invalid={!!error}
|
||||
errorMessage={error}
|
||||
>
|
||||
<Input
|
||||
value={newName}
|
||||
onChange={(e) => setNewName(e.target.value)}
|
||||
placeholder={`Enter ${translate(`::FileManager.${item.type === 'folder' ? 'FolderName' : 'FileName'}`)}`}
|
||||
autoFocus
|
||||
value={newName}
|
||||
placeholder={`Enter ${translate(`::FileManager.${item.type === 'folder' ? 'FolderName' : 'FileName'}`)}`}
|
||||
onChange={(e) => setNewName(e.target.value)}
|
||||
/>
|
||||
</FormItem>
|
||||
</form>
|
||||
|
||||
<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')}
|
||||
</Button>
|
||||
<Button
|
||||
size='sm'
|
||||
variant="solid"
|
||||
onClick={handleSubmit}
|
||||
loading={loading}
|
||||
disabled={!newName.trim()}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
{translate('::App.Listform.ListformField.Rename')}
|
||||
</Button>
|
||||
|
|
@ -195,7 +194,7 @@ export const DeleteConfirmModal = forwardRef<HTMLDivElement, DeleteConfirmModalP
|
|||
try {
|
||||
await onDelete()
|
||||
onClose()
|
||||
} catch (err) {
|
||||
} catch {
|
||||
// Error handling is done in parent component
|
||||
}
|
||||
}
|
||||
|
|
@ -240,14 +239,14 @@ export const DeleteConfirmModal = forwardRef<HTMLDivElement, DeleteConfirmModalP
|
|||
</div>
|
||||
|
||||
<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')}
|
||||
</Button>
|
||||
<Button
|
||||
size='sm'
|
||||
variant="solid"
|
||||
onClick={handleDelete}
|
||||
loading={loading}
|
||||
onClick={handleDelete}
|
||||
>
|
||||
{translate('::Delete')}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -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 { FaCloudUploadAlt, FaTimes } from 'react-icons/fa'
|
||||
import classNames from 'classnames'
|
||||
|
|
@ -22,7 +29,7 @@ interface UploadFileWithProgress {
|
|||
}
|
||||
|
||||
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 [isDragOver, setIsDragOver] = useState(false)
|
||||
|
|
@ -53,24 +60,24 @@ const FileUploadModal = forwardRef<HTMLDivElement, FileUploadModalProps>((props,
|
|||
setUploadFiles((prev) => [...prev, ...newFiles])
|
||||
}, [])
|
||||
|
||||
const handleFileInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const handleFileInputChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
if (e.target.files) {
|
||||
handleFilesSelect(e.target.files)
|
||||
}
|
||||
}
|
||||
|
||||
const handleDragOver = useCallback((e: React.DragEvent) => {
|
||||
const handleDragOver = useCallback((e: DragEvent) => {
|
||||
e.preventDefault()
|
||||
setIsDragOver(true)
|
||||
}, [])
|
||||
|
||||
const handleDragLeave = useCallback((e: React.DragEvent) => {
|
||||
const handleDragLeave = useCallback((e: DragEvent) => {
|
||||
e.preventDefault()
|
||||
setIsDragOver(false)
|
||||
}, [])
|
||||
|
||||
const handleDrop = useCallback(
|
||||
(e: React.DragEvent) => {
|
||||
(e: DragEvent) => {
|
||||
e.preventDefault()
|
||||
setIsDragOver(false)
|
||||
|
||||
|
|
@ -216,10 +223,6 @@ const FileUploadModal = forwardRef<HTMLDivElement, FileUploadModalProps>((props,
|
|||
}
|
||||
}
|
||||
|
||||
const clearCompletedFiles = () => {
|
||||
setUploadFiles((prev) => prev.filter((f) => f.status !== 'completed'))
|
||||
}
|
||||
|
||||
const clearErrorFiles = () => {
|
||||
setUploadFiles((prev) => prev.filter((f) => f.status !== 'error'))
|
||||
}
|
||||
|
|
@ -231,7 +234,7 @@ const FileUploadModal = forwardRef<HTMLDivElement, FileUploadModalProps>((props,
|
|||
const hasError = errorFiles > 0
|
||||
|
||||
return (
|
||||
<Dialog isOpen={isOpen} onClose={handleClose} className={className}>
|
||||
<Dialog isOpen={isOpen} className={className} onClose={handleClose}>
|
||||
<div ref={ref}>
|
||||
<div className="flex items-center justify-between pb-2 border-b">
|
||||
<h3 className="text-lg font-semibold">Upload Files</h3>
|
||||
|
|
@ -251,11 +254,11 @@ const FileUploadModal = forwardRef<HTMLDivElement, FileUploadModalProps>((props,
|
|||
>
|
||||
<input
|
||||
ref={fileInputRef}
|
||||
type="file"
|
||||
multiple
|
||||
type="file"
|
||||
className="absolute inset-0 w-full h-full opacity-0 cursor-pointer"
|
||||
onChange={handleFileInputChange}
|
||||
disabled={uploading}
|
||||
onChange={handleFileInputChange}
|
||||
/>
|
||||
|
||||
<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"
|
||||
size="sm"
|
||||
icon={<FaTimes />}
|
||||
onClick={() => removeFile(file.id)}
|
||||
disabled={uploading}
|
||||
className="ml-2 flex-shrink-0"
|
||||
onClick={() => removeFile(file.id)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -349,21 +352,21 @@ const FileUploadModal = forwardRef<HTMLDivElement, FileUploadModalProps>((props,
|
|||
{hasError && !uploading && (
|
||||
<Button
|
||||
variant="plain"
|
||||
onClick={clearErrorFiles}
|
||||
className="text-red-600 hover:text-red-700"
|
||||
onClick={clearErrorFiles}
|
||||
>
|
||||
Clear Errors
|
||||
</Button>
|
||||
)}
|
||||
<Button size="sm" variant="default" onClick={handleClose} disabled={uploading}>
|
||||
<Button size="sm" variant="default" disabled={uploading} onClick={handleClose}>
|
||||
{uploading ? 'Uploading...' : 'Close'}
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="solid"
|
||||
onClick={handleUpload}
|
||||
disabled={pendingFiles === 0 || uploading}
|
||||
loading={uploading}
|
||||
onClick={handleUpload}
|
||||
>
|
||||
{uploading ? 'Uploading...' : `Upload ${pendingFiles} File(s)`}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
FaSitemap,
|
||||
FaBriefcase,
|
||||
|
|
@ -19,11 +30,10 @@ import {
|
|||
OrgChartUserDto,
|
||||
} from '@/services/orgChart.service'
|
||||
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 { useCurrentMenuIcon } from '@/utils/hooks/useCurrentMenuIcon'
|
||||
import { Avatar, Button } from '@/components/ui'
|
||||
import { AVATAR_URL } from '@/constants/app.constant'
|
||||
import { useStoreState } from '@/store'
|
||||
import UserProfileCard from '@/views/intranet/SocialWall/UserProfileCard'
|
||||
|
||||
|
|
@ -436,9 +446,9 @@ function OrgChartNode({
|
|||
tenantId?: string
|
||||
zoom: number
|
||||
positions: PositionMap
|
||||
setPositions: React.Dispatch<React.SetStateAction<PositionMap>>
|
||||
nodeRefs: React.MutableRefObject<NodeRefMap>
|
||||
cardRefs: React.MutableRefObject<CardRefMap>
|
||||
setPositions: Dispatch<SetStateAction<PositionMap>>
|
||||
nodeRefs: MutableRefObject<NodeRefMap>
|
||||
cardRefs: MutableRefObject<CardRefMap>
|
||||
requestRepaint: () => void
|
||||
applySelfTransform?: boolean
|
||||
}) {
|
||||
|
|
@ -451,9 +461,8 @@ function OrgChartNode({
|
|||
const levelColor = LEVEL_COLORS[depth % LEVEL_COLORS.length]
|
||||
const borderColor = levelColor.border
|
||||
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
|
||||
if (target.closest('[data-stop-drag="true"]')) {
|
||||
return
|
||||
|
|
@ -508,12 +517,12 @@ function OrgChartNode({
|
|||
ref={(el) => {
|
||||
cardRefs.current[node.id] = el
|
||||
}}
|
||||
onMouseDown={handleDragStart}
|
||||
data-card=""
|
||||
data-depth={depth}
|
||||
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`}
|
||||
style={{ cursor: dragging ? 'grabbing' : 'grab' }}
|
||||
onMouseDown={handleDragStart}
|
||||
>
|
||||
{/* Header bar */}
|
||||
<div
|
||||
|
|
@ -534,10 +543,6 @@ function OrgChartNode({
|
|||
{hasChildren && (
|
||||
<Button
|
||||
data-stop-drag="true"
|
||||
onClick={() => {
|
||||
setCollapsed((c) => !c)
|
||||
requestRepaint()
|
||||
}}
|
||||
variant="plain"
|
||||
shape="circle"
|
||||
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"
|
||||
onClick={() => {
|
||||
setCollapsed((c) => !c)
|
||||
requestRepaint()
|
||||
}}
|
||||
></Button>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -590,7 +599,7 @@ function OrgChartNode({
|
|||
{/* Children */}
|
||||
{hasChildren && !collapsed && (
|
||||
<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 }
|
||||
|
||||
return (
|
||||
|
|
@ -639,7 +648,7 @@ function OrgChartTree({
|
|||
tenantId?: string
|
||||
zoom: number
|
||||
positions: PositionMap
|
||||
setPositions: React.Dispatch<React.SetStateAction<PositionMap>>
|
||||
setPositions: Dispatch<SetStateAction<PositionMap>>
|
||||
edges: EdgeLink[]
|
||||
}) {
|
||||
const containerRef = useRef<HTMLDivElement>(null)
|
||||
|
|
@ -836,7 +845,7 @@ const OrgChart = () => {
|
|||
setPositions({})
|
||||
}, [mode])
|
||||
|
||||
const handleWheelZoom = (e: React.WheelEvent<HTMLDivElement>) => {
|
||||
const handleWheelZoom = (e: WheelEvent<HTMLDivElement>) => {
|
||||
if (!e.ctrlKey) {
|
||||
return
|
||||
}
|
||||
|
|
@ -882,7 +891,6 @@ const OrgChart = () => {
|
|||
<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">
|
||||
<Button
|
||||
onClick={() => setMode('department')}
|
||||
variant="plain"
|
||||
shape="none"
|
||||
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-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">
|
||||
{translate('::App.Hr.Department') || 'Departman'}
|
||||
</span>
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => setMode('jobPosition')}
|
||||
variant="plain"
|
||||
shape="none"
|
||||
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-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">
|
||||
{translate('::App.Hr.JobPosition') || 'Pozisyon'}
|
||||
|
|
@ -920,8 +929,8 @@ const OrgChart = () => {
|
|||
<input
|
||||
type="checkbox"
|
||||
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"
|
||||
onChange={(e) => setShowUsers(e.target.checked)}
|
||||
/>
|
||||
<span className="hidden sm:inline">
|
||||
{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">
|
||||
<Button
|
||||
onClick={handleZoomOut}
|
||||
variant="plain"
|
||||
shape="none"
|
||||
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"
|
||||
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">
|
||||
{Math.round(zoom * 100)}%
|
||||
</span>
|
||||
<Button
|
||||
onClick={handleZoomIn}
|
||||
variant="plain"
|
||||
shape="none"
|
||||
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"
|
||||
title="Zoom In"
|
||||
onClick={handleZoomIn}
|
||||
/>
|
||||
<Button
|
||||
onClick={handleZoomReset}
|
||||
variant="plain"
|
||||
shape="none"
|
||||
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"
|
||||
title="Reset Zoom"
|
||||
onClick={handleZoomReset}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
onClick={handleExportJpg}
|
||||
disabled={exporting || loading}
|
||||
variant="plain"
|
||||
shape="none"
|
||||
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"
|
||||
title="JPG olarak indir"
|
||||
onClick={handleExportJpg}
|
||||
>
|
||||
<span className="hidden sm:inline">{exporting ? 'İşleniyor…' : 'Export'}</span>
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -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 { Field, FieldProps, Form, Formik } from 'formik'
|
||||
import { object } from 'yup'
|
||||
|
|
@ -26,7 +26,7 @@ function ChartTabAnimation(props: FormEditProps) {
|
|||
await props.onSubmit(ListFormEditTabs.ChartAnimationForm, values, formikHelpers)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, resetForm, isSubmitting, values }) => (
|
||||
{({ touched, errors, isSubmitting, values }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<FormItem
|
||||
|
|
@ -79,7 +79,7 @@ function ChartTabAnimation(props: FormEditProps) {
|
|||
<Field type="number" name="animationDto.maxPointCountSupported" component={Input} />
|
||||
</FormItem>
|
||||
<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')}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ function ChartTabAnnotations(props: FormEditProps) {
|
|||
)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, resetForm, isSubmitting, values }) => (
|
||||
{({ touched, errors, isSubmitting, values }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<Tabs defaultValue="annotations_general">
|
||||
|
|
@ -121,7 +121,7 @@ function ChartTabAnnotations(props: FormEditProps) {
|
|||
size="sm"
|
||||
title="Edit"
|
||||
icon={<FaEdit />}
|
||||
onClick={async (e) => {
|
||||
onClick={async () => {
|
||||
setJsonRowOpModalData({
|
||||
tabName: ListFormEditTabs.ChartAnnotations.GeneralJsonRow,
|
||||
operation: 'update',
|
||||
|
|
@ -660,7 +660,7 @@ function ChartTabAnnotations(props: FormEditProps) {
|
|||
</TabContent>
|
||||
</Tabs>
|
||||
<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')}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ function ChartTabAxis(props: FormEditProps) {
|
|||
await props.onSubmit(ListFormEditTabs.ChartAxis.CommonAxisForm, values, formikHelpers)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, resetForm, isSubmitting, values }) => (
|
||||
{({ touched, errors, isSubmitting, values }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<Tabs defaultValue="axis_value">
|
||||
|
|
@ -114,7 +114,7 @@ function ChartTabAxis(props: FormEditProps) {
|
|||
size="sm"
|
||||
title="Edit"
|
||||
icon={<FaEdit />}
|
||||
onClick={async (e) => {
|
||||
onClick={async () => {
|
||||
setJsonRowOpModalData({
|
||||
tabName: ListFormEditTabs.ChartAxis.ValueAxisJsonRow,
|
||||
operation: 'update',
|
||||
|
|
@ -541,7 +541,7 @@ function ChartTabAxis(props: FormEditProps) {
|
|||
</TabContent>
|
||||
</Tabs>
|
||||
<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')}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import TabList from '@/components/ui/Tabs/TabList'
|
|||
import TabNav from '@/components/ui/Tabs/TabNav'
|
||||
import { IdentityRoleDto } from '@/proxy/admin/models'
|
||||
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 { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { useStoreState } from '@/store/store'
|
||||
|
|
@ -53,7 +53,7 @@ function ChartTabCommonSettings(props: FormEditProps) {
|
|||
await props.onSubmit(ListFormEditTabs.ChartCommon, values, formikHelpers)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, resetForm, isSubmitting, values }) => (
|
||||
{({ touched, errors, isSubmitting, values }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<Tabs defaultValue="commonSettings_general">
|
||||
|
|
@ -716,7 +716,7 @@ function ChartTabCommonSettings(props: FormEditProps) {
|
|||
</TabContent>
|
||||
</Tabs>
|
||||
<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')}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ function ChartTabCrosshair(props: FormEditProps) {
|
|||
await props.onSubmit(ListFormEditTabs.ChartCrosshairForm, values, formikHelpers)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, resetForm, isSubmitting, values }) => (
|
||||
{({ touched, errors, isSubmitting, values }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<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>
|
||||
</div>
|
||||
<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')}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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 { FormEditProps } from '../../listForm/edit/FormEdit'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
|
@ -24,7 +24,7 @@ function ChartTabExport(props: FormEditProps) {
|
|||
await props.onSubmit(ListFormEditTabs.ChartExportForm, values, formikHelpers)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, resetForm, isSubmitting, values }) => (
|
||||
{({ touched, errors, isSubmitting }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<FormItem label="Enabled">
|
||||
|
|
@ -65,7 +65,7 @@ function ChartTabExport(props: FormEditProps) {
|
|||
</FormItem>
|
||||
|
||||
<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')}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,12 +5,8 @@ import {
|
|||
FormContainer,
|
||||
FormItem,
|
||||
Input,
|
||||
Select,
|
||||
Tabs,
|
||||
Select
|
||||
} 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 { Field, FieldProps, Form, Formik } from 'formik'
|
||||
import { FormEditProps } from '../../listForm/edit/FormEdit'
|
||||
|
|
@ -42,7 +38,7 @@ function ChartTabLegend(props: FormEditProps) {
|
|||
await props.onSubmit(ListFormEditTabs.ChartLegendForm, values, formikHelpers)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, resetForm, isSubmitting, values }) => (
|
||||
{({ touched, errors, isSubmitting, values }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
|
||||
|
|
@ -216,7 +212,7 @@ function ChartTabLegend(props: FormEditProps) {
|
|||
</Card>
|
||||
</div>
|
||||
<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')}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ function ChartTabPanes(props: FormEditProps) {
|
|||
)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, resetForm, isSubmitting, values }) => (
|
||||
{({ touched, errors, isSubmitting }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<Card className="my-2">
|
||||
|
|
@ -110,7 +110,7 @@ function ChartTabPanes(props: FormEditProps) {
|
|||
size="sm"
|
||||
title="Edit"
|
||||
icon={<FaEdit />}
|
||||
onClick={async (e) => {
|
||||
onClick={async () => {
|
||||
setJsonRowOpModalData({
|
||||
tabName: ListFormEditTabs.ChartPanes.PanesJsonRow,
|
||||
operation: 'update',
|
||||
|
|
@ -155,7 +155,7 @@ function ChartTabPanes(props: FormEditProps) {
|
|||
setData={setJsonRowOpModalData}
|
||||
/>
|
||||
<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')}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ import {
|
|||
chartSeriesSelectionModeOptions,
|
||||
chartSeriesDashStyleOptions,
|
||||
} from './options'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { JsonRowDialogData } from './json-row-operations/types'
|
||||
import JsonRowOpDialogSeries from './json-row-operations/JsonRowOpDialogSeries'
|
||||
import CreatableSelect from 'react-select/creatable'
|
||||
|
|
@ -52,25 +52,22 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
|
|||
const [fieldList, setFieldList] = useState<SelectBoxOption[]>([])
|
||||
|
||||
const listFormValues = useStoreState((s) => s.admin.lists.values)
|
||||
if (!listFormValues) {
|
||||
return null
|
||||
}
|
||||
|
||||
const valueAxisList = () => {
|
||||
return listFormValues?.valueAxisDto.map((key: ChartValueAxisDto) => ({
|
||||
const valueAxisList = useMemo(() => {
|
||||
return (listFormValues?.valueAxisDto ?? []).map((key: ChartValueAxisDto) => ({
|
||||
value: key.name,
|
||||
label: key.name,
|
||||
}))
|
||||
}
|
||||
}, [listFormValues?.valueAxisDto])
|
||||
|
||||
const valuePaneList = () => {
|
||||
return listFormValues?.panesDto.map((key: ChartPanesDto) => ({
|
||||
const valuePaneList = useMemo(() => {
|
||||
return (listFormValues?.panesDto ?? []).map((key: ChartPanesDto) => ({
|
||||
value: key.name,
|
||||
label: key.name,
|
||||
}))
|
||||
}
|
||||
}, [listFormValues?.panesDto])
|
||||
|
||||
const getFields = async () => {
|
||||
const getFields = useCallback(async () => {
|
||||
if (!props.listFormCode) {
|
||||
return
|
||||
}
|
||||
|
|
@ -101,13 +98,17 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
|
|||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}, [props.listFormCode])
|
||||
|
||||
useEffect(() => {
|
||||
if (props.listFormCode) {
|
||||
getFields()
|
||||
}
|
||||
}, [props.listFormCode])
|
||||
}, [getFields, props.listFormCode])
|
||||
|
||||
if (!listFormValues) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<Formik
|
||||
|
|
@ -121,7 +122,7 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
|
|||
)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, resetForm, isSubmitting, values }) => (
|
||||
{({ touched, errors, isSubmitting, values }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<Tabs defaultValue="series_general">
|
||||
|
|
@ -176,7 +177,7 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
|
|||
size="sm"
|
||||
title="Edit"
|
||||
icon={<FaEdit />}
|
||||
onClick={async (e) => {
|
||||
onClick={async () => {
|
||||
setJsonRowOpModalData({
|
||||
tabName: ListFormEditTabs.ChartSeries.GeneralJsonRow,
|
||||
operation: 'update',
|
||||
|
|
@ -346,9 +347,9 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
|
|||
(option) =>
|
||||
option.value === values.commonSeriesSettingsDto.argumentField,
|
||||
)}
|
||||
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
||||
menuPlacement="auto"
|
||||
maxMenuHeight={150}
|
||||
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
|
|
@ -362,7 +363,7 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
|
|||
}
|
||||
errorMessage={errors.commonSeriesSettingsDto?.valueField}
|
||||
>
|
||||
<Field type="text" name="valueField">
|
||||
<Field type="text" name="commonSeriesSettingsDto.valueField">
|
||||
{({ field, form }: FieldProps<SelectBoxOption>) => (
|
||||
<Select
|
||||
componentAs={CreatableSelect}
|
||||
|
|
@ -374,9 +375,9 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
|
|||
(option) =>
|
||||
option.value === values.commonSeriesSettingsDto.valueField,
|
||||
)}
|
||||
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
||||
menuPlacement="auto"
|
||||
maxMenuHeight={150}
|
||||
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
|
|
@ -398,9 +399,9 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
|
|||
<Select
|
||||
field={field}
|
||||
form={form}
|
||||
options={valueAxisList()}
|
||||
options={valueAxisList}
|
||||
isClearable={true}
|
||||
value={valueAxisList()?.find(
|
||||
value={valueAxisList.find(
|
||||
(option) => option.value === values.commonSeriesSettingsDto.axis,
|
||||
)}
|
||||
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
||||
|
|
@ -424,9 +425,9 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
|
|||
<Select
|
||||
field={field}
|
||||
form={form}
|
||||
options={valuePaneList()}
|
||||
options={valuePaneList}
|
||||
isClearable={true}
|
||||
value={valuePaneList()?.find(
|
||||
value={valuePaneList.find(
|
||||
(option) => option.value === values.commonSeriesSettingsDto.pane,
|
||||
)}
|
||||
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
||||
|
|
@ -523,7 +524,7 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
|
|||
</TabContent>
|
||||
</Tabs>
|
||||
<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')}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ const ChartTabZoomAndPan = (props: FormEditProps) => {
|
|||
await props.onSubmit(ListFormEditTabs.ChartZoomForm, values, formikHelpers)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, resetForm, isSubmitting, values }) => (
|
||||
{({ touched, errors, isSubmitting, values }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
|
||||
|
|
@ -176,7 +176,7 @@ const ChartTabZoomAndPan = (props: FormEditProps) => {
|
|||
</Card>
|
||||
</div>
|
||||
<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')}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -294,7 +294,7 @@ function FormCustomization({
|
|||
/>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -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 TabList from '@/components/ui/Tabs/TabList'
|
||||
import TabNav from '@/components/ui/Tabs/TabNav'
|
||||
|
|
@ -7,7 +7,7 @@ import { SelectBoxOption } from '@/types/shared'
|
|||
import { useStoreActions, useStoreState } from '@/store'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { FormikHelpers } from 'formik'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { Link, useParams } from 'react-router-dom'
|
||||
import FormCustomization from './FormCustomization'
|
||||
|
|
@ -27,8 +27,7 @@ import FormTabSubForm from './FormTabSubForm'
|
|||
import FormFields from './form-fields/FormFields'
|
||||
import { putListForms } from '@/services/admin/list-form.service'
|
||||
import { getRoles, getUsers } from '@/services/identity.service'
|
||||
import { GridOptionsEditDto, ListFormCustomizationDto } from '@/proxy/form/models'
|
||||
import { SelectCommandTypeEnum } from '@/proxy/form/models'
|
||||
import { SelectCommandTypeEnum, GridOptionsEditDto, ListFormCustomizationDto } from '@/proxy/form/models'
|
||||
import { IdentityRoleDto, IdentityUserDto } from '@/proxy/admin/models'
|
||||
import { getListFormCustomizations } from '@/services/admin/list-form-customization.service'
|
||||
import { sqlObjectManagerService } from '@/services/sql-query-manager.service'
|
||||
|
|
@ -95,7 +94,7 @@ const FormEdit = () => {
|
|||
}
|
||||
}, [languages])
|
||||
|
||||
const getRoleList = async () => {
|
||||
const getRoleList = useCallback(async () => {
|
||||
const response = await getRoles()
|
||||
if (response.data?.items) {
|
||||
setRoleList(
|
||||
|
|
@ -105,9 +104,9 @@ const FormEdit = () => {
|
|||
})),
|
||||
)
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
const getUserList = async () => {
|
||||
const getUserList = useCallback(async () => {
|
||||
const response = await getUsers(0, 1000)
|
||||
if (response.data?.items) {
|
||||
setUserList(
|
||||
|
|
@ -117,17 +116,17 @@ const FormEdit = () => {
|
|||
})),
|
||||
)
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
const getCustomizations = async () => {
|
||||
const getCustomizations = useCallback(async () => {
|
||||
if (!listFormCode) {
|
||||
return
|
||||
}
|
||||
const resp = await getListFormCustomizations({ listFormCode, maxResultCount: 1000 })
|
||||
setCustomizations(resp?.data?.items)
|
||||
}
|
||||
}, [listFormCode])
|
||||
|
||||
const refreshData = async () => {
|
||||
const refreshData = useCallback(async () => {
|
||||
if (!listFormCode) {
|
||||
return
|
||||
}
|
||||
|
|
@ -135,7 +134,7 @@ const FormEdit = () => {
|
|||
await getCustomizations()
|
||||
await getRoleList()
|
||||
await getUserList()
|
||||
}
|
||||
}, [getCustomizations, getListFormValues, getRoleList, getUserList, listFormCode])
|
||||
|
||||
const listFormType = listFormValues?.listFormType || 'List'
|
||||
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
|
||||
useEffect(() => {
|
||||
refreshData()
|
||||
}, [listFormCode])
|
||||
}, [refreshData])
|
||||
|
||||
useEffect(() => {
|
||||
const loadWorkflowColumns = async () => {
|
||||
|
|
@ -378,9 +377,9 @@ const FormEdit = () => {
|
|||
|
||||
<TabContent value="details" className="px-2">
|
||||
<FormTabDetails
|
||||
onSubmit={onSubmit}
|
||||
roleList={roleList}
|
||||
userList={userList}
|
||||
onSubmit={onSubmit}
|
||||
onFormTypeChange={setActiveFormType}
|
||||
/>
|
||||
</TabContent>
|
||||
|
|
@ -442,7 +441,7 @@ const FormEdit = () => {
|
|||
<FormTabSubForm />
|
||||
</TabContent>
|
||||
<TabContent value="widget" className="px-2">
|
||||
<FormTabWidgets listFormCode={listFormCode} />
|
||||
<FormTabWidgets />
|
||||
</TabContent>
|
||||
<TabContent value="workflow" className="px-2">
|
||||
<FormTabWorkflow
|
||||
|
|
@ -478,7 +477,7 @@ const FormEdit = () => {
|
|||
<ChartTabCommonSettings onSubmit={onSubmit} />
|
||||
</TabContent>
|
||||
<TabContent value="series" className="px-2">
|
||||
<ChartTabSeries onSubmit={onSubmit} listFormCode={listFormCode} />
|
||||
<ChartTabSeries listFormCode={listFormCode} onSubmit={onSubmit} />
|
||||
</TabContent>
|
||||
<TabContent value="panes" className="px-2">
|
||||
<ChartTabPanes onSubmit={onSubmit} />
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
import { Container } from '@/components/shared'
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Checkbox,
|
||||
FormContainer,
|
||||
FormItem,
|
||||
Input,
|
||||
Select,
|
||||
Tabs,
|
||||
} from '@/components/ui'
|
||||
import { ListFormEditTabs } from '@/proxy/admin/list-form/options'
|
||||
import { useStoreState } from '@/store'
|
||||
|
|
@ -310,7 +307,7 @@ function FormTabColumns(props: FormEditProps) {
|
|||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ function FormTabCommands() {
|
|||
size="sm"
|
||||
title="Edit"
|
||||
icon={<FaEdit />}
|
||||
onClick={async (e) => {
|
||||
onClick={async () => {
|
||||
setJsonRowOpModalData({
|
||||
tabName: ListFormEditTabs.CommandColumnsJsonRow,
|
||||
operation: 'update',
|
||||
|
|
|
|||
|
|
@ -263,10 +263,10 @@ function FormTabDatabaseDataSource(props: FormEditProps) {
|
|||
: []
|
||||
return (
|
||||
<Select
|
||||
isClearable
|
||||
componentAs={CreatableSelect}
|
||||
field={field}
|
||||
form={form}
|
||||
isClearable
|
||||
isLoading={isLoadingDbObjects}
|
||||
options={grouped}
|
||||
placeholder={
|
||||
|
|
@ -346,10 +346,10 @@ function FormTabDatabaseDataSource(props: FormEditProps) {
|
|||
<Field type="text" autoComplete="off" name="keyFieldName">
|
||||
{({ field, form }: FieldProps<string>) => (
|
||||
<Select
|
||||
isClearable
|
||||
componentAs={CreatableSelect}
|
||||
field={field}
|
||||
form={form}
|
||||
isClearable
|
||||
isLoading={isLoadingColumns}
|
||||
placeholder={
|
||||
isLoadingColumns
|
||||
|
|
@ -387,7 +387,7 @@ function FormTabDatabaseDataSource(props: FormEditProps) {
|
|||
</FormItem>
|
||||
</Card>
|
||||
|
||||
<Button size="sm" block variant="solid" loading={isSubmitting}>
|
||||
<Button block size="sm" variant="solid" loading={isSubmitting}>
|
||||
{isSubmitting ? translate('::Saving') : translate('::Save')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ function FormTabDatabaseDelete({
|
|||
await onSubmit(ListFormEditTabs.Database.Delete.DeleteForm, values, formikHelpers)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, values, isSubmitting }) => (
|
||||
{({ touched, errors, isSubmitting }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<Card className="my-2">
|
||||
|
|
@ -116,7 +116,7 @@ function FormTabDatabaseDelete({
|
|||
</FormItem>
|
||||
</div>
|
||||
|
||||
<Button size="sm" block variant="solid" loading={isSubmitting}>
|
||||
<Button block size="sm" variant="solid" loading={isSubmitting}>
|
||||
{isSubmitting ? translate('::Saving') : translate('::Save')}
|
||||
</Button>
|
||||
</Card>
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ function FormTabDatabaseInsert({
|
|||
await onSubmit(ListFormEditTabs.Database.Insert.InsertForm, values, formikHelpers)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, values, isSubmitting }) => (
|
||||
{({ touched, errors, isSubmitting }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<Card className="my-2">
|
||||
|
|
@ -114,7 +114,7 @@ function FormTabDatabaseInsert({
|
|||
/>
|
||||
</FormItem>
|
||||
</div>
|
||||
<Button size="sm" block variant="solid" loading={isSubmitting}>
|
||||
<Button block size="sm" variant="solid" loading={isSubmitting}>
|
||||
{isSubmitting ? translate('::Saving') : translate('::Save')}
|
||||
</Button>
|
||||
</Card>
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ function FormTabDatabaseSelect({
|
|||
await onSubmit(ListFormEditTabs.Database.Select.SelectForm, values, formikHelpers)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, values, isSubmitting }) => (
|
||||
{({ touched, errors, isSubmitting }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<Card className="my-2">
|
||||
|
|
@ -65,7 +65,7 @@ function FormTabDatabaseSelect({
|
|||
component={Input}
|
||||
/>
|
||||
</FormItem>
|
||||
<Button size="sm" block variant="solid" loading={isSubmitting}>
|
||||
<Button block size="sm" variant="solid" loading={isSubmitting}>
|
||||
{isSubmitting ? translate('::Saving') : translate('::Save')}
|
||||
</Button>
|
||||
</Card>
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ function FormTabDatabaseUpdate({
|
|||
await onSubmit(ListFormEditTabs.Database.Update.UpdateForm, values, formikHelpers)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, values, isSubmitting }) => (
|
||||
{({ touched, errors, isSubmitting }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<Card className="my-2">
|
||||
|
|
@ -114,7 +114,7 @@ function FormTabDatabaseUpdate({
|
|||
/>
|
||||
</FormItem>
|
||||
</div>
|
||||
<Button size="sm" block variant="solid" loading={isSubmitting}>
|
||||
<Button block size="sm" variant="solid" loading={isSubmitting}>
|
||||
{isSubmitting ? translate('::Saving') : translate('::Save')}
|
||||
</Button>
|
||||
</Card>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { Container } from '@/components/shared'
|
||||
import { Button, Card, Checkbox, FormContainer, FormItem, Input, Select } from '@/components/ui'
|
||||
import { ListFormEditTabs } from '@/proxy/admin/list-form/options'
|
||||
import { LanguageInfo } from '@/proxy/config/models'
|
||||
|
|
@ -47,9 +46,6 @@ function FormTabDetails(
|
|||
|
||||
const languages = useStoreState((state) => state.abpConfig.config?.localization.languages)
|
||||
const listFormValues = useStoreState((s) => s.admin.lists.values)
|
||||
if (!listFormValues) {
|
||||
return null
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (languages) {
|
||||
|
|
@ -62,6 +58,10 @@ function FormTabDetails(
|
|||
}
|
||||
}, [languages])
|
||||
|
||||
if (!listFormValues) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<Formik
|
||||
initialValues={listFormValues}
|
||||
|
|
@ -437,7 +437,7 @@ function FormTabDetails(
|
|||
</Card>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -454,7 +454,7 @@ function FormTabEdit(props: FormEditProps & { listFormCode: string }) {
|
|||
)}
|
||||
</Card>
|
||||
</div>
|
||||
<Button size="sm" block variant="solid" loading={isSubmitting}>
|
||||
<Button block size="sm" variant="solid" loading={isSubmitting}>
|
||||
{isSubmitting ? translate('::Saving') : translate('::Save')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { Container } from '@/components/shared'
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Checkbox,
|
||||
FormContainer,
|
||||
FormItem,
|
||||
|
|
@ -18,15 +17,10 @@ import * as Yup from 'yup'
|
|||
import { FormEditProps } from './FormEdit'
|
||||
import {
|
||||
applyFilterOptions,
|
||||
overflowWrapOptions,
|
||||
sortModeOptions,
|
||||
whiteSpaceOptions,
|
||||
} 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 { SelectBoxOption } from '@/types/shared'
|
||||
|
||||
const validationSchema = Yup.object().shape({})
|
||||
|
||||
|
|
@ -304,7 +298,7 @@ function FormTabFilters(props: FormEditProps) {
|
|||
</TabContent>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ import { Field, FieldProps, Form, Formik } from 'formik'
|
|||
import * as Yup from 'yup'
|
||||
import { FormEditProps } from './FormEdit'
|
||||
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 { groupBy } from 'lodash'
|
||||
import groupBy from 'lodash/groupBy'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { GanttScaleType } from 'devextreme/ui/gantt'
|
||||
import { gantScaleOptions } from './options'
|
||||
|
|
@ -30,7 +30,7 @@ function FormTabGantt(props: FormEditProps) {
|
|||
const { translate } = useLocalization()
|
||||
const [fieldList, setFieldList] = useState<SelectBoxOption[]>([])
|
||||
|
||||
const getFields = async () => {
|
||||
const getFields = useCallback(async () => {
|
||||
if (!listFormCode) {
|
||||
return
|
||||
}
|
||||
|
|
@ -61,11 +61,11 @@ function FormTabGantt(props: FormEditProps) {
|
|||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}, [listFormCode])
|
||||
|
||||
useEffect(() => {
|
||||
getFields()
|
||||
}, [listFormCode])
|
||||
}, [getFields])
|
||||
|
||||
const listFormValues = useStoreState((s) => s.admin.lists.values)
|
||||
if (!listFormValues) {
|
||||
|
|
@ -471,7 +471,7 @@ function FormTabGantt(props: FormEditProps) {
|
|||
</Card>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ function FormTabGroup(props: FormEditProps) {
|
|||
await props.onSubmit(ListFormEditTabs.GroupForm, values, formikHelpers)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, isSubmitting, values }) => (
|
||||
{({ touched, errors, isSubmitting }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<FormItem
|
||||
|
|
@ -54,7 +54,7 @@ function FormTabGroup(props: FormEditProps) {
|
|||
/>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ function FormTabPager(props: FormEditProps) {
|
|||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -26,28 +26,27 @@ function FormTabPermissions(props: FormEditProps) {
|
|||
const { translate } = useLocalization()
|
||||
|
||||
const listFormValues = useStoreState((s) => s.admin.lists.values)
|
||||
|
||||
useEffect(() => {
|
||||
const loadPermissions = async () => {
|
||||
const response = await getPermissionsList()
|
||||
if (response.data) {
|
||||
setPermissions(
|
||||
response.data.map((permission: PermissionDefinitionRecord) => ({
|
||||
value: permission.name,
|
||||
label: permission.name,
|
||||
})),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
loadPermissions()
|
||||
}, [])
|
||||
|
||||
if (!listFormValues) {
|
||||
return null
|
||||
}
|
||||
|
||||
const getPermissionList = async () => {
|
||||
const response = await getPermissionsList()
|
||||
if (response.data) {
|
||||
setPermissions(
|
||||
response.data.map((permission: PermissionDefinitionRecord) => ({
|
||||
value: permission.name,
|
||||
label: permission.name,
|
||||
})),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (permissions) {
|
||||
getPermissionList()
|
||||
}
|
||||
}, [permissions])
|
||||
|
||||
return (
|
||||
<Container className="grid xl:grid-cols-2">
|
||||
<Formik
|
||||
|
|
@ -239,7 +238,7 @@ function FormTabPermissions(props: FormEditProps) {
|
|||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ function FormTabColumns(props: FormEditProps) {
|
|||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ function FormTabRow(props: FormEditProps) {
|
|||
</Field>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ import { Field, FieldProps, Form, Formik } from 'formik'
|
|||
import * as Yup from 'yup'
|
||||
import { FormEditProps } from './FormEdit'
|
||||
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 { groupBy } from 'lodash'
|
||||
import groupBy from 'lodash/groupBy'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { firstDayOfWeekOptions, schedulerViewOptions } from './options'
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ function FormTabScheduler(props: FormEditProps) {
|
|||
const { translate } = useLocalization()
|
||||
const [fieldList, setFieldList] = useState<SelectBoxOption[]>([])
|
||||
|
||||
const getFields = async () => {
|
||||
const getFields = useCallback(async () => {
|
||||
if (!listFormCode) {
|
||||
return
|
||||
}
|
||||
|
|
@ -60,11 +60,11 @@ function FormTabScheduler(props: FormEditProps) {
|
|||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}, [listFormCode])
|
||||
|
||||
useEffect(() => {
|
||||
getFields()
|
||||
}, [listFormCode])
|
||||
}, [getFields])
|
||||
|
||||
const listFormValues = useStoreState((s) => s.admin.lists.values)
|
||||
if (!listFormValues) {
|
||||
|
|
@ -363,7 +363,7 @@ function FormTabScheduler(props: FormEditProps) {
|
|||
</FormItem>
|
||||
</Card>
|
||||
</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')}
|
||||
</Button>{' '}
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ function FormTabSearch(props: FormEditProps) {
|
|||
await props.onSubmit(ListFormEditTabs.SearchForm, values, formikHelpers)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, isSubmitting, values }) => (
|
||||
{({ touched, errors, isSubmitting }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<FormItem
|
||||
|
|
@ -55,7 +55,7 @@ function FormTabSearch(props: FormEditProps) {
|
|||
/>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ function FormTabSelect(props: FormEditProps) {
|
|||
/>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -1,32 +1,20 @@
|
|||
import { Container } from '@/components/shared'
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Checkbox,
|
||||
FormContainer,
|
||||
FormItem,
|
||||
Input,
|
||||
Select,
|
||||
Tabs,
|
||||
} from '@/components/ui'
|
||||
import { ListFormEditTabs } from '@/proxy/admin/list-form/options'
|
||||
import { useStoreState } from '@/store'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { ApplyFilterMode } from 'devextreme/common/grids'
|
||||
import { Field, FieldProps, Form, Formik } from 'formik'
|
||||
import * as Yup from 'yup'
|
||||
import { FormEditProps } from './FormEdit'
|
||||
import {
|
||||
applyFilterOptions,
|
||||
overflowWrapOptions,
|
||||
sortModeOptions,
|
||||
whiteSpaceOptions,
|
||||
} 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 { SelectBoxOption } from '@/types/shared'
|
||||
|
||||
const validationSchema = Yup.object().shape({})
|
||||
|
||||
|
|
@ -74,7 +62,7 @@ function FormTabSorting(props: FormEditProps) {
|
|||
</Field>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ function FormTabState(props: FormEditProps) {
|
|||
/>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import {
|
|||
Input,
|
||||
Select,
|
||||
toast,
|
||||
Card,
|
||||
} from '@/components/ui'
|
||||
import { ListFormEditTabs } from '@/proxy/admin/list-form/options'
|
||||
import { useStoreState } from '@/store'
|
||||
|
|
@ -16,9 +15,9 @@ import { Field, FieldProps, Form, Formik } from 'formik'
|
|||
import * as Yup from 'yup'
|
||||
import { FormEditProps } from './FormEdit'
|
||||
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 { groupBy } from 'lodash'
|
||||
import groupBy from 'lodash/groupBy'
|
||||
import { useParams } from 'react-router-dom'
|
||||
|
||||
const validationSchema = Yup.object().shape({})
|
||||
|
|
@ -28,7 +27,7 @@ function FormTabTree(props: FormEditProps) {
|
|||
const { translate } = useLocalization()
|
||||
const [fieldList, setFieldList] = useState<SelectBoxOption[]>([])
|
||||
|
||||
const getFields = async () => {
|
||||
const getFields = useCallback(async () => {
|
||||
if (!listFormCode) {
|
||||
return
|
||||
}
|
||||
|
|
@ -59,11 +58,11 @@ function FormTabTree(props: FormEditProps) {
|
|||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}, [listFormCode])
|
||||
|
||||
useEffect(() => {
|
||||
getFields()
|
||||
}, [listFormCode])
|
||||
}, [getFields])
|
||||
|
||||
const listFormValues = useStoreState((s) => s.admin.lists.values)
|
||||
if (!listFormValues) {
|
||||
|
|
@ -185,7 +184,7 @@ function FormTabTree(props: FormEditProps) {
|
|||
component={Checkbox}
|
||||
/>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import { FaEdit, FaFileMedical, FaTrash } from 'react-icons/fa'
|
|||
import { JsonRowDialogData } from './json-row-operations/types'
|
||||
import JsonRowOpDialogWidget from './json-row-operations/JsonRowOpDialogWidget'
|
||||
|
||||
function FormTabWidgets(props: { listFormCode: string }) {
|
||||
function FormTabWidgets() {
|
||||
const [isJsonRowOpDialogOpen, setIsJsonRowOpDialogOpen] = useState(false)
|
||||
const [jsonRowOpModalData, setJsonRowOpModalData] = useState<JsonRowDialogData>()
|
||||
const { translate } = useLocalization()
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import { workflowService, type WorkflowCriteriaDto } from '@/services/workflow.s
|
|||
import { WorkflowDesigner } from '../workflow/WorkflowDesigner'
|
||||
import { SelectBoxOption } from '@/types/shared'
|
||||
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 { bool, object, string } from 'yup'
|
||||
import { useStoreState } from '@/store/store'
|
||||
|
|
@ -450,7 +450,7 @@ export function FormTabWorkflow(
|
|||
</FormItem>
|
||||
</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')}
|
||||
</Button>
|
||||
</Card>
|
||||
|
|
|
|||
|
|
@ -22,12 +22,10 @@ import { FormFieldEditProps } from './FormFields'
|
|||
import FormFieldTabPivotSetting from './FormFieldTabPivotSetting'
|
||||
|
||||
function FormFieldEdit({
|
||||
listFormCode,
|
||||
item,
|
||||
onSubmit,
|
||||
fields
|
||||
fields,
|
||||
}: {
|
||||
listFormCode: string
|
||||
item: ColumnFormatEditDto | null
|
||||
fields: ColumnFormatEditDto[]
|
||||
} & FormFieldEditProps) {
|
||||
|
|
@ -74,114 +72,60 @@ function FormFieldEdit({
|
|||
<TabNav value="pivotSetting">
|
||||
{translate('::ListForms.ListFormFieldEdit.TabPivotSettings')}
|
||||
</TabNav>
|
||||
</TabList>
|
||||
</TabList>
|
||||
<div className="pt-4">
|
||||
<TabContent value="details">
|
||||
<FormFieldTabDetails
|
||||
listFormCode={listFormCode}
|
||||
initialValues={item}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
<FormFieldTabDetails initialValues={item} onSubmit={onSubmit} />
|
||||
</TabContent>
|
||||
<TabContent value="options">
|
||||
<FormFieldTabOptions
|
||||
listFormCode={listFormCode}
|
||||
initialValues={item}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
<FormFieldTabOptions initialValues={item} onSubmit={onSubmit} />
|
||||
</TabContent>
|
||||
<TabContent value="permissions">
|
||||
<FormFieldTabPermissions
|
||||
listFormCode={listFormCode}
|
||||
initialValues={item}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
<FormFieldTabPermissions initialValues={item} onSubmit={onSubmit} />
|
||||
</TabContent>
|
||||
<TabContent value="customization">
|
||||
<FormFieldTabCustomization
|
||||
listFormCode={listFormCode}
|
||||
initialValues={item}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
<FormFieldTabCustomization initialValues={item} onSubmit={onSubmit} />
|
||||
</TabContent>
|
||||
<TabContent value="filtering">
|
||||
<FormFieldTabFiltering
|
||||
listFormCode={listFormCode}
|
||||
initialValues={item}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
<FormFieldTabFiltering initialValues={item} onSubmit={onSubmit} />
|
||||
</TabContent>
|
||||
<TabContent value="headering">
|
||||
<FormFieldTabHeadering
|
||||
listFormCode={listFormCode}
|
||||
initialValues={item}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
<FormFieldTabHeadering initialValues={item} onSubmit={onSubmit} />
|
||||
</TabContent>
|
||||
<TabContent value="grouping">
|
||||
<FormFieldTabGrouping
|
||||
listFormCode={listFormCode}
|
||||
initialValues={item}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
<FormFieldTabGrouping initialValues={item} onSubmit={onSubmit} />
|
||||
</TabContent>
|
||||
<TabContent value="groupSummary">
|
||||
<FormFieldTabGroupSummary
|
||||
listFormCode={listFormCode}
|
||||
initialValues={item}
|
||||
onSubmit={onSubmit}
|
||||
fields={fields}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
</TabContent>
|
||||
<TabContent value="totalSummary">
|
||||
<FormFieldTabTotalSummary
|
||||
listFormCode={listFormCode}
|
||||
initialValues={item}
|
||||
onSubmit={onSubmit}
|
||||
fields={fields}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
</TabContent>
|
||||
<TabContent value="joinOptions">
|
||||
<FormFieldTabJoinOptions
|
||||
listFormCode={listFormCode}
|
||||
initialValues={item}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
<FormFieldTabJoinOptions initialValues={item} onSubmit={onSubmit} />
|
||||
</TabContent>
|
||||
<TabContent value="lookup">
|
||||
<FormFieldTabLookup
|
||||
listFormCode={listFormCode}
|
||||
initialValues={item}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
<FormFieldTabLookup initialValues={item} onSubmit={onSubmit} />
|
||||
</TabContent>
|
||||
<TabContent value="cssOptions">
|
||||
<FormFieldTabCssOptions
|
||||
listFormCode={listFormCode}
|
||||
initialValues={item}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
<FormFieldTabCssOptions initialValues={item} onSubmit={onSubmit} />
|
||||
</TabContent>
|
||||
<TabContent value="validationRules">
|
||||
<FormFieldTabValidationRules
|
||||
listFormCode={listFormCode}
|
||||
initialValues={item}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
<FormFieldTabValidationRules initialValues={item} onSubmit={onSubmit} />
|
||||
</TabContent>
|
||||
<TabContent value="conditionalFormatting">
|
||||
<FormFieldTabConditionalFormatting
|
||||
listFormCode={listFormCode}
|
||||
initialValues={item}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
<FormFieldTabConditionalFormatting initialValues={item} onSubmit={onSubmit} />
|
||||
</TabContent>
|
||||
<TabContent value="pivotSetting">
|
||||
<FormFieldTabPivotSetting
|
||||
listFormCode={listFormCode}
|
||||
initialValues={item}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
<FormFieldTabPivotSetting initialValues={item} onSubmit={onSubmit} />
|
||||
</TabContent>
|
||||
</div>
|
||||
</Tabs>
|
||||
|
|
|
|||
|
|
@ -46,11 +46,9 @@ const schema = object().shape({
|
|||
})
|
||||
|
||||
function FormFieldTabConditionalFormatting({
|
||||
listFormCode,
|
||||
initialValues,
|
||||
onSubmit,
|
||||
}: {
|
||||
listFormCode: string
|
||||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
|
|
@ -219,7 +217,7 @@ function FormFieldTabConditionalFormatting({
|
|||
}
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, resetForm, values }) => (
|
||||
{({ touched, errors, values }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<FormItem
|
||||
|
|
@ -316,7 +314,7 @@ function FormFieldTabConditionalFormatting({
|
|||
/>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -12,11 +12,9 @@ const schema = object().shape({
|
|||
})
|
||||
|
||||
function FormFieldTabCssOptions({
|
||||
listFormCode,
|
||||
initialValues,
|
||||
onSubmit,
|
||||
}: {
|
||||
listFormCode: string
|
||||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
|
|
@ -31,7 +29,7 @@ function FormFieldTabCssOptions({
|
|||
await onSubmit(ListFormFieldEditTabs.CssOptionsForm, values, formikHelpers)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, isSubmitting, values }) => (
|
||||
{({ touched, errors, isSubmitting }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<FormItem
|
||||
|
|
@ -63,7 +61,7 @@ function FormFieldTabCssOptions({
|
|||
/>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -20,11 +20,9 @@ const schema = object().shape({
|
|||
})
|
||||
|
||||
function FormFieldTabCustomization({
|
||||
listFormCode,
|
||||
initialValues,
|
||||
onSubmit,
|
||||
}: {
|
||||
listFormCode: string
|
||||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
|
|
@ -39,7 +37,7 @@ function FormFieldTabCustomization({
|
|||
await onSubmit(ListFormFieldEditTabs.CustomizationForm, values, formikHelpers)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, isSubmitting, values }) => (
|
||||
{({ isSubmitting, values }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<FormItem label={translate('::ListForms.ListFormFieldEdit.CustomizationFixed')}>
|
||||
|
|
@ -70,7 +68,7 @@ function FormFieldTabCustomization({
|
|||
</Field>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -23,11 +23,9 @@ const schema = object().shape({
|
|||
})
|
||||
|
||||
function FormFieldTabDetails({
|
||||
listFormCode,
|
||||
initialValues,
|
||||
onSubmit,
|
||||
}: {
|
||||
listFormCode: string
|
||||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
|
|
@ -156,7 +154,7 @@ function FormFieldTabDetails({
|
|||
onClose={() => setIsEditorOptionsDialogOpen(false)}
|
||||
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')}
|
||||
</Button>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -17,11 +17,9 @@ const schema = object().shape({
|
|||
})
|
||||
|
||||
function FormFieldTabFiltering({
|
||||
listFormCode,
|
||||
initialValues,
|
||||
onSubmit,
|
||||
}: {
|
||||
listFormCode: string
|
||||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
|
|
@ -36,7 +34,7 @@ function FormFieldTabFiltering({
|
|||
await onSubmit(ListFormFieldEditTabs.FilteringForm, values, formikHelpers)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, isSubmitting, values }) => (
|
||||
{({ touched, errors, isSubmitting }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<FormItem
|
||||
|
|
@ -84,7 +82,7 @@ function FormFieldTabFiltering({
|
|||
/>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -23,12 +23,10 @@ const schema = object().shape({
|
|||
})
|
||||
|
||||
function FormFieldTabGroupSummary({
|
||||
listFormCode,
|
||||
initialValues,
|
||||
onSubmit,
|
||||
fields,
|
||||
}: {
|
||||
listFormCode: string
|
||||
initialValues: ColumnFormatEditDto
|
||||
fields: ColumnFormatEditDto[]
|
||||
} & FormFieldEditProps) {
|
||||
|
|
@ -176,7 +174,7 @@ function FormFieldTabGroupSummary({
|
|||
/>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -17,11 +17,9 @@ const schema = object().shape({
|
|||
})
|
||||
|
||||
function FormFieldTabGrouping({
|
||||
listFormCode,
|
||||
initialValues,
|
||||
onSubmit,
|
||||
}: {
|
||||
listFormCode: string
|
||||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
|
|
@ -36,7 +34,7 @@ function FormFieldTabGrouping({
|
|||
await onSubmit(ListFormFieldEditTabs.GroupingForm, values, formikHelpers)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, isSubmitting, values }) => (
|
||||
{({ touched, errors, isSubmitting }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<FormItem label={translate('::ListForms.ListFormFieldEdit.GroupingAllowGrouping')}>
|
||||
|
|
@ -61,7 +59,7 @@ function FormFieldTabGrouping({
|
|||
/>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -17,11 +17,9 @@ const schema = object().shape({
|
|||
})
|
||||
|
||||
function FormFieldTabHeadering({
|
||||
listFormCode,
|
||||
initialValues,
|
||||
onSubmit,
|
||||
}: {
|
||||
listFormCode: string
|
||||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
|
|
@ -36,7 +34,7 @@ function FormFieldTabHeadering({
|
|||
await onSubmit(ListFormFieldEditTabs.HeaderingForm, values, formikHelpers)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, isSubmitting, values }) => (
|
||||
{({ touched, errors, isSubmitting }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<FormItem
|
||||
|
|
@ -65,7 +63,7 @@ function FormFieldTabHeadering({
|
|||
/>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { Container } from '@/components/shared'
|
||||
import { Button, Card, FormContainer, FormItem, Input, Select } from '@/components/ui'
|
||||
import { Button, Card, FormItem, Input, Select } from '@/components/ui'
|
||||
import {
|
||||
ColumnFormatEditDto,
|
||||
GridColumnJoinConditionEnum,
|
||||
|
|
@ -29,11 +28,9 @@ const schema = object().shape({
|
|||
})
|
||||
|
||||
function FormFieldTabJoinOptions({
|
||||
listFormCode,
|
||||
initialValues,
|
||||
onSubmit,
|
||||
}: {
|
||||
listFormCode: string
|
||||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
|
|
@ -234,7 +231,7 @@ function FormFieldTabJoinOptions({
|
|||
</FormItem>
|
||||
</Card>
|
||||
</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')}
|
||||
</Button>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { Container } from '@/components/shared'
|
||||
import { Button, Card, Checkbox, FormContainer, FormItem, Input, Select } from '@/components/ui'
|
||||
import { Button, Card, FormItem, Input, Select } from '@/components/ui'
|
||||
import { ColumnFormatEditDto, ListFormFieldEditTabs } from '@/proxy/admin/list-form-field/models'
|
||||
import type { DatabaseColumnDto, SqlObjectExplorerDto } from '@/proxy/sql-query-manager/models'
|
||||
import { sqlObjectManagerService } from '@/services/sql-query-manager.service'
|
||||
|
|
@ -70,11 +69,11 @@ function TablePickerModal({
|
|||
{step === 'columns' && (
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => setStep('table')}
|
||||
variant="plain"
|
||||
shape="circle"
|
||||
icon={<FaArrowLeft className="text-xs" />}
|
||||
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">
|
||||
|
|
@ -85,11 +84,11 @@ function TablePickerModal({
|
|||
</div>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
variant="plain"
|
||||
shape="circle"
|
||||
icon={<FaTimes />}
|
||||
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>
|
||||
|
||||
|
|
@ -100,9 +99,9 @@ function TablePickerModal({
|
|||
<input
|
||||
autoFocus
|
||||
value={tableSearch}
|
||||
onChange={(e) => setTableSearch(e.target.value)}
|
||||
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"
|
||||
onChange={(e) => setTableSearch(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="overflow-y-auto flex-1 p-2">
|
||||
|
|
@ -117,6 +116,9 @@ function TablePickerModal({
|
|||
<Button
|
||||
key={t.fullName}
|
||||
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 () => {
|
||||
setPickerTable(t)
|
||||
setStep('columns')
|
||||
|
|
@ -137,9 +139,6 @@ function TablePickerModal({
|
|||
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>
|
||||
{t.tableName}
|
||||
|
|
@ -165,8 +164,8 @@ function TablePickerModal({
|
|||
</label>
|
||||
<select
|
||||
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"
|
||||
onChange={(e) => setKeyCol(e.target.value)}
|
||||
>
|
||||
<option value="">-- Seçiniz --</option>
|
||||
{pickerColumns.map((c) => (
|
||||
|
|
@ -182,8 +181,8 @@ function TablePickerModal({
|
|||
</label>
|
||||
<select
|
||||
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"
|
||||
onChange={(e) => setNameCol(e.target.value)}
|
||||
>
|
||||
<option value="">-- Seçiniz --</option>
|
||||
{pickerColumns.map((c) => (
|
||||
|
|
@ -204,8 +203,10 @@ function TablePickerModal({
|
|||
</div>
|
||||
)}
|
||||
<Button
|
||||
block
|
||||
type="button"
|
||||
disabled={!keyCol || !nameCol}
|
||||
variant="solid"
|
||||
onClick={() => {
|
||||
onSelect(
|
||||
buildLookupQuery({
|
||||
|
|
@ -216,8 +217,6 @@ function TablePickerModal({
|
|||
}),
|
||||
)
|
||||
}}
|
||||
block
|
||||
variant="solid"
|
||||
>
|
||||
{translate('::OK')}
|
||||
</Button>
|
||||
|
|
@ -248,11 +247,9 @@ function getNormalizedInitialValues(initialValues: ColumnFormatEditDto) {
|
|||
}
|
||||
|
||||
function FormFieldTabLookup({
|
||||
listFormCode,
|
||||
initialValues,
|
||||
onSubmit,
|
||||
}: {
|
||||
listFormCode: string
|
||||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
|
|
@ -317,11 +314,11 @@ function FormFieldTabLookup({
|
|||
extra={
|
||||
<Button
|
||||
type="button"
|
||||
onClick={openTablePicker}
|
||||
variant="plain"
|
||||
shape="none"
|
||||
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"
|
||||
onClick={openTablePicker}
|
||||
>
|
||||
{translate('::ListForms.Wizard.Step3.GenerateFromTable') || 'Tablodan Oluştur'}
|
||||
</Button>
|
||||
|
|
@ -465,7 +462,7 @@ function FormFieldTabLookup({
|
|||
</FormItem>
|
||||
</Card>
|
||||
</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')}
|
||||
</Button>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { Container } from '@/components/shared'
|
||||
import { Button, Card, Checkbox, FormContainer, FormItem, Input, Select } from '@/components/ui'
|
||||
import { Button, Card, Checkbox, FormItem, Input, Select } from '@/components/ui'
|
||||
import { ColumnFormatEditDto, ListFormFieldEditTabs } from '@/proxy/admin/list-form-field/models'
|
||||
import { SelectBoxOption } from '@/types/shared'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
|
@ -22,11 +21,9 @@ const schema = object().shape({
|
|||
})
|
||||
|
||||
function FormFieldTabOptions({
|
||||
listFormCode,
|
||||
initialValues,
|
||||
onSubmit,
|
||||
}: {
|
||||
listFormCode: string
|
||||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
|
|
@ -113,7 +110,7 @@ function FormFieldTabOptions({
|
|||
</Card>
|
||||
</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')}
|
||||
</Button>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -21,11 +21,9 @@ const schema = object().shape({
|
|||
})
|
||||
|
||||
function FormFieldTabPermissions({
|
||||
listFormCode,
|
||||
initialValues,
|
||||
onSubmit,
|
||||
}: {
|
||||
listFormCode: string
|
||||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
|
|
@ -159,7 +157,7 @@ function FormFieldTabPermissions({
|
|||
<Field name="permissionDto.i" component={Checkbox} />
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { Container } from '@/components/shared'
|
||||
import { Button, Card, Checkbox, FormContainer, FormItem, Input, Select } from '@/components/ui'
|
||||
import { Button, Card, Checkbox, FormItem, Select } from '@/components/ui'
|
||||
import { ColumnFormatEditDto, ListFormFieldEditTabs } from '@/proxy/admin/list-form-field/models'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { Field, FieldProps, Form, Formik } from 'formik'
|
||||
|
|
@ -28,11 +27,9 @@ const schema = object().shape({
|
|||
})
|
||||
|
||||
function FormFieldTabPivotSetting({
|
||||
listFormCode,
|
||||
initialValues,
|
||||
onSubmit,
|
||||
}: {
|
||||
listFormCode: string
|
||||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
|
|
@ -214,7 +211,7 @@ function FormFieldTabPivotSetting({
|
|||
</FormItem>
|
||||
</Card>
|
||||
</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')}
|
||||
</Button>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import { columnSummaryTypeListOptions } from '../options'
|
|||
import { FormFieldEditProps } from './FormFields'
|
||||
import { tooltipFormatListOptions } from '@/proxy/admin/list-form/options'
|
||||
import { SelectBoxOption } from '@/types/shared'
|
||||
import { useState } from 'react'
|
||||
|
||||
const schema = object().shape({
|
||||
columnTotalSummaryDto: object()
|
||||
|
|
@ -24,12 +23,10 @@ const schema = object().shape({
|
|||
})
|
||||
|
||||
function FormFieldTabTotalSummary({
|
||||
listFormCode,
|
||||
initialValues,
|
||||
onSubmit,
|
||||
fields,
|
||||
}: {
|
||||
listFormCode: string
|
||||
initialValues: ColumnFormatEditDto
|
||||
fields: ColumnFormatEditDto[]
|
||||
} & FormFieldEditProps) {
|
||||
|
|
@ -177,7 +174,7 @@ function FormFieldTabTotalSummary({
|
|||
/>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -60,11 +60,9 @@ const schema = object().shape({
|
|||
})
|
||||
|
||||
function FormFieldTabValidationRules({
|
||||
listFormCode,
|
||||
initialValues,
|
||||
onSubmit,
|
||||
}: {
|
||||
listFormCode: string
|
||||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
|
|
@ -229,7 +227,7 @@ function FormFieldTabValidationRules({
|
|||
}
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, resetForm, values }) => (
|
||||
{({ touched, errors, values }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<FormItem
|
||||
|
|
@ -355,7 +353,7 @@ function FormFieldTabValidationRules({
|
|||
<Field name="trim" placeholder="Trim" component={Checkbox} />
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ import { useLocalization } from '@/utils/hooks/useLocalization'
|
|||
import setNull from '@/utils/setNull'
|
||||
import classNames from 'classnames'
|
||||
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 { number, object, string } from 'yup'
|
||||
import FormFieldEdit from './FormFieldEdit'
|
||||
|
|
@ -219,7 +219,7 @@ function FormFields({
|
|||
await getFields()
|
||||
}
|
||||
|
||||
const getFields = async (cultureName?: string, roleId?: string, userId?: string) => {
|
||||
const getFields = useCallback(async (cultureName?: string, roleId?: string, userId?: string) => {
|
||||
if (!listFormCode) {
|
||||
return
|
||||
}
|
||||
|
|
@ -254,11 +254,11 @@ function FormFields({
|
|||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}, [listFormCode])
|
||||
|
||||
useEffect(() => {
|
||||
getFields()
|
||||
}, [listFormCode])
|
||||
}, [getFields])
|
||||
|
||||
useEffect(() => {
|
||||
if (!fields || !row) {
|
||||
|
|
@ -266,10 +266,10 @@ function FormFields({
|
|||
}
|
||||
|
||||
const newRow = fields.find((f) => f.id === row.id)
|
||||
if (newRow) {
|
||||
if (newRow && newRow !== row) {
|
||||
setRow(newRow)
|
||||
}
|
||||
}, [fields])
|
||||
}, [fields, row])
|
||||
|
||||
const onSubmit = async (
|
||||
editType: string,
|
||||
|
|
@ -390,7 +390,7 @@ function FormFields({
|
|||
</Field>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
@ -454,14 +454,14 @@ function FormFields({
|
|||
<TBody>
|
||||
{fields.map((field) => (
|
||||
<Tr
|
||||
key={field.id}
|
||||
className={classNames(
|
||||
'cursor-pointer',
|
||||
field.id === row?.id ? 'bg-sozsoft-active dark:bg-gray-600' : '',
|
||||
)}
|
||||
onClick={(e: any) => {
|
||||
onClick={() => {
|
||||
setRow(field)
|
||||
}}
|
||||
key={field.id}
|
||||
>
|
||||
<Td className="flex items-center !p-0">
|
||||
<Button
|
||||
|
|
@ -505,7 +505,7 @@ function FormFields({
|
|||
</Table>
|
||||
</div>
|
||||
<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>
|
||||
</AdaptableCard>
|
||||
|
|
@ -684,7 +684,7 @@ function FormFields({
|
|||
</Field>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
@ -793,7 +793,7 @@ function FormFields({
|
|||
}
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, resetForm, isSubmitting, values }) => (
|
||||
{({ touched, errors, isSubmitting, values }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<FormItem
|
||||
|
|
@ -1023,7 +1023,7 @@ function FormFields({
|
|||
<Field name="copiedFields.pivotSetting" component={Checkbox} className="mr-1" />
|
||||
</FormItem>
|
||||
</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')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Button, Dialog } from '@/components/ui'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
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 = {
|
||||
id: string
|
||||
|
|
@ -295,51 +295,52 @@ function EditorOptionsBuilderDialog({
|
|||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
onClick={clearOptions}
|
||||
title="editorOptions alanını boşaltır. Backend'e boş string kaydedilir."
|
||||
onClick={clearOptions}
|
||||
>
|
||||
NULL / Empty
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
onClick={() => addPreset({ disabled: true })}
|
||||
title='{"disabled": true} ekler.'
|
||||
onClick={() => addPreset({ disabled: true })}
|
||||
>
|
||||
disabled
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
onClick={() => addPreset({ tooltip: { enabled: true } })}
|
||||
title='{"tooltip": {"enabled": true}} ekler.'
|
||||
onClick={() => addPreset({ tooltip: { enabled: true } })}
|
||||
>
|
||||
Tooltip
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
onClick={() => addPreset({ format: { type: 'fixedPoint', precision: 2 } })}
|
||||
title="Ondalık format precision 2 ekler."
|
||||
onClick={() => addPreset({ format: { type: 'fixedPoint', precision: 2 } })}
|
||||
>
|
||||
fixedPoint precision 2
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
title="Pasif ve precision 2 fixedPoint formatını birlikte ekler."
|
||||
onClick={() =>
|
||||
addPreset({
|
||||
disabled: true,
|
||||
format: { type: 'fixedPoint', precision: 2 },
|
||||
})
|
||||
}
|
||||
title="Pasif ve precision 2 fixedPoint formatını birlikte ekler."
|
||||
>
|
||||
disabled fixedPoint 2
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
title="Precision 1, mask behavior, spin buttons ve pasif ayarını ekler."
|
||||
onClick={() =>
|
||||
addPreset({
|
||||
format: { type: 'fixedPoint', precision: 1 },
|
||||
|
|
@ -348,13 +349,13 @@ function EditorOptionsBuilderDialog({
|
|||
disabled: true,
|
||||
})
|
||||
}
|
||||
title="Precision 1, mask behavior, spin buttons ve pasif ayarını ekler."
|
||||
>
|
||||
disabled fixedPoint 1
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
title="NumberBox için precision 2, mask behavior ve spin buttons ekler."
|
||||
onClick={() =>
|
||||
addPreset({
|
||||
format: { type: 'fixedPoint', precision: 2 },
|
||||
|
|
@ -362,34 +363,34 @@ function EditorOptionsBuilderDialog({
|
|||
showSpinButtons: true,
|
||||
})
|
||||
}
|
||||
title="NumberBox için precision 2, mask behavior ve spin buttons ekler."
|
||||
>
|
||||
numberSpin precision 2
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
onClick={() => addPreset({ format: 'dd/MM/yyyy', displayFormat: 'dd/MM/yyyy' })}
|
||||
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
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
title="DateBox için gün/ay/yıl saat:dakika formatını ekler."
|
||||
onClick={() =>
|
||||
addPreset({
|
||||
format: '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
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
title="Telefon maskesi, yer tutucu ve Türkçe hata mesajı ekler."
|
||||
onClick={() =>
|
||||
addPreset({
|
||||
format: 'phoneGlobal',
|
||||
|
|
@ -400,13 +401,13 @@ function EditorOptionsBuilderDialog({
|
|||
placeholder: '(555) 123-4567',
|
||||
})
|
||||
}
|
||||
title="Telefon maskesi, yer tutucu ve Türkçe hata mesajı ekler."
|
||||
>
|
||||
phoneGlobal mask
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
title="Saat seçimi için dxDateBox time picker ayarları ekler."
|
||||
onClick={() =>
|
||||
addPreset({
|
||||
type: 'time',
|
||||
|
|
@ -417,32 +418,31 @@ function EditorOptionsBuilderDialog({
|
|||
width: '100%',
|
||||
})
|
||||
}
|
||||
title="Saat seçimi için dxDateBox time picker ayarları ekler."
|
||||
>
|
||||
time picker
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
onClick={() => addPreset({ width: 80, height: 80, multiple: true })}
|
||||
title="ImageUpload için 80x80 ve multiple ayarlarını ekler."
|
||||
onClick={() => addPreset({ width: 80, height: 80, multiple: true })}
|
||||
>
|
||||
multi image
|
||||
</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
|
||||
</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
|
||||
</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
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
onClick={() => addPreset(buildHtmlEditorOptions())}
|
||||
title="HtmlEditor toolbar, image upload ve media resizing ayarlarını ekler."
|
||||
onClick={() => addPreset(buildHtmlEditorOptions())}
|
||||
>
|
||||
htmlEditor toolbar
|
||||
</Button>
|
||||
|
|
@ -451,12 +451,12 @@ function EditorOptionsBuilderDialog({
|
|||
|
||||
return (
|
||||
<Dialog
|
||||
preventScroll
|
||||
isOpen={isOpen}
|
||||
width={1320}
|
||||
height="88vh"
|
||||
contentClassName="flex flex-col"
|
||||
style={{ overlay: { zIndex: 1300 } }}
|
||||
preventScroll
|
||||
onClose={onClose}
|
||||
onRequestClose={onClose}
|
||||
>
|
||||
|
|
@ -545,9 +545,9 @@ function EditorOptionsBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={toInputValue(options.width)}
|
||||
onChange={(event) => setOptionValue('width', event.target.value)}
|
||||
placeholder="100% veya 240"
|
||||
title="Örnek: 100%, 240, 80"
|
||||
onChange={(event) => setOptionValue('width', event.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<label className="text-xs text-gray-500">
|
||||
|
|
@ -555,15 +555,15 @@ function EditorOptionsBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={toInputValue(options.height)}
|
||||
placeholder="200"
|
||||
type="number"
|
||||
title="Editor yüksekliği. Örnek: 60, 100, 200"
|
||||
onChange={(event) =>
|
||||
setOptionValue(
|
||||
'height',
|
||||
event.target.value ? Number(event.target.value) : undefined,
|
||||
)
|
||||
}
|
||||
placeholder="200"
|
||||
type="number"
|
||||
title="Editor yüksekliği. Örnek: 60, 100, 200"
|
||||
/>
|
||||
</label>
|
||||
<label className="text-xs text-gray-500">
|
||||
|
|
@ -571,9 +571,9 @@ function EditorOptionsBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={toInputValue(options.placeholder)}
|
||||
onChange={(event) => setOptionValue('placeholder', event.target.value)}
|
||||
placeholder="Placeholder"
|
||||
title="Editor boşken görünecek metin."
|
||||
onChange={(event) => setOptionValue('placeholder', event.target.value)}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
|
@ -592,9 +592,9 @@ function EditorOptionsBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={toInputValue(options.label)}
|
||||
onChange={(event) => setOptionValue('label', event.target.value)}
|
||||
placeholder="Alan etiketi"
|
||||
title="Editor içi label metni."
|
||||
onChange={(event) => setOptionValue('label', event.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<label className="text-xs text-gray-500">
|
||||
|
|
@ -602,8 +602,8 @@ function EditorOptionsBuilderDialog({
|
|||
<select
|
||||
className={baseInputClass}
|
||||
value={toSelectValue(options.labelMode)}
|
||||
onChange={(event) => setOptionValue('labelMode', event.target.value)}
|
||||
title="Label gösterim modu."
|
||||
onChange={(event) => setOptionValue('labelMode', event.target.value)}
|
||||
>
|
||||
<option value="">Seç</option>
|
||||
<option value="static">static</option>
|
||||
|
|
@ -617,8 +617,8 @@ function EditorOptionsBuilderDialog({
|
|||
<select
|
||||
className={baseInputClass}
|
||||
value={toSelectValue(options.stylingMode)}
|
||||
onChange={(event) => setOptionValue('stylingMode', event.target.value)}
|
||||
title="DevExtreme editor görünüm stili."
|
||||
onChange={(event) => setOptionValue('stylingMode', event.target.value)}
|
||||
>
|
||||
<option value="">Seç</option>
|
||||
<option value="outlined">outlined</option>
|
||||
|
|
@ -631,9 +631,9 @@ function EditorOptionsBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={toInputValue(options.hint)}
|
||||
onChange={(event) => setOptionValue('hint', event.target.value)}
|
||||
placeholder="Tooltip/hint metni"
|
||||
title="Editor üzerine gelince gösterilecek hint."
|
||||
onChange={(event) => setOptionValue('hint', event.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<label className="text-xs text-gray-500">
|
||||
|
|
@ -641,9 +641,9 @@ function EditorOptionsBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={toInputValue(options.valueChangeEvent)}
|
||||
onChange={(event) => setOptionValue('valueChangeEvent', event.target.value)}
|
||||
placeholder="change veya input"
|
||||
title="Değer değişimini tetikleyecek DOM event adı. Örnek: change, input, keyup."
|
||||
onChange={(event) => setOptionValue('valueChangeEvent', event.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<label className="text-xs text-gray-500">
|
||||
|
|
@ -651,11 +651,11 @@ function EditorOptionsBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={toInputValue(getByPath(options, 'inputAttr.aria-label'))}
|
||||
placeholder="Erişilebilir ad"
|
||||
title="Input için aria-label."
|
||||
onChange={(event) =>
|
||||
setOptionPathValue('inputAttr.aria-label', event.target.value)
|
||||
}
|
||||
placeholder="Erişilebilir ad"
|
||||
title="Input için aria-label."
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
|
@ -674,8 +674,8 @@ function EditorOptionsBuilderDialog({
|
|||
<select
|
||||
className={baseInputClass}
|
||||
value={toSelectValue(options.mode)}
|
||||
onChange={(event) => setOptionValue('mode', event.target.value)}
|
||||
title="Input mode. TextBox/NumberBox için kullanılabilir."
|
||||
onChange={(event) => setOptionValue('mode', event.target.value)}
|
||||
>
|
||||
<option value="">Seç</option>
|
||||
<option value="text">text</option>
|
||||
|
|
@ -692,15 +692,15 @@ function EditorOptionsBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={toInputValue(options.maxLength)}
|
||||
placeholder="50"
|
||||
type="number"
|
||||
title="Maksimum karakter sayısı."
|
||||
onChange={(event) =>
|
||||
setOptionValue(
|
||||
'maxLength',
|
||||
event.target.value ? Number(event.target.value) : undefined,
|
||||
)
|
||||
}
|
||||
placeholder="50"
|
||||
type="number"
|
||||
title="Maksimum karakter sayısı."
|
||||
/>
|
||||
</label>
|
||||
<label className="text-xs text-gray-500">
|
||||
|
|
@ -708,9 +708,9 @@ function EditorOptionsBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={toInputValue(options.mask)}
|
||||
onChange={(event) => setOptionValue('mask', event.target.value)}
|
||||
placeholder="(000) 000-0000"
|
||||
title="TextBox mask değeri."
|
||||
onChange={(event) => setOptionValue('mask', event.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<label className="text-xs text-gray-500">
|
||||
|
|
@ -718,9 +718,9 @@ function EditorOptionsBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={toInputValue(options.maskInvalidMessage)}
|
||||
onChange={(event) => setOptionValue('maskInvalidMessage', event.target.value)}
|
||||
placeholder="Geçerli değer girin"
|
||||
title="Mask geçersiz olduğunda gösterilecek mesaj."
|
||||
onChange={(event) => setOptionValue('maskInvalidMessage', event.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<label className="text-xs text-gray-500">
|
||||
|
|
@ -728,8 +728,8 @@ function EditorOptionsBuilderDialog({
|
|||
<select
|
||||
className={baseInputClass}
|
||||
value={toSelectValue(options.showMaskMode)}
|
||||
onChange={(event) => setOptionValue('showMaskMode', event.target.value)}
|
||||
title="Mask ne zaman gösterilsin?"
|
||||
onChange={(event) => setOptionValue('showMaskMode', event.target.value)}
|
||||
>
|
||||
<option value="">Seç</option>
|
||||
<option value="always">always</option>
|
||||
|
|
@ -741,9 +741,9 @@ function EditorOptionsBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={toInputValue(getByPath(options, 'maskRules.X'))}
|
||||
onChange={(event) => setOptionPathValue('maskRules.X', event.target.value)}
|
||||
placeholder="[0-9]"
|
||||
title="Custom mask rule. Örnek: X -> [0-9]"
|
||||
onChange={(event) => setOptionPathValue('maskRules.X', event.target.value)}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
|
@ -763,15 +763,15 @@ function EditorOptionsBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={toInputValue(options[key])}
|
||||
placeholder={key === 'step' ? '1' : '0'}
|
||||
type="number"
|
||||
title={`${key} numeric option.`}
|
||||
onChange={(event) =>
|
||||
setOptionValue(
|
||||
key,
|
||||
event.target.value ? Number(event.target.value) : undefined,
|
||||
)
|
||||
}
|
||||
placeholder={key === 'step' ? '1' : '0'}
|
||||
type="number"
|
||||
title={`${key} numeric option.`}
|
||||
/>
|
||||
</label>
|
||||
))}
|
||||
|
|
@ -780,8 +780,8 @@ function EditorOptionsBuilderDialog({
|
|||
<select
|
||||
className={baseInputClass}
|
||||
value={toSelectValue(getByPath(options, 'format.type'))}
|
||||
onChange={(event) => setOptionPathValue('format.type', event.target.value)}
|
||||
title="NumberBox format type."
|
||||
onChange={(event) => setOptionPathValue('format.type', event.target.value)}
|
||||
>
|
||||
<option value="">Seç</option>
|
||||
<option value="fixedPoint">fixedPoint</option>
|
||||
|
|
@ -795,15 +795,15 @@ function EditorOptionsBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={toInputValue(getByPath(options, 'format.precision'))}
|
||||
placeholder="2"
|
||||
type="number"
|
||||
title="Ondalık hassasiyeti."
|
||||
onChange={(event) =>
|
||||
setOptionPathValue(
|
||||
'format.precision',
|
||||
event.target.value ? Number(event.target.value) : undefined,
|
||||
)
|
||||
}
|
||||
placeholder="2"
|
||||
type="number"
|
||||
title="Ondalık hassasiyeti."
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
|
@ -822,8 +822,8 @@ function EditorOptionsBuilderDialog({
|
|||
<select
|
||||
className={baseInputClass}
|
||||
value={toSelectValue(options.type)}
|
||||
onChange={(event) => setOptionValue('type', event.target.value)}
|
||||
title="DateBox type."
|
||||
onChange={(event) => setOptionValue('type', event.target.value)}
|
||||
>
|
||||
<option value="">Seç</option>
|
||||
<option value="date">date</option>
|
||||
|
|
@ -836,8 +836,8 @@ function EditorOptionsBuilderDialog({
|
|||
<select
|
||||
className={baseInputClass}
|
||||
value={toSelectValue(options.pickerType)}
|
||||
onChange={(event) => setOptionValue('pickerType', event.target.value)}
|
||||
title="DateBox picker type."
|
||||
onChange={(event) => setOptionValue('pickerType', event.target.value)}
|
||||
>
|
||||
<option value="">Seç</option>
|
||||
<option value="calendar">calendar</option>
|
||||
|
|
@ -851,9 +851,9 @@ function EditorOptionsBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={toInputValue(options.displayFormat)}
|
||||
onChange={(event) => setOptionValue('displayFormat', event.target.value)}
|
||||
placeholder="dd/MM/yyyy veya HH:mm"
|
||||
title="DateBox display format."
|
||||
onChange={(event) => setOptionValue('displayFormat', event.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<label className="text-xs text-gray-500">
|
||||
|
|
@ -861,11 +861,11 @@ function EditorOptionsBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={toInputValue(options.dateSerializationFormat)}
|
||||
placeholder="yyyy-MM-ddTHH:mm:ss"
|
||||
title="Kaydedilecek date serialization format."
|
||||
onChange={(event) =>
|
||||
setOptionValue('dateSerializationFormat', event.target.value)
|
||||
}
|
||||
placeholder="yyyy-MM-ddTHH:mm:ss"
|
||||
title="Kaydedilecek date serialization format."
|
||||
/>
|
||||
</label>
|
||||
<label className="text-xs text-gray-500">
|
||||
|
|
@ -873,15 +873,15 @@ function EditorOptionsBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={toInputValue(options.interval)}
|
||||
placeholder="5"
|
||||
type="number"
|
||||
title="Time list aralığı dakika cinsinden."
|
||||
onChange={(event) =>
|
||||
setOptionValue(
|
||||
'interval',
|
||||
event.target.value ? Number(event.target.value) : undefined,
|
||||
)
|
||||
}
|
||||
placeholder="5"
|
||||
type="number"
|
||||
title="Time list aralığı dakika cinsinden."
|
||||
/>
|
||||
</label>
|
||||
<label className="text-xs text-gray-500">
|
||||
|
|
@ -889,9 +889,9 @@ function EditorOptionsBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={toInputValue(options.invalidDateMessage)}
|
||||
onChange={(event) => setOptionValue('invalidDateMessage', event.target.value)}
|
||||
placeholder="Geçerli tarih/saat girin"
|
||||
title="Geçersiz tarih mesajı."
|
||||
onChange={(event) => setOptionValue('invalidDateMessage', event.target.value)}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
|
@ -932,6 +932,8 @@ function EditorOptionsBuilderDialog({
|
|||
<input
|
||||
className={`${baseInputClass} col-span-4`}
|
||||
value={option.path}
|
||||
placeholder="path.to.option"
|
||||
title="Nokta ile nested path yaz. Örnek: toolbar.multiline"
|
||||
onChange={(event) =>
|
||||
setCustomOptions((current) =>
|
||||
current.map((item) =>
|
||||
|
|
@ -939,8 +941,6 @@ function EditorOptionsBuilderDialog({
|
|||
),
|
||||
)
|
||||
}
|
||||
placeholder="path.to.option"
|
||||
title="Nokta ile nested path yaz. Örnek: toolbar.multiline"
|
||||
/>
|
||||
<select
|
||||
className={`${baseInputClass} col-span-2`}
|
||||
|
|
@ -963,6 +963,8 @@ function EditorOptionsBuilderDialog({
|
|||
<input
|
||||
className={`${baseInputClass} col-span-5`}
|
||||
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) =>
|
||||
setCustomOptions((current) =>
|
||||
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
|
||||
type="button"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { SelectBoxOption } from '@/types/shared'
|
|||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import Editor from '@monaco-editor/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 = {
|
||||
id: string
|
||||
|
|
@ -597,12 +597,6 @@ function EditorScriptBuilderDialog({
|
|||
setAmountTotalField((current) => current || findField('TotalAmount'))
|
||||
}
|
||||
|
||||
const fillTimeDefaults = () => {
|
||||
setTimeStartField((current) => current || findField('StartTime'))
|
||||
setTimeEndField((current) => current || findField('EndTime'))
|
||||
setTimeTargetField((current) => current || findField('TotalHours'))
|
||||
}
|
||||
|
||||
const resetBuilderSelections = () => {
|
||||
setCopyMappings([])
|
||||
setDaysStartField('')
|
||||
|
|
@ -834,12 +828,12 @@ function EditorScriptBuilderDialog({
|
|||
|
||||
return (
|
||||
<Dialog
|
||||
preventScroll
|
||||
isOpen={isOpen}
|
||||
width={1100}
|
||||
height="82vh"
|
||||
contentClassName="flex flex-col"
|
||||
style={{ overlay: { zIndex: 1300 } }}
|
||||
preventScroll
|
||||
onClose={onClose}
|
||||
onRequestClose={onClose}
|
||||
>
|
||||
|
|
@ -898,6 +892,8 @@ function EditorScriptBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={mapping.source}
|
||||
placeholder="Örn: unitPrice veya Customer.Name"
|
||||
title="Seçilen kayıttaki kolon/path. Örnek: Quantity, UnitPrice, Customer.Name"
|
||||
onChange={(event) =>
|
||||
setCopyMappings((current) =>
|
||||
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>
|
||||
<div className="col-span-12 md:col-span-5">
|
||||
|
|
@ -1012,11 +1006,11 @@ function EditorScriptBuilderDialog({
|
|||
action.operator === 'empty' ||
|
||||
action.operator === 'notEmpty'
|
||||
}
|
||||
placeholder="Örn: Aktif, 1000"
|
||||
title="Koşulda kullanılacak sabit değer. Örnek: Aktif, 0, True"
|
||||
onChange={(event) =>
|
||||
updateConditionalAction(action.id, { value: event.target.value })
|
||||
}
|
||||
placeholder="Örn: Aktif, 1000"
|
||||
title="Koşulda kullanılacak sabit değer. Örnek: Aktif, 0, True"
|
||||
/>
|
||||
</label>
|
||||
<div className={actionIconCellClass}>
|
||||
|
|
@ -1054,7 +1048,7 @@ function EditorScriptBuilderDialog({
|
|||
<option value="confirm">Onay iste</option>
|
||||
<option value="calculate">Formül hesapla</option>
|
||||
<option value="setReadOnly">ReadOnly ayarla</option>
|
||||
<option value="apiToField">API sonucunu field'a yaz</option>
|
||||
<option value="apiToField">API sonucunu field'a yaz</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
|
|
@ -1077,11 +1071,11 @@ function EditorScriptBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={action.textValue}
|
||||
placeholder="text, {Field} or {selected.Name}"
|
||||
title="Sabit metin veya token yaz. Örnek: {Name}, {value}, {selected.DisplayName}"
|
||||
onChange={(event) =>
|
||||
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>
|
||||
)}
|
||||
|
|
@ -1129,11 +1123,11 @@ function EditorScriptBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={action.apiUrl}
|
||||
placeholder="/api/path/{Id}"
|
||||
title="Token kullanabilirsin: /api/orders/{OrderId}, /api/x/{selected.Id}, /api/y/{value}"
|
||||
onChange={(event) =>
|
||||
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 className={`${fieldLabelClass} col-span-12 md:col-span-3`}>
|
||||
|
|
@ -1141,13 +1135,13 @@ function EditorScriptBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
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) =>
|
||||
updateConditionalAction(action.id, {
|
||||
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>
|
||||
</>
|
||||
|
|
@ -1160,13 +1154,13 @@ function EditorScriptBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={action.textValue}
|
||||
placeholder="/report?id={Id}&type={selected.Type}"
|
||||
title="Açılacak URL. Token destekler: {Id}, {value}, {selected.Type}"
|
||||
onChange={(event) =>
|
||||
updateConditionalAction(action.id, {
|
||||
textValue: event.target.value,
|
||||
})
|
||||
}
|
||||
placeholder="/report?id={Id}&type={selected.Type}"
|
||||
title="Açılacak URL. Token destekler: {Id}, {value}, {selected.Type}"
|
||||
/>
|
||||
</label>
|
||||
<label className={`${fieldLabelClass} col-span-12 md:col-span-2`}>
|
||||
|
|
@ -1194,11 +1188,11 @@ function EditorScriptBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={action.message}
|
||||
placeholder="{Field} tokenları ile mesaj"
|
||||
title="Alert/confirm mesajı. Token destekler: {Name}, {value}, {selected.Name}"
|
||||
onChange={(event) =>
|
||||
updateConditionalAction(action.id, { message: event.target.value })
|
||||
}
|
||||
placeholder="{Field} tokenları ile mesaj"
|
||||
title="Alert/confirm mesajı. Token destekler: {Name}, {value}, {selected.Name}"
|
||||
/>
|
||||
</label>
|
||||
)}
|
||||
|
|
@ -1209,11 +1203,11 @@ function EditorScriptBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
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) =>
|
||||
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>
|
||||
)}
|
||||
|
|
@ -1292,9 +1286,9 @@ function EditorScriptBuilderDialog({
|
|||
<input
|
||||
className={baseInputClass}
|
||||
value={serviceCall}
|
||||
onChange={(event) => setServiceCall(event.target.value)}
|
||||
placeholder="UiEvalService.ApiGenerateBackgroundWorkers();"
|
||||
title="Global servis çağrısı. Örnek: UiEvalService.ApiGenerateBackgroundWorkers();"
|
||||
onChange={(event) => setServiceCall(event.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -1340,7 +1334,6 @@ function EditorScriptBuilderDialog({
|
|||
language="typescript"
|
||||
theme="vs-dark"
|
||||
value={scriptEditorValue}
|
||||
onChange={(nextValue) => setScriptEditorValue(nextValue || '')}
|
||||
options={{
|
||||
automaticLayout: true,
|
||||
fontSize: 12,
|
||||
|
|
@ -1349,6 +1342,7 @@ function EditorScriptBuilderDialog({
|
|||
tabSize: 2,
|
||||
wordWrap: 'on',
|
||||
}}
|
||||
onChange={(nextValue) => setScriptEditorValue(nextValue || '')}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -88,10 +88,10 @@ function JsonRowOpDialogAnnotation({
|
|||
id="annotationOperation"
|
||||
isOpen={isOpen}
|
||||
preventScroll={true}
|
||||
onClose={handleClose}
|
||||
onRequestClose={handleClose}
|
||||
width={900}
|
||||
height="90vh"
|
||||
onClose={handleClose}
|
||||
onRequestClose={handleClose}
|
||||
>
|
||||
{(data.operation === 'create' || data.operation === 'update') && (
|
||||
<Formik
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import { useStoreActions } from '@/store'
|
|||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { Field, FieldArray, FieldProps, Form, Formik } from 'formik'
|
||||
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 { number, object, string } from 'yup'
|
||||
import {
|
||||
|
|
@ -82,7 +82,7 @@ function JsonRowOpDialogEditForm({
|
|||
const [scriptBuilderIndex, setScriptBuilderIndex] = useState<number | null>(null)
|
||||
const [isHelperOpen, setIsHelperOpen] = useState(false)
|
||||
|
||||
const getFields = async () => {
|
||||
const getFields = useCallback(async () => {
|
||||
if (!listFormCode) {
|
||||
return
|
||||
}
|
||||
|
|
@ -113,7 +113,7 @@ function JsonRowOpDialogEditForm({
|
|||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}, [listFormCode])
|
||||
|
||||
const handleClose = async (e?: any) => {
|
||||
if (e) {
|
||||
|
|
@ -133,7 +133,7 @@ function JsonRowOpDialogEditForm({
|
|||
if (isOpen && data) {
|
||||
getFields()
|
||||
}
|
||||
}, [isOpen, data])
|
||||
}, [isOpen, data, getFields])
|
||||
|
||||
if (!data || !fieldList?.length) {
|
||||
return null
|
||||
|
|
@ -279,10 +279,10 @@ function JsonRowOpDialogEditForm({
|
|||
|
||||
<Dialog
|
||||
isOpen={isHelperOpen}
|
||||
onClose={() => setIsHelperOpen(false)}
|
||||
onRequestClose={() => setIsHelperOpen(false)}
|
||||
preventScroll={true}
|
||||
width={1000}
|
||||
onClose={() => setIsHelperOpen(false)}
|
||||
onRequestClose={() => setIsHelperOpen(false)}
|
||||
>
|
||||
<h5 className="mb-4">Helper</h5>
|
||||
|
||||
|
|
@ -396,11 +396,11 @@ function JsonRowOpDialogEditForm({
|
|||
)
|
||||
: null
|
||||
}
|
||||
menuPlacement="auto"
|
||||
maxMenuHeight={150}
|
||||
onChange={(option) =>
|
||||
form.setFieldValue(field.name, option?.value)
|
||||
}
|
||||
menuPlacement="auto"
|
||||
maxMenuHeight={150}
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
|
|
@ -422,12 +422,12 @@ function JsonRowOpDialogEditForm({
|
|||
(option) =>
|
||||
option.value === values.items?.at(index)?.editorType2,
|
||||
)}
|
||||
onChange={(option) =>
|
||||
form.setFieldValue(field.name, option?.value)
|
||||
}
|
||||
className="flex-1"
|
||||
menuPlacement="auto"
|
||||
maxMenuHeight={150}
|
||||
onChange={(option) =>
|
||||
form.setFieldValue(field.name, option?.value)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ import {
|
|||
} from '@/components/ui'
|
||||
import { ListFormJsonRowDto } from '@/proxy/admin/list-form/models'
|
||||
import { SelectBoxOption } from '@/types/shared'
|
||||
import { useStoreActions, useStoreState } from '@/store'
|
||||
import { useStoreActions } from '@/store'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
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 { JsonRowDialogData } from './types'
|
||||
import {
|
||||
|
|
@ -22,10 +22,10 @@ import {
|
|||
postListFormJsonRow,
|
||||
putListFormJsonRow,
|
||||
} from '@/services/admin/list-form.service'
|
||||
import { cascadeFilterOperator, colSpanOptions } from '../options'
|
||||
import { cascadeFilterOperator } from '../options'
|
||||
import CreatableSelect from 'react-select/creatable'
|
||||
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'
|
||||
|
||||
const schema = object().shape({
|
||||
|
|
@ -73,7 +73,7 @@ function JsonRowOpDialogExtraFilter({
|
|||
setIsOpen(false)
|
||||
}
|
||||
|
||||
const getFields = async () => {
|
||||
const getFields = useCallback(async () => {
|
||||
if (!listFormCode) {
|
||||
return
|
||||
}
|
||||
|
|
@ -104,13 +104,13 @@ function JsonRowOpDialogExtraFilter({
|
|||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}, [listFormCode])
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen && data) {
|
||||
getFields()
|
||||
}
|
||||
}, [isOpen, data])
|
||||
}, [isOpen, data, getFields])
|
||||
|
||||
if (!data || !fieldList?.length) {
|
||||
return null
|
||||
|
|
@ -121,9 +121,9 @@ function JsonRowOpDialogExtraFilter({
|
|||
id="extraFilterOperation"
|
||||
isOpen={isOpen}
|
||||
preventScroll={true}
|
||||
width={data.operation === 'create' || data.operation === 'update' ? 'sm' : '450px'}
|
||||
onClose={handleClose}
|
||||
onRequestClose={handleClose}
|
||||
width={data.operation === 'create' || data.operation === 'update' ? 'sm' : '450px'}
|
||||
>
|
||||
{(data.operation === 'create' || data.operation === 'update') && (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -5,15 +5,13 @@ import {
|
|||
FormItem,
|
||||
Input,
|
||||
Notification,
|
||||
Select,
|
||||
Tabs,
|
||||
toast,
|
||||
} from '@/components/ui'
|
||||
import { ListFormJsonRowDto } from '@/proxy/admin/list-form/models'
|
||||
import { useStoreActions } from '@/store'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
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 { JsonRowDialogData } from './types'
|
||||
import {
|
||||
|
|
@ -114,7 +112,7 @@ function JsonRowOpDialogPane({
|
|||
}
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, values, isSubmitting }) => (
|
||||
{({ touched, errors, isSubmitting }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<div className="h-full overflow-y-auto p-2">
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import { SelectBoxOption } from '@/types/shared'
|
|||
import { useStoreActions, useStoreState } from '@/store'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
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 { JsonRowDialogData } from './types'
|
||||
import {
|
||||
|
|
@ -30,7 +30,6 @@ import {
|
|||
columnSummaryTypeListOptions,
|
||||
} from '../options'
|
||||
import { ChartPanesDto, ChartValueAxisDto } from '@/proxy/admin/charts/models'
|
||||
import CreatableSelect from 'react-select/creatable'
|
||||
import { tooltipFormatListOptions } from '@/proxy/admin/list-form/options'
|
||||
|
||||
const schema = object().shape({
|
||||
|
|
@ -129,10 +128,10 @@ function JsonRowOpDialogSeries({
|
|||
id="paneOperation"
|
||||
isOpen={isOpen}
|
||||
preventScroll={true}
|
||||
onClose={handleClose}
|
||||
onRequestClose={handleClose}
|
||||
width={900}
|
||||
height="90vh"
|
||||
onClose={handleClose}
|
||||
onRequestClose={handleClose}
|
||||
>
|
||||
{(data.operation === 'create' || data.operation === 'update') && (
|
||||
<Formik
|
||||
|
|
@ -282,9 +281,9 @@ function JsonRowOpDialogSeries({
|
|||
value={fieldList?.find(
|
||||
(option) => option.value === values.argumentField,
|
||||
)}
|
||||
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
||||
menuPlacement="auto"
|
||||
maxMenuHeight={150}
|
||||
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
|
|
@ -303,9 +302,9 @@ function JsonRowOpDialogSeries({
|
|||
isClearable={true}
|
||||
options={fieldList}
|
||||
value={fieldList?.find((option) => option.value === values.valueField)}
|
||||
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
||||
menuPlacement="auto"
|
||||
maxMenuHeight={150}
|
||||
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ function JsonRowOpDialogSubForm({
|
|||
}
|
||||
|
||||
loadData()
|
||||
}, [isOpen, listFormValues?.listFormCode])
|
||||
}, [isOpen, listFormValues?.listFormCode, translate])
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@ import {
|
|||
import SqlEditor from '@/views/developerKit/SqlEditor'
|
||||
import { ListFormJsonRowDto } from '@/proxy/admin/list-form/models'
|
||||
import { SelectBoxOption } from '@/types/shared'
|
||||
import { useStoreActions, useStoreState } from '@/store'
|
||||
import { useStoreActions } from '@/store'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
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 { JsonRowDialogData } from './types'
|
||||
import {
|
||||
|
|
@ -77,10 +77,10 @@ function JsonRowOpDialogWidget({
|
|||
id="widgetOperation"
|
||||
isOpen={isOpen}
|
||||
preventScroll={true}
|
||||
onClose={handleClose}
|
||||
onRequestClose={handleClose}
|
||||
width={data.operation === 'create' || data.operation === 'update' ? 900 : 450}
|
||||
height="90vh"
|
||||
onClose={handleClose}
|
||||
onRequestClose={handleClose}
|
||||
>
|
||||
{(data.operation === 'create' || data.operation === 'update') && (
|
||||
<Formik
|
||||
|
|
@ -243,13 +243,9 @@ function JsonRowOpDialogWidget({
|
|||
<div className="space-y-3">
|
||||
<div>
|
||||
<code className="text-xs bg-gray-800 p-1 rounded block mt-1">
|
||||
SELECT 'Aktif' as title, COUNT(Id) as value,
|
||||
<br />
|
||||
'blue' as color, 'FaChartBar' as icon,
|
||||
<br />
|
||||
'Aktif kayıtlar' as subTitle
|
||||
<br />
|
||||
FROM YourTable WHERE IsActive = 1
|
||||
{
|
||||
"SELECT 'Aktif' as title, COUNT(Id) as value, 'blue' as color, 'FaChartBar' as icon, 'Aktif kayıtlar' as subTitle FROM YourTable WHERE IsActive = 1"
|
||||
}
|
||||
</code>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -269,8 +265,8 @@ function JsonRowOpDialogWidget({
|
|||
>
|
||||
<SqlEditor
|
||||
value={values.sqlQuery || ''}
|
||||
onChange={(value) => setFieldValue('sqlQuery', value || '')}
|
||||
height="35vh"
|
||||
onChange={(value) => setFieldValue('sqlQuery', value || '')}
|
||||
/>
|
||||
</div>
|
||||
</FormItem>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import { useLocation, useNavigate } from 'react-router-dom'
|
|||
import * as Yup from 'yup'
|
||||
import { getMenus } from '@/services/menu.service'
|
||||
import { getPermissions } from '@/services/identity.service'
|
||||
import { DbTypeEnum, SelectCommandTypeEnum } from '@/proxy/form/models'
|
||||
import { getDataSources } from '@/services/data-source.service'
|
||||
import { sqlObjectManagerService } from '@/services/sql-query-manager.service'
|
||||
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 { useStoreActions } from '@/store/store'
|
||||
import { deleteWizardFile, getWizardFile, postListFormWizard } from '@/services/wizard.service'
|
||||
import { UiLookupDataSourceTypeEnum } from '@/proxy/form/models'
|
||||
import { ListFormWizardDto } from '@/proxy/admin/wizard/models'
|
||||
import {
|
||||
ListFormWorkflowCriteriaDto,
|
||||
SubFormDto,
|
||||
WidgetEditDto,
|
||||
WorkflowDto,
|
||||
UiLookupDataSourceTypeEnum,
|
||||
DbTypeEnum,
|
||||
SelectCommandTypeEnum,
|
||||
} from '@/proxy/form/models'
|
||||
|
||||
// ─── Formik initial values & validation ──────────────────────────────────────
|
||||
|
|
@ -271,7 +272,9 @@ const Wizard = () => {
|
|||
setSelectCommandColumns(cols)
|
||||
const colNames = new Set(cols.map((c) => c.columnName.toLowerCase()))
|
||||
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)))
|
||||
setEditingGroups([])
|
||||
// Auto-check isTenant / isBranch based on column presence
|
||||
|
|
@ -297,7 +300,11 @@ const Wizard = () => {
|
|||
const toggleColumn = (col: string) =>
|
||||
setSelectedColumns((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
|
||||
})
|
||||
|
||||
|
|
@ -548,15 +555,17 @@ const Wizard = () => {
|
|||
const previousSpacedLabel = toSpacedLabel(formik?.values.wizardName ?? '')
|
||||
const derived = deriveListFormCode(name)
|
||||
|
||||
const setAutoText = (field: keyof Pick<
|
||||
ListFormWizardDto,
|
||||
| 'languageTextMenuEn'
|
||||
| 'languageTextMenuTr'
|
||||
| 'languageTextTitleEn'
|
||||
| 'languageTextTitleTr'
|
||||
| 'languageTextDescEn'
|
||||
| 'languageTextDescTr'
|
||||
>) => {
|
||||
const setAutoText = (
|
||||
field: keyof Pick<
|
||||
ListFormWizardDto,
|
||||
| 'languageTextMenuEn'
|
||||
| 'languageTextMenuTr'
|
||||
| 'languageTextTitleEn'
|
||||
| 'languageTextTitleTr'
|
||||
| 'languageTextDescEn'
|
||||
| 'languageTextDescTr'
|
||||
>,
|
||||
) => {
|
||||
const current = formik?.values[field]
|
||||
if (!current || current === previousSpacedLabel) {
|
||||
formik?.setFieldValue(field, spacedLabel)
|
||||
|
|
@ -789,7 +798,7 @@ const Wizard = () => {
|
|||
setSubmitting(false)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, isSubmitting, values }) => (
|
||||
{({ touched, errors, values }) => (
|
||||
<Form onKeyDown={preventEnterSubmit}>
|
||||
<FormContainer size={currentStep >= 2 ? undefined : 'sm'}>
|
||||
{/* ─── Step 1: Basic Info ─────────────────────────────── */}
|
||||
|
|
@ -856,7 +865,6 @@ const Wizard = () => {
|
|||
groups={editingGroups}
|
||||
onGroupsChange={setEditingGroups}
|
||||
dbObjects={dbObjects}
|
||||
isLoadingDbObjects={isLoadingDbObjects}
|
||||
dsCode={currentDataSource}
|
||||
translate={translate}
|
||||
onBack={() => setCurrentStep(1)}
|
||||
|
|
|
|||
|
|
@ -321,7 +321,8 @@ function MenuTreeInline({
|
|||
const toggle = (code: string) =>
|
||||
setExpanded((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
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,6 @@ export interface WizardStep3Props {
|
|||
groups: WizardGroup[]
|
||||
onGroupsChange: (groups: WizardGroup[]) => void
|
||||
dbObjects: SqlObjectExplorerDto | null
|
||||
isLoadingDbObjects: boolean
|
||||
dsCode: string
|
||||
translate: (key: string) => string
|
||||
onBack: () => void
|
||||
|
|
@ -794,7 +793,6 @@ const WizardStep3 = ({
|
|||
groups,
|
||||
onGroupsChange,
|
||||
dbObjects,
|
||||
isLoadingDbObjects: _isLoadingDbObjects,
|
||||
dsCode,
|
||||
translate,
|
||||
onBack,
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue