From 62b4d710b348a20f4ddbae88187fb0b7fbb78a34 Mon Sep 17 00:00:00 2001 From: emy Date: Sun, 25 Feb 2024 19:41:54 +0500 Subject: [PATCH] all --- src/pages/Repository/Repository.tsx | 76 +++---- src/pages/Repository/blocks/EditRepModal.tsx | 164 +++++++++++++-- src/pages/Repository/blocks/NewRepModal.tsx | 202 +++++++++++-------- src/pages/Repository/blocks/RepTableItem.tsx | 36 ++-- src/pages/Repository/types.ts | 16 +- src/services/repositoryServices.ts | 5 +- 6 files changed, 328 insertions(+), 171 deletions(-) diff --git a/src/pages/Repository/Repository.tsx b/src/pages/Repository/Repository.tsx index ac10421..7856b72 100644 --- a/src/pages/Repository/Repository.tsx +++ b/src/pages/Repository/Repository.tsx @@ -15,14 +15,15 @@ import { RepSelectNotification, SearchNotification } from './styles' -import { T_ColumnsState, T_NewRepository, T_RepositoryItem } from './types' +import { T_ColumnsState, T_RepositoryItem } from './types' type Props = {} export default function Repository({}: Props) { - const [errorState, setErrorState] = useState(false) - const [loadingState, setLoadingState] = useState(true) + const [firstLoadingState, setFirstLoadingState] = useState(true) + const [loadingState, setLoadingState] = useState(false) + const [errorState, setErrorState] = useState(false) const [searchNotification, setSearchNotification] = useState(false) const [totalCount, setTotalCount] = useState(0) @@ -40,16 +41,27 @@ export default function Repository({}: Props) { }) const getRep = async () => { - setSearchNotification(false) - const response = await RepositoryService.getRepository(queryParams) - if (response.status === 200) { - response.data.Data.length === 0 - ? setSearchNotification(true) - : (setRepository(response.data.Data), - setTotalCount(response.data.Total)) + if (!firstLoadingState) setLoadingState(true) + setErrorState(false) + try { + const response = await RepositoryService.getRepository(queryParams) + if (response.status === 200) { + response.data.Data.length === 0 + ? setSearchNotification(true) + : (setRepository(response.data.Data), + setTotalCount(response.data.Total), + setSearchNotification(false)) + } + } catch (error) { + setErrorState(true) } + setLoadingState(false) + setFirstLoadingState(false) } + useEffect(() => { + getRep() + }, []) useEffect(() => { getRep() @@ -70,10 +82,15 @@ export default function Repository({}: Props) { const [notChecked, setNotChecked] = useState([]) useEffect(() => { - notChecked.length === Repository.length && - (setSelectAll(false), setNotChecked([])) + !errorState || + loadingState || + (firstLoadingState && + notChecked.length === Repository .length && + (setSelectAll(false), setNotChecked([]))) }, [notChecked]) + const [modal, setModal] = useState(false) + const groupDelete = async () => { const deletePromises = checkedColumns.map((item) => RepositoryService.deleteRepository(item) @@ -101,33 +118,7 @@ export default function Repository({}: Props) { getRep() } - const [newRep, setNewRep] = useState({ - Name: '', - Description: '', - ShortDescription: '', - Version: '', - Category: '', - }) - const [modal, setModal] = useState(false) - - useEffect(() => { - console.log(Repository) - }, [Repository]) - - useEffect(() => { - setNewRep({ - Name: '', - Description: '', - ShortDescription: '', - Version: '', - Category: '', - }) - }, [modal]) - - useEffect(() => { - getRep() - }, []) return ( <> @@ -215,15 +206,10 @@ export default function Repository({}: Props) { )} - + )} + ) } diff --git a/src/pages/Repository/blocks/EditRepModal.tsx b/src/pages/Repository/blocks/EditRepModal.tsx index 18d285a..5f0afdf 100644 --- a/src/pages/Repository/blocks/EditRepModal.tsx +++ b/src/pages/Repository/blocks/EditRepModal.tsx @@ -1,15 +1,28 @@ -import { useEffect, useState } from 'react' +import { useEffect, useRef, useState } from 'react' import MainButton from 'src/components/UI/button/MainButton' import MainInput from 'src/components/UI/input/MainInput' import Modal from 'src/components/UI/modal/Modal' +import Textarea from 'src/components/UI/input/Textarea' +import RepositoryService from 'src/services/repositoryServices' import styled from 'styled-components' -import { T_NewRepository } from '../types' +import { T_NewRepository, T_RepositoryItem } from '../types' +const NewRepErrorMessageContainer = styled.div` + position: relative; + z-index: 4; +` + +const NewRepErrorMessage = styled.div` + display: flex; + flex-direction: column; + align-items: end; + gap: 20px; +` type Props = { modal: boolean setModal: (param: boolean) => void - repository: T_NewRepository - editRep: (param: T_NewRepository) => void + repository: T_RepositoryItem + getRep: () => void } const ModalContainer = styled.div` @@ -23,21 +36,46 @@ const ModalContainer = styled.div` gap: 20px; } ` +const NewRepFileBlock = styled.div` + display: flex; + align-items: center; + justify-content: space-between; -export default function EditRepModal({ - modal, - setModal, - repository, - editRep -}: Props) { - const [editRepData, setEditRepData] = useState(repository) + input { + display: none; + } + p { + font-size: 18px; + } - //const [errorMessage, setErrorMessage] = useState(false) + span { + font-weight: 600; + } +` +export default function EditRepModal({ modal, setModal, repository, getRep }: Props){ + const [error, setError] = useState({ + state: false, + message: '' + }) + + const [loading, setLoading] = useState(false) + + const setErrorState = (value: boolean) => { + setError({ ...error, state: value }) + } + + const [editRepData, setEditRepData] = useState({ + Name: repository.Name, + Description: repository.Description, + ShortDescription: repository.ShortDescription, + Version: repository.Version, + Category: repository.Category + }) const handleNameChange = (e: React.ChangeEvent) => { setEditRepData({ ...editRepData, Name: e.target.value }) } - const handleDescriptionChange = (e: React.ChangeEvent) => { + const handleDescriptionChange = (e: React.ChangeEvent) => { setEditRepData({ ...editRepData, Description: e.target.value }) } const handleShortDescriptionChange = (e: React.ChangeEvent) => { @@ -50,13 +88,70 @@ export default function EditRepModal({ setEditRepData({ ...editRepData, Category: e.target.value }) } - useEffect(() => { - setEditRepData({ ...editRepData,}) - }, []) + const [formValid, setFormValid] = useState(false) + useEffect(() => { + setFormValid( + editRepData.Name !== '' && + editRepData.Description !== '' && + editRepData.ShortDescription !== '' && + editRepData.Version !== '' && + editRepData.Category !== '' + ) + }, [editRepData]) + const fileInputRef = useRef(null); + const [selectedFile, setSelectedFile] = useState(null); + + const handleFileChange = () => { + const file = fileInputRef.current?.files?.[0] + if (file) { + setSelectedFile(file) + } + } + + const handleFileClick = () => { + fileInputRef.current?.click() + } + const updateRep = async () => { + setLoading(true) + try { + if ( + !( + editRepData.Category === repository.Category && + editRepData.Description === repository.Description && + editRepData.Name === repository.Name && + editRepData.ShortDescription === repository.ShortDescription && + editRepData.Version === repository.Version + ) + ) { + const response = await RepositoryService.editRepository(repository.Id, editRepData) + if (response.status === 406) { + setError({ state: true, message: response.data }) + setLoading(false) + return + } + } + + if (repository.Url !== selectedFile && selectedFile instanceof File) { + const response = await RepositoryService.addFile(selectedFile, repository.Id) + if (response.status === 406) { + setError({ state: true, message: response.data }) + setLoading(false) + return + } + } + setLoading(false) + setModal(false) + getRep() + } catch (error) {} + } + return ( + <> + +

Изменение пакета в репозитории

- +
+ + + {selectedFile ? ( +

+ Выбранный файл: + {selectedFile.name} +

+ ) : ( +

+ Файл не выбран +

+ )} + Выбрать файл +
+
setModal(false)} > Отмена - editRep(editRepData)}> + Сохранить
+ + + +

