Можно работать

This commit is contained in:
Николай 2023-04-30 23:37:07 +04:00
parent 03e08d61c2
commit ba86843ae3
39 changed files with 0 additions and 4696 deletions

View File

@ -15,7 +15,6 @@ jar {
enabled = false
}
dependencies {
implementation(project(':front'))
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-devtools'

Binary file not shown.

26
front/.gitignore vendored
View File

@ -1,26 +0,0 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
.parcel-cache

View File

@ -1,58 +0,0 @@
import com.github.gradle.node.util.PlatformHelper
import groovy.text.SimpleTemplateEngine
plugins {
id 'java'
id 'com.github.node-gradle.node' version '3.5.1'
id "de.undercouch.download" version '5.3.1'
}
node {
version = '18.15.0'
download = true
}
jar.dependsOn 'npmBuild'
clean.dependsOn 'npmClean'
nodeSetup.dependsOn 'downloadNode'
jar {
from 'dist'
into 'static'
final devHost = 'http://localhost:8080'
final prodHost = ''
filesMatching('index.html') {
filter { line -> line.replaceAll(devHost, prodHost) }
}
}
task downloadNode(type: Download) {
final helper = new PlatformHelper()
final templateData = [
"url" : node.distBaseUrl.get(),
"version": node.version.get(),
"os" : helper.osName,
"arch" : helper.osArch,
"ext" : helper.windows ? 'zip' : 'tar.gz'
]
final urlTemplate = '${url}/v${version}/node-v${version}-${os}-${arch}.${ext}'
final engine = new SimpleTemplateEngine()
final url = engine.createTemplate(urlTemplate).make(templateData).toString()
final String destDir = '.gradle/'
file(destDir).mkdirs()
src url
dest destDir
overwrite false
}
tasks.register('npmBuild', NpmTask) {
dependsOn npmInstall
args = ['run-script', 'build']
}
tasks.register('npmClean', NpmTask) {
dependsOn npmInstall
args = ['run-script', 'clean']
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

View File

@ -1,16 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script type="module" src="/node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="/node_modules/@fortawesome/fontawesome-free/css/all.min.css">
<title>ReManga</title>
</head>
<body >
<div id="app" class="d-flex flex-column h-100" ></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>

3026
front/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +0,0 @@
{
"name": "front",
"version": "1.0.0",
"source": "index.html",
"scripts": {
"start": "parcel --port 3000",
"build": "npm run clean && parcel build",
"clean": "rimraf dist"
},
"dependencies": {
"bootstrap": "5.3.0-alpha2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.4.4",
"@fortawesome/fontawesome-free": "^6.2.1"
},
"devDependencies": {
"@types/react": "^18.0.24",
"@types/react-dom": "^18.0.8",
"parcel": "2.8.3",
"process": "^0.11.10",
"rimraf": "4.4.0"
}
}

View File

@ -1,43 +0,0 @@
import { useRoutes, Outlet, BrowserRouter } from 'react-router-dom';
import Creator from './MainS/Creator';
import Reader from './MainS/Reader';
import Header from './components/Header';
import CreatorAction from './Main/CreatorAction';
import ReaderAction from './Main/ReaderAction';
import MangaPage from './Main/MangaPage';
import Catalog from './Main/Catalog';
function Router(props) {
return useRoutes(props.rootRoute);
}
export default function App() {
const routes = [
{ index: true, element: <Reader /> },
{ path: 'creator', element: <Creator />, label: 'Creator' },
{ path: 'reader', element: <Reader />, label: 'Reader' },
{ path: 'creatorAction', element: <CreatorAction />, label: 'CreatorAction' },
{ path: 'readerAction', element: <ReaderAction />, label: 'ReaderAction' },
{ path: 'catalog', element: <Catalog />, label: 'Catalog' },
{ path: 'mangapage', element: <MangaPage /> },
];
const links = routes.filter(route => route.hasOwnProperty('label'));
const rootRoute = [
{ path: '/', element: render(links), children: routes }
];
function render(links) {
return (
<>
<Header links={links} />
<Outlet />
</>
);
}
return (
<BrowserRouter>
<Router rootRoute={ rootRoute } />
</BrowserRouter>
);
}

View File

@ -1,9 +0,0 @@
export default class MangaDto {
constructor(args) {
this.id = args.id || null;
this.creatorId = args.creatorId || 0;
this.mangaName = args.mangaName || "";
this.image = args.image;
this.chapterCount = args.chapterCount || 0;
}
}

View File

@ -1,41 +0,0 @@
import React, { useEffect, useState } from 'react'
import '../components/Banner/banner.css'
import Banner from '../components/Banner/Banner.jsx'
import { Link, NavLink } from 'react-router-dom';
import MangaDto from "../Dto/Manga-Dto";
export default function Catalog() {
const host = "http://localhost:8080/api";
const [mangs, setMangs] = useState([]);
useEffect(() => {
getMangs()
.then(_data =>setMangs(_data));
console.log(2);
console.log(mangs);
},[]);
const getMangs = async function () {
const response = await fetch(host + "/manga");
const _data = await response.json()
console.log(_data);
return _data;
}
return (
<article className="p-2 catalog_article">
<Banner />
<div className = "catalog_wrapper">
<h1>Каталог</h1>
<div className="p-2 d-flex flex-wrap">
{mangs.map((manga, index) => (
<NavLink key={manga.id} to={`/mangapage?id=${manga.id}`}><img src={manga.image} alt={manga.mangaName} className="slideshow"/></NavLink>
))}
</div>
</div>
</article>
);
}

View File

@ -1,198 +0,0 @@
import { useEffect, useState } from "react";
import { NavLink } from 'react-router-dom';
import TableCreator from '../components/Table/TableCreator';
import MangaDto from "../Dto/Manga-Dto";
import MangaCreatorList from "../components/List/MangaCreatorList";
import AddMangaModal from "../components/Modal/AddMangaModal";
import EditMangaModal from "../components/Modal/EditMangaModal";
export default function CreatorAction() {
const host = "http://localhost:8080/api";
const [creatorData, setCreatorData] = useState([]);
const [creatorId, setCreatorId] = useState(0);
const [creator, setCreator] = useState([]);
const [mangaId, setMangaId] = useState(0);
const [chapterCount, setChapterCount] = useState(0);
const [mangaName, setMangaName] = useState("");
const [mangaModel, setMangaModel] = useState(new MangaDto({}));
useEffect(() => {
getCreatorData()
.then(_data =>setCreatorData(_data));
},[]);
const getCreatorData = async function () {
const response = await fetch(host + "/creator");
const _data = await response.json()
return _data;
}
useEffect(() => {
getCreator(creatorId)
.then(_data =>setCreator(_data));
},[creatorId]);
const getCreator = async function (id) {
const requestParams = {
method: "GET",
headers: {
"Content-Type": "application/json",
}
};
const response = await fetch(host + `/creator/` + id, requestParams);
const _data = await response.json()
return _data;
}
const updateButton = (e) =>{
e.preventDefault();
update().then((result) => {
alert(`Manga[id=${result.id}, mangaName=${result.mangaName}, chapterCount=${result.chapterCount}]`);
getCreator(creatorId)
.then(_data =>setCreator(_data));
});
}
const update = async function (){
console.info('Try to update item');
if (mangaId === 0) {
return;
}
mangaModel.id = mangaId;
mangaModel.chapterCount = chapterCount;
mangaModel.creatorId = creatorId;
mangaModel.image = imageURL;
mangaModel.mangaName = mangaName;
const requestParams = {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(mangaModel),
};
const response = await fetch(host + `/manga/` + mangaModel.id, requestParams);
return await response.json();
}
const setMangaIdButton = (id) =>{
setMangaId(id);
}
const removeButton = (id) =>{
remove(id).then(() => {
getCreator(creatorId)
.then(_data =>setCreator(_data));
});
}
const remove = async function (id){
console.info('Try to remove item');
if (id !== 0) {
if (!confirm('Do you really want to remove this item?')) {
return;
}
}
const requestParams = {
method: "DELETE",
headers: {
"Content-Type": "application/json",
}
};
const response = await fetch(host + `/manga/` + id, requestParams);
}
const createButton = (e) =>{
e.preventDefault()
create().then((result) => {
alert(`Manga[id=${result.id}, mangaName=${result.mangaName}, chapterCount=${result.chapterCount}]`);
getCreator(creatorId)
.then(_data =>setCreator(_data));
});
}
const create = async function (){
mangaModel.chapterCount = chapterCount;
mangaModel.creatorId = creatorId;
mangaModel.image = imageURL;
mangaModel.mangaName = mangaName;
const requestParams = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(mangaModel),
};
const response = await fetch(host + `/manga`, requestParams);
return await response.json();
}
const [imageURL, setImageURL] = useState();
const fileReader = new FileReader();
fileReader.onloadend = () => {
setImageURL(fileReader.result);
};
const handleOnChange = (event) => {
event.preventDefault();
if (event.target.files && event.target.files.length) {
const file = event.target.files[0];
fileReader.readAsDataURL(file);
}
};
return (
<main>
<div className="container" id="root-div">
<div className="content">
<h1>Creator</h1>
<form id="form">
<div className="d-flex mt-3">
<div className="col-sm-2 me-3">
<select className="form-select" value={creatorId} onChange={event => setCreatorId(event.target.value)} aria-label="Default select example">
<option value={0}>Creator</option>
{
creatorData?.map((creatorD) =>
<option key={creatorD.id} value={creatorD.id}>{creatorD.creatorName}</option>
)
}
</select>
</div>
<div className="d-grid col-sm-2">
<button type="button" className="btn btn-success" data-bs-toggle="modal" data-bs-target="#exampleModal2">Добавить</button>
</div>
</div>
</form>
<MangaCreatorList
creator={creator}
setMangaIdButton={setMangaIdButton}
removeButton={removeButton}
/>
<EditMangaModal
chapterCount={chapterCount}
setChapterCount={setChapterCount}
handleOnChange={handleOnChange}
updateButton={updateButton}
/>
<AddMangaModal
chapterCount={chapterCount}
setChapterCount={setChapterCount}
mangaName={mangaName}
setMangaName={setMangaName}
handleOnChange={handleOnChange}
createButton={createButton}
/>
</div>
</div>
</main>
);
}

View File

@ -1,114 +0,0 @@
import React, {useState, useEffect} from 'react';
import MangaDto from '../Dto/Manga-Dto';
import ReaderList from "../components/List/ReaderList";
export default function MangaPage() {
const [mangaModel, setMangaModel] = useState(new MangaDto({}));
const [readerData, setReaderData] = useState([]);
const host = "http://localhost:8080/api";
useEffect(() => {
const quryString = window.location.search;
const urlParams = new URLSearchParams(quryString);
const id = urlParams.get('id');
getCreator(id)
.then(_data =>setMangaModel(_data));
getReaderData(id)
.then(_data =>setReaderData(_data));
console.log(readerData);
}, []);
const transformer = (mangaModel) => new MangaDto(mangaModel);
const url = "manga/";
const getReaderData = async function (id) {
const requestParams = {
method: "GET",
headers: {
"Content-Type": "application/json",
}
};
const response = await fetch(host + `/manga/` + id + `/readers`, requestParams);
const _data = await response.json()
console.log(_data);
return _data;
}
useEffect(() => {
console.log(mangaModel);
console.log(readerData);
}, [mangaModel]);
useEffect(() => {
console.log(readerData);
});
const getCreator = async function (id) {
const requestParams = {
method: "GET",
headers: {
"Content-Type": "application/json",
}
};
const response = await fetch(host + `/manga/` + id, requestParams);
const _data = await response.json()
return _data;
}
const addMangaButton = (e) =>{
e.preventDefault()
getReaderData(253)
.then(_data =>setReaderData(_data));
console.log(readerData);
}
return (
<main className="p-3">
<div className="container d-flex" >
<div className="d-flex flex-column">
<img className="img_style01" style={{borderRadius: "3%"}}src={mangaModel.image} alt={mangaModel.mangaName}/>
<button type="button" onClick={addMangaButton} className="btn btn-primary mt-3">Добавить в избранное</button>
</div>
<div className="container table text-white fs-4 ms-4">
<div className="row text-white fw-bold fs-3">О манге</div>
<div className="row">
<div className="col-xs-6 col-sm-3">Год производства</div>
<div className="col-xs-6 col-sm-3">1000</div>
</div>
<div className="row">
<div className="col-xs-6 col-sm-3">Страна</div>
<div className="col-xs-6 col-sm-3">Россия</div>
</div>
<div className="row">
<div className="col-xs-6 col-sm-3">Жанр</div>
<div className="col-xs-6 col-sm-3">Драма</div>
</div>
<div className="row">
<div className="col-xs-6 col-sm-3">Количество глав</div>
<div className="col-xs-6 col-sm-3">{mangaModel.chapterCount}</div>
</div>
<div className="row">
<div className="col-xs-6 col-sm-3">Возраст</div>
<div className="col-xs-6 col-sm-3">16+</div>
</div>
<div className="row text-white fw-bold fs-3">Описание</div>
<div className="row">
<div className="col-xs-6 col-sm-12">
<p>Ким Кон Чжа спокойно живет в своей халупе, завидуя всем популярным охотникам. Однажды его желание быть лучше всех сбывается и он получает легендарный навык Копирование способностей... ценой своей жизни.</p>
<p>Прежде чем он успевает понять это, его убивает охотник 1, Летний дух! Но это активирует его навык, и теперь он скопировал новый, Путешествие во времени после смерти.</p>
<p>Как Ким Кон Чжа же будет использовать эти навыки, чтобы победить конкурентов и подняться на вершину?</p>
</div>
</div>
<ReaderList
readers={mangaModel.readers}
/>
</div>
</div>
</main>
);
}

View File

@ -1,186 +0,0 @@
import { useEffect, useState } from "react";
import TableReader from '../components/Table/TableReader';
import { NavLink } from 'react-router-dom';
import MangaReaderList from "../components/List/MangaReaderList";
import AddMangaReaderModal from "../components/Modal/AddMangaReaderModal";
export default function ReaderAction() {
const host = "http://localhost:8080/api";
const [mangaData, setMangaData] = useState([]);
const [readerData, setReaderData] = useState([]);
const [readerId, setReaderId] = useState(0);
const [reader, setReader] = useState([]);
const [mangaId, setMangaId] = useState(0);
const [chapterCount, setChapterCount] = useState(0);
const [mangaName, setMangaName] = useState("");
useEffect(() => {
const quryString = window.location.search;
const urlParams = new URLSearchParams(quryString);
const id = urlParams.get('id');
setReaderId(id);
getReaderData()
.then(_data =>setReaderData(_data));
getMangaData()
.then(_data =>setMangaData(_data));
console.log(2);
console.log(readerData);
},[]);
const getReaderData = async function () {
const response = await fetch(host + "/reader");
const _data = await response.json()
console.log(_data);
return _data;
}
const getMangaData = async function () {
const response = await fetch(host + "/manga");
const _data = await response.json()
console.log(_data);
return _data;
}
useEffect(() => {
console.log(readerId);
getReader(readerId)
.then(_data =>setReader(_data));
console.log(readerId);
},[readerId]);
const getReader = async function (id) {
const requestParams = {
method: "GET",
headers: {
"Content-Type": "application/json",
}
};
const response = await fetch(host + `/reader/` + id, requestParams);
const _data = await response.json()
return _data;
}
const updateButton = (e) =>{
e.preventDefault();
update().then((result) => {
alert(`Manga[id=${result.id}, mangaName=${result.mangaName}, chapterCount=${result.chapterCount}]`);
getReader(readerId)
.then(_data =>setReader(_data));
});
console.log(readerId);
console.log(readerId);
console.log(reader);
}
const update = async function (){
console.info('Try to update item');
if (mangaId === 0) {
return;
}
const requestParams = {
method: "PUT",
headers: {
"Content-Type": "application/json",
}
};
const response = await fetch(host + `/manga/${mangaId}?chapterCount=${chapterCount}`, requestParams);
return await response.json();
}
const setMangaIdButton = (id) =>{
setMangaId(id);
}
const removeButton = (id) =>{
remove(id).then((result) => {
getReader(readerId)
.then(_data =>setReader(_data));
});
}
const remove = async function (id){
console.info('Try to remove item');
if (!confirm('Do you really want to remove this item?')) {
console.info('Canceled');
return;
}
const requestParams = {
method: "PUT",
headers: {
"Content-Type": "application/json",
}
};
console.log(host + `/reader/${readerId}/removeManga?mangaId=${id}`, requestParams);
const response = await fetch(host + `/reader/${readerId}/removeManga?mangaId=${id}`, requestParams);
return await response.json();
}
const addMangaButton = (e) =>{
e.preventDefault()
addManga().then((result) => {
alert(`Manga[id=${result.id}, mangaName=${result.mangaName}, chapterCount=${result.chapterCount}]`);
console.log(result);
getReader(readerId)
.then(_data =>setReader(_data));
});
}
const addManga = async function (){
const requestParams = {
method: "PUT",
headers: {
"Content-Type": "application/json",
}
};
console.log(host + `/reader/${readerId}/addManga?mangaId=${mangaId}`, requestParams);
const response = await fetch(host + `/reader/${readerId}/addManga?mangaId=${mangaId}`, requestParams);
return await response.json();
}
return (
<main>
<div className="container" id="root-div">
<div className="content">
<h1>Reader</h1>
<form id="form">
<div className="d-flex mt-3">
<div className="col-sm-2 me-3">
<select className="form-select" value={readerId} onChange={event => setReaderId(event.target.value)} aria-label="Default select example">
<option value={0}>Reader</option>
{
readerData.map((readerD) =>
<option key={readerD.id} value={readerD.id}>{readerD.readerName}</option>
)
}
</select>
</div>
<div className="d-grid col-sm-2">
<button type="button" className="btn btn-success" data-bs-toggle="modal" data-bs-target="#exampleModal2">Добавить</button>
</div>
</div>
</form>
<MangaReaderList
reader={reader}
removeButton={removeButton}
/>
<AddMangaReaderModal
mangaId={mangaId}
setMangaId={setMangaId}
mangaData={mangaData}
addMangaButton={addMangaButton}
/>
</div>
</div>
</main>
);
}

View File

@ -1,158 +0,0 @@
import { useEffect, useState } from "react";
import TableCreator from '../components/Table/TableCreator';
import MangaDto from '../Dto/Manga-Dto';
export default function Creator() {
const host = "http://localhost:8080/api";
const [creatorId, setCreatorId] = useState(0);
const [creatorName, setCreatorName] = useState("");
const [password, setPassword] = useState("");
const [mangaModel, setMangaModel] = useState(new MangaDto({}));
const [data, setData] = useState([]);
const table = document.getElementById("tbody");
useEffect(() => {
getData()
},[]);
const getData = async function () {
const response = await fetch(host + "/creator");
setData(await response.json())
console.log(data);
}
const create = async function (){
const requestParams = {
method: "POST",
headers: {
"Content-Type": "application/json",
}
};
console.log((host + `/creator?creatorName=${creatorName}&password=${password}`));
const response = await fetch(host + `/creator?creatorName=${creatorName}&password=${password}`, requestParams);
getData();
}
const remove = async function (){
console.info('Try to remove item');
if (creatorId !== 0) {
if (!confirm('Do you really want to remove this item?')) {
console.info('Canceled');
return;
}
}
const requestParams = {
method: "DELETE",
headers: {
"Content-Type": "application/json",
}
};
const response = await fetch(host + `/creator/` + creatorId, requestParams);
console.log("REMOVE");
getData();
return await response.json();
}
const removeAll = async function (){
console.info('Try to remove item');
if (!confirm('Do you really want to remove this item?')) {
console.info('Canceled');
return;
}
const requestParams = {
method: "DELETE",
};
await fetch(host + `/creator/`, requestParams);
}
const update = async function (){
console.info('Try to update item');
if (creatorId === 0 || creatorName == null || password === 0) {
return;
}
const requestParams = {
method: "PUT",
headers: {
"Content-Type": "application/json",
}
};
const response = await fetch(host + `/creator/${creatorId}?creatorName=${creatorName}&password=${password}`, requestParams);
getData();
return await response.json();
}
const createButton = (e) =>{
e.preventDefault()
create();
}
const removeButton = (e) =>{
e.preventDefault()
remove();
}
const updateButton = (e) =>{
e.preventDefault()
update();
}
return (
<main>
<div className="container" id="root-div">
<div className="content">
<h1>Creator</h1>
<form id="form">
<div className="d-flex justify-content-evenly mt-3">
<div className="col-sm-2">
<label htmlFor="creatorId" className="form-label">creatorId</label>
<input type='number' value = {creatorId} onChange={event => setCreatorId(event.target.value)} className="form-control"/>
</div>
<div className="col-sm-2">
<label htmlFor="creatorName" className="form-label">creatorName</label>
<input type='text' value = {creatorName} onChange={event => setCreatorName(event.target.value)} className="form-control"/>
</div>
<div className="col-sm-2">
<label htmlFor="password" className="form-label">password</label>
<input type='text' value = {password} onChange={event => setPassword(event.target.value)} className="form-control"/>
</div>
</div>
<div className="row mt-3">
<div className="d-grid col-sm-3 mx-auto">
<button type="submit" onClick={createButton} className="btn btn-success">Добавить</button>
</div>
<div className="d-grid col-sm-3 mx-auto">
<button type="submit" onClick={updateButton} className="btn btn-success" id="btnUpdate" >Обновить</button>
</div>
<div className="d-grid col-sm-3 mx-auto">
<button id="btnRemove" onClick={removeButton} className="btn btn-success">Удалить</button>
</div>
</div>
</form>
<div className="row table-responsive text-white">
<table className="table mt-3 text-white">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">CreatorName</th>
<th scope="col">Password</th>
<th scope="col">Mangs</th>
</tr>
</thead>
<TableCreator items = {data}/>
{/* <tbody id="tbody">
</tbody> */}
</table>
</div>
</div>
</div>
</main>
);
}

View File

@ -1,218 +0,0 @@
import { useEffect, useState } from "react";
import TableReader from '../components/Table/TableReader';
export default function ReaderS() {
const host = "http://localhost:8080/api";
const [readerId, setReaderId] = useState(0);
const [mangaId, setMangaId] = useState(0);
const [readerName, setReaderName] = useState("");
const [password, setPassword] = useState("");
const [data, setData] = useState([]);
const table = document.getElementById("tbody");
useEffect(() => {
getData();
console.log(2);
},[]);
const getData = async function () {
const response = await fetch(host + "/reader");
setData(await response.json())
console.log(data);
}
const create = async function (){
const requestParams = {
method: "POST",
headers: {
"Content-Type": "application/json",
}
};
const response = await fetch(host + `/reader?readerName=${readerName}&password=${password}`, requestParams);
getData();
}
const remove = async function (id){
console.info('Try to remove item');
if (id !== 0) {
if (!confirm('Do you really want to remove this item?')) {
console.info('Canceled');
return;
}
}
const requestParams = {
method: "DELETE",
headers: {
"Content-Type": "application/json",
}
};
const response = await fetch(host + `/reader/` + id, requestParams);
getData();
return await response.json();
}
const removeAll = async function (){
console.info('Try to remove item');
if (!confirm('Do you really want to remove this item?')) {
console.info('Canceled');
return;
}
const requestParams = {
method: "DELETE",
};
await fetch(host + `/reader/`, requestParams);
getData();
}
const update = async function (){
console.info('Try to update item');
if (readerId === 0 || readerName == null || password === 0) {
return;
}
const requestParams = {
method: "PUT",
headers: {
"Content-Type": "application/json",
}
};
const response = await fetch(host + `/reader/${readerId}?readerName=${readerName}&password=${password}`, requestParams);
getData();
return await response.json();
}
const removeManga = async function (){
console.info('Try to remove item');
if (!confirm('Do you really want to remove this item?')) {
console.info('Canceled');
return;
}
const requestParams = {
method: "PUT",
headers: {
"Content-Type": "application/json",
}
};
console.log(host + `/reader/${readerId}/removeManga?mangaId=${mangaId}`, requestParams);
const response = await fetch(host + `/reader/${readerId}/removeManga?mangaId=${mangaId}`, requestParams);
return await response.json();
}
const addManga = async function () {
const requestParams = {
method: "PUT",
headers: {
"Content-Type": "application/json",
}
};
console.log(host + `/reader/${readerId}/addManga?mangaId=${mangaId}`, requestParams);
const response = await fetch(host + `/reader/${readerId}/addManga?mangaId=${mangaId}`, requestParams);
return await response.json();
}
const createButton = (e) =>{
e.preventDefault()
create();
}
const removeButton = (id) =>{
remove(id);
}
const updateButton = (e) =>{
e.preventDefault()
update();
}
const removeMangaButton = (e) =>{
e.preventDefault()
removeManga();
}
const addMangaButton = (e) =>{
e.preventDefault()
addManga();
}
const setModal_Click = (e) =>{
e.preventDefault()
setModal(true)
//setData({type:'', name:'', description:'' })
}
return (
<main>
<div className="container" id="root-div">
<div className="content">
<h1>Readers</h1>
<form id="form">
<div className="d-flex justify-content-evenly mt-3">
<div className="col-sm-2">
<label htmlFor="readerId" className="form-label">readerId</label>
<input type='number' value = {readerId} onChange={event => setReaderId(event.target.value)} className="form-control"/>
</div>
<div className="col-sm-2">
<label htmlFor="mangaId" className="form-label">mangaId</label>
<input type='number' value = {mangaId} onChange={event => setMangaId(event.target.value)} className="form-control"/>
</div>
<div className="col-sm-2">
<label htmlFor="readerName" className="form-label">readerName</label>
<input type='text' value = {readerName} onChange={event => setReaderName(event.target.value)} className="form-control"/>
</div>
<div className="col-sm-2">
<label htmlFor="password" className="form-label">password</label>
<input type='text' value = {password} onChange={event => setPassword(event.target.value)} className="form-control"/>
</div>
</div>
<div className="row m-3">
<div className="d-grid col-sm-3 m-3 mx-auto">
<button onClick={createButton} className="btn btn-success">Добавить</button>
</div>
<div className="d-grid col-sm-3 m-3 mx-auto">
<button onClick={updateButton} className="btn btn-success">Обновить</button>
</div>
<div className="d-grid col-sm-2 m-3 mx-auto">
<button onClick={removeMangaButton} className="btn btn-success">Удалить мангу</button>
</div>
<div className="d-grid col-sm-2 m-3 mx-auto">
<button onClick={addMangaButton} className="btn btn-success">Добавить мангу</button>
</div>
</div>
</form>
<div className="row table-responsive text-white">
<table className="table mt-3 text-white">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">readerName</th>
<th scope="col">Password</th>
<th scope="col">Mangs</th>
<th scope="col"></th>
<th scope="col"></th>
</tr>
</thead>
<TableReader
items = {data}
remove ={removeButton}
update ={updateButton}
/>
{/* <tbody id="tbody">
</tbody> */}
</table>
</div>
</div>
</div>
</main>
);
}

View File

@ -1,46 +0,0 @@
import { useEffect, useState } from "react";
import React from 'react'
import { useNavigate } from "react-router-dom";
import banner1 from "../../../img/popular_1.jpg";
import banner2 from "../../../img/popular_2.jpg";
import banner3 from "../../../img/popular_3.jpg"
export default function Banner() {
const length = 3;
var old = length - 1;
var current = 0;
const navigate = useNavigate();
const [bannerState, setBannerState] = useState(["show", "hide", "hide"]);
useEffect(() => {
const timer = window.setInterval(() => {
setBannerState([
...bannerState,
(bannerState[current] = "show"),
(bannerState[old] = "hide"),
]);
//setBannerState([...bannerState, ]);
console.info("Banner changed");
old = current;
current++;
if (current === length) {
current = 0;
}
}, 2000);
return () => {
window.clearInterval(timer);
};
}, []);
return (
<div className="d-flex align-items-center flex-column" id="banner">
<a className={bannerState[0]} style={{ cursor: "pointer" }}><img src={banner1}/></a>
<a className={bannerState[1]} style={{ cursor: "pointer" }}><img src={banner2}/></a>
<a className={bannerState[2]} style={{ cursor: "pointer" }}><img src={banner3}/></a>
</div>
);
}

View File

@ -1,65 +0,0 @@
#banner {
margin: 15px;
}
@keyframes newAnim {
from { opacity: 0; }
to { opacity: 1; }
}
#banner img {
max-width: 90%;
border-radius: 5px;
animation: newAnim 1s forwards;
}
#banner a.show {
text-align: center;
display: block;
}
#banner a.hide {
display: none;
}
img.show {
max-height: 200px;
width: auto;
opacity: 1;
transition: opacity 1s, visibility 0s;
}
img.hide {
max-height: 0;
width: 0;
opacity: 0;
visibility: hidden;
transition: opacity 1s, visibility 0s 1s;
}
@media (max-width: 700px){
#banner{width: 0px;}
#banner_2{width: 0px;}
#banner img.show {
height: 0;
width: 0;
opacity: 0;
visibility: hidden;
transition: opacity 1s, visibility 0s 1s;
}
#banner h3{
font-size: 0em;
}
#banner_2 h3{
font-size: 0em;
}
#banner_2 img.show {
height: 0;
width: 0;
opacity: 0;
visibility: hidden;
transition: opacity 1s, visibility 0s 1s;
}
}

