diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Administration.cs b/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Administration.cs index 1f7a263..f668d5d 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Administration.cs +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Administration.cs @@ -4104,7 +4104,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep ColumnCustomizationJson = DefaultColumnCustomizationJson, PermissionJson = DefaultFieldPermissionJson(listForm.Name), PivotSettingsJson = DefaultPivotSettingsJson, - EditorOptions = EncodeHtmlJson + EditorOptions = EncodeHtmlJson(false) }, new() { ListFormCode = listForm.ListFormCode, diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_DefaultJsons.cs b/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_DefaultJsons.cs index e353237..74176e0 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_DefaultJsons.cs +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_DefaultJsons.cs @@ -49,7 +49,7 @@ public static class ListFormSeeder_DefaultJsons }); public static readonly string DefaultFilterJson = "\"IsDeleted\" = 'false'"; - public static readonly string EncodeHtmlJson = "{ \"encodeHtml\" = false }"; + public static string EncodeHtmlJson(bool value) => JsonSerializer.Serialize(new { encodeHtml = value }); public static string DefaultFilterRowJson(bool visible = true) => JsonSerializer.Serialize(new GridFilterRowDto { Visible = visible }); public static string DefaultHeaderFilterJson(bool visible = true) => JsonSerializer.Serialize(new { Visible = visible }); public static string DefaultSearchPanelJson(bool visible = true) => JsonSerializer.Serialize(new { Visible = visible }); diff --git a/ui/src/assets/styles/tailwind/index.css b/ui/src/assets/styles/tailwind/index.css index f7c9e8e..1706cd1 100644 --- a/ui/src/assets/styles/tailwind/index.css +++ b/ui/src/assets/styles/tailwind/index.css @@ -3,6 +3,71 @@ @tailwind utilities; @layer base { + :root, + .light { + --app-scrollbar-size: 8px; + --app-scrollbar-thumb: #9ca3af; + --app-scrollbar-thumb-hover: #6b7280; + --app-scrollbar-track: transparent; + } + + .dark { + --app-scrollbar-thumb: #4b5563; + --app-scrollbar-thumb-hover: #6b7280; + } + + * { + scrollbar-color: var(--app-scrollbar-thumb) var(--app-scrollbar-track); + scrollbar-width: thin; + } + + *::-webkit-scrollbar { + width: var(--app-scrollbar-size); + height: var(--app-scrollbar-size); + } + + *::-webkit-scrollbar-track { + background: var(--app-scrollbar-track); + } + + *::-webkit-scrollbar-thumb { + min-height: 40px; + border: 2px solid transparent; + border-radius: 999px; + background-color: var(--app-scrollbar-thumb); + background-clip: content-box; + } + + *::-webkit-scrollbar-thumb:hover { + background-color: var(--app-scrollbar-thumb-hover); + } + + *::-webkit-scrollbar-corner { + background: transparent; + } + + .dx-scrollable-scrollbar.dx-scrollbar-vertical, + .dx-scrollable-scrollbar.dx-scrollbar-vertical .dx-scrollable-scroll { + width: var(--app-scrollbar-size) !important; + } + + .dx-scrollable-scrollbar.dx-scrollbar-horizontal, + .dx-scrollable-scrollbar.dx-scrollbar-horizontal .dx-scrollable-scroll { + height: var(--app-scrollbar-size) !important; + } + + .dx-scrollable-scroll { + border-radius: 999px !important; + background-color: var(--app-scrollbar-thumb) !important; + } + + .dx-scrollable-scroll:hover, + .dx-scrollable-scrollbar.dx-state-hover .dx-scrollable-scroll, + .dx-scrollable-scrollbar.dx-scrollbar-hoverable.dx-scrollable-scrollbar-active + .dx-scrollable-scroll { + background-color: var(--app-scrollbar-thumb-hover) !important; + } + body { @apply text-gray-500 dark:text-gray-400 text-xs bg-gray-100 dark:bg-gray-900 leading-normal; -webkit-font-smoothing: antialiased; diff --git a/ui/src/components/ui/ScrollBar/ScrollBar.tsx b/ui/src/components/ui/ScrollBar/ScrollBar.tsx index af1ea40..9024f92 100644 --- a/ui/src/components/ui/ScrollBar/ScrollBar.tsx +++ b/ui/src/components/ui/ScrollBar/ScrollBar.tsx @@ -10,7 +10,14 @@ export interface ScrollbarProps extends ReactCustomScrollbarProps { export type ScrollbarRef = Scrollbars const ScrollBar = forwardRef((props, ref) => { - const { direction = 'ltr', ...rest } = props + const { + direction = 'ltr', + renderThumbVertical, + renderThumbHorizontal, + renderTrackVertical, + renderTrackHorizontal, + ...rest + } = props return ( ((props, ref) => { }} /> )} + renderTrackVertical={ + renderTrackVertical || + ((props) => ( +
+ )) + } + renderTrackHorizontal={ + renderTrackHorizontal || + ((props) => ( +
+ )) + } + renderThumbVertical={ + renderThumbVertical || + ((props) => ( +
+ )) + } + renderThumbHorizontal={ + renderThumbHorizontal || + ((props) => ( +
+ )) + } {...rest} /> ) diff --git a/ui/src/views/admin/listForm/edit/form-fields/FormFieldTabDetails.tsx b/ui/src/views/admin/listForm/edit/form-fields/FormFieldTabDetails.tsx index 9bd0f6f..1370b2d 100644 --- a/ui/src/views/admin/listForm/edit/form-fields/FormFieldTabDetails.tsx +++ b/ui/src/views/admin/listForm/edit/form-fields/FormFieldTabDetails.tsx @@ -1,11 +1,13 @@ -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, ListFormFieldEditTabs } from '@/proxy/admin/list-form-field/models' import { SelectBoxOption } from '@/types/shared' import { useLocalization } from '@/utils/hooks/useLocalization' import { Field, FieldProps, Form, Formik } from 'formik' +import { useState } from 'react' +import { FaSlidersH } from 'react-icons/fa' import { number, object, string } from 'yup' import { dbSourceTypeOptions, listFormAlignmentOptions } from '../options' +import EditorOptionsBuilderDialog from '../json-row-operations/EditorOptionsBuilderDialog' import { FormFieldEditProps } from './FormFields' import { tooltipFormatListOptions } from '@/proxy/admin/list-form/options' @@ -15,6 +17,9 @@ const schema = object().shape({ placeHolder: string(), bandName: string(), sourceDbType: number().required(), + alignment: string(), + format: string(), + editorOptions: string().max(1000), }) function FormFieldTabDetails({ @@ -26,6 +31,7 @@ function FormFieldTabDetails({ initialValues: ColumnFormatEditDto } & FormFieldEditProps) { const { translate } = useLocalization() + const [isEditorOptionsDialogOpen, setIsEditorOptionsDialogOpen] = useState(false) return ( - {({ touched, errors, isSubmitting, values }) => ( + {({ touched, errors, isSubmitting, values, setFieldValue }) => (
@@ -123,16 +129,33 @@ function FormFieldTabDetails({ invalid={errors.editorOptions && touched.editorOptions} errorMessage={errors.editorOptions} > - +
+ +
+ setIsEditorOptionsDialogOpen(false)} + onApply={(val) => setFieldValue('editorOptions', val)} + /> diff --git a/ui/src/views/admin/listForm/edit/json-row-operations/EditorOptionsBuilderDialog.tsx b/ui/src/views/admin/listForm/edit/json-row-operations/EditorOptionsBuilderDialog.tsx index 7734d50..541e3aa 100644 --- a/ui/src/views/admin/listForm/edit/json-row-operations/EditorOptionsBuilderDialog.tsx +++ b/ui/src/views/admin/listForm/edit/json-row-operations/EditorOptionsBuilderDialog.tsx @@ -19,7 +19,7 @@ type EditorOptionsBuilderDialogProps = { } const baseInputClass = - 'w-full h-9 px-2 rounded border border-gray-200 dark:border-gray-600 bg-white dark:bg-gray-800 text-sm text-gray-700 dark:text-gray-100 focus:outline-none focus:border-indigo-400' + 'w-full min-w-0 h-9 px-2 rounded border border-gray-200 dark:border-gray-600 bg-white dark:bg-gray-800 text-sm text-gray-700 dark:text-gray-100 focus:outline-none focus:border-indigo-400' const boolOptions = [ { key: 'showClearButton', label: 'showClearButton' }, @@ -145,6 +145,18 @@ function toSelectValue(value: unknown): string { return typeof value === 'string' ? value : '' } +function toEncodeHtmlSelectValue(value: unknown): string { + if (value === true) return 'true' + if (value === false) return 'false' + return value === 'auto' ? 'auto' : '' +} + +function readEncodeHtmlSelectValue(value: string) { + if (value === 'true') return true + if (value === 'false') return false + return undefined +} + function readCustomValue(option: CustomOption) { if (option.type === 'boolean') return option.value === 'true' if (option.type === 'number') return Number(option.value || 0) @@ -278,23 +290,182 @@ function EditorOptionsBuilderDialog({ return isEmptyObject(next) ? '' : JSON.stringify(next, null, 2) }, [customOptions, options]) + const presetButtons = ( +
+ + + + + + + + + + + + + + + + +
+ ) + return ( - +
Editor Options Builder
@@ -306,8 +477,18 @@ function EditorOptionsBuilderDialog({
)} -
-
+
+
+ Hazır Ayarlar +
+ {presetButtons} +
+ +
+
1. Hızlı Anahtarlar
-
+
{boolOptions.map((option) => ( ))} +
@@ -340,7 +539,7 @@ function EditorOptionsBuilderDialog({ > 2. Boyut ve Görünüm
-
+
-
+
-
+
-
-
-
- Hazır Ayarlar -
-
- - - - - - - - - - - - - - - - -
-
- +
- - JSON Önizleme + + + JSON Önizleme + + + {preview ? `${preview.length} karakter` : 'boş'} +
-
+            
               {preview || '{}'}