Compare commits

...

4 Commits

Author SHA1 Message Date
7bccb29aa6 qrcode temporary fix
All checks were successful
publish-main / release-image (push) Successful in 10m12s
2024-07-03 19:35:51 +03:00
2b50f7c332 articles styles fix
All checks were successful
publish-main / release-image (push) Successful in 10m46s
2024-07-03 18:56:34 +03:00
0e1dc49f59 ticket 16, 4, 18, 19, 20, 21, 22
Some checks failed
publish-main / release-image (push) Has been cancelled
2024-07-03 16:26:24 +03:00
d25e54f73f mybutton fix
All checks were successful
publish-main / release-image (push) Successful in 4m40s
2024-06-27 23:07:29 +03:00
40 changed files with 1200 additions and 573 deletions

View File

@ -38,10 +38,14 @@
"@uiw/react-markdown-editor": "^5.12.1", "@uiw/react-markdown-editor": "^5.12.1",
"axios": "^1.6.8", "axios": "^1.6.8",
"bootstrap": "^5.3.3", "bootstrap": "^5.3.3",
"inputmask": "^5.0.9",
"primereact": "^10.6.6",
"qrcode": "^1.5.3",
"react": "^18.2.0", "react": "^18.2.0",
"react-bootstrap": "^2.10.1", "react-bootstrap": "^2.10.1",
"react-cookie": "^7.1.4", "react-cookie": "^7.1.4",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-qr-code": "^2.0.15",
"react-router-dom": "^6.22.1" "react-router-dom": "^6.22.1"
} }
} }

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect, useLayoutEffect } from "react"; import React, { useState, useEffect, useLayoutEffect, useRef } from "react";
import { Outlet, useNavigate } from "react-router-dom"; import { Outlet, useNavigate } from "react-router-dom";
import { FormsData, UserData, TypeAnswerData, answersData } from "./context"; import { FormsData, UserData, TypeAnswerData, answersData } from "./context";
import { useCookies } from "react-cookie"; import { useCookies } from "react-cookie";
@ -20,6 +20,9 @@ const App = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const [forms, setForms] = useState([]); const [forms, setForms] = useState([]);
const [user, setUser] = useState(false); const [user, setUser] = useState(false);
globalRender(window.location.pathname, user, navigate);
const userRef = useRef(false)
const [answersList, setAnswersList] = useState([]); const [answersList, setAnswersList] = useState([]);
const [listTypeAnswer, setListTypeAnswer] = useState([ const [listTypeAnswer, setListTypeAnswer] = useState([
{id: 1, text: 'Краткий ответ', typeTag: InputText}, {id: 1, text: 'Краткий ответ', typeTag: InputText},
@ -37,13 +40,16 @@ const App = () => {
useEffect(() => { useEffect(() => {
async function verifyUser() { async function verifyUser() {
const response = await verifyUserApi(cookies.token); const response = await verifyUserApi(cookies.token);
console.log("verifyUser App")
if (response.status === 200) { if (response.status === 200) {
setUser(response.data); setUser(response.data);
globalRender(window.location.pathname, response.data, navigate); userRef.current = response.data
// globalRender(window.location.pathname, response.data, navigate);
} }
else { else {
globalRender(window.location.pathname, false, navigate); // globalRender(window.location.pathname, false, navigate);
setUser(false);
} }
} }
@ -51,7 +57,7 @@ const App = () => {
}, []); }, []);
return ( return (
<UserData.Provider value={{ user, setUser }}> <UserData.Provider value={{ user, setUser, userRef }}>
<answersData.Provider value={{ answersList, setAnswersList }}> <answersData.Provider value={{ answersList, setAnswersList }}>
<FormsData.Provider value={{ forms, setForms }}> <FormsData.Provider value={{ forms, setForms }}>
<TypeAnswerData.Provider <TypeAnswerData.Provider

View File

@ -12,8 +12,8 @@
} }
.admin { .admin {
width: 70%; width: 85%;
height: 70%; height: 80%;
background: #fff; background: #fff;
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px; border-radius: 16px;
@ -84,7 +84,7 @@
} }
&__item { &__item {
width: 100%; width: 100%;
height: 20%; height: 60px;
border-bottom: 1px solid rgb(200, 200, 200); border-bottom: 1px solid rgb(200, 200, 200);
position: relative; position: relative;
&__wrapper { &__wrapper {

View File

@ -1,94 +1,166 @@
.main { .main {
width: 100%; width: 100%;
height: 100%; min-height: 100%;
padding: 4% 8%; padding: 4% 8%;
} }
.wrapper { .wrapper {
width: 100%; width: 100%;
height: 100%; min-height: 100%;
} }
.panel { .panel {
width: 100%; width: 100%;
height: 10%; display: flex;
justify-content: space-between;
align-items: end;
margin-bottom: 25px;
gap: 15px;
div:first-child {
flex-grow: 1;
input {
width: 100%;
}
}
}
.listforms {
border: 1px solid rgba(0, 0, 0, 0.1);
background: #fff;
border-radius: 16px;
height: 70%;
min-height: 700px;
margin-bottom: 50px;
width: 100%;
&__columns {
display: flex; display: flex;
justify-content: space-between; justify-content: start;
align-items: end; align-items: center;
padding: 0 5%; padding: 20px 25px;
border-bottom: 1px solid rgb(220, 220, 220);
&__item {
font-size: 15px;
font-family: "Montserrat", sans-serif;
font-weight: bold;
}
}
&__forms {
min-height: 100%;
display: inline;
overflow-y: auto;
&__item {
display: flex;
justify-content: start;
align-items: center;
width: 100%;
padding: 20px 25px;
font-family: "Montserrat", sans-serif;
position: relative;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
&:hover {
background-color: rgba(240, 240, 240, 0.8);
}
&__title {
text-align: center;
cursor: pointer;
&:hover {
text-decoration: underline;
}
}
&__answers {
width: 33.3%;
text-align: center;
}
&__update {
width: 33.3%;
text-align: center;
}
i {
position: absolute;
font-size: 15px;
right: 30px;
top: calc(50% - 7px);
cursor: pointer;
}
ul {
li {
cursor: pointer;
}
}
}
}
} }
.listArticles { .listArticles {
box-shadow: 0 0 5px 1px rgb(200, 200, 200); border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 5px; background: #fff;
margin-top: 5%; border-radius: 16px;
height: 70%; height: 70%;
min-height: 700px;
margin-bottom: 50px;
width: 100%;
&__columns {
display: flex;
justify-content: start;
align-items: center;
padding: 20px 25px;
border-bottom: 1px solid rgb(220, 220, 220);
&__item {
width: 33.3%;
font-size: 15px;
font-family: "Montserrat", sans-serif;
}
}
&__forms {
width: 100%; width: 100%;
&__columns { height: 85%;
display: flex; overflow-y: auto;
justify-content: start; &::-webkit-scrollbar {
align-items: center; width: 7px;
padding: 0 2%;
height: 15%;
width: 100%;
border-bottom: 1px solid rgb(220, 220, 220);
&__item {
width: 33.3%;
font-size: 15px;
// text-align: center;
font-family: "Montserrat", sans-serif;
}
} }
&__forms { &::-webkit-scrollbar-thumb {
width: 100%; background-color: rgb(200, 200, 200);
height: 85%;
overflow-y: auto;
&::-webkit-scrollbar {
width: 7px;
}
&::-webkit-scrollbar-thumb {
background-color: rgb(200, 200, 200);
}
&__item {
display: flex;
justify-content: start;
align-items: center;
padding: 0 2%;
height: 25%;
width: 100%;
font-family: "Montserrat", sans-serif;
position: relative;
&:hover {
background-color: rgba(240, 240, 240, 0.8);
}
&__title {
width: 33.3%;
// text-align: center;
cursor: pointer;
&:hover {
text-decoration: underline;
}
}
&__date {
width: 33.3%;
// text-align: center;
}
&__author {
width: 33.3%;
// text-align: center;
}
i {
position: absolute;
font-size: 15px;
right: 30px;
top: calc(50% - 7px);
cursor: pointer;
}
ul {
li {
cursor: pointer;
}
}
}
} }
} &__item {
display: flex;
justify-content: start;
align-items: center;
width: 100%;
padding: 20px 25px;
font-family: "Montserrat", sans-serif;
position: relative;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
&:hover {
background-color: rgba(240, 240, 240, 0.8);
}
&__title {
width: 33.3%;
// text-align: center;
cursor: pointer;
&:hover {
text-decoration: underline;
}
}
&__date {
width: 33.3%;
// text-align: center;
}
&__author {
width: 33.3%;
// text-align: center;
}
i {
position: absolute;
font-size: 15px;
right: 30px;
top: calc(50% - 7px);
cursor: pointer;
}
ul {
li {
cursor: pointer;
}
}
}
}
}

View File

@ -32,7 +32,27 @@
padding: 0 1%; padding: 0 1%;
} }
&__file { &__file {
// margin-top: 10px;
display: none;
}
&__fileLabel {
margin-top: 10px; margin-top: 10px;
border: 1px solid rgb(100, 100, 100);
background-color: rgb(240, 240, 240);
font-family: "Montserrat", sans-serif;
color: rgb(100, 100, 100);
cursor: pointer;
padding: 1%;
transition: 0.3s;
&:hover {
background-color: rgb(230, 230, 230);
transition: 0.3s;
}
}
&__listFile {
margin-left: 10px;
font-family: "Montserrat", sans-serif;
color: rgb(100, 100, 100);
} }
} }
&__comment { &__comment {

View File

@ -0,0 +1,5 @@
.main {
width: 100%;
height: 100%;
padding: 2%;
}

View File

@ -0,0 +1,8 @@
.main {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
padding: 2% 0;
}

View File

@ -30,7 +30,6 @@
&:hover { &:hover {
border: 1px solid rgba(0, 0, 0, 0.3); border: 1px solid rgba(0, 0, 0, 0.3);
} }
<<<<<<< HEAD
&__green { &__green {
color: white; color: white;
background-color: rgb(150, 209, 158); background-color: rgb(150, 209, 158);
@ -53,8 +52,5 @@
transition: 0.3s; transition: 0.3s;
} }
} }
}
=======
} }
} }
>>>>>>> 750b571374c05b915d136af481fe93bf966bac39

View File

@ -35,6 +35,14 @@
} }
} }
&__answer { &__answer {
&__file {
margin-right: 10px;
color: rgb(105, 136, 220);
text-decoration: none;
&:hover {
text-decoration: underline;
color: rgb(53, 88, 182);
}
}
} }
} }