View File

@ -1,43 +0,0 @@
import React from 'react';
const EditReaderForm =(props) => {
const types = ([
{name:'Манга'},
{name:'Манхва'},
{name:'Маньхуа'},
])
function done(e) {
e.preventDefault();
// if (formRef.current.checkValidity()) {
// props.onDone();
// props.setModalEdit();
// props.setData({type:'', name:'', description:'' })
// }else {
// formRef.current.reportValidity();
// props.setData({type:'', name:'', description:'' })
// }
}
const formRef = React.createRef();
return (
<form id="frm-items" ref={formRef} className="row g-3 text-dark">
<div className="col-md-3 ">
</div>
<div className="col-sm-2">
<label htmlFor="readerName" className="form-label">readerName</label>
<input type='text' value = {props.readerName} onChange={event => props.setReaderName(event.target.value)} className="form-control"/>
</div>
<div className="col-sm-2">
<label htmlFor="password" className="form-label">password</label>
<input type='text' value = {props.password} onChange={event => props.setPassword(event.target.value)} className="form-control"/>
</div>
<div className="col-md-3">
<button onClick={() => props.update(item.id)} id="btn-add-item" className="btn btn-primary" type="submit">Изменить</button>
</div>
</form>
);
}
export default EditReaderForm

View File

@ -1,27 +0,0 @@
import { NavLink } from 'react-router-dom';
export default function Header(props) {
return (
<nav className="navbar navbar-expand-lg navbar-dark">
<div className="container-fluid">
<button className="navbar-toggler" type="button"
data-bs-toggle="collapse" data-bs-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarNav">
<ul className="navbar-nav">
{props.links.map(route =>
<li key={route.path}
className="nav-item">
<NavLink className="nav-link" to={route.path}>
{route.label}
</NavLink>
</li>
)}
</ul>
</div>
</div>
</nav >
);
}

