diff --git a/ui/dev-dist/sw.js b/ui/dev-dist/sw.js index 30800934..3f45c2fa 100644 --- a/ui/dev-dist/sw.js +++ b/ui/dev-dist/sw.js @@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict'; "revision": "3ca0b8505b4bec776b69afdba2768812" }, { "url": "index.html", - "revision": "0.hld5cocdcl" + "revision": "0.uun45k3p9s" }], {}); workbox.cleanupOutdatedCaches(); workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), { diff --git a/ui/package-lock.json b/ui/package-lock.json index 84192a3d..267bc5d0 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -3742,11 +3742,10 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -4370,9 +4369,9 @@ "dev": true }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6171,9 +6170,9 @@ } }, "node_modules/eslint-plugin-n/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "dependencies": { "balanced-match": "^1.0.0" @@ -6642,9 +6641,9 @@ } }, "node_modules/filelist/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "dependencies": { "balanced-match": "^1.0.0" @@ -10421,10 +10420,9 @@ } }, "node_modules/readdir-glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "license": "MIT", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dependencies": { "balanced-match": "^1.0.0" } @@ -11991,10 +11989,9 @@ } }, "node_modules/sucrase/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "license": "MIT", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dependencies": { "balanced-match": "^1.0.0" } @@ -12825,11 +12822,10 @@ } }, "node_modules/vite": { - "version": "5.4.15", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.15.tgz", - "integrity": "sha512-6ANcZRivqL/4WtwPGTKNaosuNJr5tWiftOC7liM7G9+rMb8+oeJeyzymDu4rTN93seySBmbjSfsS3Vzr19KNtA==", + "version": "5.4.19", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", + "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", "dev": true, - "license": "MIT", "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", diff --git a/ui/src/views/menu/MenuItemComponent.tsx b/ui/src/views/menu/MenuItemComponent.tsx index 932b1817..514c9af3 100644 --- a/ui/src/views/menu/MenuItemComponent.tsx +++ b/ui/src/views/menu/MenuItemComponent.tsx @@ -1,9 +1,29 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import { useSortable } from '@dnd-kit/sortable' import { CSS } from '@dnd-kit/utilities' import * as Icons from 'lucide-react' import { MenuItem } from '@/@types/menu' import { useLocalization } from '@/utils/hooks/useLocalization' +import { MenuService } from '@/services/menu.service' +import { MenuDto } from '@/proxy/menus' +import navigationIcon from '@/configs/navigation-icon.config' +import { FaQuestionCircle } from 'react-icons/fa' +import { + Button, + Dialog, + FormContainer, + FormItem, + Input, + Switcher, + Notification, + toast, + Select, +} from '@/components/ui' +import { Field, FieldProps, Form, Formik } from 'formik' +import { SelectBoxOption } from '@/shared/types' +import { getPermissionsList } from '@/proxy/admin/identity.service' +import { PermissionDefinitionRecord } from '@/proxy/admin' +import * as Yup from 'yup' interface MenuItemComponentProps { item: MenuItem @@ -11,6 +31,7 @@ interface MenuItemComponentProps { depth: number children?: React.ReactNode isDragOverlay?: boolean + refetch: () => void } export const MenuItemComponent: React.FC = ({ @@ -19,7 +40,9 @@ export const MenuItemComponent: React.FC = ({ depth, children, isDragOverlay = false, + refetch, }) => { + const [permissions, setPermissions] = useState([]) const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id: item.id || '', data: { @@ -29,8 +52,20 @@ export const MenuItemComponent: React.FC = ({ disabled: !isDesignMode, }) - const { translate } = useLocalization() + const validationSchema = Yup.object().shape({ + code: Yup.string().required('Code is required'), + displayName: Yup.string().required('Display Name is required'), + order: Yup.number().typeError('Order must be a number').required('Order is required'), + url: Yup.string().nullable(), + icon: Yup.string().nullable(), + cssClass: Yup.string().nullable(), + requiredPermissionName: Yup.string().nullable(), + target: Yup.string().nullable(), + elementId: Yup.string().nullable(), + isDisabled: Yup.boolean(), + }) + const { translate } = useLocalization() const style = { transform: CSS.Transform.toString(transform), transition, @@ -42,14 +77,59 @@ export const MenuItemComponent: React.FC = ({ return IconComponent ? : } - const [isExpanded, setIsExpanded] = React.useState(true) + const [isExpanded, setIsExpanded] = useState(true) + const [isModalOpen, setIsModalOpen] = useState(false) + const [formData, setFormData] = useState>({ + code: '', + displayName: '', + order: (item.children?.length || 0) + 1, + parentCode: item.code, + url: '', + icon: '', + cssClass: '', + requiredPermissionName: '', + target: '', + isDisabled: false, + elementId: '', + }) const toggleExpanded = () => { - if (!isDesignMode) { - setIsExpanded(!isExpanded) + if (!isDesignMode) setIsExpanded(!isExpanded) + } + + const handleCreate = async () => { + const menuService = new MenuService() + await menuService.create(formData as MenuDto) + setIsModalOpen(false) + refetch() + } + + const handleDelete = async () => { + const confirmed = window.confirm(`Delete "${item.displayName}"?`) + if (!confirmed) return + const menuService = new MenuService() + await menuService.delete(item.id!) + refetch() + } + + 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 (
= ({ `} {...(isDesignMode ? { ...attributes, ...listeners } : { onClick: toggleExpanded })} > + {isDesignMode && ( +
+ + +
+ )} +
-
{item.icon && getIcon(item.icon)}
+
+ {navigationIcon[item.icon || ''] ?? } +
0 ? 'font-semibold' : 'font-normal'} + ${item.children && item.children.length > 0 ? 'font-semibold' : 'font-normal'} `} > {translate('::' + item.displayName)} @@ -95,6 +188,147 @@ export const MenuItemComponent: React.FC = ({
{children && (!isDesignMode ? isExpanded : true) &&
{children}
} + + {isModalOpen && ( + setIsModalOpen(false)} + onRequestClose={() => setIsModalOpen(false)} + width={600} + > +
{translate('::New Item')}
+ { + try { + const menuService = new MenuService() + await menuService.create(values as MenuDto) + toast.push( + + {translate('::KayitEklendi')} + , + { placement: 'top-center' }, + ) + setIsModalOpen(false) + refetch() + } catch (error) { + toast.push( + + {translate('::IslemBasarisiz')} + , + { placement: 'top-center' }, + ) + } finally { + setSubmitting(false) + } + }} + > + {({ values, errors, touched, isSubmitting, handleChange }) => ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {({ field, form }: FieldProps) => ( +