Исправил все баги и ошибки в репозитории + добавил обрадотку ошибок в регистрации + параметра в ссылках работают на всех страницах
This commit is contained in:
parent
013fe0c082
commit
7c247316ae
|
@ -6,35 +6,33 @@ export const GlobalStyles = createGlobalStyle`
|
||||||
padding: 0;
|
padding: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: "Roboto";
|
font-family: "Roboto";
|
||||||
color: ${props => props.theme.textColor};
|
color: ${(props) => props.theme.textColor};
|
||||||
background: ${props => props.theme.bg};
|
background: ${(props) => props.theme.bg};
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: ${props => props.theme.textColor};
|
color: ${(props) => props.theme.textColor};
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
${props => props.theme.h1}
|
${(props) => props.theme.h1}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
${props => props.theme.h2}
|
${(props) => props.theme.h2}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
${props => props.theme.h3}
|
${(props) => props.theme.h3}
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
${props => props.theme.paragraph}
|
${(props) => props.theme.paragraph}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
|
@ -9,15 +9,16 @@ const TextareaContainer = styled.div`
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
background: ${(props) => props.theme.bg};
|
background: ${(props) => props.theme.bg};
|
||||||
border: 1px solid ${(props) => props.theme.text};
|
border: 1px solid ${(props) => props.theme.text};
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 500;
|
|
||||||
outline: none;
|
outline: none;
|
||||||
resize: none;
|
resize: none;
|
||||||
height: 110px;
|
height: 110px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: -moz-scrollbars-none;
|
overflow: -moz-scrollbars-none;
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
}
|
font-family: Roboto;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
interface PlaceholderProps {
|
interface PlaceholderProps {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import {
|
||||||
SearchNotification
|
SearchNotification
|
||||||
} from './styles'
|
} from './styles'
|
||||||
import { T_ColumnsState, T_NewRegistration, T_RegistrationItem } from './types'
|
import { T_ColumnsState, T_NewRegistration, T_RegistrationItem } from './types'
|
||||||
|
import { useLocation, useNavigate } from 'react-router-dom'
|
||||||
|
|
||||||
type Props = {}
|
type Props = {}
|
||||||
|
|
||||||
|
@ -26,17 +27,36 @@ export default function Registrations({}: Props) {
|
||||||
|
|
||||||
const [registrations, setRegistrations] = useState<T_RegistrationItem[]>([])
|
const [registrations, setRegistrations] = useState<T_RegistrationItem[]>([])
|
||||||
|
|
||||||
const handleSearchQueryChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const location = useLocation()
|
||||||
setQueryParams({ ...queryParams, search: e.target.value })
|
const searchParams = new URLSearchParams(location.search)
|
||||||
}
|
const navigate = useNavigate()
|
||||||
|
|
||||||
const [queryParams, setQueryParams] = useState<I_QueryParams>({
|
const [queryParams, setQueryParams] = useState<I_QueryParams>({
|
||||||
page: 1,
|
page: 1,
|
||||||
count: 10,
|
count: 10,
|
||||||
search: '',
|
search: '',
|
||||||
order: undefined
|
order: 'email'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const handleSearchQueryChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const newSearchQuery = e.target.value
|
||||||
|
setQueryParams({ ...queryParams, search: e.target.value, page: 1 })
|
||||||
|
const searchParams = new URLSearchParams(window.location.search)
|
||||||
|
if (searchParams.has('page')) {
|
||||||
|
searchParams.delete('page')
|
||||||
|
}
|
||||||
|
searchParams.append('page', '1')
|
||||||
|
if (searchParams.has('search')) {
|
||||||
|
searchParams.delete('search')
|
||||||
|
}
|
||||||
|
if (newSearchQuery.trim() !== '') {
|
||||||
|
searchParams.append('search', newSearchQuery.trim())
|
||||||
|
}
|
||||||
|
navigate(`?${searchParams.toString()}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const getReg = async () => {
|
const getReg = async () => {
|
||||||
setSearchNotification(false)
|
setSearchNotification(false)
|
||||||
setErrorState(false)
|
setErrorState(false)
|
||||||
|
@ -54,6 +74,21 @@ export default function Registrations({}: Props) {
|
||||||
setLoadingState(false)
|
setLoadingState(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const pageParam = searchParams.get('page')
|
||||||
|
const countParam = searchParams.get('count')
|
||||||
|
const searchParam = searchParams.get('search')
|
||||||
|
const orderParam = searchParams.get('order')
|
||||||
|
setQueryParams((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
page: pageParam ? parseInt(pageParam, 10) : prevState.page,
|
||||||
|
count: countParam ? parseInt(countParam, 10) : prevState.count,
|
||||||
|
search: searchParam || prevState.search,
|
||||||
|
order: orderParam || prevState.order
|
||||||
|
}))
|
||||||
|
getReg()
|
||||||
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getReg()
|
getReg()
|
||||||
}, [queryParams])
|
}, [queryParams])
|
||||||
|
@ -66,7 +101,7 @@ export default function Registrations({}: Props) {
|
||||||
EndDate: { name: 'Дата окончания', status: true },
|
EndDate: { name: 'Дата окончания', status: true },
|
||||||
CreatedDate: { name: 'Дата создания', status: false },
|
CreatedDate: { name: 'Дата создания', status: false },
|
||||||
UpdatedDate: { name: 'Дата изменения', status: true },
|
UpdatedDate: { name: 'Дата изменения', status: true },
|
||||||
Enabled: { name: 'Статус', status: true }
|
Enabled: { name: 'Состояние', status: true }
|
||||||
})
|
})
|
||||||
|
|
||||||
const [checkedColumns, setCheckedColumns] = useState<number[]>([])
|
const [checkedColumns, setCheckedColumns] = useState<number[]>([])
|
||||||
|
@ -127,10 +162,6 @@ export default function Registrations({}: Props) {
|
||||||
})
|
})
|
||||||
}, [modal])
|
}, [modal])
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
getReg()
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{loadingState ? (
|
{loadingState ? (
|
||||||
|
@ -167,9 +198,9 @@ export default function Registrations({}: Props) {
|
||||||
<RegSelectNotification>
|
<RegSelectNotification>
|
||||||
<h3>
|
<h3>
|
||||||
{selectAll
|
{selectAll
|
||||||
? `Выбранно: ${totalCount - notChecked.length}`
|
? `Выбрано: ${totalCount - notChecked.length}`
|
||||||
: checkedColumns.length !== 0 &&
|
: checkedColumns.length !== 0 &&
|
||||||
`Выбранно: ${checkedColumns.length}`}
|
`Выбрано: ${checkedColumns.length}`}
|
||||||
</h3>
|
</h3>
|
||||||
<div className='menu'>
|
<div className='menu'>
|
||||||
<img
|
<img
|
||||||
|
|
|
@ -2,14 +2,15 @@ import { useEffect, useState } from 'react'
|
||||||
import MainButton from 'src/components/UI/button/MainButton'
|
import MainButton from 'src/components/UI/button/MainButton'
|
||||||
import MainInput from 'src/components/UI/input/MainInput'
|
import MainInput from 'src/components/UI/input/MainInput'
|
||||||
import Modal from 'src/components/UI/modal/Modal'
|
import Modal from 'src/components/UI/modal/Modal'
|
||||||
|
import RegistrationsService from 'src/services/registrationsServices'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { T_NewRegistration } from '../types'
|
import { T_RegistrationItem } from '../types'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
modal: boolean
|
modal: boolean
|
||||||
setModal: (param: boolean) => void
|
setModal: (param: boolean) => void
|
||||||
registration: T_NewRegistration
|
registration: T_RegistrationItem
|
||||||
editReg: (param: T_NewRegistration) => void
|
getReg: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const ModalContainer = styled.div`
|
const ModalContainer = styled.div`
|
||||||
|
@ -24,16 +25,45 @@ const ModalContainer = styled.div`
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const ErrorContainer = styled.div`
|
||||||
|
position: relative;
|
||||||
|
z-index: 4;
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: end;
|
||||||
|
width:420px;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
export default function EditRegModal({
|
export default function EditRegModal({
|
||||||
modal,
|
modal,
|
||||||
setModal,
|
setModal,
|
||||||
registration,
|
registration,
|
||||||
editReg
|
getReg
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const [editRegData, setEditRegData] = useState(registration)
|
const [editRegData, setEditRegData] = useState(registration)
|
||||||
|
|
||||||
const [errorMessage, setErrorMessage] = useState(false)
|
const [errorMessage, setErrorMessage] = useState(false)
|
||||||
|
|
||||||
|
const editReg = async () => {
|
||||||
|
try {
|
||||||
|
const response = await RegistrationsService.editRegistration(
|
||||||
|
registration.Id,
|
||||||
|
editRegData
|
||||||
|
)
|
||||||
|
if (response.status === 200) {
|
||||||
|
getReg()
|
||||||
|
setModal(false)
|
||||||
|
} else if (response.status === 406) {
|
||||||
|
console.log(1)
|
||||||
|
setErrorMessage(true)
|
||||||
|
}
|
||||||
|
} catch (error) {}
|
||||||
|
}
|
||||||
|
|
||||||
const handleContNumChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleContNumChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setEditRegData({ ...editRegData, ContNum: e.target.value })
|
setEditRegData({ ...editRegData, ContNum: e.target.value })
|
||||||
}
|
}
|
||||||
|
@ -44,12 +74,24 @@ export default function EditRegModal({
|
||||||
setEditRegData({ ...editRegData, Email: e.target.value })
|
setEditRegData({ ...editRegData, Email: e.target.value })
|
||||||
}
|
}
|
||||||
const handleCountChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleCountChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setEditRegData({ ...editRegData, Count: e.target.value })
|
setEditRegData({ ...editRegData, Count: parseInt(e.target.value) })
|
||||||
}
|
}
|
||||||
const handleEndDateChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleEndDateChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setEditRegData({ ...editRegData, EndDate: e.target.value })
|
setEditRegData({ ...editRegData, EndDate: e.target.value })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
function formatDate(isoDateString: string): string {
|
||||||
|
const date = new Date(isoDateString)
|
||||||
|
const year = date.getFullYear()
|
||||||
|
const month = ('0' + (date.getMonth() + 1)).slice(-2)
|
||||||
|
const day = ('0' + date.getDate()).slice(-2)
|
||||||
|
return `${year}-${month}-${day}`
|
||||||
|
}
|
||||||
|
const formattedDate = formatDate(registration.EndDate)
|
||||||
|
setEditRegData({ ...registration, EndDate: formattedDate })
|
||||||
|
}, [modal])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function formatDate(isoDateString: string): string {
|
function formatDate(isoDateString: string): string {
|
||||||
const date = new Date(isoDateString)
|
const date = new Date(isoDateString)
|
||||||
|
@ -63,47 +105,57 @@ export default function EditRegModal({
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal modal={modal} setModal={setModal}>
|
<>
|
||||||
<ModalContainer>
|
<Modal modal={modal} setModal={setModal}>
|
||||||
<MainInput
|
<ModalContainer>
|
||||||
placeholder='Номер контракта'
|
<MainInput
|
||||||
value={editRegData.ContNum}
|
placeholder='Номер контракта'
|
||||||
onChange={handleContNumChange}
|
value={editRegData.ContNum}
|
||||||
/>
|
onChange={handleContNumChange}
|
||||||
<MainInput
|
/>
|
||||||
placeholder='Номер поставки'
|
<MainInput
|
||||||
value={editRegData.RegNum}
|
placeholder='Номер поставки'
|
||||||
onChange={handleRegNumChange}
|
value={editRegData.RegNum}
|
||||||
/>
|
onChange={handleRegNumChange}
|
||||||
<MainInput
|
/>
|
||||||
placeholder='Email'
|
<MainInput
|
||||||
value={editRegData.Email}
|
placeholder='Email'
|
||||||
onChange={handleEmailChange}
|
value={editRegData.Email}
|
||||||
/>
|
onChange={handleEmailChange}
|
||||||
<MainInput
|
/>
|
||||||
placeholder='Кол-во активаций'
|
<MainInput
|
||||||
value={editRegData.Count}
|
placeholder='Кол-во активаций'
|
||||||
onChange={handleCountChange}
|
value={editRegData.Count}
|
||||||
/>
|
onChange={handleCountChange}
|
||||||
<MainInput
|
/>
|
||||||
placeholder='Дата окончания'
|
<MainInput
|
||||||
value={editRegData.EndDate}
|
placeholder='Дата окончания'
|
||||||
onChange={handleEndDateChange}
|
value={editRegData.EndDate}
|
||||||
type='date'
|
onChange={handleEndDateChange}
|
||||||
/>
|
type='date'
|
||||||
<div className='buttonBlock'>
|
/>
|
||||||
<MainButton
|
<div className='buttonBlock'>
|
||||||
color='secondary'
|
<MainButton
|
||||||
fullWidth={true}
|
color='secondary'
|
||||||
onClick={() => setModal(false)}
|
fullWidth={true}
|
||||||
>
|
onClick={() => setModal(false)}
|
||||||
Отмена
|
>
|
||||||
</MainButton>
|
Отмена
|
||||||
<MainButton fullWidth={true} onClick={() => editReg(editRegData)}>
|
</MainButton>
|
||||||
Сохранить
|
<MainButton fullWidth={true} onClick={editReg}>
|
||||||
</MainButton>
|
Сохранить
|
||||||
</div>
|
</MainButton>
|
||||||
</ModalContainer>
|
</div>
|
||||||
</Modal>
|
</ModalContainer>
|
||||||
|
</Modal>
|
||||||
|
<ErrorContainer>
|
||||||
|
<Modal setModal={setErrorMessage} modal={errorMessage}>
|
||||||
|
<div className="content">
|
||||||
|
<h3>Номер контракта/поставки уже существует</h3>
|
||||||
|
<MainButton onClick={() => setErrorMessage(false)}>Ok</MainButton>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
</ErrorContainer>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
|
import { useNavigate } from 'react-router-dom'
|
||||||
import ContextMenu from 'src/components/UI/contextMenu/ContextMenu'
|
import ContextMenu from 'src/components/UI/contextMenu/ContextMenu'
|
||||||
import Checkbox from 'src/components/UI/input/Checkbox'
|
import Checkbox from 'src/components/UI/input/Checkbox'
|
||||||
import Table from 'src/components/UI/table/Table'
|
import Table from 'src/components/UI/table/Table'
|
||||||
|
@ -71,28 +72,65 @@ export default function RegTable({
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const [contextMenuState, setContextMenuState] = useState(false)
|
const [contextMenuState, setContextMenuState] = useState(false)
|
||||||
|
|
||||||
const [activeSort, setActiveSort] = useState('')
|
const navigate = useNavigate()
|
||||||
|
|
||||||
|
const [activeSort, setActiveSort] = useState('email')
|
||||||
const [sortState, setSortState] = useState(false)
|
const [sortState, setSortState] = useState(false)
|
||||||
|
|
||||||
const sort = (value: string) => {
|
const sort = (value: string) => {
|
||||||
const sortOptions: { [key: string]: string } = {
|
const sortOptions: { [key: string]: string } = {
|
||||||
'Номер поставки': 'reg',
|
'Номер поставки': 'reg',
|
||||||
'Номер контракта': 'cont',
|
'Номер контракта': 'cont',
|
||||||
'Эл. почта': 'email',
|
'Эл. почта': 'email',
|
||||||
'Кол-во активаций': 'count',
|
'Кол-во активаций': 'count',
|
||||||
'Дата окончания': 'end',
|
'Дата окончания': 'end',
|
||||||
'Дата изменения': 'updated',
|
'Дата изменения': 'updated',
|
||||||
'Статус': 'enabled'
|
Состояние: 'enabled'
|
||||||
};
|
}
|
||||||
|
|
||||||
const sortParam = sortOptions[value];
|
const sortParam = sortOptions[value]
|
||||||
if (!sortParam) return;
|
if (!sortParam) return
|
||||||
|
|
||||||
setActiveSort(value);
|
setActiveSort(value)
|
||||||
const newOrder = queryParams.order === sortParam ? `!${sortParam}` : sortParam;
|
const newOrder =
|
||||||
setQueryParams({ ...queryParams, order: newOrder });
|
queryParams.order === sortParam ? `!${sortParam}` : sortParam
|
||||||
setSortState(queryParams.order === sortParam);
|
setQueryParams({ ...queryParams, order: newOrder })
|
||||||
};
|
setSortState(queryParams.order === sortParam)
|
||||||
|
|
||||||
|
const searchParams = new URLSearchParams(window.location.search)
|
||||||
|
if (searchParams.has('order')) {
|
||||||
|
searchParams.delete('order')
|
||||||
|
}
|
||||||
|
if (newOrder.trim() !== '') {
|
||||||
|
searchParams.append('order', newOrder.trim())
|
||||||
|
}
|
||||||
|
navigate(`?${searchParams.toString()}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const searchParams = new URLSearchParams(location.search)
|
||||||
|
const orderParam = searchParams.get('order')
|
||||||
|
|
||||||
|
// Проверяем наличие параметра order в URL
|
||||||
|
if (orderParam) {
|
||||||
|
const sortOptions: { [key: string]: string } = {
|
||||||
|
reg: 'Номер поставки',
|
||||||
|
cont: 'Номер контракта',
|
||||||
|
email: 'Эл. почта',
|
||||||
|
count: 'Кол-во активаций',
|
||||||
|
end: 'Дата окончания',
|
||||||
|
updated: 'Дата изменения',
|
||||||
|
enabled: 'Состояние',
|
||||||
|
}
|
||||||
|
|
||||||
|
const activeSortValue = sortOptions[orderParam.replace('!', '')]
|
||||||
|
const sortStateValue = orderParam[0] === '!'
|
||||||
|
|
||||||
|
setActiveSort(activeSortValue || '')
|
||||||
|
setSortState(sortStateValue)
|
||||||
|
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Table>
|
<Table>
|
||||||
|
|
|
@ -74,17 +74,7 @@ export default function RrgTableItem ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const editReg = async (reg: T_NewRegistration) => {
|
|
||||||
setContextMenuState(false)
|
|
||||||
const response = await RegistrationsService.editRegistration(
|
|
||||||
registration.Id,
|
|
||||||
reg
|
|
||||||
)
|
|
||||||
if (response.status === 200) {
|
|
||||||
getReg()
|
|
||||||
}
|
|
||||||
setEditModalState(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -116,7 +106,7 @@ export default function RrgTableItem ({
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
{Object.entries(activeColumns).map(([key, item]) =>
|
{Object.entries(activeColumns).map(([key, _]) =>
|
||||||
activeColumns[key as keyof typeof activeColumns].status ? (
|
activeColumns[key as keyof typeof activeColumns].status ? (
|
||||||
<td key={key}>
|
<td key={key}>
|
||||||
<p>
|
<p>
|
||||||
|
@ -203,7 +193,7 @@ export default function RrgTableItem ({
|
||||||
modal={editModalState}
|
modal={editModalState}
|
||||||
setModal={setEditModalState}
|
setModal={setEditModalState}
|
||||||
registration={registration}
|
registration={registration}
|
||||||
editReg={editReg}
|
getReg={getReg}
|
||||||
/>
|
/>
|
||||||
</tr>
|
</tr>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -16,6 +16,7 @@ import {
|
||||||
SearchNotification
|
SearchNotification
|
||||||
} from './styles'
|
} from './styles'
|
||||||
import { T_ColumnsState, T_RepositoryItem } from './types'
|
import { T_ColumnsState, T_RepositoryItem } from './types'
|
||||||
|
import { useLocation, useNavigate } from 'react-router-dom'
|
||||||
|
|
||||||
|
|
||||||
type Props = {}
|
type Props = {}
|
||||||
|
@ -29,9 +30,9 @@ export default function Repository({}: Props) {
|
||||||
|
|
||||||
const [Repository, setRepository] = useState<T_RepositoryItem[]>([])
|
const [Repository, setRepository] = useState<T_RepositoryItem[]>([])
|
||||||
|
|
||||||
const handleSearchQueryChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const location = useLocation()
|
||||||
setQueryParams({ ...queryParams, search: e.target.value })
|
const searchParams = new URLSearchParams(location.search)
|
||||||
}
|
const navigate = useNavigate()
|
||||||
|
|
||||||
const [queryParams, setQueryParams] = useState<I_QueryParams>({
|
const [queryParams, setQueryParams] = useState<I_QueryParams>({
|
||||||
page: 1,
|
page: 1,
|
||||||
|
@ -40,6 +41,23 @@ export default function Repository({}: Props) {
|
||||||
order: undefined
|
order: undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const handleSearchQueryChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const newSearchQuery = e.target.value
|
||||||
|
setQueryParams({ ...queryParams, search: e.target.value, page: 1 })
|
||||||
|
const searchParams = new URLSearchParams(window.location.search)
|
||||||
|
if (searchParams.has('page')) {
|
||||||
|
searchParams.delete('page')
|
||||||
|
}
|
||||||
|
searchParams.append('page', '1')
|
||||||
|
if (searchParams.has('search')) {
|
||||||
|
searchParams.delete('search')
|
||||||
|
}
|
||||||
|
if (newSearchQuery.trim() !== '') {
|
||||||
|
searchParams.append('search', newSearchQuery.trim())
|
||||||
|
}
|
||||||
|
navigate(`?${searchParams.toString()}`)
|
||||||
|
}
|
||||||
|
|
||||||
const getRep = async () => {
|
const getRep = async () => {
|
||||||
if (!firstLoadingState) setLoadingState(true)
|
if (!firstLoadingState) setLoadingState(true)
|
||||||
setErrorState(false)
|
setErrorState(false)
|
||||||
|
@ -59,7 +77,19 @@ export default function Repository({}: Props) {
|
||||||
setLoadingState(false)
|
setLoadingState(false)
|
||||||
setFirstLoadingState(false)
|
setFirstLoadingState(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const pageParam = searchParams.get('page')
|
||||||
|
const countParam = searchParams.get('count')
|
||||||
|
const searchParam = searchParams.get('search')
|
||||||
|
const orderParam = searchParams.get('order')
|
||||||
|
setQueryParams((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
page: pageParam ? parseInt(pageParam, 10) : prevState.page,
|
||||||
|
count: countParam ? parseInt(countParam, 10) : prevState.count,
|
||||||
|
search: searchParam || prevState.search,
|
||||||
|
order: orderParam || prevState.order
|
||||||
|
}))
|
||||||
getRep()
|
getRep()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
@ -73,8 +103,8 @@ export default function Repository({}: Props) {
|
||||||
Description: { name: 'Полное описание', status: true },
|
Description: { name: 'Полное описание', status: true },
|
||||||
ShortDescription: { name: 'Краткое описание', status: true },
|
ShortDescription: { name: 'Краткое описание', status: true },
|
||||||
Category: { name: 'Категория', status: true },
|
Category: { name: 'Категория', status: true },
|
||||||
UpdatedDate: { name: 'Дата изменения', status: true },
|
UpdatedDate: { name: 'Дата обновления', status: true },
|
||||||
Enabled: { name: 'Статус', status: true }
|
Enabled: { name: 'Состояние', status: true }
|
||||||
})
|
})
|
||||||
|
|
||||||
const [checkedColumns, setCheckedColumns] = useState<number[]>([])
|
const [checkedColumns, setCheckedColumns] = useState<number[]>([])
|
||||||
|
@ -122,7 +152,7 @@ export default function Repository({}: Props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{loadingState ? (
|
{firstLoadingState ? (
|
||||||
<RepLoaderContainer>
|
<RepLoaderContainer>
|
||||||
<Loader />
|
<Loader />
|
||||||
</RepLoaderContainer>
|
</RepLoaderContainer>
|
||||||
|
@ -190,6 +220,7 @@ export default function Repository({}: Props) {
|
||||||
getRep={getRep}
|
getRep={getRep}
|
||||||
queryParams={queryParams}
|
queryParams={queryParams}
|
||||||
setQueryParams={setQueryParams}
|
setQueryParams={setQueryParams}
|
||||||
|
loadingState={loadingState}
|
||||||
/>
|
/>
|
||||||
<div className='bottom-menu'>
|
<div className='bottom-menu'>
|
||||||
<Pagination
|
<Pagination
|
||||||
|
@ -206,7 +237,6 @@ export default function Repository({}: Props) {
|
||||||
</>
|
</>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</RepContainer>
|
</RepContainer>
|
||||||
)}
|
)}
|
||||||
<NewRepModal modal={modal} setModal={setModal} getRep={getRep} />
|
<NewRepModal modal={modal} setModal={setModal} getRep={getRep} />
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { useEffect, useRef, useState } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import MainButton from 'src/components/UI/button/MainButton'
|
import MainButton from 'src/components/UI/button/MainButton'
|
||||||
import MainInput from 'src/components/UI/input/MainInput'
|
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 Textarea from 'src/components/UI/input/Textarea'
|
||||||
|
import Modal from 'src/components/UI/modal/Modal'
|
||||||
import RepositoryService from 'src/services/repositoryServices'
|
import RepositoryService from 'src/services/repositoryServices'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { T_NewRepository, T_RepositoryItem } from '../types'
|
import { T_NewRepository, T_RepositoryItem } from '../types'
|
||||||
|
@ -52,7 +52,12 @@ const NewRepFileBlock = styled.div`
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
export default function EditRepModal({ modal, setModal, repository, getRep }: Props){
|
export default function EditRepModal({
|
||||||
|
modal,
|
||||||
|
setModal,
|
||||||
|
repository,
|
||||||
|
getRep
|
||||||
|
}: Props) {
|
||||||
const [error, setError] = useState({
|
const [error, setError] = useState({
|
||||||
state: false,
|
state: false,
|
||||||
message: ''
|
message: ''
|
||||||
|
@ -75,10 +80,14 @@ export default function EditRepModal({ modal, setModal, repository, getRep }: Pr
|
||||||
const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setEditRepData({ ...editRepData, Name: e.target.value })
|
setEditRepData({ ...editRepData, Name: e.target.value })
|
||||||
}
|
}
|
||||||
const handleDescriptionChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
const handleDescriptionChange = (
|
||||||
|
e: React.ChangeEvent<HTMLTextAreaElement>
|
||||||
|
) => {
|
||||||
setEditRepData({ ...editRepData, Description: e.target.value })
|
setEditRepData({ ...editRepData, Description: e.target.value })
|
||||||
}
|
}
|
||||||
const handleShortDescriptionChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleShortDescriptionChange = (
|
||||||
|
e: React.ChangeEvent<HTMLInputElement>
|
||||||
|
) => {
|
||||||
setEditRepData({ ...editRepData, ShortDescription: e.target.value })
|
setEditRepData({ ...editRepData, ShortDescription: e.target.value })
|
||||||
}
|
}
|
||||||
const handleVersionChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleVersionChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
@ -93,15 +102,26 @@ export default function EditRepModal({ modal, setModal, repository, getRep }: Pr
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setFormValid(
|
setFormValid(
|
||||||
editRepData.Name !== '' &&
|
editRepData.Name !== '' &&
|
||||||
editRepData.Description !== '' &&
|
editRepData.Description !== '' &&
|
||||||
editRepData.ShortDescription !== '' &&
|
editRepData.ShortDescription !== '' &&
|
||||||
editRepData.Version !== '' &&
|
editRepData.Version !== '' &&
|
||||||
editRepData.Category !== ''
|
editRepData.Category !== ''
|
||||||
)
|
)
|
||||||
}, [editRepData])
|
}, [editRepData])
|
||||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
||||||
const [selectedFile, setSelectedFile] = useState<File | null>(null);
|
useEffect(() => {
|
||||||
|
setEditRepData({
|
||||||
|
Name: repository.Name,
|
||||||
|
Description: repository.Description,
|
||||||
|
ShortDescription: repository.ShortDescription,
|
||||||
|
Version: repository.Version,
|
||||||
|
Category: repository.Category
|
||||||
|
})
|
||||||
|
}, [modal])
|
||||||
|
|
||||||
|
const fileInputRef = useRef<HTMLInputElement>(null)
|
||||||
|
const [selectedFile, setSelectedFile] = useState<File | null>(null)
|
||||||
|
|
||||||
const handleFileChange = () => {
|
const handleFileChange = () => {
|
||||||
const file = fileInputRef.current?.files?.[0]
|
const file = fileInputRef.current?.files?.[0]
|
||||||
if (file) {
|
if (file) {
|
||||||
|
@ -114,70 +134,75 @@ export default function EditRepModal({ modal, setModal, repository, getRep }: Pr
|
||||||
}
|
}
|
||||||
const updateRep = async () => {
|
const updateRep = async () => {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
if (
|
if (
|
||||||
!(
|
!(
|
||||||
editRepData.Category === repository.Category &&
|
editRepData.Category === repository.Category &&
|
||||||
editRepData.Description === repository.Description &&
|
editRepData.Description === repository.Description &&
|
||||||
editRepData.Name === repository.Name &&
|
editRepData.Name === repository.Name &&
|
||||||
editRepData.ShortDescription === repository.ShortDescription &&
|
editRepData.ShortDescription === repository.ShortDescription &&
|
||||||
editRepData.Version === repository.Version
|
editRepData.Version === repository.Version
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
const response = await RepositoryService.editRepository(repository.Id, editRepData)
|
const response = await RepositoryService.editRepository(
|
||||||
if (response.status === 406) {
|
repository.Id,
|
||||||
setError({ state: true, message: response.data })
|
editRepData
|
||||||
setLoading(false)
|
)
|
||||||
return
|
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 (repository.Url !== selectedFile && selectedFile instanceof File) {
|
||||||
if (response.status === 406) {
|
const response = await RepositoryService.addFile(
|
||||||
setError({ state: true, message: response.data })
|
selectedFile,
|
||||||
setLoading(false)
|
repository.Id
|
||||||
return
|
)
|
||||||
}
|
if (response.status === 406) {
|
||||||
|
setError({ state: true, message: response.data })
|
||||||
|
setLoading(false)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
setLoading(false)
|
}
|
||||||
setModal(false)
|
setLoading(false)
|
||||||
getRep()
|
setModal(false)
|
||||||
} catch (error) {}
|
getRep()
|
||||||
}
|
} catch (error) {}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Modal modal={modal} setModal={setModal}>
|
<Modal modal={modal} setModal={setModal}>
|
||||||
<ModalContainer>
|
<ModalContainer>
|
||||||
|
<h2>Изменение пакета в репозитории</h2>
|
||||||
<h2>Изменение пакета в репозитории</h2>
|
<MainInput
|
||||||
<MainInput
|
placeholder='Название'
|
||||||
placeholder='Название'
|
value={editRepData.Name}
|
||||||
value={editRepData.Name}
|
onChange={handleNameChange}
|
||||||
onChange={handleNameChange}
|
/>
|
||||||
/>
|
<MainInput
|
||||||
<MainInput
|
placeholder='Версия'
|
||||||
placeholder='Версия'
|
value={editRepData.Version}
|
||||||
value={editRepData.Version}
|
onChange={handleVersionChange}
|
||||||
onChange={handleVersionChange}
|
/>
|
||||||
/>
|
<MainInput
|
||||||
<MainInput
|
placeholder='Краткое описание'
|
||||||
placeholder='Краткое описание'
|
value={editRepData.ShortDescription}
|
||||||
value={editRepData.Description}
|
onChange={handleShortDescriptionChange}
|
||||||
onChange={handleShortDescriptionChange}
|
/>
|
||||||
/>
|
<Textarea
|
||||||
<Textarea
|
placeholder='Полное описание'
|
||||||
placeholder='Полное описание'
|
value={editRepData.Description}
|
||||||
value={editRepData.Description}
|
onChange={handleDescriptionChange}
|
||||||
onChange={handleDescriptionChange}
|
/>
|
||||||
/>
|
<MainInput
|
||||||
<MainInput
|
placeholder='Категория'
|
||||||
placeholder='Категория'
|
value={editRepData.Category}
|
||||||
value={editRepData.Category}
|
onChange={handleCategoryChange}
|
||||||
onChange={handleCategoryChange}
|
/>
|
||||||
/>
|
<div>
|
||||||
<div>
|
|
||||||
<NewRepFileBlock>
|
<NewRepFileBlock>
|
||||||
<input
|
<input
|
||||||
ref={fileInputRef}
|
ref={fileInputRef}
|
||||||
|
@ -198,21 +223,21 @@ export default function EditRepModal({ modal, setModal, repository, getRep }: Pr
|
||||||
<MainButton onClick={handleFileClick}>Выбрать файл</MainButton>
|
<MainButton onClick={handleFileClick}>Выбрать файл</MainButton>
|
||||||
</NewRepFileBlock>
|
</NewRepFileBlock>
|
||||||
</div>
|
</div>
|
||||||
<div className='buttonBlock'>
|
<div className='buttonBlock'>
|
||||||
<MainButton
|
<MainButton
|
||||||
color='secondary'
|
color='secondary'
|
||||||
fullWidth
|
fullWidth
|
||||||
onClick={() => setModal(false)}
|
onClick={() => setModal(false)}
|
||||||
>
|
>
|
||||||
Отмена
|
Отмена
|
||||||
</MainButton>
|
</MainButton>
|
||||||
<MainButton fullWidth onClick={updateRep} disabled={!formValid}>
|
<MainButton fullWidth onClick={updateRep} disabled={!formValid}>
|
||||||
Сохранить
|
Сохранить
|
||||||
</MainButton>
|
</MainButton>
|
||||||
</div>
|
</div>
|
||||||
</ModalContainer>
|
</ModalContainer>
|
||||||
</Modal>
|
</Modal>
|
||||||
<NewRepErrorMessageContainer>
|
<NewRepErrorMessageContainer>
|
||||||
<Modal modal={error.state} setModal={setErrorState}>
|
<Modal modal={error.state} setModal={setErrorState}>
|
||||||
<NewRepErrorMessage>
|
<NewRepErrorMessage>
|
||||||
<h3>{error.message}</h3>
|
<h3>{error.message}</h3>
|
||||||
|
@ -220,7 +245,6 @@ export default function EditRepModal({ modal, setModal, repository, getRep }: Pr
|
||||||
</NewRepErrorMessage>
|
</NewRepErrorMessage>
|
||||||
</Modal>
|
</Modal>
|
||||||
</NewRepErrorMessageContainer>
|
</NewRepErrorMessageContainer>
|
||||||
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { useEffect, useRef, useState } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import MainButton from 'src/components/UI/button/MainButton'
|
import MainButton from 'src/components/UI/button/MainButton'
|
||||||
import MainInput from 'src/components/UI/input/MainInput'
|
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 Textarea from 'src/components/UI/input/Textarea'
|
||||||
|
import Modal from 'src/components/UI/modal/Modal'
|
||||||
import RepositoryService from 'src/services/repositoryServices'
|
import RepositoryService from 'src/services/repositoryServices'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { T_NewRepository } from '../types'
|
import { T_NewRepository } from '../types'
|
||||||
|
@ -79,23 +79,26 @@ export default function NewRepModal({ modal, setModal, getRep }: Props) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setFormValid(
|
setFormValid(
|
||||||
newRep.Name !== '' &&
|
newRep.Name !== '' &&
|
||||||
newRep.Description !== '' &&
|
newRep.Description !== '' &&
|
||||||
newRep.ShortDescription !== '' &&
|
newRep.ShortDescription !== '' &&
|
||||||
newRep.Version !== '' &&
|
newRep.Version !== '' &&
|
||||||
newRep.Category !== ''
|
newRep.Category !== ''
|
||||||
)
|
)
|
||||||
}, [newRep])
|
}, [newRep])
|
||||||
|
|
||||||
const [errorState, setErrorState] = useState(false)
|
const [errorState, setErrorState] = useState(false)
|
||||||
|
|
||||||
|
|
||||||
const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setNewRep({ ...newRep, Name: e.target.value })
|
setNewRep({ ...newRep, Name: e.target.value })
|
||||||
}
|
}
|
||||||
const handleDescriptionChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
const handleDescriptionChange = (
|
||||||
|
e: React.ChangeEvent<HTMLTextAreaElement>
|
||||||
|
) => {
|
||||||
setNewRep({ ...newRep, Description: e.target.value })
|
setNewRep({ ...newRep, Description: e.target.value })
|
||||||
}
|
}
|
||||||
const handleShortDescriptionChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleShortDescriptionChange = (
|
||||||
|
e: React.ChangeEvent<HTMLInputElement>
|
||||||
|
) => {
|
||||||
setNewRep({ ...newRep, ShortDescription: e.target.value })
|
setNewRep({ ...newRep, ShortDescription: e.target.value })
|
||||||
}
|
}
|
||||||
const handleVersionChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleVersionChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
@ -121,7 +124,6 @@ export default function NewRepModal({ modal, setModal, getRep }: Props) {
|
||||||
try {
|
try {
|
||||||
const response = await RepositoryService.createRep(newRep)
|
const response = await RepositoryService.createRep(newRep)
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
|
|
||||||
selectedFile !== null &&
|
selectedFile !== null &&
|
||||||
(await RepositoryService.addFile(selectedFile, response.data.Id))
|
(await RepositoryService.addFile(selectedFile, response.data.Id))
|
||||||
} else if (response.status === 406) {
|
} else if (response.status === 406) {
|
||||||
|
@ -138,31 +140,31 @@ export default function NewRepModal({ modal, setModal, getRep }: Props) {
|
||||||
<Modal modal={modal} setModal={setModal}>
|
<Modal modal={modal} setModal={setModal}>
|
||||||
<ModalContainer>
|
<ModalContainer>
|
||||||
<h2>Внесение пакета в репозиторий</h2>
|
<h2>Внесение пакета в репозиторий</h2>
|
||||||
<MainInput
|
<MainInput
|
||||||
placeholder='Название'
|
placeholder='Название'
|
||||||
value={newRep.Name}
|
value={newRep.Name}
|
||||||
onChange={handleNameChange}
|
onChange={handleNameChange}
|
||||||
/>
|
/>
|
||||||
<MainInput
|
<MainInput
|
||||||
placeholder='Версия'
|
placeholder='Версия'
|
||||||
value={newRep.Version}
|
value={newRep.Version}
|
||||||
onChange={handleVersionChange}
|
onChange={handleVersionChange}
|
||||||
/>
|
/>
|
||||||
<MainInput
|
<MainInput
|
||||||
placeholder='Краткое описание'
|
placeholder='Краткое описание'
|
||||||
value={newRep.ShortDescription}
|
value={newRep.ShortDescription}
|
||||||
onChange={handleShortDescriptionChange}
|
onChange={handleShortDescriptionChange}
|
||||||
/>
|
/>
|
||||||
<Textarea
|
<Textarea
|
||||||
placeholder='Полное описание'
|
placeholder='Полное описание'
|
||||||
value={newRep.Description}
|
value={newRep.Description}
|
||||||
onChange={handleDescriptionChange}
|
onChange={handleDescriptionChange}
|
||||||
/>
|
/>
|
||||||
<MainInput
|
<MainInput
|
||||||
placeholder='Категория'
|
placeholder='Категория'
|
||||||
value={newRep.Category}
|
value={newRep.Category}
|
||||||
onChange={handleCategoryChange}
|
onChange={handleCategoryChange}
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
<NewAppFileBlock>
|
<NewAppFileBlock>
|
||||||
<input
|
<input
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
|
import { useNavigate } from 'react-router-dom'
|
||||||
import ContextMenu from 'src/components/UI/contextMenu/ContextMenu'
|
import ContextMenu from 'src/components/UI/contextMenu/ContextMenu'
|
||||||
import Checkbox from 'src/components/UI/input/Checkbox'
|
import Checkbox from 'src/components/UI/input/Checkbox'
|
||||||
import Table from 'src/components/UI/table/Table'
|
import Table from 'src/components/UI/table/Table'
|
||||||
|
@ -53,6 +54,7 @@ type Props = {
|
||||||
getRep: () => void
|
getRep: () => void
|
||||||
queryParams: I_QueryParams
|
queryParams: I_QueryParams
|
||||||
setQueryParams: (param: I_QueryParams) => void
|
setQueryParams: (param: I_QueryParams) => void
|
||||||
|
loadingState?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function RepTable({
|
export default function RepTable({
|
||||||
|
@ -67,33 +69,68 @@ export default function RepTable({
|
||||||
repository,
|
repository,
|
||||||
getRep,
|
getRep,
|
||||||
queryParams,
|
queryParams,
|
||||||
setQueryParams
|
setQueryParams,
|
||||||
|
loadingState
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const [contextMenuState, setContextMenuState] = useState(false)
|
const [contextMenuState, setContextMenuState] = useState(false)
|
||||||
|
|
||||||
const [activeSort, setActiveSort] = useState('')
|
const [activeSort, setActiveSort] = useState('')
|
||||||
const [sortState, setSortState] = useState(false)
|
const [sortState, setSortState] = useState(false)
|
||||||
|
|
||||||
|
const navigate = useNavigate()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const searchParams = new URLSearchParams(location.search)
|
||||||
|
const orderParam = searchParams.get('order')
|
||||||
|
|
||||||
|
// Проверяем наличие параметра order в URL
|
||||||
|
if (orderParam) {
|
||||||
|
const sortOptions: { [key: string]: string } = {
|
||||||
|
name: 'Название',
|
||||||
|
updated: 'Дата обновления',
|
||||||
|
version: 'Версия',
|
||||||
|
short: 'Краткое описание',
|
||||||
|
enabled: 'Состояние'
|
||||||
|
}
|
||||||
|
|
||||||
|
const activeSortValue = sortOptions[orderParam.replace('!', '')]
|
||||||
|
const sortStateValue = orderParam[0] === '!'
|
||||||
|
|
||||||
|
setActiveSort(activeSortValue || '')
|
||||||
|
setSortState(sortStateValue)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
const sort = (value: string) => {
|
const sort = (value: string) => {
|
||||||
const sortOptions: { [key: string]: string } = {
|
const sortOptions: { [key: string]: string } = {
|
||||||
'Статус': 'enabled',
|
Название: 'name',
|
||||||
'Название': 'string',
|
'Дата обновления': 'updated',
|
||||||
'Версия': 'string',
|
Версия: 'version',
|
||||||
'Описание': 'string',
|
'Краткое описание': 'short',
|
||||||
'Дата изменения': 'updated',
|
Состояние: 'enabled'
|
||||||
};
|
}
|
||||||
|
|
||||||
const sortParam = sortOptions[value];
|
const sortParam = sortOptions[value]
|
||||||
if (!sortParam) return;
|
if (!sortParam) return
|
||||||
|
|
||||||
setActiveSort(value);
|
setActiveSort(value)
|
||||||
const newOrder = queryParams.order === sortParam ? `!${sortParam}` : sortParam;
|
const newOrder =
|
||||||
setQueryParams({ ...queryParams, order: newOrder });
|
queryParams.order === sortParam ? `!${sortParam}` : sortParam
|
||||||
setSortState(queryParams.order === sortParam);
|
setQueryParams({ ...queryParams, order: newOrder })
|
||||||
};
|
setSortState(queryParams.order === sortParam)
|
||||||
|
|
||||||
|
const searchParams = new URLSearchParams(window.location.search)
|
||||||
|
if (searchParams.has('order')) {
|
||||||
|
searchParams.delete('order')
|
||||||
|
}
|
||||||
|
if (newOrder.trim() !== '') {
|
||||||
|
searchParams.append('order', newOrder.trim())
|
||||||
|
}
|
||||||
|
navigate(`?${searchParams.toString()}`)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Table>
|
<Table loaderState={loadingState}>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { HOST_NAME } from 'src/constants/host'
|
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import MainButton from 'src/components/UI/button/MainButton'
|
import MainButton from 'src/components/UI/button/MainButton'
|
||||||
import ContextMenu from 'src/components/UI/contextMenu/ContextMenu'
|
import ContextMenu from 'src/components/UI/contextMenu/ContextMenu'
|
||||||
import Checkbox from 'src/components/UI/input/Checkbox'
|
import Checkbox from 'src/components/UI/input/Checkbox'
|
||||||
import Modal from 'src/components/UI/modal/Modal'
|
import Modal from 'src/components/UI/modal/Modal'
|
||||||
|
import { HOST_NAME } from 'src/constants/host'
|
||||||
import RepositoryService from 'src/services/repositoryServices'
|
import RepositoryService from 'src/services/repositoryServices'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { T_ColumnsState, T_RepositoryItem } from '../types'
|
import { T_ColumnsState, T_RepositoryItem } from '../types'
|
||||||
|
@ -51,16 +51,13 @@ export default function ({
|
||||||
|
|
||||||
const deleteRep = async () => {
|
const deleteRep = async () => {
|
||||||
setContextMenuState(false)
|
setContextMenuState(false)
|
||||||
const response = await RepositoryService.deleteRepository(
|
const response = await RepositoryService.deleteRepository(repository.Id)
|
||||||
repository.Id
|
|
||||||
)
|
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
getRep()
|
getRep()
|
||||||
}
|
}
|
||||||
setDeleteNotificationState(false)
|
setDeleteNotificationState(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const onRep = async () => {
|
const onRep = async () => {
|
||||||
setContextMenuState(false)
|
setContextMenuState(false)
|
||||||
const response = await RepositoryService.onRepository(repository.Id)
|
const response = await RepositoryService.onRepository(repository.Id)
|
||||||
|
@ -76,11 +73,10 @@ export default function ({
|
||||||
getRep()
|
getRep()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const repRep = async () => {
|
const repackRep = async () => {
|
||||||
setContextMenuState(false)
|
setContextMenuState(false)
|
||||||
const response = await RepositoryService.RepackReposytory(repository.Id)
|
const response = await RepositoryService.RepackRepository(repository.Id)
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
getRep()
|
getRep()
|
||||||
}
|
}
|
||||||
|
@ -88,12 +84,14 @@ export default function ({
|
||||||
|
|
||||||
const depRep = async () => {
|
const depRep = async () => {
|
||||||
setContextMenuState(false)
|
setContextMenuState(false)
|
||||||
const response = await RepositoryService.DependenciesReposytory(repository.Id)
|
const response = await RepositoryService.DependenciesRepository(
|
||||||
|
repository.Id
|
||||||
|
)
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
getRep()
|
getRep()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const dowRep = async () => {
|
const dowRep = async () => {
|
||||||
setContextMenuState(false)
|
setContextMenuState(false)
|
||||||
const response = await RepositoryService.DownloadFile(repository.Id)
|
const response = await RepositoryService.DownloadFile(repository.Id)
|
||||||
|
@ -101,7 +99,6 @@ export default function ({
|
||||||
getRep()
|
getRep()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -133,7 +130,7 @@ export default function ({
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
{Object.entries(activeColumns).map(([key, item]) =>
|
{Object.entries(activeColumns).map(([key, _]) =>
|
||||||
activeColumns[key as keyof typeof activeColumns].status ? (
|
activeColumns[key as keyof typeof activeColumns].status ? (
|
||||||
<td key={key}>
|
<td key={key}>
|
||||||
<p>
|
<p>
|
||||||
|
@ -156,15 +153,15 @@ export default function ({
|
||||||
active={contextMenuState}
|
active={contextMenuState}
|
||||||
setActive={setContextMenuState}
|
setActive={setContextMenuState}
|
||||||
>
|
>
|
||||||
<div className='target'>
|
<div className='target'>
|
||||||
<img
|
<img
|
||||||
src='/src/images/menu.svg'
|
src='/src/images/menu.svg'
|
||||||
alt=''
|
alt=''
|
||||||
onClick={() => setContextMenuState(!contextMenuState)}
|
onClick={() => setContextMenuState(!contextMenuState)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='content'>
|
<div className='content'>
|
||||||
{repository.Enabled ? (
|
{repository.Enabled ? (
|
||||||
<Item onClick={offRep}>
|
<Item onClick={offRep}>
|
||||||
<img src='/src/images/stop.svg' alt='' />
|
<img src='/src/images/stop.svg' alt='' />
|
||||||
<p>Выключить</p>
|
<p>Выключить</p>
|
||||||
|
@ -175,34 +172,39 @@ export default function ({
|
||||||
<p>Включить</p>
|
<p>Включить</p>
|
||||||
</Item>
|
</Item>
|
||||||
)}
|
)}
|
||||||
<Item onClick={repRep}>
|
<Item onClick={repackRep}>
|
||||||
<img src='/src/images/reload.svg' alt='' />
|
<img src='/src/images/reload.svg' alt='' />
|
||||||
<p>Перепаковать</p>
|
<p>Перепаковать</p>
|
||||||
</Item>
|
</Item>
|
||||||
<Item onClick={depRep}>
|
<Item onClick={depRep}>
|
||||||
<img src='/src/images/trash.svg' alt='' />
|
<img src='/src/images/trash.svg' alt='' />
|
||||||
<p>Очистить зависимости</p>
|
<p>Очистить зависимости</p>
|
||||||
</Item>
|
</Item>
|
||||||
{repository.Url !== '' && (
|
{repository.Url !== '' && (
|
||||||
<Link
|
<Link
|
||||||
to={`${HOST_NAME}/${repository.Url}`}
|
to={`${HOST_NAME}/${repository.Url}`}
|
||||||
onClick={() => setContextMenuState(false)}
|
onClick={() => setContextMenuState(false)}
|
||||||
|
>
|
||||||
|
<Item onClick={dowRep}>
|
||||||
|
<img
|
||||||
|
src='/src/images/download.svg'
|
||||||
|
alt=''
|
||||||
|
style={{ width: '20px' }}
|
||||||
|
/>
|
||||||
|
<p>Скачать</p>
|
||||||
|
</Item>
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
<Item
|
||||||
|
onClick={() => (
|
||||||
|
setEditModalState(true), setContextMenuState(false)
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
<Item onClick={dowRep}>
|
<img src='/src/images/edit.svg' alt='' />
|
||||||
<img
|
<p>Редактировать</p>
|
||||||
src='/src/images/download.svg'
|
</Item>
|
||||||
alt=''
|
<Item
|
||||||
style={{ width: '20px' }}
|
onClick={() => {
|
||||||
/>
|
|
||||||
<p>Скачать</p>
|
|
||||||
</Item>
|
|
||||||
</Link>
|
|
||||||
)}
|
|
||||||
<Item onClick={() => (setEditModalState(true), setContextMenuState(false))}>
|
|
||||||
<img src='/src/images/edit.svg' alt='' />
|
|
||||||
<p>Редактировать</p>
|
|
||||||
</Item>
|
|
||||||
<Item onClick={() => {
|
|
||||||
setContextMenuState(false)
|
setContextMenuState(false)
|
||||||
setDeleteNotificationState(true)
|
setDeleteNotificationState(true)
|
||||||
}}
|
}}
|
||||||
|
@ -210,7 +212,7 @@ export default function ({
|
||||||
<img src='/src/images/trash.svg' alt='' />
|
<img src='/src/images/trash.svg' alt='' />
|
||||||
<p>Удалить</p>
|
<p>Удалить</p>
|
||||||
</Item>
|
</Item>
|
||||||
</div>
|
</div>
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
</td>
|
</td>
|
||||||
<Modal
|
<Modal
|
||||||
|
|
|
@ -169,7 +169,7 @@ export default function Store({}: Props) {
|
||||||
<SearchInput
|
<SearchInput
|
||||||
value={queryParams.search}
|
value={queryParams.search}
|
||||||
onChange={handleSearchQueryChange}
|
onChange={handleSearchQueryChange}
|
||||||
placeholder='Введите номер контракта, поставки или email'
|
placeholder='Введите название приложения, версию, категорию или краткое описание'
|
||||||
/>
|
/>
|
||||||
<>
|
<>
|
||||||
{searchNotification ? (
|
{searchNotification ? (
|
||||||
|
|
|
@ -18,18 +18,18 @@ export default class RepositoryService {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(url, { params })
|
const response = await axios.get(url, { params })
|
||||||
console.log(response.data)
|
|
||||||
return response
|
return response
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
return error.response
|
return error.response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async createRep(
|
static async createRep(newRep: T_NewRepository): Promise<AxiosResponse> {
|
||||||
newRep: T_NewRepository
|
|
||||||
): Promise<AxiosResponse> {
|
|
||||||
try {
|
try {
|
||||||
const response = await axios.post(`${API_HOST_NAME}/repository/packages`, newRep)
|
const response = await axios.post(
|
||||||
|
`${API_HOST_NAME}/repository/packages`,
|
||||||
|
newRep
|
||||||
|
)
|
||||||
return response
|
return response
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
return error.response
|
return error.response
|
||||||
|
@ -48,10 +48,12 @@ export default class RepositoryService {
|
||||||
return error.response
|
return error.response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async onRepository(id: number): Promise<AxiosResponse> {
|
static async onRepository(id: number): Promise<AxiosResponse> {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post(`${API_HOST_NAME}/repository/packages/${id}/enable`)
|
const response = await axios.post(
|
||||||
|
`${API_HOST_NAME}/repository/packages/${id}/enable`
|
||||||
|
)
|
||||||
return response
|
return response
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
return error.response
|
return error.response
|
||||||
|
@ -60,23 +62,29 @@ export default class RepositoryService {
|
||||||
|
|
||||||
static async offRepository(id: number): Promise<AxiosResponse> {
|
static async offRepository(id: number): Promise<AxiosResponse> {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post(`${API_HOST_NAME}/repository/packages/${id}/disable`)
|
const response = await axios.post(
|
||||||
|
`${API_HOST_NAME}/repository/packages/${id}/disable`
|
||||||
|
)
|
||||||
return response
|
return response
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
return error.response
|
return error.response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static async RepackReposytory(id: number): Promise<AxiosResponse> {
|
static async RepackRepository(id: number): Promise<AxiosResponse> {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post(`${API_HOST_NAME}/repository/packages/${id}/repack`)
|
const response = await axios.post(
|
||||||
|
`${API_HOST_NAME}/repository/packages/${id}/repack`
|
||||||
|
)
|
||||||
return response
|
return response
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
return error.response
|
return error.response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static async DependenciesReposytory(id: number): Promise<AxiosResponse> {
|
static async DependenciesRepository(id: number): Promise<AxiosResponse> {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post(`${API_HOST_NAME}/repository/packages/${id}/dependencies`)
|
const response = await axios.post(
|
||||||
|
`${API_HOST_NAME}/repository/packages/${id}/dependencies`
|
||||||
|
)
|
||||||
return response
|
return response
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
return error.response
|
return error.response
|
||||||
|
@ -87,18 +95,20 @@ export default class RepositoryService {
|
||||||
const response = await axios.get(
|
const response = await axios.get(
|
||||||
`${API_HOST_NAME}/repository/packages/${id}/package/download`,
|
`${API_HOST_NAME}/repository/packages/${id}/package/download`,
|
||||||
{
|
{
|
||||||
responseType: 'arraybuffer',
|
responseType: 'arraybuffer'
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return response;
|
return response
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
return error.response;
|
return error.response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async deleteRepository(id: number): Promise<AxiosResponse> {
|
static async deleteRepository(id: number): Promise<AxiosResponse> {
|
||||||
try {
|
try {
|
||||||
const response = await axios.delete(`${API_HOST_NAME}/repository/packages/${id}`)
|
const response = await axios.delete(
|
||||||
|
`${API_HOST_NAME}/repository/packages/${id}`
|
||||||
|
)
|
||||||
return response
|
return response
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
return error.response
|
return error.response
|
||||||
|
@ -110,7 +120,10 @@ export default class RepositoryService {
|
||||||
rep: T_NewRepository
|
rep: T_NewRepository
|
||||||
): Promise<AxiosResponse> {
|
): Promise<AxiosResponse> {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post(`${API_HOST_NAME}/repository/packages/${id}`, rep)
|
const response = await axios.post(
|
||||||
|
`${API_HOST_NAME}/repository/packages/${id}`,
|
||||||
|
rep
|
||||||
|
)
|
||||||
return response
|
return response
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
return error.response
|
return error.response
|
||||||
|
|
Loading…
Reference in New Issue