View File

@ -1,36 +0,0 @@
import { useEffect, useState } from "react";
import { NavLink } from 'react-router-dom';
import TableCreator from '../Table/TableCreator';
import MangaDto from "../../Dto/Manga-Dto";
export default function MangaCreatorList(props) {
return (
<div className="row table-responsive text-white">
{
props.creator.mangas?.map((manga) =>
<div key={manga.id} className="d-flex flex-row flex-wrap flex-grow-1 align-items-center mt-3">
<div className="me-3">
<NavLink to={`/mangapage?id=${manga.id}`} ><img src={manga.image} alt={manga.mangaName} className="slideshow" /></NavLink>
</div>
<div>
<div className="pt-3 description d-flex flex-column justify-content-start mb-3 fs-6 fw-bold">
<NavLink className="text-white fs-5 unic_class fw-bold pt-3 mb-3"
to={`/mangapage?id=${manga.id}`}>Название: {manga.mangaName}
</NavLink>
<p>Глав: {manga.chapterCount}</p>
</div>
<div>
<button type="button" className="btn btn-primary" onClick = {() => props.setMangaIdButton(manga.id)} data-bs-toggle="modal" data-bs-target="#exampleModal">
<i className="fas fa-edit"></i>
</button>
<button className="delete bg-danger p-2 px-2 mx-2 border border-0 rounded text-white fw-bold" onClick = {() => props.removeButton(manga.id)} type="button">Удалить</button>
</div>
</div>
</div>
)
}
</div>
);
}