{error.message}

+ setErrorState(false)}>Ok +
+
+
+ + ) } diff --git a/src/pages/Repository/blocks/NewRepModal.tsx b/src/pages/Repository/blocks/NewRepModal.tsx index bda248c..e2d2414 100644 --- a/src/pages/Repository/blocks/NewRepModal.tsx +++ b/src/pages/Repository/blocks/NewRepModal.tsx @@ -1,13 +1,39 @@ -import { useEffect, useRef, ChangeEvent, useState } from 'react' +import { useEffect, useRef, useState } from 'react' import MainButton from 'src/components/UI/button/MainButton' import MainInput from 'src/components/UI/input/MainInput' import Modal from 'src/components/UI/modal/Modal' +import Textarea from 'src/components/UI/input/Textarea' import RepositoryService from 'src/services/repositoryServices' import styled from 'styled-components' import { T_NewRepository } from '../types' +const NewRepErrorMessageContainer = styled.div` + position: relative; + z-index: 4; +` +const NewRepErrorMessage = styled.div` + display: flex; + flex-direction: column; + align-items: end; + gap: 20px; +` +const NewAppFileBlock = styled.div` + display: flex; + align-items: center; + justify-content: space-between; + input { + display: none; + } + p { + font-size: 18px; + } + + span { + font-weight: 600; + } +` const ModalContainer = styled.div` display: flex; @@ -21,66 +47,52 @@ const ModalContainer = styled.div` } ` -const ErrorMessageContainer = styled.div` - display: flex; - flex-direction: column; - align-items: end; - gap: 20px; -` - -const Test = styled.div` - z-index: 3; -` - type Props = { modal: boolean setModal: (param: boolean) => void - newRep: T_NewRepository - setNewRep: (param: T_NewRepository) => void getRep: () => void } -export default function NewRepModal({ - modal, - setModal, - newRep, - setNewRep, - getRep -}: Props) { - const [errorMessage, setErrorMessage] = useState(false) +export default function NewRepModal({ modal, setModal, getRep }: Props) { + const [newRep, setNewRep] = useState({ + Name: '', + Description: '', + ShortDescription: '', + Version: '', + Category: '' + }) + const [selectedFile, setSelectedFile] = useState(null) + useEffect(() => { + setNewRep({ + Name: '', + Description: '', + ShortDescription: '', + Version: '', + Category: '' + }) + setSelectedFile(null) + }, [modal]) + + const [formValid, setFormValid] = useState(false) + + useEffect(() => { + setFormValid( + newRep.Name !== '' && + newRep.Description !== '' && + newRep.ShortDescription !== '' && + newRep.Version !== '' && + newRep.Category !== '' + ) + }, [newRep]) + + const [errorState, setErrorState] = useState(false) - const CreateRep = async () => { - const response = await RepositoryService.createRepository(newRep) - if (response.status === 406) { - setNewRep({ ...newRep}) - setErrorMessage(true) - } else { - setModal(false) - getRep() - } - } - const fileInputRef = useRef(null); - const [selectedFile, setSelectedFile] = useState(null); - - const handleFileChange = (event: ChangeEvent) => { - const files = event.target.files; - if (files && files.length > 0) { - const file = files[0]; - setSelectedFile(file); - } - }; - - const handleButtonClick = () => { - if (fileInputRef.current) { - fileInputRef.current.click(); - } - }; const handleNameChange = (e: React.ChangeEvent) => { setNewRep({ ...newRep, Name: e.target.value }) } - const handleDescriptionChange = (e: React.ChangeEvent) => { + const handleDescriptionChange = (e: React.ChangeEvent) => { setNewRep({ ...newRep, Description: e.target.value }) } const handleShortDescriptionChange = (e: React.ChangeEvent) => { @@ -92,10 +104,40 @@ export default function NewRepModal({ const handleCategoryChange = (e: React.ChangeEvent) => { setNewRep({ ...newRep, Category: e.target.value }) } + const fileInputRef = useRef(null) + + const handleFileChange = () => { + const file = fileInputRef.current?.files?.[0] + if (file) { + setSelectedFile(file) + } + } + + const handleFileClick = () => { + fileInputRef.current?.click() + } + + const repCreate = async () => { + try { + const response = await RepositoryService.createRep(newRep) + if (response.status === 200) { + + selectedFile !== null && + (await RepositoryService.addFile(selectedFile, response.data.Id)) + } else if (response.status === 406) { + setErrorState(true) + } + setModal(false) + getRep() + } catch (error) { + console.log(error) + } + } return ( <> +

Внесение пакета в репозиторий

- -
-
- - Имя файла: - - - - Выбрать файл - -
-
+
+ + + {selectedFile ? ( +

+ Выбранный файл: + {selectedFile.name} +

+ ) : ( +

+ Файл не выбран +

+ )} + Выбрать файл +
+
setModal(false)} > Отмена - + Создать
- - - -

Пакет уже существует

- setErrorMessage(false)}>Ok -
+ + + +

Имя и версия уже существует

+ setErrorState(false)}>Ok +
-
+ ) } diff --git a/src/pages/Repository/blocks/RepTableItem.tsx b/src/pages/Repository/blocks/RepTableItem.tsx index ffb7589..bf59218 100644 --- a/src/pages/Repository/blocks/RepTableItem.tsx +++ b/src/pages/Repository/blocks/RepTableItem.tsx @@ -7,14 +7,13 @@ import Checkbox from 'src/components/UI/input/Checkbox' import Modal from 'src/components/UI/modal/Modal' import RepositoryService from 'src/services/repositoryServices' import styled from 'styled-components' -import { T_ColumnsState, T_NewRepository, T_RepositoryItem } from '../types' +import { T_ColumnsState, T_RepositoryItem } from '../types' import EditRepModal from './EditRepModal' type Props = { repository: T_RepositoryItem selectAll: boolean notChecked: number[] - checkedColumns: number[] setNotChecked: (param: any) => void setCheckedColumns: (param: any) => void @@ -102,17 +101,7 @@ export default function ({ getRep() } } - const editRep = async (rep: T_NewRepository) => { - setContextMenuState(false) - const response = await RepositoryService.editRepository( - repository.Id, - rep - ) - if (response.status === 200) { - getRep() - } - setEditModalState(false) - } + return ( <> @@ -194,10 +183,21 @@ export default function ({

Очистить зависимости

+ {repository.Url !== '' && ( + setContextMenuState(false)} + > - -

Скачать пакет

+ +

Скачать

+ + )} (setEditModalState(true), setContextMenuState(false))}>

Редактировать

@@ -222,12 +222,12 @@ export default function ({
setDeleteNotificationState(false)} > Отмена - deleteRep()}> + deleteRep()}> Удалить
@@ -237,7 +237,7 @@ export default function ({ modal={editModalState} setModal={setEditModalState} repository={repository} - editRep={editRep} + getRep={getRep} /> diff --git a/src/pages/Repository/types.ts b/src/pages/Repository/types.ts index fad3ffd..8796221 100644 --- a/src/pages/Repository/types.ts +++ b/src/pages/Repository/types.ts @@ -8,12 +8,16 @@ export type T_NewRepository = { export interface T_RepositoryItem { Id: number; - Name: string - Description: string - ShortDescription: string - Version: string - Category: string - UpdatedDate: string + Name: string; + Description: string; + ShortDescription: string; + Version: string; + DependenciesReceived: boolean; + Arch: "amd64" | "x86" | string; + Category: string; + CreatedDate: string; + UpdatedDate: string; + Url: string|null; Enabled: boolean; } diff --git a/src/services/repositoryServices.ts b/src/services/repositoryServices.ts index 5e0ca60..47c4aa9 100644 --- a/src/services/repositoryServices.ts +++ b/src/services/repositoryServices.ts @@ -1,7 +1,6 @@ import axios, { AxiosResponse } from 'axios' import { API_HOST_NAME } from 'src/constants/host' import { T_NewRepository } from 'src/pages/Repository/types' - import { I_QueryParams } from './type' export default class RepositoryService { @@ -9,7 +8,7 @@ export default class RepositoryService { queryParams: I_QueryParams ): Promise { const { page, count, search, order } = queryParams - const url = `${API_HOST_NAME}/repository/packages` + const url = `${API_HOST_NAME}/repository/packages?full=true` const params = new URLSearchParams() if (page !== undefined) params.append('page', String(page)) @@ -26,7 +25,7 @@ export default class RepositoryService { } } - static async createRepository( + static async createRep( newRep: T_NewRepository ): Promise { try {