View File

@ -51,7 +51,7 @@
} }
&__listBtn { &__listBtn {
display: flex; display: flex;
justify-content: space-between; justify-content: end;
width: 30%; width: 30%;
} }

View File

@ -1,150 +1,150 @@
.main { .main {
width: 100%; width: 100%;
height: 100%; height: 100%;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.wrapper { .wrapper {
width: 90%; width: 90%;
height: 90%; height: 90%;
} }
.header { .header {
width: 100%;
// height: 10%;
&__wrapper {
width: 100%; width: 100%;
height: 10%; height: 100%;
&__wrapper { background: #fff;
width: 100%; border: 1px solid rgba(255, 255, 255, 0.1);
height: 100%; border-bottom: none;
border: 1px solid rgb(180, 180, 180); border-radius: 5px 5px 0 0;
border-bottom: none; padding: 0 5px;
border-radius: 5px 5px 0 0; &__article {
padding: 0 5px; width: 100%;
&__article { height: 100%;
width: 100%; display: flex;
height: 100%; justify-content: space-between;
display: flex; align-items: center;
justify-content: space-between; &__title {
align-items: center; width: 20%;
&__title { height: 75%;
width: 20%; display: flex;
height: 75%; border-right: 1px solid rgb(180, 180, 180);
display: flex; justify-content: center;
border-right: 1px solid rgb(180, 180, 180); align-items: center;
justify-content: center; position: relative;
align-items: center; &__name {
position: relative; position: absolute;
&__name { top: -20%;
position: absolute; left: 3px;
top: -20%; font-size: 8px;
left: 3px; font-family: "Montserrat", sans-serif;
font-size: 8px;
font-family: "Montserrat", sans-serif;
}
&__text {
font-size: 15px;
font-family: "Montserrat", sans-serif;
}
}
&__tags {
width: 60%;
height: 75%;
display: flex;
justify-content: start;
align-items: center;
flex-wrap: wrap;
padding: 0 5px;
position: relative;
overflow-y: auto;
// &::-webkit-scrollbar {
// width: 10px;
// }
// &::-webkit-scrollbar-thumb {
// background-color: rgb(200, 200, 200);
// }
// &::-webkit-scrollbar-button:single-button {
// background-color: #bbbbbb;
// display: block;
// border-style: solid;
// height: 10px;
// width: 16px;
// }
&__item {
padding: 0 5px;
border-radius: 5px;
border: 1px solid rgb(100, 100, 100);
margin: 1px 3px;
span {
}
}
}
&__owner {
width: 20%;
height: 75%;
border-left: 1px solid rgb(180, 180, 180);
display: flex;
justify-content: center;
align-items: center;
position: relative;
&__name {
position: absolute;
top: -20%;
right: 3px;
font-size: 8px;
font-family: "Montserrat", sans-serif;
}
&__text {
font-size: 15px;
font-family: "Montserrat", sans-serif;
}
}
} }
&__tags { &__text {
width: 100%; font-size: 15px;
height: 50%; font-family: "Montserrat", sans-serif;
display: flex;
justify-content: start;
align-items: center;
margin-top: 20px;
&__item {
padding: 0 5px;
border-radius: 5px;
border: 1px solid rgb(100, 100, 100);
margin: 1px 3px;
span {
}
}
} }
}
&__tags {
width: 60%;
height: 75%;
display: flex;
justify-content: start;
align-items: center;
flex-wrap: wrap;
padding: 5px;
position: relative;
overflow-y: auto;
// &::-webkit-scrollbar {
// width: 10px;
// }
// &::-webkit-scrollbar-thumb {
// background-color: rgb(200, 200, 200);
// }
// &::-webkit-scrollbar-button:single-button {
// background-color: #bbbbbb;
// display: block;
// border-style: solid;
// height: 10px;
// width: 16px;
// }
&__item {
padding: 0 5px;
border-radius: 5px;
border: 1px solid rgb(100, 100, 100);
margin: 1px 3px;
span {
}
}
}
&__owner {
width: 20%;
height: 75%;
border-left: 1px solid rgb(180, 180, 180);
display: flex;
justify-content: center;
align-items: center;
position: relative;
&__name {
position: absolute;
top: -20%;
right: 3px;
font-size: 8px;
font-family: "Montserrat", sans-serif;
}
&__text {
font-size: 15px;
font-family: "Montserrat", sans-serif;
}
}
} }
&__tags {
width: 100%;
height: 50%;
display: flex;
justify-content: start;
align-items: center;
margin-top: 20px;
&__item {
padding: 0 5px;
border-radius: 5px;
border: 1px solid rgb(100, 100, 100);
margin: 1px 3px;
span {
}
}
}
}
} }
.content { .content {
width: 100%;
height: 90%;
&__wrapper {
width: 100%; width: 100%;
height: 90%; height: 100%;
&__wrapper { background: #fff;
width: 100%; border: 1px solid rgba(255, 255, 255, 0.1);
height: 100%; padding: 5px;
border: 1px solid rgb(180, 180, 180); border-radius: 0 0 5px 5px;
padding: 5px; overflow: auto;
// border-radius: 0 0 5px 5px; &::-webkit-scrollbar {
overflow: auto; width: 7px;
&::-webkit-scrollbar {
width: 7px;
}
&::-webkit-scrollbar {
height: 7px;
}
&::-webkit-scrollbar-thumb {
background-color: rgb(200, 200, 200);
}
&__article {
max-width: 100%;
height: 100%;
}
} }
&::-webkit-scrollbar {
height: 7px;
}
&::-webkit-scrollbar-thumb {
background-color: rgb(200, 200, 200);
}
&__article {
max-width: 100%;
height: 100%;
}
}
} }
// .image { // .image {
@ -156,4 +156,4 @@
// height: 200px; // height: 200px;
// aspect-ratio: 1000/700; // aspect-ratio: 1000/700;
// } // }
// } // }

View File

@ -26,7 +26,8 @@ const AnswerModal = ({
setComment, setComment,
setCurrentTypeAnswer, setCurrentTypeAnswer,
setFile, setFile,
removeOptionAnswer removeOptionAnswer,
addFiles
}) => { }) => {
return ( return (
@ -45,13 +46,15 @@ const AnswerModal = ({
<div className={classes.myModal__dialog__content__body__answer}> <div className={classes.myModal__dialog__content__body__answer}>
<span className={classes.myModal__dialog__content__body__answer__title}>Вопрос</span> <span className={classes.myModal__dialog__content__body__answer__title}>Вопрос</span>
<MarkDowm mkValue={question} setMkValue={setQuestion}></MarkDowm> <MarkDowm mkValue={question} setMkValue={setQuestion}></MarkDowm>
<label for="fileUpload" className={classes.myModal__dialog__content__body__answer__fileLabel}>Добавить файл</label>
<label for="fileUpload" className={classes.myModal__dialog__content__body__answer__listFile}>Файлы : {file ? file.map(item => `${item.name}; `) : Нет}</label>
<input <input
id="fileUpload"
type="file" type="file"
multiple multiple
accept="image/*,image/jpeg,video/mp4,video/x-m4v,video/*" accept="image/*,image/jpeg,video/mp4,video/x-m4v,video/*"
className={classes.myModal__dialog__content__body__answer__file} className={classes.myModal__dialog__content__body__answer__file}
value={file} onChange={e => addFiles(e.target.files)}
onChange={event => setFile(event.target.value)}
></input> ></input>
</div> </div>
<div className={classes.myModal__dialog__content__body__comment}> <div className={classes.myModal__dialog__content__body__comment}>

View File

@ -5,14 +5,13 @@ import MyButton from "./MyButton.jsx";
const DefaultModal = ({ const DefaultModal = ({
name, name,
postfix,
btn, btn,
BodyModal BodyModal
}) => { }) => {
return ( return (
<div class="modal fade myModal" className={classes.main} id={`${name}`} tabIndex="-1" aria-labelledby="exampleModalLabel" data-bs-backdrop="static" aria-hidden="true"> <div class="modal fade myModal" className={classes.main} id={`${name}`} tabIndex="-1" aria-labelledby="exampleModalLabel" data-bs-backdrop="static" aria-hidden="true">
<div class="modal-dialog myModal__dialog" className={classes.main__dialog}> <div class="modal-dialog modal-dialog-centered myModal__dialog" className={classes.main__dialog}>
<div class="modal-content" className={classes.main__dialog__content}> <div class="modal-content" className={classes.main__dialog__content}>
{BodyModal} {BodyModal}
<div class="modal-footer myModal__dialog__content__footer" className={classes.myModal__dialog__content__footer}> <div class="modal-footer myModal__dialog__content__footer" className={classes.myModal__dialog__content__footer}>

View File

@ -4,11 +4,23 @@ import MarkdownEditor from "@uiw/react-markdown-editor";
import { parseTotalLinkVideo } from "../hooks/sundry/parseLinkVideo"; import { parseTotalLinkVideo } from "../hooks/sundry/parseLinkVideo";
const GeneratingFormFields = ({listBlock, listTypeAnswer, answers, updateAnswersForm}) => { const GeneratingFormFields = ({listBlock, listTypeAnswer, answers, updateAnswersForm}) => {
const getUint8Array = (binary) => {
let bytesArray = []
let len = binary.length
for (let i = 0; i < len; i++) {
bytesArray.push(binary.charCodeAt(i))
}
return [new Uint8Array(bytesArray)]
}
return ( return (
listBlock.map((item, i) => listBlock.map((item, i) =>
<div className={classes.item} key={i}> <div className={classes.item} key={i}>
<div className={classes.item__question}> <div className={classes.item__question}>
<p className={classes.item__question__text}>{i + 1}) <MarkdownEditor.Markdown source={item.question}/></p> <p className={classes.item__question__text}><MarkdownEditor.Markdown source={`${i + 1}) ${item.question}`}/></p>
<p className={classes.item__question__comment}>{item.comment}</p> <p className={classes.item__question__comment}>{item.comment}</p>
<div className={classes.item__question__video}> <div className={classes.item__question__video}>
{item.video ? {item.video ?
@ -37,6 +49,13 @@ const GeneratingFormFields = ({listBlock, listTypeAnswer, answers, updateAnswers
updateAnswersForm: updateAnswersForm ? updateAnswersForm : false updateAnswersForm: updateAnswersForm ? updateAnswersForm : false
}) })
} }
{
item.file.map(f => <a className={classes.item__answer__file} download={f.name} href={
URL.createObjectURL(
new Blob(getUint8Array(atob(f.binary)), { type: f.type })
)
}>{f.name}</a>)
}
</div> </div>
</div> </div>
) )

View File

@ -1,16 +1,28 @@
import React from "react"; import React from "react";
import { InputMask } from "primereact/inputmask";
import classes from "../assets/styles/components/myInput.module.scss"; import classes from "../assets/styles/components/myInput.module.scss";
const MyInput = (props) => { const MyInput = (props) => {
return ( return (
<div className={classes.main} style={{...props.otherMainStyle}}> <div className={classes.main} style={{...props.otherMainStyle}}>
<input {
type={props.type} props.mask ?
placeholder={props.placeholder} <InputMask
style={{...props.otherInputStyle}} type={props.type}
onChange={(e) => props.change(e.target.value)} placeholder={props.placeholder}
value={props.value} style={{...props.otherInputStyle}}
/> onChange={(e) => props.change(e.target.value)}
value={props.value}
mask={props.mask}
/> :
<input
type={props.type}
placeholder={props.placeholder}
style={{...props.otherInputStyle}}
onChange={(e) => props.change(e.target.value)}
value={props.value}
/>
}
</div> </div>
) )
} }

View File

@ -0,0 +1,11 @@
import React from "react";
import QRCode from "react-qr-code";
const MyQrCode = ({value}) => {
return (
<QRCode value={value}/>
)
}
export default MyQrCode

View File

@ -3,6 +3,33 @@ import { CKEditor } from '@ckeditor/ckeditor5-react';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic'; import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
const TextEditor = ({data, setData}) => { const TextEditor = ({data, setData}) => {
function uploadAdapter(loader) {
return {
upload: () => {
return new Promise(async (resolve, reject) => {
try {
const file = await loader.file;
const buff = await file.arrayBuffer()
const bytesArray = new Uint8Array(buff)
const bytesString = btoa(String.fromCharCode.apply(null, bytesArray))
resolve({
default: `data:image/jpg;base64, ${bytesString}`
});
} catch (error) {
reject("Hello");
}
});
}
}
}
function uploadPlugin(editor) {
editor.plugins.get("FileRepository").createUploadAdapter = (loader) => {
return uploadAdapter(loader);
};
}
return ( return (
<div className="App"> <div className="App">
<h2>Редактор статьи</h2> <h2>Редактор статьи</h2>
@ -10,6 +37,7 @@ const TextEditor = ({data, setData}) => {
editor={ ClassicEditor } editor={ ClassicEditor }
data={data} data={data}
config = {{ config = {{
extraPlugins: [uploadPlugin],
mediaEmbed: {previewsInData: true } mediaEmbed: {previewsInData: true }
}} }}
onReady={ editor => { onReady={ editor => {
@ -19,15 +47,11 @@ const TextEditor = ({data, setData}) => {
onChange={ ( event, editor ) => { onChange={ ( event, editor ) => {
setData(editor.getData()) setData(editor.getData())
}} }}
onBlur={ ( event, editor ) => { onBlur={ ( event, editor ) => {}}
console.log( 'Blur.', editor ); onFocus={ ( event, editor ) => {}}
} }
onFocus={ ( event, editor ) => {
console.log( 'Focus.', editor );
} }
/> />
</div> </div>
); );
} }
export default TextEditor; export default TextEditor

View File

@ -0,0 +1,14 @@
import React from "react";
import classes from "../../assets/styles/components/bodyModal/editToken.module.scss";
import MyInput from "../MyInput.jsx";
const EditToken = ({titleToken, setTitleToken}) => {
return (
<div className={classes.main}>
<MyInput type={"text"} value={titleToken} change={setTitleToken} placeholder={"Название"}/>
</div>
)
}
export default EditToken

View File

@ -1,4 +1,4 @@
import React, {useState} from "react"; import React, {useState, useRef} from "react";
import classes from "../../assets/styles/components/bodyModal/editUserAdminPanel.module.scss"; import classes from "../../assets/styles/components/bodyModal/editUserAdminPanel.module.scss";
import MyInput from "../../components/MyInput.jsx"; import MyInput from "../../components/MyInput.jsx";
@ -12,6 +12,7 @@ const EditUserAdminPanel = ({
lastName, lastName,
login, login,
phone, phone,
pass,
setEmail, setEmail,
setFirstName, setFirstName,
setIsAdmin, setIsAdmin,
@ -19,10 +20,9 @@ const EditUserAdminPanel = ({
setLastName, setLastName,
setLogin, setLogin,
setPhone, setPhone,
setPass
}) => { }) => {
console.log('228', id, isAdmin, isAdmin)
return ( return (
<div className={classes.main}> <div className={classes.main}>
<MyInput <MyInput
@ -35,6 +35,7 @@ const EditUserAdminPanel = ({
/> />
<MyInput <MyInput
type={"text"} type={"text"}
mask={"9 (999) 999-99-99"}
value={phone} value={phone}
placeholder={"Телефон"} placeholder={"Телефон"}
change={setPhone} change={setPhone}
@ -65,6 +66,14 @@ const EditUserAdminPanel = ({
otherMainStyle={{width: "100%", height: "100%", marginTop: "1%"}} otherMainStyle={{width: "100%", height: "100%", marginTop: "1%"}}
otherInputStyle={{width: "100%", height: "10%"}} otherInputStyle={{width: "100%", height: "10%"}}
/> />
<MyInput
type={"text"}
value={pass}
placeholder={"Пароль"}
change={setPass}
otherMainStyle={{width: "100%", height: "100%", marginTop: "1%"}}
otherInputStyle={{width: "100%", height: "10%"}}
/>
<div className={classes.main__status}> <div className={classes.main__status}>
<div className={classes.main__status__admin}> <div className={classes.main__status__admin}>
<div className={classes.main__status__admin__text}>Администратор</div> <div className={classes.main__status__admin__text}>Администратор</div>

View File

@ -0,0 +1,13 @@
import React from "react";
import classes from "../../assets/styles/components/bodyModal/qrCodeToken.module.scss";
import MyQrCode from "../MyQrCode.jsx";
const QrCodeToken = ({ value }) => {
return (
<div className={classes.main}>
<MyQrCode value={`http://minerva.krbl.ru/forms/${value}`} />
</div>
);
};
export default QrCodeToken;

View File

@ -1,42 +0,0 @@
// import axios from "axios";
// async function listUsersApi(token) {
// try {
// const response = await axios.get(`https://api.minerva.krbl.ru/auth/manage/users`,
// {
// headers: {
// "Authorization": `Token ${token}`
// }
// })
// return response
// }
// catch (e) {
// return e
// }
// };
// async function editUserApi(token, data) {
// try {
// const response = await axios.post(`https://api.minerva.krbl.ru/auth/manage/edit`,
// {
// "email": data.email,
// "first_name": data.first_name,
// "id": data.id,
// "is_admin": data.is_admin,
// "last_name": data.last_name,
// "login": data.login,
// "phone": data.phone
// },
// {
// headers: {
// "Authorization": `Token ${token}`
// }
// })
// return response
// }
// catch (e) {
// return e
// }
// };
// export {listUsersApi, editUserApi}

View File

@ -11,7 +11,7 @@ async function getAnswersApi(token, formToken) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -29,7 +29,7 @@ async function removeAnswerFormApi(token, formId, answerId) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };

View File

@ -16,7 +16,7 @@ async function createArticleApi(token, data) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -32,7 +32,7 @@ async function getListArticlesApi(token) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -48,7 +48,7 @@ async function getArticleApi(token, articleId) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -68,7 +68,7 @@ async function editTagsApi(token, articleId, tags, flag) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -88,7 +88,7 @@ async function editTitleArticleApi(token, articleId, title) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -108,7 +108,7 @@ async function addArticleApi(token, articleId, content) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -128,7 +128,7 @@ async function editArticleApi(token, articleId, content) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };

View File

@ -7,7 +7,7 @@ async function logIn(login, password) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -41,7 +41,7 @@ async function verifyUserApi(token=false) {
return response return response
} }
catch(e) { catch(e) {
return e return e.response
} }
} }
return false return false

View File

@ -11,7 +11,7 @@ async function listFormBlockApi(token, formId) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
} }
@ -29,7 +29,7 @@ async function addFormBlockApi(token, formId, data) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -48,7 +48,7 @@ async function updateBlockApi(token, formId, data, order) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -67,7 +67,7 @@ async function removeBlockApi(token, formId, order) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -86,7 +86,7 @@ async function updateOrderBlockApi(token, formId, data) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
} }
@ -104,7 +104,7 @@ async function saveFormApi(token) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -119,7 +119,7 @@ async function listFormBlockByTokenApi(token, formToken) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -135,7 +135,7 @@ async function saveAnswersApi(token, formToken, data) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -153,7 +153,7 @@ async function getBlockApi(token, formId, order) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };

View File

@ -11,7 +11,7 @@ async function listFormsApi(token) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -30,7 +30,7 @@ async function createFormApi(token) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -44,7 +44,7 @@ async function removeFormApi(token, formId) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -62,15 +62,15 @@ async function updateTitleFormApi(token, formId, title) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
async function newFormTokenApi(token, formId) { async function newFormTokenApi(token, formId, name) {
try { try {
const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/access/new`, const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/access/new`,
{ {
"name": "test" "name": name
}, },
{ {
headers: { headers: {
@ -80,7 +80,7 @@ async function newFormTokenApi(token, formId) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -96,7 +96,7 @@ async function listFormsByTokenApi(token, formId) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -114,9 +114,29 @@ async function removeTokenFormApi(token, formId, formToken) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
} };
async function editTokenFormApi(token, formId, formToken, name) {
try {
const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/access/revoke`,
{
"token_id": formToken,
"is_active": true,
"name": name
},
{
headers: {
"Authorization": `Token ${token}`
}
})
return response
}
catch (e) {
return e.response
}
};
export { export {
listFormsApi, listFormsApi,
@ -125,5 +145,6 @@ export {
updateTitleFormApi, updateTitleFormApi,
newFormTokenApi, newFormTokenApi,
listFormsByTokenApi, listFormsByTokenApi,
removeTokenFormApi removeTokenFormApi,
editTokenFormApi
}; };

View File

@ -21,8 +21,7 @@ async function editUserApi(token, data) {
return response return response
} }
catch(e) { catch(e) {
console.log(e) return e.response
return e
} }
}; };
@ -38,7 +37,7 @@ async function getListUserApi(token) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -63,7 +62,7 @@ async function addUserApi(token, data) {
return response return response
} }
catch (e) { catch (e) {
return e return e.response
} }
}; };
@ -82,8 +81,27 @@ async function removeUserApi(token, login) {
return response return response
} }
catch(e) { catch(e) {
console.log(e) return e.response
return e }
};
async function editUserPass(token, login, pass) {
try {
const response = await axios.post("https://api.minerva.krbl.ru/auth/manage/updatePassword",
{
"login": login,
"password": pass
},
{
headers: {
"Authorization": `Token ${token}`,
},
})
return response
}
catch(e) {
return e.response
} }
} }
@ -91,5 +109,6 @@ export {
editUserApi, editUserApi,
getListUserApi, getListUserApi,
addUserApi, addUserApi,
removeUserApi removeUserApi,
editUserPass
} }

View File

@ -13,11 +13,13 @@ function responseDataToListBlock(data) {
} }
for (let param of block.data) { for (let param of block.data) {
if (Array.isArray(param.Value) && param.Value.length) { if (Array.isArray(param.Value) && param.Value.length) {
newParam[param.Key] = param.Value.map(item => ({ newParam[param.Key] = param.Value.map(item => ({
id: item.find(obj => obj.Key === "id").Value, id: item.find(obj => obj.Key === "id") ? item.find(obj => obj.Key === "id").Value : null,
text: item.find(obj => obj.Key === "text").Value text: item.find(obj => obj.Key === "text") ? item.find(obj => obj.Key === "text").Value : null,
name: item.find(obj => obj.Key === "name") ? item.find(obj => obj.Key === "name").Value : null,
type: item.find(obj => obj.Key === "type") ? item.find(obj => obj.Key === "type").Value : null,
binary: item.find(obj => obj.Key === "binary") ? item.find(obj => obj.Key === "binary").Value : null,
})) }))
} }
else { else {

View File

@ -3,7 +3,7 @@ import { useCookies } from "react-cookie";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import classes from "../assets/styles/adminPanel.module.scss"; import classes from "../assets/styles/adminPanel.module.scss";
import { UserData } from "../context"; import { UserData } from "../context";
import { getListUserApi, editUserApi, addUserApi, removeUserApi } from "../hooks/api/profileApi.js"; import { getListUserApi, editUserApi, addUserApi, removeUserApi, editUserPass } from "../hooks/api/profileApi.js";
import { verifyUser } from "../hooks/services/profile.js"; import { verifyUser } from "../hooks/services/profile.js";
import DefaultModal from "../components/DefaultModal.jsx"; import DefaultModal from "../components/DefaultModal.jsx";
import EditUserAdminPanel from "../components/bodyModal/EditUserAdminPanel.jsx"; import EditUserAdminPanel from "../components/bodyModal/EditUserAdminPanel.jsx";
@ -14,33 +14,36 @@ import CheckModal from "../components/CheckModal.jsx";
const AdminPanel = () => { const AdminPanel = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const [cookies, setCookies] = useCookies(["user"]); const [cookies, setCookies] = useCookies(["user"]);
const {user, setUser} = useContext(UserData); const {user, setUser, userRef} = useContext(UserData);
const [listUser, setListUser] = useState([]); const [listUser, setListUser] = useState([]);
const [email, setEmail] = useState("") const [email, setEmail] = useState("");
const [firstName, setFirstName] = useState("") const [firstName, setFirstName] = useState("");
const [id, setId] = useState(false) const [id, setId] = useState(false);
const [isAdmin, setIsAdmin] = useState(false) const [isAdmin, setIsAdmin] = useState(false);
const [isTeacher, setIsTeacher] = useState(false) const [isTeacher, setIsTeacher] = useState(false);
const [lastName, setLastName] = useState("") const [lastName, setLastName] = useState("");
const [login, setLogin] = useState("") const [login, setLogin] = useState("");
const [phone, setPhone] = useState("") const [phone, setPhone] = useState("");
const [pass, setPass] = useState("");
useEffect(() => { useEffect(() => {
async function getListUser() { async function getListUser() {
const responseListUser = await getListUserApi(cookies.token); const responseListUser = await getListUserApi(cookies.token);
const responseCurrentUser = await verifyUser(cookies, user, setUser)
if ( if (
responseListUser.status === 200 && responseListUser.status === 200
responseCurrentUser.status === 200 &&
responseCurrentUser.data.is_admin
) { ) {
setListUser([...responseListUser.data].filter(item => item.id !== responseCurrentUser.data.id)) setListUser(responseListUser.data)
}
else if (
responseListUser.status === 401
) {
// navigate("/enter")
setUser(false)
} }
else { else {
console.log('responseListUser', responseListUser) console.log(responseListUser)
console.log('responseCurrentUser', responseCurrentUser)
} }
} }
@ -56,7 +59,8 @@ const AdminPanel = () => {
setLastName("") setLastName("")
setLogin("") setLogin("")
setPhone("") setPhone("")
} setPass("")
};
async function addUser() { async function addUser() {
const currentState = { const currentState = {
@ -73,9 +77,22 @@ const AdminPanel = () => {
if (response.status === 200) { if (response.status === 200) {
setListUser([...listUser, currentState]) setListUser([...listUser, currentState])
if (pass) {
await editUserPass(cookies.token, login, pass);
}
}
else if (
response.status === 401
) {
// navigate("/enter")
setUser(false)
}
else {
console.log(response)
} }
clearState() clearState()
} };
async function editUser() { async function editUser() {
const currentState = { const currentState = {
@ -87,14 +104,27 @@ const AdminPanel = () => {
last_name: lastName, last_name: lastName,
login: login, login: login,
phone: phone phone: phone
} };
const response = await editUserApi(cookies.token, currentState) const response = await editUserApi(cookies.token, currentState);
if (response.status === 200) { if (response.status === 200) {
setListUser(listUser.map(item => item.id === id ? currentState : item)) setListUser(listUser.map(item => item.id === id ? currentState : item));
if (pass) {
await editUserPass(cookies.token, login, pass);
};
} }
clearState() else if (
} response.status === 401
) {
// navigate("/enter")
setUser(false)
}
else {
console.log(response)
}
clearState();
};
function openUser(user) { function openUser(user) {
setEmail(user.email) setEmail(user.email)
@ -113,6 +143,15 @@ const AdminPanel = () => {
if (response.status === 200) { if (response.status === 200) {
setListUser(listUser.filter(item => item.login !== login)) setListUser(listUser.filter(item => item.login !== login))
} }
else if (
response.status === 401
) {
// navigate("/enter")
setUser(false)
}
else {
console.log(response)
}
} }
return ( return (
@ -168,7 +207,7 @@ const AdminPanel = () => {
</div> </div>
<div className={classes.admin__wrapper__body__users__item__info}> <div className={classes.admin__wrapper__body__users__item__info}>
{ {
item.admin ? item.is_admin ?
<i class="fa-solid fa-circle-check" style={{color: "rgb(150, 209, 158)"}}></i> : <i class="fa-solid fa-circle-check" style={{color: "rgb(150, 209, 158)"}}></i> :
<i class="fa-solid fa-circle-xmark" style={{color: "rgb(235, 130, 130)"}}></i>} <i class="fa-solid fa-circle-xmark" style={{color: "rgb(235, 130, 130)"}}></i>}
</div> </div>
@ -205,6 +244,8 @@ const AdminPanel = () => {
setLastName={setLastName} setLastName={setLastName}
setLogin={setLogin} setLogin={setLogin}
setPhone={setPhone} setPhone={setPhone}
pass={pass}
setPass={setPass}
/> />
} }
btn={[ btn={[

View File

@ -3,16 +3,18 @@ import { useCookies } from "react-cookie";
import { useNavigate, useParams } from 'react-router-dom'; import { useNavigate, useParams } from 'react-router-dom';
import { answersData } from "../context"; import { answersData } from "../context";
import classes from "../assets/styles/answersForm.module.scss"; import classes from "../assets/styles/answersForm.module.scss";
import { responseDataToListBlock, dateTimeParse } from "../hooks/sundry/parseListBlock"; import { responseDataToListBlock, dateTimeParse } from "../hooks/sundry/parseListBlock.js";
import { listFormBlockApi } from "../hooks/api/formApi"; import { listFormBlockApi } from "../hooks/api/formApi.js";
import { listUsersApi } from "../hooks/api/adminApi"; import { getListUserApi } from "../hooks/api/profileApi.js";
import { removeAnswerFormApi, getAnswersApi } from "../hooks/api/answersApi.js"; import { removeAnswerFormApi, getAnswersApi } from "../hooks/api/answersApi.js";
import Loading from "../components/Loading.jsx"; import Loading from "../components/Loading.jsx";
import CheckModal from "../components/CheckModal.jsx"; import CheckModal from "../components/CheckModal.jsx";
import { UserData } from "../context";
const AnswersForm = () => { const AnswersForm = () => {
const { formId } = useParams(); const { formId } = useParams();
const {answersList, setAnswersList} = useContext(answersData); const {answersList, setAnswersList} = useContext(answersData);
const {user, setUser} = useContext(UserData);
const [data, setData] = useState(false); const [data, setData] = useState(false);
const [cookies, _, __] = useCookies(["user"]); const [cookies, _, __] = useCookies(["user"]);
@ -21,7 +23,7 @@ const AnswersForm = () => {
const result = [] const result = []
const responseBlocks = await listFormBlockApi(cookies.token, formId); const responseBlocks = await listFormBlockApi(cookies.token, formId);
const responseAnswers = await getAnswersApi(cookies.token, formId); const responseAnswers = await getAnswersApi(cookies.token, formId);
const listUsers = await listUsersApi(cookies.token); const listUsers = await getListUserApi(cookies.token);
if (responseBlocks.status === 200 && responseBlocks.data) { if (responseBlocks.status === 200 && responseBlocks.data) {
const listBlocks = responseDataToListBlock(responseBlocks.data); const listBlocks = responseDataToListBlock(responseBlocks.data);
@ -55,8 +57,14 @@ const AnswersForm = () => {
setData(result) setData(result)
} }
else if (
response.status === 401
) {
// navigate("/enter")
setUser(false)
}
else { else {
console.log(responseBlocks) console.log(response)
} }
}; };
@ -69,6 +77,12 @@ const AnswersForm = () => {
if (response.status === 200) { if (response.status === 200) {
setData([...data].filter(item => item.id !== answerId)) setData([...data].filter(item => item.id !== answerId))
} }
else if (
response.status === 401
) {
// navigate("/enter")
setUser(false)
}
else { else {
console.log(response) console.log(response)
} }

View File

@ -1,86 +1,138 @@
import React, { useState, useContext, useEffect } from "react"; import React, { useState, useContext, useEffect } from "react";
import { useCookies } from "react-cookie"; import { useCookies } from "react-cookie";
import { useNavigate } from 'react-router-dom'; import { useNavigate } from "react-router-dom";
import classes from "../assets/styles/articles.module.scss" import classes from "../assets/styles/articles.module.scss";
import MyButton from "../components/MyButton.jsx"; import MyButton from "../components/MyButton.jsx";
import MyInput from "../components/MyInput.jsx"; import MyInput from "../components/MyInput.jsx";
import { UserData } from "../context"; import { UserData } from "../context";
import CheckModal from "../components/CheckModal.jsx"; import CheckModal from "../components/CheckModal.jsx";
import { createArticleApi, getListArticlesApi } from "../hooks/api/articleApi.js"; import {
createArticleApi,
getListArticlesApi,
} from "../hooks/api/articleApi.js";
const Articles = () => { const Articles = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const {user, setUser} = useContext(UserData); const { user, setUser } = useContext(UserData);
const [stateLoading, setStateLoading] = useState(false); const [stateLoading, setStateLoading] = useState(false);
const [listArticles, setListArticles] = useState([]); const [listArticles, setListArticles] = useState([]);
const [cookies, _, __] = useCookies(["user"]); const [cookies, _, __] = useCookies(["user"]);
useEffect(() => { useEffect(() => {
async function getListArticles() { async function getListArticles() {
const response = await getListArticlesApi(cookies.token) const response = await getListArticlesApi(cookies.token);
if (response.status === 200) { if (response.status === 200) {
setListArticles(response.data) setListArticles(response.data);
} } else if (response.status === 401) {
} // navigate("/enter")
setUser(false);
getListArticles() } else {
}, []) console.log(response);
}
async function createArticle() {
const response = await createArticleApi(cookies.token)
console.log(response)
if (response.status === 200) {
navigate(`/articles/${response.data.id}/edit`)
}
} }
return ( getListArticles();
<div className={classes.main}> }, []);
<div className={classes.wrapper}>
<div className={classes.panel}>
<MyInput placeholder={'Поиск...'}/>
<MyButton click={createArticle} class={"main__green"} otherStyle={{width: '200px'}} text={
stateLoading ? <div class="spinner-border text-light" role="status">
<span class="visually-hidden">Загрузка...</span>
</div> : 'Создать'
}/>
</div>
<div className={classes.listArticles}>
<div className={classes.listArticles__columns}>
<div className={classes.listArticles__columns__item}>Название</div>
<div className={classes.listArticles__columns__item}>Дата публикации</div>
<div className={classes.listArticles__columns__item}>Автор</div>
</div>
<div className={classes.listArticles__forms}>
{listArticles.map(item => <div className={classes.listArticles__forms__item}>
<div className={classes.listArticles__forms__item__title} onClick={() => navigate(`/articles/${item.id}/edit`)}>{item.title}</div>
<div className={classes.listArticles__forms__item__date}>24.06.24</div>
<div className={classes.listArticles__forms__item__author}>kuwsh1n</div>
<i class="fa-solid fa-ellipsis-vertical" id="action" data-bs-toggle="dropdown"></i>
<ul class="dropdown-menu" aria-labelledby="action">
<li><a class="dropdown-item" onClick={() => navigate(`/articles/${item.id}/`)}>Открыть</a></li>
<li><a class="dropdown-item" data-bs-toggle="modal" data-bs-target={`#checkModaltest`}>Удалить</a></li>
</ul>
<CheckModal async function createArticle() {
postfix={'test'} const response = await createArticleApi(cookies.token);
message={`Вы хотетите удалить статью <Test article>?`}
action={{ if (response.status === 200) {
execute: () => {}, navigate(`/articles/${response.data.id}/edit`);
cancel: () => {} } else if (response.status === 401) {
}} // navigate("/enter")
/> setUser(false);
</div>)} } else {
</div> console.log(response);
}
}
return (
<div className={classes.main}>
<div className={classes.wrapper}>
<div className={classes.panel}>
<MyInput placeholder={"Поиск..."} />
<MyButton
click={createArticle}
class={"main__blue"}
otherStyle={{ width: "200px" }}
text={
stateLoading ? (
<div class="spinner-border text-light" role="status">
<span class="visually-hidden">Загрузка...</span>
</div> </div>
</div> ) : (
"Создать"
)
}
/>
</div> </div>
) <div className={classes.listArticles}>
} <div className={classes.listArticles__columns}>
<div className={classes.listArticles__columns__item}>Название</div>
<div className={classes.listArticles__columns__item}>
Дата публикации
</div>
<div className={classes.listArticles__columns__item}>Автор</div>
</div>
<div className={classes.listArticles__forms}>
{listArticles.map((item) => (
<div className={classes.listArticles__forms__item}>
<div
className={classes.listArticles__forms__item__title}
onClick={() => navigate(`/articles/${item.id}/edit`)}
>
{item.title}
</div>
<div className={classes.listArticles__forms__item__date}>
24.06.24
</div>
<div className={classes.listArticles__forms__item__author}>
kuwsh1n
</div>
<i
class="fa-solid fa-ellipsis-vertical"
id="action"
data-bs-toggle="dropdown"
></i>
<ul class="dropdown-menu" aria-labelledby="action">
<li>
<a
class="dropdown-item"
onClick={() => navigate(`/articles/${item.id}/`)}
>
Открыть
</a>
</li>
<li>
<a
class="dropdown-item"
data-bs-toggle="modal"
data-bs-target={`#checkModaltest`}
>
Удалить
</a>
</li>
</ul>
export default Articles; <CheckModal
postfix={"test"}
message={`Вы хотетите удалить статью <Test article>?`}
action={{
execute: () => {},
cancel: () => {},
}}
/>
</div>
))}
</div>
</div>
</div>
</div>
);
};
export default Articles;

View File

@ -6,6 +6,7 @@ import MyButton from "../components/MyButton.jsx";
import MyInput from "../components/MyInput.jsx"; import MyInput from "../components/MyInput.jsx";
import { FormsData, UserData } from "../context"; import { FormsData, UserData } from "../context";
import CheckModal from "../components/CheckModal.jsx"; import CheckModal from "../components/CheckModal.jsx";
import { verifyUserApi } from "../hooks/api/enterAccountApi.js";
import { import {
listFormsApi, listFormsApi,
createFormApi, createFormApi,
@ -17,22 +18,27 @@ import {
const Forms = () => { const Forms = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const { forms, setForms } = useContext(FormsData); const { forms, setForms } = useContext(FormsData);
const { user, setUser } = useContext(UserData); const { user, setUser, userRef } = useContext(UserData);
const [stateLoading, setStateLoading] = useState(false); const [stateLoading, setStateLoading] = useState(false);
const [searchForm, setSearchForm] = useState(""); const [searchForm, setSearchForm] = useState("");
const [cookies, _, __] = useCookies(["user"]); const [cookies, setCookies, __] = useCookies(["user"]);
useEffect(() => { useEffect(() => {
async function listForms() { async function listForms() {
const response = await listFormsApi(cookies.token); const responseForms = await listFormsApi(cookies.token);
const responseUser = await verifyUserApi(cookies.token)
if (response.data) { if (responseForms.data && responseUser) {
setForms(response.data); setForms(responseForms.data.filter(item => item.owner_id === responseUser.data.id));
} else if (response.status === 200 && response.data) { } else if (responseForms.status === 200 && response.data) {
setForms([]); setForms([]);
} else if (responseForms.status === 401 || responseUser.status === 401) {
// navigate("/enter")
setUser(false)
} else { } else {
console.log(response); console.log(responseForms);
console.log(responseUser)
} }
} }
@ -44,11 +50,17 @@ const Forms = () => {
const response = await createFormApi(cookies.token); const response = await createFormApi(cookies.token);
setStateLoading(false); setStateLoading(false);
if (response.data) { if (response.data && response.status === 200) {
const token = await newFormTokenApi(cookies.token, response.data.id); const token = await newFormTokenApi(cookies.token, response.data.id, "Админ");
navigate(`/forms/${response.data.id}/edit`); navigate(`/forms/${response.data.id}/edit`);
} else { } else if (
console.log(response); response.status === 401
) {
// navigate("/enter")
setUser(false)
}
else {
console.log(response)
} }
} }
@ -61,8 +73,15 @@ const Forms = () => {
if (response.status === 200) { if (response.status === 200) {
setForms([...forms.filter((item) => item.id !== id)]); setForms([...forms.filter((item) => item.id !== id)]);
} else { }
console.log(response); else if (
response.status === 401
) {
// navigate("/enter")
setUser(false)
}
else {
console.log(response)
} }
} }
@ -71,8 +90,15 @@ const Forms = () => {
if (response.status === 200 && response.data.tokens) { if (response.status === 200 && response.data.tokens) {
navigate(`/forms/${response.data.tokens[0].id}/`); navigate(`/forms/${response.data.tokens[0].id}/`);
} else { }
console.log(response); else if (
response.status === 401
) {
// navigate("/enter")
setUser(false)
}
else {
console.log(response)
} }
} }
@ -83,8 +109,15 @@ const Forms = () => {
navigator.clipboard.writeText( navigator.clipboard.writeText(
`${window.location.host}/forms/${response.data.tokens[0].id}/` `${window.location.host}/forms/${response.data.tokens[0].id}/`
); );
} else { }
console.log(response); else if (
response.status === 401
) {
// navigate("/enter")
setUser(false)
}
else {
console.log(response)
} }
} }

View File

@ -6,19 +6,21 @@ import MyButton from "../components/MyButton.jsx";
import Loading from "../components/Loading.jsx"; import Loading from "../components/Loading.jsx";
import MyInput from "../components/MyInput.jsx"; import MyInput from "../components/MyInput.jsx";
import TextEditor from "../components/TextEditor.jsx"; import TextEditor from "../components/TextEditor.jsx";
import { UserData } from "../context/index.js";
import { getArticleApi, editTagsApi, editTitleArticleApi, editArticleApi, addArticleApi } from "../hooks/api/articleApi.js"; import { getArticleApi, editTagsApi, editTitleArticleApi, editArticleApi, addArticleApi } from "../hooks/api/articleApi.js";
const NewArticle = () => { const NewArticle = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation(); const location = useLocation();
const { articleId } = useParams(); const { articleId } = useParams();
const {user, setUser} = useContext(UserData)
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [title, setTitle] = useState(""); const [title, setTitle] = useState("");
const [tags, setTags] = useState([]); const [tags, setTags] = useState([]);
const [newTag, setNewTag] = useState("") const [newTag, setNewTag] = useState("")
const [ownerId, setOwnerId] = useState(""); const [ownerId, setOwnerId] = useState("");
const [contentArticle, setContentArticle] = useState(''); const [contentArticle, setContentArticle] = useState('');
const [blocks, setBlocks] = useState(''); const [blocks, setBlocks] = useState('');
@ -29,13 +31,21 @@ const NewArticle = () => {
const response = await getArticleApi(cookies.token, articleId) const response = await getArticleApi(cookies.token, articleId)
if (response.status === 200) { if (response.status === 200) {
console.log(response)
setTitle(response.data.article.title) setTitle(response.data.article.title)
setTags(response.data.article.tags ? response.data.article.tags : []) setTags(response.data.article.tags ? response.data.article.tags : [])
setOwnerId(response.data.article.owner_id) setOwnerId(response.data.article.owner_id)
setContentArticle(response.data.blocks ? response.data.blocks[0].data : '') setContentArticle(response.data.blocks ? response.data.blocks[0].data : '')
setBlocks(response.data.blocks ? response.data.blocks : false) setBlocks(response.data.blocks ? response.data.blocks : false)
} }
else if (
response.status === 401
) {
// navigate("/enter")
setUser(false)
}
else {
console.log(response)
}
} }
getArticle() getArticle()
@ -48,7 +58,16 @@ const NewArticle = () => {
if (response.status === 200) { if (response.status === 200) {
setTags([...tags, newTag]) setTags([...tags, newTag])
setNewTag("") setNewTag("")
} }
else if (
response.status === 401
) {
// navigate("/enter")
setUser(false)
}
else {
console.log(response)
}
} }
} }
@ -60,20 +79,36 @@ const NewArticle = () => {
cTags.splice(index, 1) cTags.splice(index, 1)
setTags(cTags) setTags(cTags)
} }
else if (
response.status === 401
) {
// navigate("/enter")
setUser(false)
}
else {
console.log(response)
}
} }
async function saveArticle() { async function saveArticle() {
const responseTitle = await editTitleArticleApi(cookies.token, articleId, title) const responseTitle = await editTitleArticleApi(cookies.token, articleId, title)
console.log(blocks)
const responseContentArticle = blocks ? const responseContentArticle = blocks ?
await editArticleApi(cookies.token, articleId, contentArticle) : await editArticleApi(cookies.token, articleId, contentArticle) :
await addArticleApi(cookies.token, articleId, contentArticle) await addArticleApi(cookies.token, articleId, contentArticle)
console.log(responseContentArticle)
if (responseTitle.status === 200 && responseContentArticle.status === 200) { if (responseTitle.status === 200 && responseContentArticle.status === 200) {
navigate("/articles") navigate("/articles")
} }
else if (
responseTitle.status === 401 || responseContentArticle.status === 401
) {
// navigate("/enter")
setUser(false)
}
else {
console.log(responseTitle)
console.log(responseContentArticle)
}
} }
return ( return (

View File

@ -8,6 +8,7 @@ import PreviewModal from "../components/PreviewModal.jsx";
import Loading from "../components/Loading.jsx"; import Loading from "../components/Loading.jsx";
import { FormsData, TypeAnswerData } from "../context"; import { FormsData, TypeAnswerData } from "../context";
import { listFormsApi, updateTitleFormApi } from "../hooks/api/listFormsApi.js"; import { listFormsApi, updateTitleFormApi } from "../hooks/api/listFormsApi.js";
import { UserData } from "../context";
import { import {
saveFormApi, saveFormApi,
addFormBlockApi, addFormBlockApi,
@ -27,6 +28,7 @@ const NewForm = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation(); const location = useLocation();
const { formId } = useParams(); const { formId } = useParams();
const {user, setUser} = useContext(UserData);
const [dragElem, setDragElem] = useState(null); const [dragElem, setDragElem] = useState(null);
const [dropElem, setDropElem] = useState(null); const [dropElem, setDropElem] = useState(null);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
@ -78,13 +80,19 @@ const NewForm = () => {
responseBlock.data && responseBlock.data &&
responseForms.status === 200 responseForms.status === 200
) { ) {
console.log(responseDataToListBlock(responseBlock.data))
setListBlock(responseDataToListBlock(responseBlock.data)); setListBlock(responseDataToListBlock(responseBlock.data));
const title = responseForms.data.find( const title = responseForms.data.find(
(item) => item.id === formId (item) => item.id === formId
).title; ).title;
setNewTitleForm(title); setNewTitleForm(title);
setOldTitleForm(title); setOldTitleForm(title);
} else { }
else if (responseForms.status === 401 || responseBlock.status === 401) {
// navigate("/enter")
setUser(false)
}
else {
setListBlock([]); setListBlock([]);
setNewTitleForm("Новыя форма"); setNewTitleForm("Новыя форма");
setOldTitleForm("Новыя форма"); setOldTitleForm("Новыя форма");
@ -132,6 +140,7 @@ const NewForm = () => {
setOptionAnswer(obj.optionAnswer); setOptionAnswer(obj.optionAnswer);
setMandatory(obj.mandatory); setMandatory(obj.mandatory);
setStateModal(obj.id); setStateModal(obj.id);
console.log(obj.file.map(item => item.name))
} }
async function updateBlock() { async function updateBlock() {
@ -160,9 +169,16 @@ const NewForm = () => {
} else { } else {
setListBlock([]); setListBlock([]);
} }
} else { }
console.log(response); else if (
response.status === 401
) {
// navigate("/enter")
setUser(false)
} }
else {
console.log(response)
}
cleanStates(); cleanStates();
} }
@ -172,13 +188,42 @@ const NewForm = () => {
if (response.status === 200) { if (response.status === 200) {
setListBlock([...listBlock.filter((item) => item.order !== order)]); setListBlock([...listBlock.filter((item) => item.order !== order)]);
} else { }
console.log(response); else if (
response.status === 401
) {
// navigate("/enter")
setUser(false)
}
else {
console.log(response)
}
}
async function addFiles(newFile) {
const fileData = []
for (let item of newFile) {
let binary = ""
const buff = await item.arrayBuffer()
const bytesArray = new Uint8Array(buff)
let len = bytesArray.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode( bytesArray[ i ] );
}
fileData.push({
name: item.name,
type: item.type,
binary: btoa(binary)
})
setFile([...file, ...fileData])
} }
} }
async function addFormBlock() { async function addFormBlock() {
console.log(optionAnswer);
const newBlock = { const newBlock = {
question: question, question: question,
@ -200,8 +245,15 @@ const NewForm = () => {
} else { } else {
setListBlock([]); setListBlock([]);
} }
} else { }
console.log(response); else if (
response.status === 401
) {
// navigate("/enter")
setUser(false)
}
else {
console.log(response)
} }
cleanStates(); cleanStates();
} }
@ -237,11 +289,30 @@ const NewForm = () => {
setListBlock(numberingBlocks(tListBlock, "order")); setListBlock(numberingBlocks(tListBlock, "order"));
} }
else if (
response.status === 401
) {
// navigate("/enter")
setUser(false)
}
else {
console.log(response)
}
} }
async function saveForm() { async function saveForm() {
if (oldTitleFrom !== newTitleForm) { if (oldTitleFrom !== newTitleForm) {
await updateTitleFormApi(cookies.token, formId, newTitleForm); const response = await updateTitleFormApi(cookies.token, formId, newTitleForm);
if (
response.status === 401
) {
// navigate("/enter")
setUser(false)
}
else {
console.log(response)
}
} }
cleanStates(); cleanStates();
@ -253,14 +324,14 @@ const NewForm = () => {
<div className={classes.wrapper}> <div className={classes.wrapper}>
<div className={classes.header}> <div className={classes.header}>
<div className={classes.header__listInput}> <div className={classes.header__listInput}>
<div className={classes.header__listInput__date}> {/* <div className={classes.header__listInput__date}>
<span>Дедлайн выполнения</span> <span>Дедлайн выполнения</span>
<MyInput <MyInput
type={"datetime-local"} type={"datetime-local"}
value={datetime} value={datetime}
change={setDatetime} change={setDatetime}
/> />
</div> </div> */}
<div className={classes.header__listInput__title}> <div className={classes.header__listInput__title}>
<span>Название формы</span> <span>Название формы</span>
<MyInput <MyInput
@ -327,6 +398,7 @@ const NewForm = () => {
updateBlock={updateBlock} updateBlock={updateBlock}
setCurrentTypeAnswer={setCurrentTypeAnswer} setCurrentTypeAnswer={setCurrentTypeAnswer}
removeOptionAnswer={removeOptionAnswer} removeOptionAnswer={removeOptionAnswer}
addFiles={addFiles}
/> />
<div className={classes.content__newForm}> <div className={classes.content__newForm}>

View File

@ -33,6 +33,12 @@ const Profile = () => {
setFirst_name(response.data.first_name); setFirst_name(response.data.first_name);
setLast_name(response.data.last_name); setLast_name(response.data.last_name);
} }
else if (
response.status === 401
) {
// navigate("/enter")
setUser(false)
}
else { else {
console.log(response) console.log(response)
} }
@ -83,7 +89,16 @@ const Profile = () => {
is_admin: user.is_admin is_admin: user.is_admin
}) })
setEdit(!edit) setEdit(!edit)
} }
else if (
response.status === 401
) {
navigate("/enter")
setUser(false);
}
else {
console.log(response)
}
} }
}; };

View File

@ -1,125 +1,239 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect, useContext } from "react";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { useCookies } from "react-cookie"; import { useCookies } from "react-cookie";
import classes from "../assets/styles/tokensForm.module.scss"; import classes from "../assets/styles/tokensForm.module.scss";
import { listFormsByTokenApi, newFormTokenApi, removeTokenFormApi } from "../hooks/api/listFormsApi"; import {
listFormsByTokenApi,
newFormTokenApi,
removeTokenFormApi,
editTokenFormApi,
} from "../hooks/api/listFormsApi";
import MyButton from "../components/MyButton.jsx"; import MyButton from "../components/MyButton.jsx";
import MyInput from "../components/MyInput.jsx"; import { UserData } from "../context/index.js";
import CheckModal from "../components/CheckModal.jsx"; import DefaultModal from "../components/DefaultModal.jsx";
import EditToken from "../components/bodyModal/EditToken.jsx";
import QrCodeToken from "../components/bodyModal/QrCodeToken.jsx";
import QRCode from "qrcode";
const TokensForm = () => { const TokensForm = () => {
const { formId } = useParams(); const { formId } = useParams();
const [tokens, setTokens] = useState([]) const [tokens, setTokens] = useState([]);
const [loading, setLoading] = useState(true) const [currentIdToken, setCurrentIdToken] = useState(false);
const [titleToken, setTitleToken] = useState('') const [loading, setLoading] = useState(true);
const [titleToken, setTitleToken] = useState("");
const { user, setUser } = useContext(UserData);
const [qrCodeUrl, setQrcodeUrl] = useState("");
const [cookies, _, __] = useCookies(["user"]); const [cookies, _, __] = useCookies(["user"]);
useEffect(() => { useEffect(() => {
async function listFormsByToken() { async function listFormsByToken() {
const response = await listFormsByTokenApi(cookies.token, formId) const response = await listFormsByTokenApi(cookies.token, formId);
console.log(response)
if (response.data.tokens) {
setTokens(response.data.tokens.filter(item => item.is_active === true))
setLoading(false)
}
else {
console.log(response)
}
}
listFormsByToken() if (response.status === 200) {
}, []) setTokens(
response.data.tokens.filter(
async function newFormToken() { (item, i) => item.is_active === true && i !== 0
const response = await newFormTokenApi(cookies.token, formId) )
);
if (response.status === 200) { setLoading(false);
setTokens([...tokens, response.data.token]) } else if (response.status === 401) {
} // navigate("/enter")
else { setUser(false);
console.log(response) } else {
} console.log(response);
}
} }
async function removeTokenForm(tokenForm) { listFormsByToken();
const response = await removeTokenFormApi(cookies.token, formId, tokenForm) }, []);
if (response.status === 200) { async function newFormToken() {
setTokens(tokens.filter(item => item.id !== tokenForm)) const response = await newFormTokenApi(cookies.token, formId, titleToken);
}
else { if (response.status === 200) {
console.log(response) setTokens([...tokens, response.data.token]);
} } else if (response.status === 401) {
// navigate("/enter")
setUser(false);
} else {
console.log(response);
} }
}
return ( // async function editTokenForm(tokenForm) {
<div className={classes.main}> // const response = await editTokenFormApi(cookies.token, formId, tokenForm, titleToken)
<div className={classes.wrapper}>
<div className={classes.answers}>
<div className={classes.answers__wrapper}>
<div className={classes.answers__wrapper__header}>
<h3>Токены формы</h3>
<MyButton text={"Создать"} class={"main__green"} click={newFormToken}/>
</div>
<div className={classes.answers__wrapper__body}>
<div className={classes.answers__wrapper__body__column}>
<div className={classes.answers__wrapper__body__column__wrapper}>
<div>Название</div>
<div>Токен</div>
</div>
</div>
{tokens ? // if (response.status === 200) {
tokens.map((item, i) => // setTokens([])
<div className={classes.answers__wrapper__body__item} key={i}> // }
<div className={classes.answers__wrapper__body__item__wrapper}> // else if (
<div className={classes.answers__wrapper__body__item__wrapper__title}> // response.status === 401
По умолчанию // ) {
</div> // // navigate("/enter")
<div className={classes.answers__wrapper__body__item__wrapper__token}> // setUser(false);
{item.id} // }
</div> // else {
</div> // console.log(response)
<div className={classes.answers__wrapper__body__item__btn}> // }
<i // }
async function removeTokenForm(tokenForm) {
const response = await removeTokenFormApi(cookies.token, formId, tokenForm);
if (response.status === 200) {
setTokens(tokens.filter((item) => item.id !== tokenForm));
} else if (response.status === 401) {
// navigate("/enter")
setUser(false);
} else {
console.log(response);
}
}
return (
<div className={classes.main}>
<div className={classes.wrapper}>
<div className={classes.answers}>
<div className={classes.answers__wrapper}>
<div className={classes.answers__wrapper__header}>
<h3>Токены формы</h3>
<MyButton
text={"Создать"}
class={"main__green"}
click={() => {
setTitleToken("");
setCurrentIdToken(false);
}}
target={"#tokenModal"}
toggle={"modal"}
/>
</div>
<div className={classes.answers__wrapper__body}>
<div className={classes.answers__wrapper__body__column}>
<div
className={classes.answers__wrapper__body__column__wrapper}
>
<div>Название</div>
<div>Токен</div>
</div>
</div>
{tokens ? (
tokens.map((item, i) => (
<div className={classes.answers__wrapper__body__item} key={i}>
<div
className={classes.answers__wrapper__body__item__wrapper}
>
<div
className={
classes.answers__wrapper__body__item__wrapper__title
}
>
{item.name}
</div>
<div
className={
classes.answers__wrapper__body__item__wrapper__token
}
>
{item.id}
</div>
</div>
<div className={classes.answers__wrapper__body__item__btn}>
{/* <i
class="fa-solid fa-pen" class="fa-solid fa-pen"
data-bs-toggle="modal" data-bs-toggle="modal"
data-bs-target={`#tokensModal${i}`} data-bs-target={`#tokenModal`}
onClick={() => setTitleToken("По умолчанию")}> onClick={() => {
</i> setTitleToken(item.name)
<i class="fa-solid fa-trash" onClick={() => removeTokenForm(item.id)}></i> setCurrentIdToken(item.id)
</div> }}>
</i> */}
<i
<div class="modal fade myModal" className={classes.myModal} id={`tokensModal${i}`} tabIndex="-1" aria-labelledby="exampleModalLabel" data-bs-backdrop="static" aria-hidden="true"> class="fa-solid fa-qrcode"
<div class="modal-dialog myModal__dialog" className={classes.myModal__dialog}> onClick={() => {
<div class="modal-content" className={classes.myModal__dialog__content}> QRCode.toDataURL(
<div class="modal-body" className={classes.myModal__dialog__content__body}> `http://minerva.krbl.ru/forms/${item.id}`,
<MyInput type={"text"} value={titleToken} change={setTitleToken}/> {},
</div> (err, url) => {
<div class="modal-footer myModal__dialog__content__footer" className={classes.myModal__dialog__content__footer}> setQrcodeUrl(url);
<MyButton text={"Сохранить"} class={"main__green"} dismiss={"modal"}/> }
<MyButton text={"Отмена"} class={"main__white"} dismiss={"modal"}/> );
</div> }}
</div> data-bs-toggle="modal"
</div> data-bs-target={`#qrModal`}
</div> ></i>
</div> <i
) class="fa-solid fa-trash"
: onClick={() => removeTokenForm(item.id)}
<div className={classes.loading__wrapper}> ></i>
<div class="spinner-border text-dark" className={classes.loading__wrapper__body} role="status">
<span class="visually-hidden">Загрузка...</span>
</div>
</div>}
</div>
</div> </div>
<DefaultModal
name={"qrModal"}
btn={[
{
text: "Скачать",
class: "main__green",
dismiss: "modal",
action: () => {
const aElem = document.createElement("a");
aElem.href = qrCodeUrl;
aElem.download = `${item.name}.png`;
aElem.click();
},
},
{
text: "Отмена",
class: "main__white",
dismiss: "modal",
action: () => {},
},
]}
BodyModal={<QrCodeToken value={item.id} />}
/>
</div>
))
) : (
<div className={classes.loading__wrapper}>
<div
class="spinner-border text-dark"
className={classes.loading__wrapper__body}
role="status"
>
<span class="visually-hidden">Загрузка...</span>
</div>
</div> </div>
)}
<DefaultModal
name={"tokenModal"}
btn={[
{
text: "Сохранить",
class: "main__green",
dismiss: "modal",
action: () => newFormToken(),
},
{
text: "Отмена",
class: "main__white",
dismiss: "modal",
action: () => {},
},
]}
BodyModal={
<EditToken
titleToken={titleToken}
setTitleToken={setTitleToken}
/>
}
/>
</div> </div>
</div>
</div> </div>
) </div>
} </div>
);
};
export default TokensForm; export default TokensForm;

View File

@ -12,6 +12,7 @@ const ViewArticle = () => {
const navigate = useNavigate(); const navigate = useNavigate();
// const location = useLocation(); // const location = useLocation();
const { articleId } = useParams(); const { articleId } = useParams();
const {user, setUser} = useContext(UserData)
const [title, setTitle] = useState(""); const [title, setTitle] = useState("");
const [tags, setTags] = useState([]); const [tags, setTags] = useState([]);
@ -25,15 +26,23 @@ const ViewArticle = () => {
useEffect(() => { useEffect(() => {
async function getArticle() { async function getArticle() {
const response = await getArticleApi(cookies.token, articleId) const response = await getArticleApi(cookies.token, articleId)
const user = await getListUserApi(cookies.token) const responseUser = await getListUserApi(cookies.token)
if (response.status === 200) { if (response.status === 200) {
console.log(response)
setTitle(response.data.article.title) setTitle(response.data.article.title)
setTags(response.data.article.tags ? response.data.article.tags : []) setTags(response.data.article.tags ? response.data.article.tags : [])
setOwner(user.status === 200 ? user.data.find(item => item.id === response.data.article.owner_id).login : response.data.article.owner_id) setOwner(responseUser.status === 200 ? responseUser.data.find(item => item.id === response.data.article.owner_id).login : response.data.article.owner_id)
setContentArticle(response.data.blocks ? response.data.blocks[0].data : '') setContentArticle(response.data.blocks ? response.data.blocks[0].data : '')
} }
else if (
response.status === 401
) {
// navigate("/enter")
setUser(false);
}
else {
console.log(response)
}
} }
getArticle() getArticle()

View File

@ -32,6 +32,12 @@ const ViewForm = () => {
{id: item.id, answer: []} {id: item.id, answer: []}
))); )));
} }
else if (
responseBlocks.status === 401
) {
// navigate("/enter")
setUser(false);
}
else { else {
setResponseStatus(responseBlocks.status) setResponseStatus(responseBlocks.status)
} }
@ -52,7 +58,6 @@ const ViewForm = () => {
}; };
async function saveAnswers() { async function saveAnswers() {
console.log(answers)
const response = await saveAnswersApi(cookies.token, formId, answers); const response = await saveAnswersApi(cookies.token, formId, answers);
if (response.status === 200) { if (response.status === 200) {
@ -65,6 +70,15 @@ const ViewForm = () => {
setAnswers([]); setAnswers([]);
navigate("/forms"); navigate("/forms");
} }
else if (
response.status === 401
) {
// navigate("/enter")
setUser(false);
}
else {
console.log(response)
}
} }
return ( return (

View File

@ -6,6 +6,8 @@ const protectedUrl = {
new RegExp("/forms/\\w+/answers"), new RegExp("/forms/\\w+/answers"),
new RegExp("/tokens/\\w+"), new RegExp("/tokens/\\w+"),
new RegExp("/admin"), new RegExp("/admin"),
new RegExp("/articles"),
new RegExp("/articles/\\w+/edit"),
], ],
Authorized: [ Authorized: [
"/enter" "/enter"
@ -16,6 +18,8 @@ const protectedUrl = {
new RegExp("/forms/\\w+/answers"), new RegExp("/forms/\\w+/answers"),
new RegExp("/tokens/\\w+"), new RegExp("/tokens/\\w+"),
new RegExp("/admin"), new RegExp("/admin"),
new RegExp("/articles"),
new RegExp("/articles/\\w+/edit"),
] ]
} }

View File

@ -1,5 +1,6 @@
const HtmlWebpackPlugin = require("html-webpack-plugin"); const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// const Inputmask = require('inputmask');
const path = require("path"); const path = require("path");
module.exports = (env) => { module.exports = (env) => {