View File

@ -1,33 +0,0 @@
import { useEffect, useState } from "react";
import { NavLink } from 'react-router-dom';
import TableCreator from '../Table/TableCreator';
import MangaDto from "../../Dto/Manga-Dto";
export default function MangaReaderList(props) {
return (
<div className="row table-responsive text-white">
{
props.reader.mangas?.map((manga) =>
<div key={manga.id} className="d-flex flex-row flex-wrap flex-grow-1 align-items-center mt-3">
<div className="me-3">
<NavLink to={`/mangapage?id=${manga.id}`} ><img src={manga.image} alt={manga.mangaName} className="slideshow" /></NavLink>
</div>
<div>
<div className="pt-3 description d-flex flex-column justify-content-start mb-3 fs-6 fw-bold">
<NavLink className="text-white fs-5 unic_class fw-bold pt-3 mb-3"
to={`/mangapage?id=${manga.id}`}>Название: {manga.mangaName}
</NavLink>
<p>Глав: {manga.chapterCount}</p>
</div>
<div>
<button className="delete bg-danger p-2 px-2 mx-2 border border-0 rounded text-white fw-bold" onClick = {() => props.removeButton(manga.id)} type="button">Удалить</button>
</div>
</div>
</div>
)
}
</div>
);
}

View File

