test ci/cd

This commit is contained in:
commit 1e8243ab9a
265 changed files with 216965 additions and 0 deletions

View file

@ -0,0 +1,137 @@
import React, {useState} from 'react';
import styled, { css } from 'styled-components';
import { DeviceUser } from "../../../store/useDeviceStore";
import {buttonNames} from "../../../const/buttons/names";
import {ModalMap} from "../../modalwindows/windowsType";
import {IconComponent} from "../../../const/buttons/icons";
import {useModalContext} from "../../../store";
interface DeviceCardProps {
device: DeviceUser;
status: 'online' | 'offline';
}
const CardWrapper = styled.div<{ status: 'online' | 'offline' }>`
background: white;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
overflow: hidden;
transition: all 0.3s ease;
cursor: pointer;
margin-bottom: 16px;
&:hover {
transform: translateY(-2px);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15);
}
`;
const CardHeader = styled.div<{ status: 'online' | 'offline' }>`
background: ${({ status, theme }) =>
status === 'online' ? theme.successColor : theme.offlineColor};
color: white;
padding: 16px;
font-size: 18px;
font-weight: 500;
display: flex;
justify-content: space-between;
align-items: center;
`;
const CardContent = styled.div<{ isExpanded: boolean }>`
max-height: 0;
opacity: 0;
padding: 0 16px;
transition: all 0.3s ease;
color: #333;
font-size: 14px;
display: grid;
gap: 12px;
${({ isExpanded }) => isExpanded && css`
max-height: 500px;
opacity: 1;
padding: 16px;
`}
`;
const InfoRow = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
`;
const Label = styled.span`
font-weight: 500;
color: #666;
`;
const Value = styled.span`
color: #333;
`;
const DeviceCard: React.FC<DeviceCardProps> = ({ device, status }) => {
const [isExpanded, setIsExpanded] = useState(false);
const toggleExpanded = () => setIsExpanded(!isExpanded);
const { openModal } = useModalContext();
const openModalNote = (e: React.MouseEvent) => {
e.stopPropagation();
openModal(ModalMap['6'], {
address: device.mac,
currentNote: device.note || ''
});
};
return (
<CardWrapper status={status} onClick={toggleExpanded}>
<CardHeader status={status}>
<p>
MAC: {device.mac}
</p>
<span onClick={openModalNote}>
<IconComponent name={buttonNames[16]} width="28" height="28" setColor={'white'} />
</span>
</CardHeader>
<CardContent isExpanded={isExpanded}>
<InfoRow>
<Label>Имя:</Label>
<Value>{device.hostname || device.ip}</Value>
</InfoRow>
<InfoRow>
<Label>Производитель:</Label>
<Value>{device.vendor || 'Неизвестно'}</Value>
</InfoRow>
<InfoRow>
<Label>IP адрес:</Label>
<Value>{device.ip}</Value>
</InfoRow>
{device.open_ports?.length > 0 && (
<InfoRow>
<Label>Открытые порты:</Label>
<Value>{device.open_ports.join(', ')}</Value>
</InfoRow>
)}
<InfoRow>
<Label>Последняя активность:</Label>
<Value>{device.last_seen}</Value>
</InfoRow>
<InfoRow>
<Label>Заметка:</Label>
<Value>{device.note || '-'}</Value>
</InfoRow>
</CardContent>
</CardWrapper>
);
};
export default DeviceCard;

View file

@ -0,0 +1,130 @@
import React, {useEffect, useRef, useState} from 'react';
import styled from "styled-components";
import {buttonNames} from "../../../const/buttons/names";
import {IconComponent} from "../../../const/buttons/icons";
type Option = {
value: number,
label: string,
}
interface DropdownTypeProps {
options: Option[];
label?: string;
onChange?: (selectedItem: Option) => void;
value: Option | null;
}
const DropdownWrapper = styled.div`
position: absolute;
top: 18px;
right:20px;
display: inline-block;
background-color: ${({theme}) => theme.background};
padding: 12px 16px;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
z-index: 10;
`
const Label = styled.p`
color: ${({theme}) => theme.textColor};
font-size: 16px;
`
const Dropdown = styled.div`
background-color: ${({theme}) => theme.primary};
border-radius: 15px;
overflow: hidden;
transition: all .3s ease;
cursor: pointer;
z-index: 10;
margin-top: 6px;
`
const DropdownHeader = styled.div`
display: flex;
justify-content: space-between;
gap: 14px;
padding: 12px 24px;
font-size: 16px;
align-items: center;
height: 100%;
min-width: 200px;
`
const DropdownContent = styled.div<{$isOpen: boolean}>`
max-height: ${({$isOpen}) => $isOpen ? '500px' : '0'};
opacity: ${({$isOpen}) => $isOpen ? 1 : 0};
transition: all .3s ease;
display: flex;
flex-direction: column;
overflow: hidden;
`
const DropdownRow = styled.button`
padding: 12px 24px;
background-color: transparent;
text-align: start;
font-size: 16px;
border: none;
width: 100%;
color: ${({theme}) => theme.textColor};
transition: all .3s ease;
cursor: pointer;
&:hover {
background-color: ${({theme}) => theme.background};
}
`
const DropdownArrow = styled.div<{ $isOpen: boolean }>`
transition: transform 0.3s ease;
transform: rotate(${({ $isOpen }) => ($isOpen ? "90deg" : "0deg")});
`;
const DropdownType = ({options, value, onChange, label}: DropdownTypeProps) => {
const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null);
function toggleOpen() {
setIsOpen((prev) => !prev);
}
function handleSelect(option: Option) {
onChange?.(option);
setIsOpen(false);
}
useEffect(() => {
function handleClickOutside(event: MouseEvent) {
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
setIsOpen(false);
}
}
document.addEventListener("mousedown", handleClickOutside);
return () => document.removeEventListener("mousedown", handleClickOutside);
}, []);
return (
<DropdownWrapper ref={dropdownRef}>
<Label>{label}</Label>
<Dropdown>
<DropdownHeader onClick={toggleOpen}>
<p>{value?.label || 'Select an option'}</p>
<DropdownArrow $isOpen={isOpen}>
<IconComponent name={buttonNames[6]} />
</DropdownArrow>
</DropdownHeader>
<DropdownContent $isOpen={isOpen}>
{options.map((option, i) => (
<DropdownRow key={i} onClick={() => handleSelect(option)}>
{option.label}
</DropdownRow>
))}
</DropdownContent>
</Dropdown>
</DropdownWrapper>
);
};
export default DropdownType;