From 85cefc6f72f3255e486f5c61eb7b6fcec5ab9ef2 Mon Sep 17 00:00:00 2001 From: Shahmar Date: Thu, 5 Feb 2026 00:10:05 +0300 Subject: [PATCH 1/7] Tar -> tar --- src/app/(withHeader)/script/create/page.usecase.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/(withHeader)/script/create/page.usecase.tsx b/src/app/(withHeader)/script/create/page.usecase.tsx index 8d25feb..c6ef210 100644 --- a/src/app/(withHeader)/script/create/page.usecase.tsx +++ b/src/app/(withHeader)/script/create/page.usecase.tsx @@ -13,7 +13,7 @@ export const pageCreateUsecase = { placeholder: 'Введите название скрипта', }, scriptCode: { - title: 'Tar-архив (.tar, .tar.gz, .tgz) *', + title: 'tar-архив (.tar, .tar.gz, .tgz) *', placeholder: 'Выберите tar-архив', }, From 0403bf7096e3196b1bfb1ddc93e4bb76932c00f1 Mon Sep 17 00:00:00 2001 From: Shahmar Date: Thu, 5 Feb 2026 00:11:13 +0300 Subject: [PATCH 2/7] remove dark changeable --- src/app/(withHeader)/page.module.css | 16 ---------------- src/app/globals.css | 13 ------------- 2 files changed, 29 deletions(-) diff --git a/src/app/(withHeader)/page.module.css b/src/app/(withHeader)/page.module.css index b82c799..2c12574 100644 --- a/src/app/(withHeader)/page.module.css +++ b/src/app/(withHeader)/page.module.css @@ -14,16 +14,6 @@ font-family: var(--font-geist-sans); } -@media (prefers-color-scheme: dark) { - .page { - --gray-rgb: 255, 255, 255; - --gray-alpha-200: rgb(var(--gray-rgb), 0.145); - --gray-alpha-100: rgb(var(--gray-rgb), 0.06); - --button-primary-hover: #ccc; - --button-secondary-hover: #1a1a1a; - } -} - .main { display: flex; flex-direction: column; @@ -162,12 +152,6 @@ a.secondary { } } -@media (prefers-color-scheme: dark) { - .logo { - filter: invert(); - } -} - .page__search { max-width: 42rem; } diff --git a/src/app/globals.css b/src/app/globals.css index b03a60b..3e7c45c 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -70,13 +70,6 @@ --shadow-lg: 0px 4px 8px 0px #00000040; } -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } -} - html, body { max-width: 100vw; @@ -105,12 +98,6 @@ a { text-decoration: none; } -@media (prefers-color-scheme: dark) { - html { - color-scheme: dark; - } -} - .layout__title { font-size: var(--font-size-lg); font-weight: 700; From 9b0161be510ef586cec4a53f3e3ca96c985daae5 Mon Sep 17 00:00:00 2001 From: Shahmar Date: Thu, 5 Feb 2026 00:57:31 +0300 Subject: [PATCH 3/7] add type label RU transform --- src/app/(withHeader)/script/[id]/page.tsx | 5 +++-- src/utils/send.ts | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/app/(withHeader)/script/[id]/page.tsx b/src/app/(withHeader)/script/[id]/page.tsx index 7d8092e..fa06e27 100644 --- a/src/app/(withHeader)/script/[id]/page.tsx +++ b/src/app/(withHeader)/script/[id]/page.tsx @@ -21,6 +21,7 @@ import { runScriptValidationSchema } from '@/app/(withHeader)/script/[id]/page.u import { useStartScript } from '@/hooks/script/useStartScript'; import { useCustomToast } from '@/hooks/other/useCustomToast'; import { notifyMutationError } from '@/utils/notifyMutationError'; +import { getTypeLabelRu } from '@/utils/send'; import { Loading } from '@/shared/Loading'; import { CsvUploader } from '@/components/CsvUploader'; @@ -200,7 +201,7 @@ export default function Page() { formikName={`in_params[${id}].data`} key={id} typeOfCard='input' - type={item.type} + type={getTypeLabelRu(item.type)} name={item.name} description={item.desc || ''} unit={item.unit || ''} @@ -217,7 +218,7 @@ export default function Page() { { @@ -15,6 +15,19 @@ export const getSendValues = (value: string) => { return 'error'; }; +export const getTypeLabelRu = (value: string) => { + switch (value) { + case ValueType.Real: + return 'Вещественное'; + case ValueType.Integer: + return 'Целое'; + case ValueType.String: + return 'Строка'; + default: + return value; + } +}; + export const getStatus = (state: JobState, code: number | undefined) => { switch (state) { case JobState.Running: From 0f72a32d3b2dc68e2046006abfda8740df723ebb Mon Sep 17 00:00:00 2001 From: Shahmar Date: Thu, 5 Feb 2026 01:12:47 +0300 Subject: [PATCH 4/7] [fix] correct visibility unit label --- .../components/ScriptParametrLayout/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/layouts/ScriptParametrsLayout/components/ScriptParametrLayout/index.tsx b/src/layouts/ScriptParametrsLayout/components/ScriptParametrLayout/index.tsx index 84c343a..6e9b90c 100644 --- a/src/layouts/ScriptParametrsLayout/components/ScriptParametrLayout/index.tsx +++ b/src/layouts/ScriptParametrsLayout/components/ScriptParametrLayout/index.tsx @@ -20,7 +20,7 @@ export const ScriptParametrLayout: FC = ({

{name}

{type}

-

{unit}

+ {unit &&

{unit}

}
@@ -47,7 +47,7 @@ export const ScriptParametrLayout: FC = ({

{name}

{type}

-

{unit}

+ {unit &&

{unit}

}

{description}

From 2f23410dd4c109e4ab9dc3af91d0e3ed6f92dcf9 Mon Sep 17 00:00:00 2001 From: Shahmar Date: Thu, 5 Feb 2026 01:25:50 +0300 Subject: [PATCH 5/7] [feat] identify own admin row --- src/app/(withHeader)/users/handle/page.tsx | 3 +++ src/components/UserTable/UserTable.module.css | 26 +++++++++++++++++++ src/components/UserTable/UserTable.props.ts | 1 + .../components/UserRow/UserRow.props.ts | 1 + .../UserTable/components/UserRow/index.tsx | 7 +++-- src/components/UserTable/index.tsx | 18 ++++++++++--- 6 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/app/(withHeader)/users/handle/page.tsx b/src/app/(withHeader)/users/handle/page.tsx index ad3415d..5045471 100644 --- a/src/app/(withHeader)/users/handle/page.tsx +++ b/src/app/(withHeader)/users/handle/page.tsx @@ -15,6 +15,7 @@ import style from './page.module.css'; import { UserTable } from '@/components/UserTable'; import { pageSelectStyles, roleUsecase } from '@/components/Filter/Filter.usecase'; import { useGetAllUsers } from '@/hooks/user/useGetAllUsers'; +import { useGetUserMe } from '@/hooks/user/useGetUserMe'; import { usePatchUser } from '@/hooks/user/usePatchUser'; import { useDeleteUser } from '@/hooks/user/useDeleteUser'; import { useCustomToast } from '@/hooks/other/useCustomToast'; @@ -24,6 +25,7 @@ const ITEMS_PER_PAGE = 8; export default function HandlePage() { const { data: usersData, isLoading, refetch } = useGetAllUsers(); + const { data: currentUser } = useGetUserMe(); const { mutate: patchUser } = usePatchUser(); const { mutate: deleteUser } = useDeleteUser(); const notify = useCustomToast(); @@ -155,6 +157,7 @@ export default function HandlePage() { ) : paginatedUsers.length > 0 ? ( diff --git a/src/components/UserTable/UserTable.module.css b/src/components/UserTable/UserTable.module.css index 46ee9ef..7de4cde 100644 --- a/src/components/UserTable/UserTable.module.css +++ b/src/components/UserTable/UserTable.module.css @@ -14,6 +14,32 @@ border-bottom: 1px solid var(--color-gray-border); } +.currentUserRow { + position: relative; + background: linear-gradient( + 90deg, + rgb(124 58 237 / 8%) 0%, + rgb(124 58 237 / 4%) 8%, + white 20%, + white 100% + ); + border-left: 3px solid var(--color-purple-main); +} + +.currentUserRow::before { + content: 'Вы'; + position: absolute; + top: 0.75rem; + right: 1rem; + padding: 0.25rem 0.5rem; + font-size: 0.75rem; + font-weight: 600; + color: var(--color-purple-main); + background: rgb(124 58 237 / 12%); + border-radius: 0.5rem; + letter-spacing: 0.02em; +} + .rowCell { padding: 1rem 1.5rem; flex: 1; diff --git a/src/components/UserTable/UserTable.props.ts b/src/components/UserTable/UserTable.props.ts index 8b88f03..0479d79 100644 --- a/src/components/UserTable/UserTable.props.ts +++ b/src/components/UserTable/UserTable.props.ts @@ -3,6 +3,7 @@ import type { HTMLAttributes } from 'react'; export interface Props extends HTMLAttributes { users: User[]; + currentUserId?: string; className?: string; onEditUser: (user: User) => void; onDeleteUser: (userId: string) => void; diff --git a/src/components/UserTable/components/UserRow/UserRow.props.ts b/src/components/UserTable/components/UserRow/UserRow.props.ts index fa65675..c010168 100644 --- a/src/components/UserTable/components/UserRow/UserRow.props.ts +++ b/src/components/UserTable/components/UserRow/UserRow.props.ts @@ -3,6 +3,7 @@ import type { HTMLAttributes } from 'react'; export interface Props extends HTMLAttributes { user: User; + isCurrentUser?: boolean; onEditUser: (user: User) => void; onDeleteUser: (userId: string) => void; } diff --git a/src/components/UserTable/components/UserRow/index.tsx b/src/components/UserTable/components/UserRow/index.tsx index 75fdaff..d207df9 100644 --- a/src/components/UserTable/components/UserRow/index.tsx +++ b/src/components/UserTable/components/UserRow/index.tsx @@ -8,9 +8,10 @@ import { PasswordCell } from '../cells/PasswordCell'; import { RoleCell } from '../cells/RoleCell'; import { ActionsCell } from '../cells/ActionsCell'; import { validateEmail, validateFullname, validatePassword } from '@/utils/validators'; +import cn from 'classnames'; import generalStyle from './../../UserTable.module.css'; -export const UserRow: FC = ({ user, onEditUser, onDeleteUser }) => { +export const UserRow: FC = ({ user, isCurrentUser, onEditUser, onDeleteUser }) => { const [isEditing, setIsEditing] = useState(false); const [editData, setEditData] = useState({ name: user.name, @@ -133,7 +134,9 @@ export const UserRow: FC = ({ user, onEditUser, onDeleteUser }) => { }; return ( -
+
void; } | null; -export const UserTable: FC = ({ users, className, onEditUser, onDeleteUser }) => { +export const UserTable: FC = ({ + users, + currentUserId, + className, + onEditUser, + onDeleteUser, +}) => { const [dialog, setDialog] = useState(null); + const orderedUsers = + currentUserId != null + ? [...users].sort((a, b) => (a.id === currentUserId ? -1 : b.id === currentUserId ? 1 : 0)) + : users; + const handleEditUser = (user: User) => { setDialog({ visible: true, @@ -34,7 +45,7 @@ export const UserTable: FC = ({ users, className, onEditUser, onDeleteUse }; const handleDeleteUser = (userId: string) => { - const user = users.find((u) => u.id === userId); + const user = orderedUsers.find((u) => u.id === userId); if (!user) { return; } @@ -68,10 +79,11 @@ export const UserTable: FC = ({ users, className, onEditUser, onDeleteUse )}
- {users.map((user) => ( + {orderedUsers.map((user) => ( From d4e2e6e13510b945f4e7bdaab9492340759c6eb2 Mon Sep 17 00:00:00 2001 From: Shahmar Date: Thu, 5 Feb 2026 01:51:41 +0300 Subject: [PATCH 6/7] [fix] change field templates restrictions --- .../script/create/page.usecase.tsx | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/app/(withHeader)/script/create/page.usecase.tsx b/src/app/(withHeader)/script/create/page.usecase.tsx index c6ef210..6ed1081 100644 --- a/src/app/(withHeader)/script/create/page.usecase.tsx +++ b/src/app/(withHeader)/script/create/page.usecase.tsx @@ -42,29 +42,23 @@ export const pageCreateUsecase = { const ParametrSheme = Yup.object().shape({ name: Yup.string() - .min(1, 'Название должно иметь хотя бы 2 символа') + .min(1, 'Название должно иметь хотя бы 1 символ') .max(50, 'Название должно быть меньше 50 символов') .required('Название обязательно'), - desc: Yup.string() - .min(1, 'Описание должно иметь хотя бы 2 символа') - .max(50, 'Описание должно быть меньше 50 символов') - .required('Описание обязательно'), + desc: Yup.string().max(80, 'Описание должно быть меньше 80 символов').optional(), type: Yup.string() - .min(1, 'Тип должен иметь хотя бы 2 символа') + .min(1, 'Тип должен иметь хотя бы 1 символ') .max(50, 'Тип должен быть меньше 50 символов') .required('Тип обязателен'), - measure: Yup.string() - .min(1, 'Единица измерения должна иметь хотя бы 2 символа') - .max(50, 'Единица измерения должна быть меньше 50 символов') - .required('Единица измерения обязательна'), + measure: Yup.string().max(50, 'Единица измерения должна быть меньше 50 символов').optional(), }); export const ScriptSchema = Yup.object().shape({ name: Yup.string() - .min(1, 'Название должно иметь хотя бы 2 символа') - .max(50, 'Название должно быть меньше 50 символов') + .min(1, 'Название должно иметь хотя бы 1 символ') + .max(80, 'Название должно быть меньше 80 символов') .required('Название обязательно'), - desc: Yup.string().max(50, 'Описание должно быть меньше 50 символов'), + desc: Yup.string().max(1000, 'Описание должно быть меньше 1000 символов'), inputParams: Yup.array().of(ParametrSheme), outputParams: Yup.array().of(ParametrSheme), file: Yup.mixed().required('Скрипт обязателен'), From 65b1ca1897c849bbf799ff8bf3efa04000933ccc Mon Sep 17 00:00:00 2001 From: Shahmar Date: Thu, 5 Feb 2026 02:08:15 +0300 Subject: [PATCH 7/7] [fix] trim before send --- src/app/(withHeader)/script/create/page.tsx | 16 ++++++++-------- .../(withHeader)/script/create/page.usecase.tsx | 17 ++++++++++++++--- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/app/(withHeader)/script/create/page.tsx b/src/app/(withHeader)/script/create/page.tsx index 527ca7d..a4037ad 100644 --- a/src/app/(withHeader)/script/create/page.tsx +++ b/src/app/(withHeader)/script/create/page.tsx @@ -45,19 +45,19 @@ export default function CreatePage() { createScript( { - name: values.name, - desc: values.desc, + name: values.name.trim(), + desc: values.desc?.trim() ?? '', archiveID: String(file_id), in: values.inputParams.map((param) => ({ - name: param.name, - desc: param.desc, - unit: param.measure, + name: param.name.trim(), + desc: param.desc?.trim() ?? '', + unit: param.measure?.trim() ?? '', type: getSendValues(param.type) as ValueType, })), out: values.outputParams.map((param) => ({ - name: param.name, - desc: param.desc, - unit: param.measure, + name: param.name.trim(), + desc: param.desc?.trim() ?? '', + unit: param.measure?.trim() ?? '', type: getSendValues(param.type) as ValueType, })), }, diff --git a/src/app/(withHeader)/script/create/page.usecase.tsx b/src/app/(withHeader)/script/create/page.usecase.tsx index 6ed1081..ea723b9 100644 --- a/src/app/(withHeader)/script/create/page.usecase.tsx +++ b/src/app/(withHeader)/script/create/page.usecase.tsx @@ -4,6 +4,8 @@ import cn from 'classnames'; import { AddParametrIcon } from '@/components/icons/AddParametricon'; import * as Yup from 'yup'; +const trimString = (v: unknown) => (typeof v === 'string' ? v.trim() : v); + export const pageCreateUsecase = { main: { header:

Основная информация

, @@ -42,23 +44,32 @@ export const pageCreateUsecase = { const ParametrSheme = Yup.object().shape({ name: Yup.string() + .transform(trimString) .min(1, 'Название должно иметь хотя бы 1 символ') .max(50, 'Название должно быть меньше 50 символов') .required('Название обязательно'), - desc: Yup.string().max(80, 'Описание должно быть меньше 80 символов').optional(), + desc: Yup.string() + .transform(trimString) + .max(80, 'Описание должно быть меньше 80 символов') + .optional(), type: Yup.string() + .transform(trimString) .min(1, 'Тип должен иметь хотя бы 1 символ') .max(50, 'Тип должен быть меньше 50 символов') .required('Тип обязателен'), - measure: Yup.string().max(50, 'Единица измерения должна быть меньше 50 символов').optional(), + measure: Yup.string() + .transform(trimString) + .max(50, 'Единица измерения должна быть меньше 50 символов') + .optional(), }); export const ScriptSchema = Yup.object().shape({ name: Yup.string() + .transform(trimString) .min(1, 'Название должно иметь хотя бы 1 символ') .max(80, 'Название должно быть меньше 80 символов') .required('Название обязательно'), - desc: Yup.string().max(1000, 'Описание должно быть меньше 1000 символов'), + desc: Yup.string().transform(trimString).max(1000, 'Описание должно быть меньше 1000 символов'), inputParams: Yup.array().of(ParametrSheme), outputParams: Yup.array().of(ParametrSheme), file: Yup.mixed().required('Скрипт обязателен'),