@ -1,24 +0,0 @@
import { useEffect, useState } from "react";
import { NavLink } from 'react-router-dom';
export default function ReaderList(props) {
return (
<div className="row table-responsive text-white">
{
props.readers?.map((reader) =>
<div key={reader.id} className="d-flex flex-row flex-wrap flex-grow-1 align-items-center mt-3">
<div>
<div className="pt-3 description d-flex flex-column justify-content-start mb-3 fs-6 fw-bold">
<NavLink className="text-white fs-5 fw-bold pt-3 mb-3"
to={`/readeraction?id=${reader.id}`}>Имя пользователя: {reader.readerName}
</NavLink>
</div>
</div>
</div>
)
}
</div>
);
}

View File

@ -1,49 +0,0 @@
import { useEffect, useState } from "react";
import { NavLink } from 'react-router-dom';
import TableCreator from '../Table/TableCreator';
import MangaDto from "../../Dto/Manga-Dto";
export default function AddMangaModal(props) {
return (
<div className="modal fade text-black" id="exampleModal2" tabIndex="-1" aria-labelledby="exampleModalLabel2" aria-hidden="true">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title" id="exampleModalLabel2">Создание манги</h5>
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div className="modal-body">
<div>
<label htmlFor="chapterCount" className="form-label">chapterCount</label>
<input type='number' value = {props.chapterCount} onChange={event => props.setChapterCount(event.target.value)} className="form-control"/>
</div>
<div>
<label htmlFor="mangaName" className="form-label">mangaName</label>
<input type='text' value = {props.mangaName} onChange={event => props.setMangaName(event.target.value)} className="form-control"/>
</div>
<div>
<label
htmlFor="file-loader-button"
className="form-label">
Загрузить файл
</label>
<input
id="file-loader-button"
type="file"
className="form-control text-white"
onChange={props.handleOnChange}
/>
</div>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" onClick={props.createButton} className="btn btn-primary" data-bs-dismiss="modal">Save changes</button>
</div>
</div>
</div>
</div>
);
}

