creae update devices
This commit is contained in:
parent
d9c3bfa35e
commit
65b924c174
|
@ -0,0 +1,6 @@
|
||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="DBE_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||||
|
<data-source source="LOCAL" name="@localhost" uuid="bfd16a45-57c4-4cdd-9553-7a07934e4c31">
|
||||||
|
<driver-ref>postgresql</driver-ref>
|
||||||
|
<synchronize>true</synchronize>
|
||||||
|
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
||||||
|
<jdbc-url>jdbc:postgresql://localhost:5432/</jdbc-url>
|
||||||
|
<working-dir>$ProjectFileDir$</working-dir>
|
||||||
|
</data-source>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/Yuna.iml" filepath="$PROJECT_DIR$/.idea/Yuna.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="SqlDialectMappings">
|
||||||
|
<file url="file://$APPLICATION_CONFIG_DIR$/consoles/db/bfd16a45-57c4-4cdd-9553-7a07934e4c31/console_1.sql" dialect="PostgreSQL" />
|
||||||
|
<file url="PROJECT" dialect="PostgreSQL" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -80,5 +80,27 @@ namespace Yuna.Tests.Repositories
|
||||||
Assert.NotNull(result);
|
Assert.NotNull(result);
|
||||||
Assert.True(result.All(x => x.UserId == 1));
|
Assert.True(result.All(x => x.UserId == 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Update_Updates()
|
||||||
|
{
|
||||||
|
//Arrange
|
||||||
|
Settings.Init();
|
||||||
|
var _context = new DapperContext(true);
|
||||||
|
var repo = new DeviceRepository(_context);
|
||||||
|
|
||||||
|
//Act
|
||||||
|
var initial = await repo.GetById(1);
|
||||||
|
|
||||||
|
initial!.Name += "1";
|
||||||
|
var returnResult = await repo.Update(initial);
|
||||||
|
|
||||||
|
var realChanged = await repo.GetById(1);
|
||||||
|
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
Assert.Equal(initial.Name, returnResult!.Name);
|
||||||
|
Assert.Equal(initial!.Name, realChanged!.Name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,9 +16,6 @@ namespace Yuna.Website.Server.API
|
||||||
app.MapPost("/api/device", CreateDevice)
|
app.MapPost("/api/device", CreateDevice)
|
||||||
.WithTags("device");
|
.WithTags("device");
|
||||||
|
|
||||||
app.MapDelete("/api/device/{id:long}", () => { })
|
|
||||||
.WithTags("device");
|
|
||||||
|
|
||||||
app.MapGet("/api/device/{deviceId:long}", GetById)
|
app.MapGet("/api/device/{deviceId:long}", GetById)
|
||||||
.WithTags("device");
|
.WithTags("device");
|
||||||
|
|
||||||
|
@ -32,6 +29,12 @@ namespace Yuna.Website.Server.API
|
||||||
|
|
||||||
app.MapPut("/api/device/{deviceId:long}", AddSkillsToDevice)
|
app.MapPut("/api/device/{deviceId:long}", AddSkillsToDevice)
|
||||||
.WithTags("device");
|
.WithTags("device");
|
||||||
|
|
||||||
|
app.MapPut("/api/device", Update)
|
||||||
|
.WithTags("device");
|
||||||
|
|
||||||
|
app.MapDelete("/api/device/{deviceId:long}", Delete)
|
||||||
|
.WithTags("device");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -99,10 +102,18 @@ namespace Yuna.Website.Server.API
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public async Task<IResult> Delete(IDeviceService deviceService, long id)
|
public async Task<IResult> Delete(IDeviceService deviceService, HttpContext context, long deviceId)
|
||||||
{
|
{
|
||||||
var result = await deviceService.Delete(id);
|
var isAdmin = context.GetRoleFromCookie();
|
||||||
if (result is null) return Results.NotFound();
|
var userId = context.GetUserIdFromCookie();
|
||||||
|
|
||||||
|
var deviceToDelete = await deviceService.GetById(deviceId);
|
||||||
|
if(deviceToDelete is null) return Results.NotFound();
|
||||||
|
|
||||||
|
if (userId != deviceToDelete.UserId && !isAdmin) return Results.Forbid();
|
||||||
|
|
||||||
|
var result = await deviceService.Delete(deviceId);
|
||||||
|
if (result is null) return Results.Problem(statusCode: 500);
|
||||||
return Results.Ok(result);
|
return Results.Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,5 +140,40 @@ namespace Yuna.Website.Server.API
|
||||||
|
|
||||||
return Results.Ok(result);
|
return Results.Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class UpdateDeviceRequest
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")]
|
||||||
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("name")]
|
||||||
|
public string Name { get; set; } = null!;
|
||||||
|
|
||||||
|
[JsonPropertyName("description")]
|
||||||
|
public string Description { get; set; } = "";
|
||||||
|
|
||||||
|
[JsonPropertyName("deviceUrl")]
|
||||||
|
public string DeviceUrl { get; set; } = null!;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize]
|
||||||
|
public async Task<IResult> Update([FromBody] UpdateDeviceRequest request, HttpContext context, IDeviceService deviceService)
|
||||||
|
{
|
||||||
|
var userId = context.GetUserIdFromCookie();
|
||||||
|
var isAdmin = context.GetRoleFromCookie();
|
||||||
|
|
||||||
|
var device = await deviceService.GetById(request.Id);
|
||||||
|
|
||||||
|
if (device is null) return Results.NotFound();
|
||||||
|
if (device.UserId != userId && !isAdmin) return Results.Forbid();
|
||||||
|
|
||||||
|
device.DeviceUrl = request.DeviceUrl;
|
||||||
|
device.Name = request.Name;
|
||||||
|
device.Description = request.Description;
|
||||||
|
|
||||||
|
var result = await deviceService.Update(device);
|
||||||
|
return Results.Ok(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,11 @@ namespace Yuna.Website.Server.Infrastructure
|
||||||
|
|
||||||
private static void LoadConnectionStrs(JsonElement connectionStrs)
|
private static void LoadConnectionStrs(JsonElement connectionStrs)
|
||||||
{
|
{
|
||||||
|
var env = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT");
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
DbConnectionStr = connectionStrs.GetProperty("Db").GetString()!;
|
DbConnectionStr = connectionStrs.GetProperty("Db").GetString()!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,9 +107,6 @@ namespace Yuna.Website.Server.Services.DeviceService
|
||||||
|
|
||||||
public async Task<Device?> Delete(long id)
|
public async Task<Device?> Delete(long id)
|
||||||
{
|
{
|
||||||
var prop = await _deviceRepository.GetById(id);
|
|
||||||
if (prop is null) return null;
|
|
||||||
|
|
||||||
var result = await _deviceRepository.Delete(id);
|
var result = await _deviceRepository.Delete(id);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -130,5 +127,11 @@ namespace Yuna.Website.Server.Services.DeviceService
|
||||||
var result = await _deviceRepository.GetList(userId);
|
var result = await _deviceRepository.GetList(userId);
|
||||||
return result ?? [];
|
return result ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<Device?> Update(Device device)
|
||||||
|
{
|
||||||
|
var result = await _deviceRepository.Update(device);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,5 +12,6 @@ namespace Yuna.Website.Server.Services.DeviceService
|
||||||
public Task<Device?> Delete(long id);
|
public Task<Device?> Delete(long id);
|
||||||
public Task<Device?> AddProps(IReadOnlyList<Prop> props, long deviceId);
|
public Task<Device?> AddProps(IReadOnlyList<Prop> props, long deviceId);
|
||||||
public Task<Dictionary<long, string>?> FetchPropsData(Device device);
|
public Task<Dictionary<long, string>?> FetchPropsData(Device device);
|
||||||
|
public Task<Device?> Update(Device device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using Dapper;
|
using Dapper;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
|
using Yuna.Website.Server.Model;
|
||||||
|
|
||||||
namespace Yuna.Website.Server.Storage.Repositories.Device
|
namespace Yuna.Website.Server.Storage.Repositories.Device
|
||||||
{
|
{
|
||||||
|
@ -36,9 +37,18 @@ namespace Yuna.Website.Server.Storage.Repositories.Device
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Model.Device?> Delete(long id)
|
public async Task<Model.Device?> Delete(long id)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
var query =
|
||||||
|
$@"
|
||||||
|
UPDATE ""Yuna_Devices""
|
||||||
|
SET ""IsDeleted"" = TRUE
|
||||||
|
WHERE ""Id"" = {id}
|
||||||
|
AND NOT ""IsDeleted""
|
||||||
|
returning *
|
||||||
|
";
|
||||||
|
|
||||||
|
return await _context.Connection.QuerySingleOrDefaultAsync<Model.Device>(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Model.Device?> GetById(long id)
|
public async Task<Model.Device?> GetById(long id)
|
||||||
|
@ -58,7 +68,8 @@ namespace Yuna.Website.Server.Storage.Repositories.Device
|
||||||
FROM ""Yuna_Devices"" d
|
FROM ""Yuna_Devices"" d
|
||||||
LEFT JOIN ""Yuna_Props_In_Devices"" pd ON d.""Id"" = pd.""DeviceId""
|
LEFT JOIN ""Yuna_Props_In_Devices"" pd ON d.""Id"" = pd.""DeviceId""
|
||||||
LEFT JOIN ""Yuna_Props"" p ON pd.""PropId"" = p.""Id""
|
LEFT JOIN ""Yuna_Props"" p ON pd.""PropId"" = p.""Id""
|
||||||
WHERE d.""Id"" = {id}";
|
WHERE d.""Id"" = {id}
|
||||||
|
AND NOT d.""IsDeleted""";
|
||||||
|
|
||||||
var deviceDict = new Dictionary<long, Model.Device>();
|
var deviceDict = new Dictionary<long, Model.Device>();
|
||||||
var result = await _context.Connection.QueryAsync<Model.Device, Model.Prop, Model.Device>(
|
var result = await _context.Connection.QueryAsync<Model.Device, Model.Prop, Model.Device>(
|
||||||
|
@ -96,7 +107,9 @@ namespace Yuna.Website.Server.Storage.Repositories.Device
|
||||||
p.""Type"" as {nameof(Model.Prop.Type)}
|
p.""Type"" as {nameof(Model.Prop.Type)}
|
||||||
FROM ""Yuna_Devices"" d
|
FROM ""Yuna_Devices"" d
|
||||||
LEFT JOIN ""Yuna_Props_In_Devices"" pd ON d.""Id"" = pd.""DeviceId""
|
LEFT JOIN ""Yuna_Props_In_Devices"" pd ON d.""Id"" = pd.""DeviceId""
|
||||||
LEFT JOIN ""Yuna_Props"" p ON pd.""PropId"" = p.""Id""";
|
LEFT JOIN ""Yuna_Props"" p ON pd.""PropId"" = p.""Id""
|
||||||
|
WHERE NOT d.""IsDeleted""
|
||||||
|
ORDER BY d.""Id""";
|
||||||
|
|
||||||
var deviceDict = new Dictionary<long, Model.Device>();
|
var deviceDict = new Dictionary<long, Model.Device>();
|
||||||
var result = await _context.Connection.QueryAsync<Model.Device, Model.Prop, Model.Device>(
|
var result = await _context.Connection.QueryAsync<Model.Device, Model.Prop, Model.Device>(
|
||||||
|
@ -135,7 +148,9 @@ namespace Yuna.Website.Server.Storage.Repositories.Device
|
||||||
FROM ""Yuna_Devices"" d
|
FROM ""Yuna_Devices"" d
|
||||||
LEFT JOIN ""Yuna_Props_In_Devices"" pd ON d.""Id"" = pd.""DeviceId""
|
LEFT JOIN ""Yuna_Props_In_Devices"" pd ON d.""Id"" = pd.""DeviceId""
|
||||||
LEFT JOIN ""Yuna_Props"" p ON pd.""PropId"" = p.""Id""
|
LEFT JOIN ""Yuna_Props"" p ON pd.""PropId"" = p.""Id""
|
||||||
WHERE d.""UserId"" = {userId};";
|
WHERE d.""UserId"" = {userId}
|
||||||
|
AND NOT d.""IsDeleted""
|
||||||
|
ORDER BY d.""Id""";
|
||||||
|
|
||||||
var deviceDict = new Dictionary<long, Model.Device>();
|
var deviceDict = new Dictionary<long, Model.Device>();
|
||||||
var result = await _context.Connection.QueryAsync<Model.Device, Model.Prop, Model.Device>(
|
var result = await _context.Connection.QueryAsync<Model.Device, Model.Prop, Model.Device>(
|
||||||
|
@ -156,5 +171,22 @@ namespace Yuna.Website.Server.Storage.Repositories.Device
|
||||||
|
|
||||||
return result.Distinct().ToList();
|
return result.Distinct().ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<Model.Device?> Update(Model.Device device)
|
||||||
|
{
|
||||||
|
var query =
|
||||||
|
$@"
|
||||||
|
UPDATE public.""Yuna_Devices""
|
||||||
|
SET ""Name"" = @Name,
|
||||||
|
""Description"" = @Description,
|
||||||
|
""DeviceUrl"" = @DeviceUrl,
|
||||||
|
""UserId"" = @UserId
|
||||||
|
WHERE ""Id"" = @Id
|
||||||
|
AND NOT ""IsDeleted""
|
||||||
|
returning *
|
||||||
|
";
|
||||||
|
|
||||||
|
return await _context.Connection.QuerySingleOrDefaultAsync<Model.Device>(query, device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,7 +8,7 @@ namespace Yuna.Website.Server.Storage.Repositories.Device
|
||||||
public Task<IReadOnlyList<Model.Device>> GetList();
|
public Task<IReadOnlyList<Model.Device>> GetList();
|
||||||
public Task<IReadOnlyList<Model.Device>> GetList(long userId);
|
public Task<IReadOnlyList<Model.Device>> GetList(long userId);
|
||||||
public Task<Model.Device?> Create(Model.Device device);
|
public Task<Model.Device?> Create(Model.Device device);
|
||||||
//public Task<User?> Update(User user);
|
public Task<Model.Device?> Update(Model.Device device);
|
||||||
public Task<Model.Device?> Delete(long id);
|
public Task<Model.Device?> Delete(long id);
|
||||||
public Task AddProps(IReadOnlyList<Model.Prop> skills, long deviceId);
|
public Task AddProps(IReadOnlyList<Model.Prop> skills, long deviceId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
import { Header } from "../../components/Header"
|
import { Header } from "../../components/Header"
|
||||||
import { DeviceList } from "./components/DeviceList";
|
import { DeviceList } from "./components/DeviceList";
|
||||||
|
import { EditModal } from "./components/modals/EditModal";
|
||||||
|
|
||||||
export const HomePage = () => {
|
export const HomePage = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
||||||
<Header />
|
<Header />
|
||||||
<DeviceList />
|
<DeviceList />
|
||||||
|
<EditModal />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -2,8 +2,10 @@ import { useEffect, useMemo } from "react";
|
||||||
import "../../../resources/styles/home.scss"
|
import "../../../resources/styles/home.scss"
|
||||||
import { IDeviceDto, IPropDto } from "../types";
|
import { IDeviceDto, IPropDto } from "../types";
|
||||||
import { DeviceCardStore } from "../model/DeviceCardStore";
|
import { DeviceCardStore } from "../model/DeviceCardStore";
|
||||||
import { Button, Center, Skeleton, useInterval } from "@chakra-ui/react";
|
import { Button, Center, IconButton, Skeleton, Spacer, useInterval } from "@chakra-ui/react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
|
import { MdOutlineDelete, MdOutlineSettings } from "react-icons/md";
|
||||||
|
import { homePageStore } from "../model/HomePageStore";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,11 +38,25 @@ export const DeviceCard = observer((props: { data: IDeviceDto }) => {
|
||||||
<div className="device_card">
|
<div className="device_card">
|
||||||
<div className="h1_container">
|
<div className="h1_container">
|
||||||
<h1>{props.data.name}</h1>
|
<h1>{props.data.name}</h1>
|
||||||
<Button>sdfs</Button>
|
<div className="button_container">
|
||||||
|
<IconButton
|
||||||
|
colorScheme="red"
|
||||||
|
onClick={() => homePageStore.deleteDevice(props.data.id)}
|
||||||
|
icon={<MdOutlineDelete />}
|
||||||
|
aria-label={"delete"}
|
||||||
|
fontSize={"90%"}
|
||||||
|
size={'sm'} />
|
||||||
|
<IconButton
|
||||||
|
onClick={() => homePageStore.setEditModalOpened(props.data.id, true)}
|
||||||
|
icon={<MdOutlineSettings />}
|
||||||
|
aria-label={"edit"}
|
||||||
|
fontSize={"90%"}
|
||||||
|
size={'sm'} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p style={{ textAlign: 'center' }}>{props.data.description}</p>
|
<p style={{ textAlign: 'center' }}>{props.data.description}</p>
|
||||||
<ul>
|
<ul>
|
||||||
{getPropsList(props.data.props, deviceCardStore.isLoading)}
|
{getPropsList(props.data.props ?? [], deviceCardStore.isLoading)}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import { homePageStore } from "../../model/HomePageStore";
|
||||||
|
import { Button, Center, Input, Modal, ModalBody, ModalCloseButton, ModalContent, ModalHeader, ModalOverlay, Stack, Textarea } from "@chakra-ui/react";
|
||||||
|
import { IDeviceDto } from "../../types";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
export const EditModal = observer(() => {
|
||||||
|
const currentDevice = homePageStore.currentEditDevice
|
||||||
|
|
||||||
|
const [name, setName] = useState(currentDevice?.name);
|
||||||
|
const [description, setDescription] = useState(currentDevice?.description);
|
||||||
|
const [url, setUrl] = useState(currentDevice?.deviceUrl);
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
() => {
|
||||||
|
setName(currentDevice?.name);
|
||||||
|
setDescription(currentDevice?.description);
|
||||||
|
setUrl(currentDevice?.deviceUrl)
|
||||||
|
},
|
||||||
|
[currentDevice]
|
||||||
|
)
|
||||||
|
|
||||||
|
const onUpdateDevice = () => {
|
||||||
|
homePageStore.setEditModalOpened(currentDevice!.id, false);
|
||||||
|
homePageStore.updateDevice({
|
||||||
|
id: currentDevice?.id,
|
||||||
|
name: name,
|
||||||
|
description: description,
|
||||||
|
deviceUrl: url
|
||||||
|
} as IDeviceDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (<Modal
|
||||||
|
onClose={() => homePageStore.setEditModalOpened(homePageStore.editModalCurrentId!, false)}
|
||||||
|
isOpen={homePageStore.isEditModalOpened}
|
||||||
|
isCentered
|
||||||
|
blockScrollOnMount={false}
|
||||||
|
>
|
||||||
|
<ModalOverlay />
|
||||||
|
<ModalContent>
|
||||||
|
<ModalHeader>Редактировать</ModalHeader>
|
||||||
|
<ModalCloseButton />
|
||||||
|
<ModalBody>
|
||||||
|
<Stack spacing={3}>
|
||||||
|
<label>Название:</label>
|
||||||
|
<Input
|
||||||
|
value={name ?? ""}
|
||||||
|
onChange={e => setName(e.target.value)}
|
||||||
|
disabled={homePageStore.isLoading} />
|
||||||
|
<label>Описание:</label>
|
||||||
|
<Textarea
|
||||||
|
value={description ?? ""}
|
||||||
|
onChange={e => setDescription(e.target.value)}
|
||||||
|
disabled={homePageStore.isLoading} />
|
||||||
|
<label>URL:</label>
|
||||||
|
<Input
|
||||||
|
value={url ?? ""}
|
||||||
|
onChange={e => setUrl(e.target.value)}
|
||||||
|
disabled={homePageStore.isLoading} />
|
||||||
|
</Stack>
|
||||||
|
<Center>
|
||||||
|
<Button
|
||||||
|
colorScheme="green"
|
||||||
|
marginTop={10}
|
||||||
|
onClick={() => onUpdateDevice()}
|
||||||
|
isLoading={homePageStore.isLoading}>Сохранить</Button>
|
||||||
|
</Center>
|
||||||
|
</ModalBody>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>);
|
||||||
|
});
|
|
@ -1,15 +1,29 @@
|
||||||
import { makeAutoObservable } from "mobx";
|
import { makeAutoObservable } from "mobx";
|
||||||
import { IDeviceDto } from "../types";
|
import { IDeviceDto } from "../types";
|
||||||
import { HomePageService } from "../services/HomePageService";
|
import { HomePageService } from "../services/HomePageService";
|
||||||
|
import { error, info } from "../../../utils/ToastHelper";
|
||||||
|
|
||||||
class HomePageStore {
|
class HomePageStore {
|
||||||
|
|
||||||
devices: IDeviceDto[] = []
|
devices: IDeviceDto[] = []
|
||||||
isLoading: boolean = false;
|
isLoading: boolean = false;
|
||||||
|
isEditModalOpened: boolean = false;
|
||||||
|
editModalCurrentId: number | null = null;
|
||||||
|
currentEditDevice: IDeviceDto | undefined;
|
||||||
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setEditModalOpened(id: number, isOpened: boolean): void {
|
||||||
|
this.currentEditDevice = { ...this.devices.find(device => device.id === id) } as IDeviceDto;
|
||||||
|
this.isEditModalOpened = isOpened;
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrentEditDevice(value: IDeviceDto | undefined) {
|
||||||
|
this.currentEditDevice = value;
|
||||||
|
}
|
||||||
|
|
||||||
setDevices(value: IDeviceDto[]) {
|
setDevices(value: IDeviceDto[]) {
|
||||||
this.devices = value;
|
this.devices = value;
|
||||||
|
@ -21,6 +35,29 @@ class HomePageStore {
|
||||||
this.setDevices(result);
|
this.setDevices(result);
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async updateDevice(value: IDeviceDto) {
|
||||||
|
const result = await HomePageService.updateDevice(value);
|
||||||
|
if (result === null) {
|
||||||
|
error("Ошибка", "Запрос не был выполнен");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setCurrentEditDevice(undefined);
|
||||||
|
info("Успешно", "Изменения были сохранены")
|
||||||
|
await this.loadDevices();
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteDevice(value: number) {
|
||||||
|
const result = await HomePageService.deleteDevice(value);
|
||||||
|
if (result === null) {
|
||||||
|
error("Ошибка", "Запрос не был выполнен");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
info("Успешно", "Устройство было удалено");
|
||||||
|
await this.loadDevices();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const homePageStore = new HomePageStore();
|
export const homePageStore = new HomePageStore();
|
|
@ -21,4 +21,30 @@ export class HomePageService {
|
||||||
if (response.status === 200) return response.data;
|
if (response.status === 200) return response.data;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async updateDevice(dto: IDeviceDto): Promise<IDeviceDto | null> {
|
||||||
|
try {
|
||||||
|
const response = await api.put<IDeviceDto>(`device`, dto);
|
||||||
|
if (response.status === 200) return response.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (error) {
|
||||||
|
console.error("Error: ", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async deleteDevice(id: number): Promise<IDeviceDto | null> {
|
||||||
|
try {
|
||||||
|
const response = await api.delete<IDeviceDto>(`device/${id}`);
|
||||||
|
if (response.status === 200) return response.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (error) {
|
||||||
|
console.error("Error: ", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
export interface IDeviceDto {
|
export interface IDeviceDto {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description?: string;
|
||||||
props: IPropDto[]
|
props?: IPropDto[]
|
||||||
deviceUrl: string;
|
deviceUrl?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum propType {
|
export enum propType {
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
width: 80%;
|
width: 80%;
|
||||||
height: 70px;
|
height: 70px;
|
||||||
box-shadow: 5px 5px 0px #319795;
|
box-shadow: 5px 5px 0px #319795;
|
||||||
|
z-index: 1;
|
||||||
/* x-offset y-offset blur-radius color */
|
/* x-offset y-offset blur-radius color */
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
|
|
|
@ -15,19 +15,26 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
padding: 0px 50px;
|
padding: 0px 0px;
|
||||||
|
|
||||||
.h1_container {
|
.h1_container {
|
||||||
overflow: hidden;
|
|
||||||
height: 80px;
|
|
||||||
|
|
||||||
h1 {}
|
|
||||||
|
|
||||||
button {
|
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -50px;
|
overflow: visible;
|
||||||
width: 10px;
|
width: 100%;
|
||||||
float: right;
|
|
||||||
|
h1 {
|
||||||
|
max-width: 450px;
|
||||||
|
display: block;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button_container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 5px;
|
||||||
|
position: absolute;
|
||||||
|
top: 25px;
|
||||||
|
right: 30px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mobx-react": "^9.1.1"
|
"mobx-react": "^9.1.1",
|
||||||
|
"react-icons": "^5.2.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/js-tokens": {
|
"node_modules/js-tokens": {
|
||||||
|
@ -96,6 +97,14 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-icons": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-zdbW5GstTzXaVKvGSyTaBalt7HSfuK5ovrzlpyiWHAFXndXTdd/1hdDHI4xBM1Mn7YriT6aqESucFl9kEXzrdw==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/use-sync-external-store": {
|
"node_modules/use-sync-external-store": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mobx-react": "^9.1.1"
|
"mobx-react": "^9.1.1",
|
||||||
|
"react-icons": "^5.2.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue