fix tickets 4, 6, 15, 12
All checks were successful
publish-main / release-image (push) Successful in 6m44s

This commit is contained in:
kuwsh1n 2024-05-05 23:04:39 +03:00
parent e3455e3e6d
commit cdd43807f8
7 changed files with 363 additions and 7 deletions

View File

@ -0,0 +1,172 @@
.main {
width: 100%;
height: 100%;
}
.wrapper {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.loading__wrapper {
width: 100%;
height: 80%;
display: flex;
justify-content: center;
align-items: center;
&__body {
// margin-top: 100px;
span {
}
}
}
.answers {
width: 70%;
height: 70%;
box-shadow: 0 0 5px 1px rgb(200, 200, 200);
padding: 1.5%;
&__linkAdmin {
position: absolute;
bottom: 103%;
left: 10px;
span {
font-size: 15px;
font-family: "Montserrat", sans-serif;
color: rgb(100, 100, 100);
cursor: pointer;
&:hover {
text-decoration: underline;
color: rgb(66, 68, 189);
}
}
}
&__wrapper {
width: 100%;
height: 100%;
&__header {
width: 100%;
height: 15%;
display: flex;
justify-content: start;
align-items: center;
margin-bottom: 10px;
display: flex;
justify-content: space-between;
align-items: center;
h3 {
font-size: 25px;
font-family: "Montserrat", sans-serif;
color: rgb(100, 100, 100);
display: block;
}
}
&__body {
width: 100%;
height: 85%;
overflow-y: auto;
border-bottom: 1px solid rgb(200, 200, 200);
&::-webkit-scrollbar {
width: 7px;
}
&::-webkit-scrollbar-thumb {
background-color: rgb(200, 200, 200);
}
&__column {
font-size: 15px;
width: 100%;
font-family: "Montserrat", sans-serif;
padding: 5px 30px 5px 5px;
border-bottom: 1px solid rgb(200, 200, 200);
&__wrapper {
display: flex;
justify-content: space-between;
align-items: center;
width: 90%;
}
}
&__item {
padding: 0 30px 0 5px;
// border-bottom: 1px solid rgb(200, 200, 200);
font-size: 15px;
font-family: "Montserrat", sans-serif;
height: 20%;
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
&:hover {
background-color: rgba(230, 230, 230, 0.6);
}
&__wrapper {
display: flex;
justify-content: space-between;
align-items: center;
width: 90%;
height: 100%;
&__title {
cursor: pointer;
&:hover {
text-decoration: underline;
}
}
&__token {
}
}
&__btn {
width: 10%;
display: flex;
justify-content: space-around;
align-items: center;
padding: 0 5px;
font-size: 13px;
i {
display: block;
cursor: pointer;
}
i:first-child:hover {
color: rgb(42, 64, 187);
}
i:last-child:hover {
color: rgb(199, 73, 73);
}
}
}
}
}
}
.myModal {
&__item {
padding: 5px;
border-bottom: 1px solid rgb(200, 200, 200);
font-size: 15px;
font-family: "Montserrat", sans-serif;
cursor: pointer;
&__question {
&__text {
font-size: 15px;
font-family: "Montserrat", sans-serif;
}
&__comment {
font-size: 11px;
font-family: "Montserrat", sans-serif;
font-style: italic;
color: rgb(200, 200, 200);
}
}
&__answer {
&__text {
font-size: 15px;
font-family: "Montserrat", sans-serif;
}
}
}
}

View File

@ -33,10 +33,11 @@ async function addFormBlockApi(token, formId, data) {
} }
}; };
async function updateBlockApi(token, formId, data) { async function updateBlockApi(token, formId, data, order) {
try { try {
const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/set`, const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/set`,
{ {
order: order,
data: data data: data
}, },
{ {
@ -51,6 +52,25 @@ async function updateBlockApi(token, formId, data) {
} }
}; };
async function removeBlockApi(token, formId, order) {
try {
const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/set`,
{
order: order,
delete_flag: true
},
{
headers: {
"Authorization": `Token ${token}`,
}
})
return response
}
catch (e) {
return e
}
};
async function updateOrderBlockApi(token, formId, data) { async function updateOrderBlockApi(token, formId, data) {
try { try {
const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/moveTo`, const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/moveTo`,
@ -133,4 +153,4 @@ async function getAnswersApi(token, formToken) {
} }
}; };
export { addFormBlockApi, listFormBlockApi, saveFormApi, updateBlockApi, updateOrderBlockApi, listFormBlockByTokenApi, saveAnswersApi, getAnswersApi } export { addFormBlockApi, listFormBlockApi, saveFormApi, updateBlockApi, updateOrderBlockApi, listFormBlockByTokenApi, saveAnswersApi, getAnswersApi, removeBlockApi }

View File

@ -95,4 +95,22 @@ async function listFormsByTokenApi(token, formId) {
} }
}; };
export { listFormsApi, createFormApi, removeFormApi, updateTitleFormApi, newFormTokenApi, listFormsByTokenApi }; async function removeTokenFormApi(token, formId, formToken) {
try {
const response = await axios.post(`https://api.minerva.krbl.ru/formBuilder/edit/${formId}/access/revoke`,
{
"token_id": formToken
},
{
headers: {
"Authorization": `Token ${token}`
}
})
return response
}
catch (e) {
return e
}
}
export { listFormsApi, createFormApi, removeFormApi, updateTitleFormApi, newFormTokenApi, listFormsByTokenApi, removeTokenFormApi };

View File

@ -119,6 +119,7 @@ const Forms = () => {
<ul class="dropdown-menu" aria-labelledby="action"> <ul class="dropdown-menu" aria-labelledby="action">
<li><a class="dropdown-item" onClick={() => openFormView(item.id)}>Открыть</a></li> <li><a class="dropdown-item" onClick={() => openFormView(item.id)}>Открыть</a></li>
<li><a class="dropdown-item" onClick={() => navigate(`/forms/${item.id}/answers`)}>Ответы</a></li> <li><a class="dropdown-item" onClick={() => navigate(`/forms/${item.id}/answers`)}>Ответы</a></li>
<li><a class="dropdown-item" onClick={() => navigate(`/tokens/${item.id}`)}>Список токенов</a></li>
<li><a class="dropdown-item" onClick={() => copyLinkToFormView(item.id)}>Скопировать ссылку</a></li> <li><a class="dropdown-item" onClick={() => copyLinkToFormView(item.id)}>Скопировать ссылку</a></li>
<li><a class="dropdown-item" data-bs-toggle="modal" data-bs-target="#checkModal" onClick={() => setCurrentRemoveForm({id: item.id, title: item.title})}>Удалить</a></li> <li><a class="dropdown-item" data-bs-toggle="modal" data-bs-target="#checkModal" onClick={() => setCurrentRemoveForm({id: item.id, title: item.title})}>Удалить</a></li>
</ul> </ul>

View File

@ -7,7 +7,7 @@ import AnswerModal from "../components/AnswerModal.jsx";
import PreviewModal from "../components/PreviewModal.jsx" import PreviewModal from "../components/PreviewModal.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 { saveFormApi, addFormBlockApi, listFormBlockApi, updateBlockApi, updateOrderBlockApi } from "../hooks/api/formApi.js"; import { saveFormApi, addFormBlockApi, listFormBlockApi, updateBlockApi, updateOrderBlockApi, removeBlockApi } from "../hooks/api/formApi.js";
import { responseDataToListBlock } from "../hooks/sundry/parseListBlock.js"; import { responseDataToListBlock } from "../hooks/sundry/parseListBlock.js";
import MyInput from "../components/MyInput.jsx"; import MyInput from "../components/MyInput.jsx";
@ -89,7 +89,7 @@ const NewForm = () => {
setCurrentOptionAnswer(""); setCurrentOptionAnswer("");
}; };
function editAnswerByForm(id) { function editAnswerByForm(id, order) {
const obj = listBlock.find(item => item.id === id); const obj = listBlock.find(item => item.id === id);
setQuestion(obj.question); setQuestion(obj.question);
setComment(obj.comment); setComment(obj.comment);
@ -112,7 +112,12 @@ const NewForm = () => {
typeAnswer: currentTypeAnswer, typeAnswer: currentTypeAnswer,
} }
const response = await updateBlockApi(cookies.token, formId, data); const response = await updateBlockApi(
cookies.token,
formId,
data,
listBlock.find(item => item.id === stateModal).order
);
console.log(response) console.log(response)
if (response.status === 200) { if (response.status === 200) {
@ -130,6 +135,17 @@ const NewForm = () => {
cleanStates(); cleanStates();
}; };
async function removeBlock(order) {
const response = await removeBlockApi(cookies.token, formId, order)
if (response.status === 200) {
setListBlock([...listBlock.filter(item => item.order !== order)]);
}
else {
console.log(response)
}
}
async function addFormBlock() { async function addFormBlock() {
const newBlock = { const newBlock = {
question: question, question: question,
@ -304,7 +320,7 @@ const NewForm = () => {
</div> </div>
<div className={classes.content__newForm__list__item__btn}> <div className={classes.content__newForm__list__item__btn}>
<i class="fa-solid fa-pen" data-bs-toggle="modal" data-bs-target="#answerModal" onClick={() => {editAnswerByForm(item.id)}}></i> <i class="fa-solid fa-pen" data-bs-toggle="modal" data-bs-target="#answerModal" onClick={() => {editAnswerByForm(item.id)}}></i>
<i class="fa-solid fa-trash" onClick={() => removeAnswerByForm(item.id)}></i> <i class="fa-solid fa-trash" onClick={() => removeBlock(item.order)}></i>
</div> </div>
</div> </div>
)} )}

124
src/pages/TokensForm.jsx Normal file
View File

@ -0,0 +1,124 @@
import React, { useState, useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { useCookies } from "react-cookie";
import classes from "../assets/styles/tokensForm.module.scss";
import { listFormsByTokenApi, newFormTokenApi, removeTokenFormApi } from "../hooks/api/listFormsApi";
import MyButton from "../components/MyButton.jsx";
import MyInput from "../components/MyInput.jsx";
import CheckModal from "../components/CheckModal.jsx";
const TokensForm = () => {
const { formId } = useParams();
const [tokens, setTokens] = useState([])
const [loading, setLoading] = useState(true)
const [titleToken, setTitleToken] = useState('')
const [cookies, _, __] = useCookies(["user"]);
useEffect(() => {
async function listFormsByToken() {
const response = await listFormsByTokenApi(cookies.token, formId)
if (response.data.tokens) {
setTokens(response.data.tokens.filter(item => item.is_active === true))
setLoading(false)
}
else {
console.log(response)
}
}
listFormsByToken()
}, [])
async function newFormToken() {
const response = await newFormTokenApi(cookies.token, formId)
if (response.status === 200) {
setTokens([...tokens, response.data.token])
}
else {
console.log(response)
}
}
async function removeTokenForm(tokenForm) {
const response = await removeTokenFormApi(cookies.token, formId, tokenForm)
if (response.status === 200) {
setTokens(tokens.filter(item => item.id !== tokenForm))
}
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={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 ?
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}>
По умолчанию
</div>
<div className={classes.answers__wrapper__body__item__wrapper__token}>
{item.form_id}
</div>
</div>
<div className={classes.answers__wrapper__body__item__btn}>
<i
class="fa-solid fa-pen"
data-bs-toggle="modal"
data-bs-target={`#tokensModal${i}`}
onClick={() => setTitleToken("По умолчанию")}>
</i>
<i class="fa-solid fa-trash" onClick={() => removeTokenForm(item.id)}></i>
</div>
<div class="modal fade myModal" className={classes.myModal} id={`tokensModal${i}`} tabIndex="-1" aria-labelledby="exampleModalLabel" data-bs-backdrop="static" aria-hidden="true">
<div class="modal-dialog myModal__dialog" className={classes.myModal__dialog}>
<div class="modal-content" className={classes.myModal__dialog__content}>
<div class="modal-body" className={classes.myModal__dialog__content__body}>
<MyInput type={"text"} value={titleToken} change={setTitleToken}/>
</div>
<div class="modal-footer myModal__dialog__content__footer" className={classes.myModal__dialog__content__footer}>
<MyButton text={"Сохранить"} class={"main__green"} dismiss={"modal"}/>
<MyButton text={"Отмена"} class={"main__white"} dismiss={"modal"}/>
</div>
</div>
</div>
</div>
</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>
</div>
</div>
</div>
</div>
)
}
export default TokensForm;

View File

@ -9,6 +9,7 @@ import Profile from "../pages/Profile.jsx";
import ViewForm from "../pages/ViewForm.jsx"; import ViewForm from "../pages/ViewForm.jsx";
import AdminPanel from '../pages/AdminPanel.jsx'; import AdminPanel from '../pages/AdminPanel.jsx';
import AnswersForm from '../pages/AnswersForm.jsx'; import AnswersForm from '../pages/AnswersForm.jsx';
import TokensForm from '../pages/TokensForm.jsx';
const router = createBrowserRouter([ const router = createBrowserRouter([
{ {
@ -45,6 +46,10 @@ const router = createBrowserRouter([
{ {
path: "/forms/:formId/answers", path: "/forms/:formId/answers",
element: <AnswersForm/> element: <AnswersForm/>
},
{
path: "/tokens/:formId",
element: <TokensForm/>
} }
] ]
} }