View File

@ -1,37 +0,0 @@
import { useEffect, useState } from "react";
import { NavLink } from 'react-router-dom';
import TableCreator from '../Table/TableCreator';
import MangaDto from "../../Dto/Manga-Dto";
export default function AddMangaReaderModal(props) {
return (
<div className="modal fade text-black" id="exampleModal2" tabIndex="-1" aria-labelledby="exampleModalLabel2" aria-hidden="true">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title" id="exampleModalLabel2">Добавление манги к читателю</h5>
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div className="modal-body">
<div>
<select className="form-select" value={props.mangaId} onChange={event => props.setMangaId(event.target.value)} aria-label="Default select example">
<option value={0}>Manga</option>
{
props.mangaData.map((mangaD) =>
<option key={mangaD.id} value={mangaD.id}>{mangaD.mangaName}</option>
)
}
</select>
</div>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" onClick={props.addMangaButton} className="btn btn-primary" data-bs-dismiss="modal">Save changes</button>
</div>
</div>
</div>
</div>
);
}

View File

@ -1,44 +0,0 @@
import { useEffect, useState } from "react";
import { NavLink } from 'react-router-dom';
import TableCreator from '../Table/TableCreator';
import MangaDto from "../../Dto/Manga-Dto";
export default function EditMangaModal(props) {
return (
<div className="modal fade text-black" id="exampleModal" tabIndex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title" id="exampleModalLabel">Изменение манги</h5>
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div className="modal-body">
<div>
<label htmlFor="chapterCount" className="form-label">chapterCount</label>
<input type='number' value={props.chapterCount} onChange={event => props.setChapterCount(event.target.value)} className="form-control"/>
</div>
<div>
<label
htmlFor="file-loader-button"
className="form-label">
Загрузить файл
</label>
<input
id="file-loader-button"
type="file"
className="form-control text-white"
onChange={props.handleOnChange}
/>
</div>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" onClick={props.updateButton} className="btn btn-primary" data-bs-dismiss="modal">Save changes</button>
</div>
</div>
</div>
</div>
);
}

View File

@ -1,26 +0,0 @@
import { useState } from 'react';
export default function TableCreator(props) {
return (
<tbody>
{
props.items?.map((item, index) =>
<tr key={item.id}>
<td>{item.id}</td>
<td>{item.creatorName}</td>
<td>{item.hashedPassword}</td>
<td>
<select className="form-select" aria-label="Default select example">{item.mangas?.map(manga =>
<option key={manga.mangaName } >{manga.mangaName + " " +manga.chapterCount}</option>)}
</select>
</td>
</tr>
)
}
</tbody >
);
}

View File

@ -1,27 +0,0 @@
import { useState } from 'react';
export default function TableReader(props) {
return (
<tbody>
{
props.items?.map((item, index) =>
<tr key={item.id}>
<td>{item.id}</td>
<td>{item.readerName}</td>
<td>{item.hashedPassword}</td>
<td>
<select className="form-select" aria-label="Default select example">{item.mangas?.map(manga =>
<option key={manga.id}>{manga.mangaName}</option>)}
</select>
</td>
<td>
<button onClick={() => props.remove(item.id)} className="btn btn-success">Удалить</button>
</td>
</tr>
)
}
</tbody >
);
}

View File

@ -1,8 +0,0 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './style.css'
ReactDOM.createRoot(document.getElementById('app')).render(
<App />
)

View File

@ -1,107 +0,0 @@
html,
body {
background-color: #000000;
color: #ffffff;
padding: 0;
margin: 0;
font-family: sans-serif;
line-height: 1.15;
height: 100%;
}
header {
background-color: #3c3c3c;
color: #ffffff;
}
header a {
color: #ffffff;
text-decoration: none;
margin: 0 0.5em;
}
header a:hover {
text-decoration: underline;
}
#logo {
margin-left: 0.5em;
}
article a {
color: #ffffff;
text-decoration: none;
margin: 0.5em 0.5em;
}
header a:hover {
text-decoration: underline;
}
h2 {
font-size: 1.25em;
}
h3 {
font-size: 1.1em;
}
footer {
background-color: #9c9c9c;
color: #ffffff;
height: 32px;
padding: 0.5em;
}
.manga_pages{
display: flex;
flex-direction: column;
align-items: center;
}
.catalog_wrapper{
display: flex;
width: 73%;
flex-direction: column;
}
.catalog_article{
display: flex;
}
.poster{
width:140px;
}
th {
border: 0px solid rgb(255, 255, 255);
}
.added_manga{
display: flex;
flex-direction: column;
}
@media (min-width: 992px) {
.manga_pages img{
max-width: 900px;
width: auto;
height: auto;
}
}
.flex_grow {
flex-grow: 1;
display: flex;
align-items: center;
}
@media (min-width: 1024px){
.article_1 {
max-width: -webkit-calc(1600px + (100vw/64*7)*2);
max-width: -moz-calc(1600px + (100vw/64*7)*2);
max-width: calc(1600px + (100vw/64*7)*2);
padding-left: -webkit-calc(100vw/64*7);
padding-left: -moz-calc(100vw/64*7);
padding-left: calc(100vw/64*7);
padding-right: -webkit-calc(100vw/64*7);
padding-right: -moz-calc(100vw/64*7);
padding-right: calc(100vw/64*7);
}
}
.registration_div {
width: 100%;
height: 100%;
}
.slideshow{
height: 250px;
width: auto;/*maintain aspect ratio*/
max-width:180px;
border-radius: 7%;
}

Binary file not shown.

View File

@ -1,5 +0,0 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@ -1,2 +1 @@
rootProject.name = 'app'
include 'front'