diff --git a/next.config.mjs b/next.config.mjs index 950d26acffb7e086f72c1635aebcd093ea30f05b..7fe6a5fa6fffdcfa49fe673b76216ad5f96b3af3 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -30,7 +30,7 @@ const nextConfig = { remotePatterns: [ { protocol: 'https', - hostname: 'api.mecred.c3sl.ufpr.br', + hostname: 's3.c3sl.ufpr.br', port: '', pathname: '/**', }, diff --git a/src/app/components/InfiniteScroll.js b/src/app/components/InfiniteScroll.js index edee4e2afd3deeea8bc1d8842a10787fb7b94f32..0a29c19f50dd31274ce4b3a8f636432f59f3ff3f 100644 --- a/src/app/components/InfiniteScroll.js +++ b/src/app/components/InfiniteScroll.js @@ -2,7 +2,6 @@ import React, { useState, useEffect, useCallback } from "react"; import InfiniteScrollCards from "./InfiniteScrollCards";'' import mecredApi from "@/axiosConfig"; import Loading from "./Loading"; -import { useSearchParams, useRouter } from "next/navigation"; const getUrlFromFilterState = (filterState, page) => { const apiParams = new URLSearchParams(); @@ -33,7 +32,6 @@ export default function InfiniteScroll({ filterState, setNewSize, newSize, setIt const [isLoading, setIsLoading] = useState(false); const [page, setPage] = useState(0); const [isScroll, setIsScroll] = useState(false) - const router = useRouter(); // começa com 1 pq quando carrega a página a primeira vez, caso zero, a mensagem aparece por alguns segundos const [totalCount, setTotalCount] = useState(1) diff --git a/src/app/components/publisherInfo.js b/src/app/components/publisherInfo.js index de10b6f58984ad541377d2ce6470ca62e2404ea8..b86a45be1af7e739c2e84ab040b7b2be65dfde9a 100644 --- a/src/app/components/publisherInfo.js +++ b/src/app/components/publisherInfo.js @@ -1,7 +1,7 @@ import { Avatar, Button, Paper } from "@mui/material"; import { useLoginBarrier } from "@/app/handlers/loginHandler"; import { useState, useEffect } from "react"; -import mecredApi, { mecredURL } from "@/axiosConfig"; +import mecredApi, { s3URL } from "@/axiosConfig"; import { getStoredValue } from "@/app/handlers/localStorageHandler"; export default function PublisherInfo({ publisher, disabledButton = false }) { @@ -9,8 +9,7 @@ export default function PublisherInfo({ publisher, disabledButton = false }) { const loginBarrier = useLoginBarrier(); const token = getStoredValue("access_token") - const client = getStoredValue("client") - const uid = getStoredValue("uid") + useEffect(() => { setFollowed(publisher?.followed ?? false); @@ -22,16 +21,12 @@ export default function PublisherInfo({ publisher, disabledButton = false }) { const followHandler = () => { loginBarrier(); + //passa quem eu vou seguir mecredApi.put( - `users/${publisher.id}/follow/`, - {}, + `api/user/follow/${publisher.id}`, { headers: { - "access-token": token, - "token-type": "Bearer", - client: client, - uid: uid, - Expires: 0, + Authorization:`bearer ${token}` }, } ); @@ -63,10 +58,10 @@ export default function PublisherInfo({ publisher, disabledButton = false }) { <Paper className="bg-white-HC-dark outline outline-1 outline-ice-HC-white shadow-none flex flex-shrink-0 rounded-xl p-1 m-1 normal-case text-sm font-bold max-sm:flex-col"> <Button href={`/perfil/${publisher.id}`} > <div className="flex flex-row truncate"> - {publisher?.avatar ? ( + {publisher ? ( <Avatar fill="true" - src={mecredURL + publisher.avatar} + src={s3URL + 'avatar/' + publisher.id} alt="Publisher Avatar" title={publisher.name} className="m-4" diff --git a/src/app/handlers/loginHandler.js b/src/app/handlers/loginHandler.js index 09ebd87999e6eb27093b5bbca4aa2d24f0b7b4d8..7cb30394e532b70fd479a0e36679f3f88cc079e0 100644 --- a/src/app/handlers/loginHandler.js +++ b/src/app/handlers/loginHandler.js @@ -16,7 +16,7 @@ export function useLoginBarrier() { const router = useRouter(); return useCallback(() => { - if (isLoggedIn()) return true; + if (!localStorage.getItem('token')) return true; const params = new URLSearchParams(); params.set("redirect", pathname); diff --git a/src/app/publicar/components/Form.js b/src/app/publicar/components/Form.js index ea6143284e89275b1af841dc1a5468910ce4a7b3..58a869e8cd707329f5e5c3942ed8f792da0fbd95 100644 --- a/src/app/publicar/components/Form.js +++ b/src/app/publicar/components/Form.js @@ -3,63 +3,28 @@ import { useEffect, useState } from "react"; import UploadForm from "./UploadForm"; import InfoForm from "./InfoForm"; import RevisionForm from "./RevisionForm" -import mecredApi from "@/axiosConfig"; -import { getStoredValue } from "@/app/handlers/localStorageHandler"; import AdvanceNotice from "./AdvanceNotice"; export default function Form() { const [step, setStep] = useState(0); const [draft, setDraft] = useState(null); + const [userData, setUserData] = useState(null); const [authorType, setAuthorType] = useState("a"); const [file, setFile] = useState(null); - const [attachmentId, setAttachmentId] = useState(null); - const [userData, setUserData] = useState(null); const [thumbURL, setThumbURL] = useState(null); const [thumb, setThumb] = useState(null); - - const token = getStoredValue("access_token"); - const client = getStoredValue("client"); - const uid = getStoredValue("uid"); - const payload = {} - useEffect(() => { - const fetchData = async () => { - try { - setUserData(JSON.parse(getStoredValue("user_data"))); - - if (draft && draft.id) { - return; - } - - const response = await mecredApi.post(`/learning_objects/`, payload, { - headers: { - "access-token": token, - "token-type": "Bearer", - client: client, - uid: uid, - Expires: 0, - }, - }); - - setDraft(response.data); - } catch (error) { - // Tratar erros, se necessário - console.error('Erro ao enviar dados:', error); - } - }; - - fetchData(); - }, [client, token, uid, draft]); - + setUserData(userData()); + }, []) - return ( + return ( userData && <> <div className="flex flex-col justify-start w-full mt-15 max-sm:mx-0 max-md:mb-16 overflow-auto scrollbar-none"> - <HorizontalLinearAlternativeLabelStepper step={step} /> - {step === 0 && userData && <InfoForm userData={userData} setStep={setStep} draft={draft} setDraft={setDraft} authorType={authorType} setAuthorType={setAuthorType} />} - {step === 1 && <UploadForm thumbURL={thumbURL} setThumbURL={setThumbURL} thumb={thumb} setThumb={setThumb} setStep={setStep} draft={draft} setDraft={setDraft} file={file} setFile={setFile} attachmentId={attachmentId} setAttachmentId={setAttachmentId} />} - {step === 2 && <RevisionForm setStep={setStep} draft={draft} setDraft={setDraft} />} + <HorizontalLinearAlternativeLabelStepper step={step} /> + {step === 0 && <InfoForm setStep={setStep} draft={draft} setDraft={setDraft} userData={userData} authorType={authorType} setAuthorType={setAuthorType} />} + {step === 1 && <UploadForm thumbURL={thumbURL} setThumbURL={setThumbURL} thumb={thumb} setThumb={setThumb} setStep={setStep} draft={draft} setDraft={setDraft} file={file} setFile={setFile} />} + {step === 2 && <RevisionForm setStep={setStep} draft={draft} userData={userData} setDraft={setDraft} />} <AdvanceNotice /> </div> </> diff --git a/src/app/publicar/components/InfoForm.js b/src/app/publicar/components/InfoForm.js index fb4978464cbc5af4dc2a61d95a7968ae202d22c3..af788df5c9c4f1850331342c4d5ca19212ac27e6 100644 --- a/src/app/publicar/components/InfoForm.js +++ b/src/app/publicar/components/InfoForm.js @@ -5,48 +5,53 @@ import FormControlLabel from "@mui/material/FormControlLabel"; import SubjectSelection from "./SubjectSelection"; import ObjectTypeSelection from "./ObjectTypeSelection"; import LicenseSelection from "./LicenseSelection"; -import TagInput from "./TagsInput"; +//import TagInput from "./TagsInput"; import AuthorSelection from "./AuthorSelection"; import mecredApi from "@/axiosConfig"; import ModalIncompleteField from "./ModalIncompleteField"; import CancelSubmitModal from "./CancelSubmitModal"; import CustomTextField from "./CustomTextField"; -import CustomCheckbox from "./CustomCheckbox"; - +import { authHeaders } from "@/app/handlers/loginHandler"; +//o codigo de tags esta comentado, pq pode ser que no futuro seja usado export default function InfoForm({ userData, setStep, draft, setDraft, authorType, setAuthorType }) { const [languagesAvailable, setLanguagesAvailable] = useState([]); const [scholarityLevelsAvailable, setScholarityLevelAvailable] = useState([]); const [openModal, setOpenModal] = useState(false); const [filled, setFilled] = useState(false); - const [title, setTitle] = useState(draft?.name ?? ""); const [description, setDescription] = useState(draft?.description ?? ""); - const [tags, setTags] = useState(draft?.tags ?? []); + // const [tags, setTags] = useState(draft?.tags ?? []); + // const [tagInput, setTagInput] = useState(""); const [author, setAuthor] = useState(draft?.author ?? userData.name); - const [tagInput, setTagInput] = useState(""); - const [languages, setLanguages] = useState(draft?.language ?? []); - const [objectTypes, setObjectTypes] = useState(draft?.object_type_f ?? []); - const [scholarityLevelsName, setScholarityLevelsName] = useState(draft?.educational_stages_name ?? []); + const [objectTypes, setObjectTypes] = useState([draft?.object_type_id] ?? []); const [subjects, setSubjects] = useState(draft?.subjects ?? []); const [licenseValue, setLicenseValue] = useState(draft?.license_id ?? ""); - - const [languageIds, setLanguageIds] = useState(draft?.language_ids ?? []); + const [languageIds, setLanguageIds] = useState(draft?.language ?? []); const [scholarityLevelsId, setScholarityLevelsId] = useState(draft?.educational_stages ?? []); - const [openModalCancel, setOpenModalCancel] = useState(false); - - useEffect(() => { - mecredApi.get("/languages") - .then((response) => { setLanguagesAvailable(response.data) }); - }, []); - useEffect(() => { - mecredApi.get("/educational_stages") - .then((response) => { setScholarityLevelAvailable(response.data) }); + const fetchData = async () => { + try { + // faz as duas requisiçoes ao mesmo tempo + //fica mais rapido + const [educationalStageRes, languageRes] = await Promise.all([ + mecredApi.get("public/educationalStage/all"), + mecredApi.get("public/language/all"), + ]); + + setScholarityLevelAvailable(educationalStageRes.data); + setLanguagesAvailable(languageRes.data); + } catch (error) { + console.error("Erro ao buscar dados:", error); + } + }; + + fetchData(); }, []); + const handleTitleChange = (e) => setTitle(e.target.value); const handleDescriptionChange = (e) => setDescription(e.target.value); @@ -59,83 +64,78 @@ export default function InfoForm({ userData, setStep, draft, setDraft, authorTyp const handleAuthorChange = (e) => setAuthor(e.target.value); const handleLicenseValueChange = (e) => setLicenseValue(e.target.value); - const handleKeyDown = (e) => { - // Verifica se a tecla pressionada foi "Enter" - if (e.key === "Enter") { - addTagFromInput(); - } - }; - - const handleTagInput = (e) => { - const value = e.target.value; - - // Verifica se o valor contém uma vírgula - if (value.includes(",")) { - addTagFromInput(value); - } else { - setTagInput(value); - } - }; - - const addTagFromInput = (value = tagInput) => { - // Remove a vírgula, se houver, e os espaços - const trimmedValue = value.replace(",", "").trim(); - - // Adiciona a tag se não estiver vazia e não for duplicada - if (trimmedValue !== "" && !tags.includes(trimmedValue)) { - setTags((prevTags) => [...prevTags, trimmedValue]); - } - - // Limpa o campo de entrada - setTagInput(""); - }; - + // const handleKeyDown = (e) => { + // // Verifica se a tecla pressionada foi "Enter" + // if (e.key === "Enter") { + // addTagFromInput(); + // } + // }; - const handleTagDelete = (tag) => { - setTags(tags.filter((t) => t !== tag)); - }; + // const handleTagInput = (e) => { + // const value = e.target.value; + + // // Verifica se o valor contém uma vírgula + // if (value.includes(",")) { + // addTagFromInput(value); + // } else { + // setTagInput(value); + // } + // }; + + // const addTagFromInput = (value = tagInput) => { + // // Remove a vírgula, se houver, e os espaços + // const trimmedValue = value.replace(",", "").trim(); + + // // Adiciona a tag se não estiver vazia e não for duplicada + // if (trimmedValue !== "" && !tags.includes(trimmedValue)) { + // setTags((prevTags) => [...prevTags, trimmedValue]); + // } + + // // Limpa o campo de entrada + // setTagInput(""); + // }; + + //talvez por um parse, pq tem coisa vindo a mais + + // const handleTagDelete = (tag) => { + // setTags(tags.filter((t) => t !== tag)); + // }; const handleLanguagesChange = (e) => { - const lang = JSON.parse(e.target.value); - if (languages.includes(lang.name)) { - setLanguages(l => l.filter((language) => language !== lang.name)); - setLanguageIds(l => l.filter((language) => language !== lang.id)); - } - else { - setLanguages([...languages, lang.name]) - setLanguageIds([...languageIds, lang.id]) - }; + const id = Number(e.target.value); + + setLanguageIds((prev) => e.target.checked ? + [...prev, id] + : prev.filter((languageId) => languageId !== id)); + }; - const handleObjectsTypeChange = (subject) => { - if (objectTypes.includes(subject)) - setObjectTypes(objectTypes.filter((object) => object.id !== subject.id)); - else setObjectTypes([subject]); + const handleObjectsTypeChange = (objectT) => { + if (objectTypes.includes(objectT)) + setObjectTypes(objectTypes.filter((object) => object.id !== objectT.id)); + else setObjectTypes([objectT]); }; const handleScholarityChange = (e) => { - const sl = JSON.parse(e.target.value); - if (scholarityLevelsName.includes(sl.name)) { - setScholarityLevelsName(s => s.filter((educational_stages) => educational_stages !== sl.name)); - setScholarityLevelsId(scholarityLevelsId.filter((educational_stages) => educational_stages !== (JSON.stringify(sl.id)))); - } - else { - setScholarityLevelsName([...scholarityLevelsName, sl.name]); - setScholarityLevelsId([...scholarityLevelsId, (JSON.stringify(sl.id))]); - } + const id = Number(e.target.value); + setScholarityLevelsId((prev) => + e.target.checked + ? [...prev, id] + : prev.filter((scholarityId) => scholarityId !== id) + ); }; const handleSubjectsChange = (subject) => { if (subjects.includes(subject)) - setSubjects(subjects.filter((subj) => subj.id !== subject.id)); + setSubjects(subjects.filter((subj) => subj !== subject)); else { setSubjects([...subjects, subject]) }; }; const handleIncompleteField = () => { - if (!title || !description || !tags.length || !scholarityLevelsId.length || !objectTypes.length - || !languages.length || !subjects.length || !licenseValue) { + if (!title || !description || !scholarityLevelsId.length || !objectTypes.length + || !languageIds.length || !subjects.length || !licenseValue) { setFilled(true) return true } @@ -143,40 +143,63 @@ export default function InfoForm({ userData, setStep, draft, setDraft, authorTyp } + //só faz quando vai para a proxima etapa + //para nao gerar muitos drafts vazios + const handleSubmit = async (e) => { + e.preventDefault(); + + if (handleIncompleteField()) { + setOpenModal(true); + return; + } + + const newDraft = { + ...(draft ?? {}), + name: title, + description: description, + // tags: tags, + object_type_id: objectTypes[0], + language: languageIds, + educational_stages: scholarityLevelsId, + subjects: subjects, + license_id: Number(licenseValue), + author: author, + }; - const handleSubmit = (e) => { + //em author colocar o pessoa logada, quando gustavo fazser + + setDraft(newDraft); + + console.log("newDraft:", newDraft) - if (handleIncompleteField()) { - e.preventDefault() - setOpenModal(true) - - } else { - - setDraft((curr) => ({ - ...curr, - name: title, - description: description, - tags: tags, - author: author, - object_type_f: objectTypes, - language_ids: languageIds, - language: languages, - educational_stages: scholarityLevelsId, - educational_stages_name: scholarityLevelsName, - subjects: subjects, - license_id: licenseValue, - })); + try { + if (draft?.id) { + + // Atualiza o rascunho existente + await mecredApi + .post(`api/resource/update`, newDraft, {headers: authHeaders()}); + } else { + // Cria um novo rascunho + const response = await mecredApi.post("api/resource/create", newDraft, {headers: authHeaders()}); + const createdDraft = response.data; + setDraft(createdDraft); // atualiza com o draft com ID gerado + } + + console.log("Draft salvo com sucesso PAGINA 1:", newDraft); setStep((curr) => curr + 1); + } catch (error) { + console.error("Erro ao salvar o draft PAGINA 2:", error); } + }; + - } return ( <> <form className="mb-10" onSubmit={handleSubmit} onKeyDown={(e) => { if (e.key === "Enter") e.preventDefault() }} > - <Paper - className="rounded-lg p-10 max-xl:p-5 max-xl:mx-5 " + <Paper + className="rounded-lg p-10 max-xl:p-5 max-xl:mx-5 " elevation={1} sx={{ backgroundColor: 'var(--white-HC-dark)', @@ -187,10 +210,11 @@ export default function InfoForm({ userData, setStep, draft, setDraft, authorTyp <h1 className="text-darkGray-HC-white font-light text-2xl text-center"> Os campos marcados com * são obrigatórios </h1> - <FieldLabel - name="Título do Recurso*" + <FieldLabel + name="Título do Recurso*" error={(!title && filled)} /> + <CustomTextField multiline fullWidth @@ -204,9 +228,9 @@ export default function InfoForm({ userData, setStep, draft, setDraft, authorTyp className="mb-5" sx={{ "& .MuiOutlinedInput-input::placeholder": { - color: "var(--darkGray-HC-white)", - opacity: 0.5, - }, + color: "var(--darkGray-HC-white)", + opacity: 0.5, + }, }} /> <FieldLabel name="Descrição geral do Recurso*" error={(!description && filled)} /> @@ -223,7 +247,8 @@ export default function InfoForm({ userData, setStep, draft, setDraft, authorTyp error={(description.length > 1500) || (!description && filled)} className="mb-5" /> - <FieldLabel + + {/* <FieldLabel name="Palavras-chave Relacionadas ao Conteúdo do seu Recurso*" description="(Use Enter ou vírgula para confirmar a palavra-chave)" error={(!tags.length && filled)} @@ -240,7 +265,8 @@ export default function InfoForm({ userData, setStep, draft, setDraft, authorTyp </div>} className="mb-5" /> - <TagInput tags={tags} handleTagDelete={handleTagDelete} /> + <TagInput tags={tags} handleTagDelete={handleTagDelete} /> */} + <AuthorSelection selectedValue={authorType} handleRadioChange={handleRadioChange} @@ -252,30 +278,40 @@ export default function InfoForm({ userData, setStep, draft, setDraft, authorTyp selected={objectTypes} handleSelection={handleObjectsTypeChange} /> - <FieldLabel name="Idiomas do Recurso*" error={!languages.length && filled} /> + <FieldLabel name="Idiomas do Recurso*" error={!languageIds.length && filled} /> <FormGroup className="flex flex-wrap mb-10" row> - {languagesAvailable?.map((language, index) => ( + {languagesAvailable.map((language) => ( <FormControlLabel - onChange={handleLanguagesChange} - key={index} - control={<CustomCheckbox checked={languages.includes(language.name)} />} - value={JSON.stringify(language)} + key={language.id} + control={ + <Checkbox + checked={languageIds.includes(language.id)} + onChange={handleLanguagesChange} + value={language.id} + /> + } label={<span className="text-darkGray-HC-white">{language.name}</span>} /> ))} </FormGroup> + <FieldLabel name="Nível de ensino" description="(Selecione uma ou mais opções)*" error={!scholarityLevelsId.length && filled} /> + <FormGroup className="flex flex-wrap mt-5 mb-10"> - {scholarityLevelsAvailable.map((sl, index) => ( + {scholarityLevelsAvailable.map((sl) => ( <FormControlLabel - onChange={handleScholarityChange} - key={index} - control={<CustomCheckbox checked={scholarityLevelsName.includes(sl.name)} />} - value={JSON.stringify(sl)} + key={sl.id} + control={ + <Checkbox + checked={scholarityLevelsId.includes(sl.id)} + onChange={handleScholarityChange} + value={sl.id} + /> + } label={<span className="text-darkGray-HC-white">{sl.name}</span>} /> ))} diff --git a/src/app/publicar/components/ObjectTypeSelection.js b/src/app/publicar/components/ObjectTypeSelection.js index 5b149e353d43d4254861eac6d8358cd54881c0d6..e77a34cb9ddcab1e9d4f3c16bed32a4a5ee11738 100644 --- a/src/app/publicar/components/ObjectTypeSelection.js +++ b/src/app/publicar/components/ObjectTypeSelection.js @@ -8,7 +8,6 @@ export default function ObjectTypeSelection({ selected, handleSelection, error } <FieldLabel name="Tipo de Recurso*" error={error} /> <div className="flex flex-wrap justify-center"> {objectTypes.map((subject, index) => { - return ( <SelectOption key={index} diff --git a/src/app/publicar/components/RevisionForm.js b/src/app/publicar/components/RevisionForm.js index b52ebb8616fcdb808b40f4a3b5043c4a53a81893..9d6b5f23d4c7c5d739ed5fc61ff99f30941acd2a 100644 --- a/src/app/publicar/components/RevisionForm.js +++ b/src/app/publicar/components/RevisionForm.js @@ -1,7 +1,6 @@ "use client" import mecredApi from "@/axiosConfig" import { Button, Paper } from "@mui/material" -import { getStoredValue } from "@/app/handlers/localStorageHandler"; import { useEffect, useState } from "react"; import Tags from "@/app/components/tags"; import PublisherInfo from "@/app/components/publisherInfo"; @@ -10,113 +9,66 @@ import ResourcePreview from "@/app/recurso/[id]/components/resourcePreview"; import ModalSuccess from "./ModalSuccess"; import { useRouter } from "next/navigation"; import CancelSubmitModal from "./CancelSubmitModal"; +import { authHeaders } from "@/app/handlers/loginHandler"; -function headerConfig() { - return { - headers: { - "access-token": getStoredValue("access_token"), - "token-type": "Bearer", - client: getStoredValue("client"), - uid: getStoredValue("uid"), - Expires: 0, - } - }; -} -export default function RevisionForm({ setStep, draft, setDraft }) { +export default function RevisionForm({ userData, setStep, draft, setDraft }) { const [permission, setPermission] = useState(false) const [openModal, setOpenModal] = useState(false) + const [preview, setPreview] = useState(draft); + const [openModalCancel, setOpenModalCancel] = useState(false) - let userData = JSON.parse(getStoredValue("user_data")) const router = useRouter(); - /// Ira ser enviado ao backend - let data = { - attachmentID: draft.attachmentID, - file: draft.file, - name: draft.name, - description: draft.description, - tags: draft.tags.map(tag => { return { name: tag } }), - author: draft.author, - object_type_id: draft.object_type_f[0].id, - language_ids: draft.language_ids, - language_names: draft.language, - educational_stages: draft.educational_stages, - subjects: draft.subjects.map(subj => { return subj.id }), - license_id: draft.license_id, - link: draft.link, - } - - /// Irá ser enviado ao componente de visualizacao para preview - let preview = { - ...draft, - default_mime_type: draft.attachments[0]?.mime_type, - object_type: draft.object_type_f[0]?.name, - language: draft.language.map(lang => { return { name: lang } }), - tags: draft.tags.map(tag => { return { name: tag } }), - subjects: draft.subjects.map(subject => { return { name: subject.name } }), - educational_stages: draft.educational_stages_name.map(educa => { return { name: educa } }) - } - - useEffect(() => { - mecredApi.get("/learning_objects/" + draft.id, headerConfig()) - .then((response) => { - setDraft(curr => { - return { ...curr, attachments: response.data.attachments } - }) - }); - - }, [draft.id, setDraft]) - useEffect(() => { for (let i = 0; i < userData.roles.length; i++) { - if (userData.roles[i].name === "partner" || userData.roles[i].name === "admin") { + if (userData.roles[i] === "admin" || userData.roles[i] === "contributor") { setPermission(true) return } } - }, [userData.roles]) + const fetchPreview = async () => { + await mecredApi + .get(`public/resource/${draft.id}`) + .then((response) => setPreview(response.data)); + console.log("resposta", preview) + }; + fetchPreview(); + }, []) - const submitHomologation = () => { - mecredApi - .put(`/learning_objects/${draft.id}`, data, headerConfig()) - .then( - () => { - let payload = { - "submission": { - "learning_object_id": draft.id - } - } + const submitHomologation = () => { - return ( - mecredApi - .post("/submissions", payload, headerConfig()) - ) - } - ) + const previewData = { + ...draft, + state: 'submitted' + } + + mecredApi + .post('api/resource/update', previewData, { headers: authHeaders() }) .then( setOpenModal(true) ) } + //publica direto const fetchSubmit = () => { + const previewData = { + ...draft, + state: 'accepted' + } + mecredApi - .put(`/learning_objects/${draft.id}`, data, headerConfig()) - .then( - () => - mecredApi - .post(`/learning_objects/${draft.id}/publish`, {}, headerConfig()) - ) + .post('api/resource/update', previewData, { headers: authHeaders() }) .then( setOpenModal(true) ) @@ -129,21 +81,21 @@ export default function RevisionForm({ setStep, draft, setDraft }) { openModal={openModal} onClose={() => { setOpenModal(false); - router.push("/busca?page=LearningObject"); + router.push("/sobre"); }} - permission={permission} + permission={permission} idResource={draft.id} - /> + /> <form> - <Paper + <Paper className="rounded-lg p-10 max-xl:mx-5 mx-5" elevation={1} sx={{ backgroundColor: 'var(--white-HC-dark)', border: '2px solid var(--ice-HC-white)', }} - > + > <div className="flex flex-col text-center py-6"> <p className="text-2xl text-darkGray-HC-white pb-6"> Quase lá, agora só falta revisar e submeter! @@ -165,15 +117,17 @@ export default function RevisionForm({ setStep, draft, setDraft }) { </div> <div className="text-darkGray-HC-white mt-5 text-2xl font-bold"> {/* Título */} - <h1>{draft.name}</h1> + <h1>{preview.name}</h1> </div> + <div className="text-darkGray-HC-white mt-3 text-sm font-bold"> {/* tags */} - <Tags tags={preview.tags} /> + {/* <Tags tags={preview.tags} /> */} </div> + <div className=""> {/* Publicador */} - <PublisherInfo publisher={draft?.publisher} disabledButton={true} /> + {/* <PublisherInfo publisher={draft?.publisher} disabledButton={true} /> */} </div> <div className=""> {/* Informações */} diff --git a/src/app/publicar/components/SelectOption.js b/src/app/publicar/components/SelectOption.js index 0ed92d5baf0594b0f1eb9df31c9e831dd71cbd5d..f11182d80f153db59b2d14e6cd4a6a10559492f7 100644 --- a/src/app/publicar/components/SelectOption.js +++ b/src/app/publicar/components/SelectOption.js @@ -1,32 +1,24 @@ import Image from "next/image"; export default function SelectOption({ selected, handleSelection, subject }) { - return ( <div - onClick={() => handleSelection(subject)} + onClick={() => handleSelection(subject.id)} className={`group bg-ice-HC-dark hover:bg-lightGray-HC-white hover:cursor-pointer h-24 w-24 max-lg:h-20 max-lg:w-20 border-2 flex flex-col m-2 items-center p-2 text-center justify-center rounded-lg ${ - selected.includes(subject) && "border-2 border-turquoise-HC-white bg-lightGray-HC-white " + selected && Array.isArray(selected) && selected?.includes(subject.id) && "border-2 border-turquoise-HC-white bg-lightGray-HC-white " }`} > - {/* <Image - alt={subject.name} - height={0} - width={0} - className="w-12 h-12 max-lg:w-8 max-lg:h-8 fill-current text-pink" - src={subject.image} - /> */} <div alt={subject.name} className={`w-12 h-12 max-lg:w-8 max-lg:h-8 fill-current - ${selected.includes(subject) ? "text-turquoise-HC-dark" : "text-turquoise-HC-white group-hover:text-turquoise-HC-dark"} + ${selected && Array.isArray(selected) && selected?.includes(subject.id) ? "text-turquoise-HC-dark" : "text-turquoise-HC-white group-hover:text-turquoise-HC-dark"} `} dangerouslySetInnerHTML={{ __html: subject.image }} ></div> <span className={`text-xs max-lg:text-xs - ${selected.includes(subject) ? "text-turquoise-HC-dark-underline" : "text-turquoise-HC-white-underline group-hover:text-turquoise-HC-dark-underline"} + ${selected && Array.isArray(selected) && selected?.includes(subject) ? "text-turquoise-HC-dark-underline" : "text-turquoise-HC-white-underline group-hover:text-turquoise-HC-dark-underline"} `}>{subject.name}</span> </div> ); diff --git a/src/app/publicar/components/SubmitThumbnail.js b/src/app/publicar/components/SubmitThumbnail.js index 91368145e0e08474bb3cf89fb07cc0f457b9023e..1f7ff7fa854bbf7b1c155e808fb4c5669f78da86 100644 --- a/src/app/publicar/components/SubmitThumbnail.js +++ b/src/app/publicar/components/SubmitThumbnail.js @@ -14,22 +14,24 @@ export default function SubmitThumbnail({ error, setThumb, thumbURL, setThumbURL const handleThumbnail = (e) => { - if (!imageType(e.target.files[0]?.type)) { - e.target.files = null - setOpenType(true) - return + const file = e.target.files[0]; + + if (!imageType(file?.type)) { + e.target.value = ""; + setOpenType(true); + return; } - - if (e.target.files[0].size > 4e6) { - e.target.files = null - setOpen(true) - return + + if (file.size > 4 * 1024 * 1024) { + e.target.value = ""; + setOpen(true); + return; } - - e.preventDefault() - setThumb(e.target.files[0]); - setThumbURL(URL.createObjectURL(e.target.files[0])); - }; + + e.preventDefault(); + setThumb(file); + setThumbURL(URL.createObjectURL(file)); + }; return ( diff --git a/src/app/publicar/components/UploadFile.js b/src/app/publicar/components/UploadFile.js index a87f91db5364346fe346edd39f7eccbcff86c20f..b8e88c70e0836c858742f0a2d932ac97063c614c 100644 --- a/src/app/publicar/components/UploadFile.js +++ b/src/app/publicar/components/UploadFile.js @@ -1,75 +1,43 @@ "use client"; -import { Button, LinearProgress } from "@mui/material"; +import { Button } from "@mui/material"; import mecredApi from "@/axiosConfig"; -import { getStoredValue } from "@/app/handlers/localStorageHandler"; import FileUploadIcon from '@mui/icons-material/FileUpload'; import { useState } from "react"; import { imageType, videoType, textType, audioType } from "@/app/components/FileTypeUtilities"; import ErrorType from "./ErrorType"; import ErrorSize from "./ErrorSize"; +import { authHeaders } from "@/app/handlers/loginHandler"; -//const chunkSize = 262144; -const chunkSize = 1024 * 1024; - -function headerConfig() { - return { - headers: { - "access-token": getStoredValue("access_token"), - "token-type": "Bearer", - client: getStoredValue("client"), - uid: getStoredValue("uid"), - Expires: 0, - } - }; -} -export default function UploadFile({ setUploading, setProgress, draft, file, setFile, attachmentId, setAttachmentId }) { +export default function UploadFile({ setUploading, uploading, setProgress, draft, file, setFile }) { const [open, setOpen] = useState(false); const [openType, setOpenType] = useState(false); const fileUpload = async (file) => { setUploading("sending"); - let numChunksToSend = Math.ceil(file.size / chunkSize); - let start = 0; - let response = null; - - for (let i = 0; i < numChunksToSend; i++) { - let fileSlice = file.slice(start, Math.min(start + chunkSize, file.size)); - - let formData = new FormData(); - formData.append('_chunkFilename', file.name); - formData.append('_chunkIdentifier', draft.id + '-' + file.name); - formData.append('_totalChunks', numChunksToSend); - formData.append('_chunkSize', chunkSize); - formData.append('_currentChunkSize', fileSlice.size); - formData.append('_chunkNumber', i); - formData.append('_totalSize', file.size); - formData.append('file', fileSlice); - formData.append('cancel', false); - - response = await mecredApi.post("/learning_objects/" + draft.id + "/chunk", formData, headerConfig()) - .catch((error) => console.error(error)); - - // Atualiza o progresso com base nos chunks enviados - setProgress(Math.round(((i + 1) / numChunksToSend) * 100)); - start += chunkSize; - } + let formData = new FormData(); + formData.set('file', file); + formData.set('id_resource', String(draft.id)); + formData.set('content_type', file.type); // tipo MIME do arquivo (image/png, image/jpeg etc) + + + await mecredApi + .post("api/s3/upload/resource", formData, { headers: authHeaders() }) + .catch((error) => console.error(error)); - setAttachmentId(response.data.id); setUploading("file"); } const handleDelete = async () => { - let url = `/learning_objects/${draft.id}/attachment/${attachmentId}`; + let url = `api/s3/delete/resource/${draft.id}`; await mecredApi - .delete(url, headerConfig()) + .delete(url, { headers: authHeaders() }) .then(() => { - setAttachmentId(null); setUploading("nothing"); setFile(null); - setProgress(0); // Reset progress + setProgress(0); //reseta a barra de progresso }) .catch((error) => console.error(error)); } @@ -109,7 +77,7 @@ export default function UploadFile({ setUploading, setProgress, draft, file, set <FileUploadIcon fontSize="large" className="text-darkGray-HC-dark" /> </div> - {!attachmentId ? ( + {uploading === "nothing" ? ( <> <h1 className="text-center text-2xl text-darkGray-HC-white"> Envie o arquivo do recurso diff --git a/src/app/publicar/components/UploadForm.js b/src/app/publicar/components/UploadForm.js index a766456ec61429d00d5d630d0fd58b817438975d..07d6d80ca227731f86011ac3b1d7dfcd8df76fad 100644 --- a/src/app/publicar/components/UploadForm.js +++ b/src/app/publicar/components/UploadForm.js @@ -9,29 +9,15 @@ import UploadFile from "./UploadFile"; import { useState } from "react"; import SubmitThumbnail from "./SubmitThumbnail"; import mecredApi from "@/axiosConfig"; -import { getStoredValue } from "@/app/handlers/localStorageHandler"; import ModalIncompleteField from "./ModalIncompleteField"; import CancelSubmitModal from "./CancelSubmitModal"; import HelpIcon from '@mui/icons-material/Help'; import Tooltip, { tooltipClasses } from '@mui/material/Tooltip'; import { styled } from '@mui/material/styles'; import { LinearProgress } from "@mui/material"; +import { authHeaders } from "@/app/handlers/loginHandler"; - - -function headerConfig() { - return { - headers: { - "access-token": getStoredValue("access_token"), - "token-type": "Bearer", - client: getStoredValue("client"), - uid: getStoredValue("uid"), - Expires: 0, - } - }; -} - const CustomWidthTooltip = styled(({ className, ...props }) => ( <Tooltip {...props} classes={{ popper: className }} /> ))({ @@ -55,20 +41,22 @@ const longText = () => { }; -export default function UploadForm({ thumbURL, thumb, setThumb, setThumbURL, setStep, draft, setDraft, file, setFile, attachmentId, setAttachmentId }) { +export default function UploadForm({ thumbURL, thumb, setThumb, setThumbURL, setStep, draft, setDraft, file, setFile }) { const [uploading, setUploading] = useState(draft.link ? "link" : file ? "file" : "nothing") const [filled, setFilled] = useState(false) const [openModal, setOpenModal] = useState(false) const [openModalCancel, setOpenModalCancel] = useState(false) const [progress, setProgress] = useState(0); // Estado para a barra de progresso - const submitThumb = async () => { let finalThumb = new FormData() - finalThumb.set('learning_object[thumbnail]', thumb); + finalThumb.set('file', thumb); + finalThumb.set('id_resource', String(draft.id)); + finalThumb.set('content_type', thumb.type); // tipo MIME do arquivo (image/png, image/jpeg etc) + await mecredApi - .put(`/learning_objects/${draft.id}`, finalThumb, headerConfig()) + .post(`api/s3/upload/thumbnail/resource`, finalThumb, { headers: authHeaders() }) .catch((error) => { console.error(error) }) } @@ -88,29 +76,29 @@ export default function UploadForm({ thumbURL, thumb, setThumb, setThumbURL, set } else { submitThumb(); - setDraft((curr) => ({ - ...curr, - attachmentID: (JSON.stringify(attachmentId)), - file: file?.name, - })) + + mecredApi + .post('api/resource/update', draft, { headers: authHeaders() }) + .then((response) => { setDraft(response.data) }) + + setStep(curr => curr + 1); } } - function linkOrFileUpload(uploading, setUploading, attachmentId, file, link) { + function linkOrFileUpload(uploading, setUploading, file, link) { switch (uploading) { case "nothing": return ( - draft.object_type_f[0].name !== "Website Externo" ? + draft.object_type_id !== 13 ? <> <div className="pb-10"> - <UploadFile setUploading={setUploading} setProgress={setProgress} draft={draft} setDraft={setDraft} file={file} setFile={setFile} attachmentId={attachmentId} setAttachmentId={setAttachmentId} /> + <UploadFile setUploading={setUploading} uploading={uploading} setProgress={setProgress} draft={draft} setDraft={setDraft} file={file} setFile={setFile} /> </div> </> - : <> <SubmitLink setUploading={setUploading} setDraft={setDraft} draft={draft} /> @@ -126,7 +114,7 @@ export default function UploadForm({ thumbURL, thumb, setThumb, setThumbURL, set ) case "file": return ( - <UploadFile setUploading={setUploading} setProgress={setProgress} draft={draft} setDraft={setDraft} file={file} setFile={setFile} attachmentId={attachmentId} setAttachmentId={setAttachmentId} /> + <UploadFile setUploading={setUploading} setProgress={setProgress} draft={draft} setDraft={setDraft} file={file} setFile={setFile} /> ) case "link": return ( @@ -138,8 +126,8 @@ export default function UploadForm({ thumbURL, thumb, setThumb, setThumbURL, set return ( <> <form className="mb-10" onKeyDown={(e) => { if (e.key === "Enter") e.preventDefault() }}> - <Paper - className="rounded-lg px-10 py-1 max-xl:mx-5" + <Paper + className="rounded-lg px-10 py-1 max-xl:mx-5" elevation={1} sx={{ backgroundColor: 'var(--white-HC-dark)', @@ -147,13 +135,13 @@ export default function UploadForm({ thumbURL, thumb, setThumb, setThumbURL, set }} > <div className="flex w-full justify-between"> - <FieldLabel - name="Enviar Recurso*" - description={ - draft.object_type_f[0].name !== "Website Externo" ? "Envie um arquivo" : "Envie um link externo" - } - error={(filled && !draft.link) && (filled && !file)} - /> + <FieldLabel + name="Enviar Recurso*" + description={ + draft.object_type_id !== 13 ? "Envie um arquivo" : "Envie um link externo" + } + error={(filled && !draft.link) && (filled && !file)} + /> <div className="mt-10 pl-8"> <CustomWidthTooltip title={longText()} > <HelpIcon fontSize="large" className="text-turquoise-HC-white " /> @@ -162,14 +150,14 @@ export default function UploadForm({ thumbURL, thumb, setThumb, setThumbURL, set </div> </div> - {linkOrFileUpload(uploading, setUploading, attachmentId, file, draft.link)} + {linkOrFileUpload(uploading, setUploading, file, draft.link)} <Divider /> - <SubmitThumbnail error={filled && !thumbURL} setThumb={setThumb} thumbURL={thumbURL} setThumbURL={setThumbURL} draft={draft} setDraft={setDraft} /> + <SubmitThumbnail error={filled && !thumbURL} setThumb={setThumb} thumbURL={thumbURL} setThumbURL={setThumbURL} draft={draft} setDraft={setDraft} /> </Paper> <h1 className="text-darkGray-HC-white font-light text-base pt-1 text-end max-xl:pr-6"> - + </h1> <div className="flex w-full justify-end p-3"> <Button @@ -184,11 +172,6 @@ export default function UploadForm({ thumbURL, thumb, setThumb, setThumbURL, set variant="text" className="normal-case w-36 text-base text-darkGray-HC-white-underline font-bold mr-2 outline outline-1 outline-ice-HC-white bg-ice-HC-dark hover:bg-lightGray-HC-white hover:text-darkGray-HC-dark-underline" onClick={() => { - setDraft((curr) => ({ - ...curr, - attachmentID: (JSON.stringify(attachmentId)), - file: file?.name, - })) setStep(curr => curr - 1) } } diff --git a/src/app/publicar/page.js b/src/app/publicar/page.js index 84ca7547d12a97baca90c1ae818143c32f8efcc6..4b9cbc08567d86f1b82a42f48f6040d6aae5489c 100644 --- a/src/app/publicar/page.js +++ b/src/app/publicar/page.js @@ -1,15 +1,12 @@ "use client"; import Overlay from "../components/Overlay"; -import { useLoginBarrier } from "../handlers/loginHandler"; +import { useLoggedIn } from "../handlers/loginHandler"; import Form from "./components/Form"; -import { useEffect } from "react"; export default function Submit() { - const loginBarrier = useLoginBarrier(); - - useEffect(() => { - loginBarrier() - }, [loginBarrier]) + const loggedIn = useLoggedIn(); + + if(!loggedIn) return; return ( <Overlay> diff --git a/src/app/recurso/[id]/components/actionButtons.js b/src/app/recurso/[id]/components/actionButtons.js index 4ee38dc572a0943560f19aea999c65d01d1a38c7..342017b7e4e3d169bfc4323579e8052593a41991 100644 --- a/src/app/recurso/[id]/components/actionButtons.js +++ b/src/app/recurso/[id]/components/actionButtons.js @@ -9,7 +9,7 @@ import DeleteOutlinedIcon from '@mui/icons-material/DeleteOutlined'; import FlagOutlinedIcon from "@mui/icons-material/FlagOutlined"; import FlagIcon from "@mui/icons-material/Flag"; import mecredApi, { mecredURL } from "@/axiosConfig"; -import { isLoggedIn, useLoginBarrier } from "@/app/handlers/loginHandler"; +import { authHeaders, isLoggedIn, useLoginBarrier } from "@/app/handlers/loginHandler"; import { getStoredValue } from "@/app/handlers/localStorageHandler"; import { useState, useEffect, useLayoutEffect } from "react"; import ShareModal from "../../../components/ShareModal"; @@ -40,9 +40,6 @@ export default function ActionButtons({ learningObject, setNeedLoginOpen, state const [submitted, setSubmitted] = useState(state) const token = getStoredValue("access_token"); - const client = getStoredValue("client"); - const uid = getStoredValue("uid"); - const pathname = usePathname(); useEffect(() => { if (!isLoggedIn()) return; @@ -56,42 +53,43 @@ export default function ActionButtons({ learningObject, setNeedLoginOpen, state }, [learningObject.liked, userData]); useEffect(() => { - if(!isLoggedIn() || !learningObject?.id) return; + if (!isLoggedIn() || !learningObject?.id) return; setReported(learningObject.complained); }, [learningObject]) + let buttonInfo = [ - // Botão de Acessar PDF - learningObject.default_mime_type !== "application/pdf" ? null : { - name: "Acessar", - icon: <OpenInNewOutlinedIcon />, - action: () => { - if (typeof window !== "undefined") { - const uri = - mecredURL + "inline/" + learningObject.id; - window.open(uri); - } - }, - extraProps: {}, + // Botão de Acessar PDF + learningObject.contentType !== "application/pdf" ? null : { + name: "Acessar", + icon: <OpenInNewOutlinedIcon />, + action: () => { + if (typeof window !== "undefined") { + const uri = + mecredURL + "inline/" + learningObject.id; + window.open(uri); + } }, - // Botão de Acessar ou Baixar - { - name: learningObject.link ? "Acessar" : "Baixar", - icon: learningObject.link ? ( - <OpenInNewOutlinedIcon /> - ) : ( - <DownloadOutlinedIcon /> - ), - action: () => { - if (typeof window !== "undefined") { - window.open( - mecredApi.getUri() + - `/learning_objects/${learningObject.id}/download` - ); - } - }, - extraProps: {}, + extraProps: {}, + }, + // Botão de Acessar ou Baixar + { + name: learningObject.link ? "Acessar" : "Baixar", + icon: learningObject.link ? ( + <OpenInNewOutlinedIcon /> + ) : ( + <DownloadOutlinedIcon /> + ), + action: () => { + if (typeof window !== "undefined") { + window.open( + mecredApi.getUri() + + `public/resource/download/${learningObject.id}` + ); + } }, + extraProps: {}, + }, // Botão de curtir { name: liked ? ( @@ -107,23 +105,17 @@ export default function ActionButtons({ learningObject, setNeedLoginOpen, state } mecredApi.put( - `learning_objects/${learningObject.id}/like`, + `api/resourceLikes/like/${learningObject.id}`, {}, { - headers: { - "access-token": token, - "token-type": "Bearer", - client: client, - uid: uid, - Expires: 0, - }, + headers: authHeaders(), } ); setLiked(!liked); }, extraProps: {}, }, - + // Botão de Colecionar { name: "Colecionar", icon: <BookmarkBorderOutlinedIcon />, action: () => { @@ -143,7 +135,7 @@ export default function ActionButtons({ learningObject, setNeedLoginOpen, state }, extraProps: {}, }, - // Botão de Reportar + // Botão de Reportar { name: reported ? "Reportado" : "Reportar", icon: reported ? <FlagIcon /> : <FlagOutlinedIcon />, @@ -158,25 +150,25 @@ export default function ActionButtons({ learningObject, setNeedLoginOpen, state }, extraProps: { disabled: reported }, }, - userData.id !== learningObject.publisher.id ? null : - { - name: "Deletar", - icon: <DeleteOutlinedIcon />, - action: () => { - if (!isLoggedIn()) { - setNeedLoginOpen(true); - return; - } + userData.id !== learningObject.user_id ? null : + { + name: "Deletar", + icon: <DeleteOutlinedIcon />, + action: () => { + if (!isLoggedIn()) { + setNeedLoginOpen(true); + return; + } - setDeleteOpen(true); - }, - extraProps: {}, - } + setDeleteOpen(true); + }, + extraProps: {}, + } ]; let buttonKey = 0; let genButton = (info) => ( - !info ? null : <Button + !info ? null : <Button id="conteudo" key={buttonKey++} className="group first:bg-turquoise-HC-white first:hover:text-darkGray-HC-white first:text-darkGray-HC-dark first:hover:bg-darkTurquoise-HC-dark text-darkGray-HC-white group outline outline-1 outline-ice-HC-white group/button shadow-none flex justify-start rounded-xl p-1 m-1 normal-case text-sm min-w-min font-bold bg-white-HC-dark hover:bg-lightGray-HC-white text-darkGray-HC-white-underline hover:text-darkGray-HC-dark focus:bg-ice-HC-dark" @@ -187,12 +179,12 @@ export default function ActionButtons({ learningObject, setNeedLoginOpen, state <div className="p-1 text-darkGray-HC-white group-hover:text-darkGray-HC-dark-underline group-first:group-hover:text-white-HC-underline group-first:text-white-HC-dark-underline">{info.name}</div> </Button> ); - + return ( <> - <DeleteModal open={deleteOpen} onClose={() => setDeleteOpen(false)} idLogin={userData["id"]} resourceId={learningObject.id} /> - <HomologationModal open={submitOpen} onClose={() => setSubmitOpen(false)} name={learningObject.name} id={learningObject.submission_id} setSubmitted={setSubmitted}/> + <DeleteModal open={deleteOpen} onClose={() => setDeleteOpen(false)} idLogin={userData["id"]} resourceId={learningObject.id} /> + <HomologationModal open={submitOpen} onClose={() => setSubmitOpen(false)} name={learningObject.name} id={learningObject.submission_id} setSubmitted={setSubmitted} /> <ShareModal open={shareOpen} onClose={() => setShareOpen(false)} /> <ReportModal learningObject={learningObject} @@ -209,7 +201,7 @@ export default function ActionButtons({ learningObject, setNeedLoginOpen, state : <div className="flex justify-start py-4 max-sm:no-scrollbar max-sm:overflow-x-auto animate-scrollHint text-red-800"> {genButton(buttonInfo[1] || buttonInfo[2])} - </div> + </div> } </> ); diff --git a/src/app/recurso/[id]/components/collectionInfo.js b/src/app/recurso/[id]/components/collectionInfo.js index 62d25ab6000c15e355bda8f23e446f57f04bc175..92a64f8f9a93208397d6df56b2f22a7235d0a41a 100644 --- a/src/app/recurso/[id]/components/collectionInfo.js +++ b/src/app/recurso/[id]/components/collectionInfo.js @@ -20,21 +20,16 @@ export default function CollectionInfo({ resourceId, collectionId }) { if (isLoggedIn()) { headers = { - "access-token": token, - "token-type": "Bearer", - client: client, - uid: uid, - Expires: 0, + Authorization:`bearer ${token}` }; } - const response = await mecredApi.get(`collections/${collectionId}`, { + const response = await mecredApi.get(`public/collection/${collectionId}`, { headers: headers, }); - setCollection(response.data); }; - + fetchData(); }, [collectionId, client, token, uid]); diff --git a/src/app/recurso/[id]/components/comments.js b/src/app/recurso/[id]/components/comments.js index fb95625880741166f0e28643559c1d9a035d9bd2..202fa913799ec274bde002ef89599af37119ecaa 100644 --- a/src/app/recurso/[id]/components/comments.js +++ b/src/app/recurso/[id]/components/comments.js @@ -1,62 +1,43 @@ -import { Paper, Modal, Button, Accordion, AccordionSummary, Typography, AccordionDetails } from "@mui/material"; +import { Paper, Accordion, AccordionSummary, AccordionDetails } from "@mui/material"; import { useEffect, useState } from "react"; import mecredApi from "@/axiosConfig"; import { getStoredValue } from "@/app/handlers/localStorageHandler"; import PrintComments from "./printComments"; import CreateComments from "./createComments"; -import { isLoggedIn } from "@/app/handlers/loginHandler"; -import { setConfig } from "next/config"; +import {authHeaders, useLoggedIn } from "@/app/handlers/loginHandler"; import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'; + export default function Comments({ learningObjectId }) { const [comments, setComments] = useState(null) const [newComment, setNewComment] = useState(""); - - - const token = getStoredValue("access_token") - const client = getStoredValue("client") - const uid = getStoredValue("uid") - + const loggedIn = useLoggedIn(); + + const [userData, setUserData] = useState({}); const [logged, setLogged] = useState(false); useEffect(() => { - if (!isLoggedIn()) return; - const data = JSON.parse(getStoredValue("user_data")); - setUserData(data); + if (!loggedIn) return; + setUserData(userData()); setLogged(true); - }, [token]) + }, [loggedIn, userData]) const handleSubmitComment = async () => { - if (!logged) return + if (!loggedIn) return if (newComment === "") return - const url = `/learning_objects/${learningObjectId}/reviews` + const url = `api/comments/create` let payload = { - review: { - description: newComment, - review_ratings_attributes: [ - { - rating_id: 1, - value: 5, - }, - ], - }, + resource_id: learningObjectId, + text: newComment, }; try { await mecredApi - .post(url, payload, { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': 0 - } - },) + .post(url, payload, {headers: authHeaders()},) .then((response) => setComments(old => [...old, response.data])) } catch (error) { console.error(error) @@ -66,32 +47,19 @@ export default function Comments({ learningObjectId }) { setNewComment("") } - // `/learning_objects/${props.recursoId}/reviews?page=${currPageReviews}` useEffect(() => { - - - const url = `/learning_objects/${learningObjectId}/reviews?page=0` - + const url = `/public/comments/findCommentsByResource/${learningObjectId}` const getComments = async (url) => { await mecredApi - .get(url, { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': 0 - } - }) + .get(url) .then(({ data }) => { setComments(data) } ) } - getComments(url) - }, [token, learningObjectId, client, uid]) + }, [learningObjectId]) return ( <div> diff --git a/src/app/recurso/[id]/components/complaintsModal.js b/src/app/recurso/[id]/components/complaintsModal.js index b76bef237d89c3a69e4a70d5d089428c5069daa4..7ae7d9da16c925229c361b919d39fc0e55ba6733 100644 --- a/src/app/recurso/[id]/components/complaintsModal.js +++ b/src/app/recurso/[id]/components/complaintsModal.js @@ -3,7 +3,7 @@ import { getStoredValue } from "@/app/handlers/localStorageHandler"; import mecredApi from "@/axiosConfig"; import { Alert, FormControlLabel, Modal, Radio, RadioGroup, TextField } from "@mui/material"; import { useEffect, useState } from "react"; -import { isLoggedIn } from "@/app/handlers/loginHandler"; +import { isLoggedIn, userData } from "@/app/handlers/loginHandler"; import CloseIcon from '@mui/icons-material/Close'; export default function ComplaintModal({ open, onClose, name, id, setSubmitted }) { @@ -27,8 +27,9 @@ export default function ComplaintModal({ open, onClose, name, id, setSubmitted } useEffect(() => { if (isLoggedIn()) { - let data = JSON.parse(getStoredValue("user_data")); - setMyId(data["id"]); + let data = userData(); + console.log(data, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") + setMyId(data.id); } }, []); diff --git a/src/app/recurso/[id]/components/editComments.js b/src/app/recurso/[id]/components/editComments.js index d6fe2eb7f797b15342133ac0728a5aba9bcb29c2..a30ef398fa700780d941eca513900b4b280b91a6 100644 --- a/src/app/recurso/[id]/components/editComments.js +++ b/src/app/recurso/[id]/components/editComments.js @@ -49,7 +49,7 @@ return ( <div className="flex flex-col gap-1 w-full "> <div className="bg-ice-HC-dark rounded-lg p-4 outline outline-1 outline-ice-HC-white "> <div className="text-lg pb-2 text-darkGray-HC-white"> - {comment.user.name} + {comment.author_name} </div> <div className="flex flex-col mt-2 gap-1 w-full justify-center "> diff --git a/src/app/recurso/[id]/components/metrics.js b/src/app/recurso/[id]/components/metrics.js index 2a6274e612d118cc121ea125a495f0f8266b6049..1f2740f431f06bfd5c0842f8d3d6b59a343ae525 100644 --- a/src/app/recurso/[id]/components/metrics.js +++ b/src/app/recurso/[id]/components/metrics.js @@ -26,9 +26,9 @@ const genMetric = ({ icon, name, data }) => { export default function Specifications({ learningObject }) { const metricInfo = [ - { icon: <IconViews className="text-2xl invertLogo-HC-white" />, name: "Visualizações", data: learningObject.views_count }, - { icon: <FavoriteOutlinedIcon />, name: "Curtidas", data: learningObject.likes_count }, - { icon: <IoMdShareAlt className="text-2xl" />, name: "Compartilhamentos", data: learningObject.shares_count }, + { icon: <IconViews className="text-2xl invertLogo-HC-white" />, name: "Visualizações", data: learningObject.stats.views }, + { icon: <FavoriteOutlinedIcon />, name: "Curtidas", data: learningObject.stats.likes }, + { icon: <IoMdShareAlt className="text-2xl" />, name: "Compartilhamentos", data: learningObject.stats.shares }, ]; return ( <div className="flex flex-col p-1 text-darkGray-HC-white"> diff --git a/src/app/recurso/[id]/components/printComments.js b/src/app/recurso/[id]/components/printComments.js index 891d6651951dee65f30dd05d4d6919a5bac1e9b0..3d91e16a3d2956e1a712d08a399ad946deb1edc4 100644 --- a/src/app/recurso/[id]/components/printComments.js +++ b/src/app/recurso/[id]/components/printComments.js @@ -4,7 +4,7 @@ import DeleteCommentModal from "./deleteCommentModal"; import Link from "next/link"; import EditComment from "./editComments"; -import { mecredURL } from "@/axiosConfig"; +import { s3URL } from "@/axiosConfig"; @@ -29,49 +29,52 @@ function getRandomBg(id) { } - - - export default function PrintComments({ comment, userData, learningObjectId, comments, setComments }) { const [openDeleteModal, setOpenDeleteModal] = useState(false) const [edit, setEdit] = useState(false) const timeFunction = (updated_time) => { - let data = new Date(updated_time) - let dataAtual = new Date(); - let time = dataAtual.getTime() - data.getTime(); - let dia = Math.floor(time / (1000 * 60 * 60 * 24)); - let ano; - let mes; - - if ((ano = Math.floor(dia / 365)) > 0) - return <span className="text-sm font-light"> há {ano} {ano === 1 ? "ano" : "anos"} </span> - else if (((mes = Math.floor(dia / 31)) > 0)) - return <span className="text-sm font-light"> há {mes} {mes === 1 ? "mês" : "meses"}</span> - - if (dia === 0) - return <span className="text-sm font-light"> hoje</span> - return <span className="text-sm font-light"> há {dia} {dia === 1 ? "dia" : "dias"}</span> - } + const [datePart, timePart] = updated_time.split(" "); + const [year, month, day] = datePart.split("-").map(Number); + const [hour, minute, secondWithMs] = timePart.split(":"); + const [second, ms] = secondWithMs.split(".").map(Number); + + const data = new Date(Date.UTC(year, month - 1, day, +hour, +minute, second, ms || 0)); + const dataAtual = new Date(); + const timeDiff = dataAtual.getTime() - data.getTime(); + + const dias = Math.floor(timeDiff / (1000 * 60 * 60 * 24)); + const anos = Math.floor(dias / 365); + const meses = Math.floor(dias / 30); + + if (anos > 0) + return <span className="text-sm font-light">há {anos} {anos === 1 ? "ano" : "anos"}</span>; + else if (meses > 0) + return <span className="text-sm font-light">há {meses} {meses === 1 ? "mês" : "meses"}</span>; + else if (dias === 0) + return <span className="text-sm font-light">hoje</span>; + + return <span className="text-sm font-light">há {dias} {dias === 1 ? "dia" : "dias"}</span>; + }; + return ( <> <div className="flex p-4 max-sm:p-2"> <div className="w-20 h-20 flex-shrink-0 rounded-full mr-7 max-sm:mr-0 max-sm:w-16"> - <Link href={`/perfil/${comment.user.id}`}> - {comment?.user?.avatar ? ( + <Link href={`/perfil/${comment.user_id}`}> + {comment?.user_id ? ( <Avatar - fill="true" - src={mecredURL + comment.user.avatar} + src={s3URL + `avatar/${comment.user_id}`} alt="Comment Avatar" - title={comment.user.name} + title={comment.user_id} sx={{ width: 80, height: 80 }} className="max-sm:w-10 max-sm:h-10" /> ) : ( - <div className={`flex items-center justify-center text-xl m-2 font-bold text-ice-HC-dark rounded-full h-20 w-20 max-sm:h-10 max-sm:w-10 ${getRandomBg(comment.user.id)}`} >{comment.user.name[0]}</div> + <div className={`flex items-center justify-center text-xl m-2 font-bold text-ice-HC-dark rounded-full h-20 w-20 max-sm:h-10 max-sm:w-10 ${getRandomBg(comment.user_id)}`} >{comment.author_name[0]}</div> )} </Link> </div> @@ -86,16 +89,16 @@ export default function PrintComments({ comment, userData, learningObjectId, com <div className="flex flex-col gap-1 w-full "> <div className="bg-ice-HC-dark rounded-lg p-4 outline outline-1 outline-ice-HC-white "> <div className="text-lg pb-2 text-darkGray-HC-white max-sm:text-sm"> - {comment.user.name} + {comment.author_name} </div> <div className="font-normal"> - {comment?.description} + {comment?.text} </div> </div> <div className="flex flex-row justify-between ml-1 mt-2 gap-2 rounded-lg "> {timeFunction(comment.updated_at)} - {(userData.id === comment.user.id) && + {(userData.id === comment.user_id) && <div className=" flex gap-2"> <button className="hover:bg-ice-HC-dark p-1 rounded-lg" onClick={() => setEdit(true)}> editar </button> <button className="hover:bg-ice-HC-dark p-1 rounded-lg" onClick={() => setOpenDeleteModal(true)}> excluir </button> diff --git a/src/app/recurso/[id]/components/resourcePreview.js b/src/app/recurso/[id]/components/resourcePreview.js index 179169427943ed2a6246d7d62d7b592bc67b5fa8..2afd25c44b1f10c0300f2d274ed3216e871849c6 100644 --- a/src/app/recurso/[id]/components/resourcePreview.js +++ b/src/app/recurso/[id]/components/resourcePreview.js @@ -1,6 +1,6 @@ import Image from "next/image"; import { imageType, videoType, audioType } from "@/app/components/FileTypeUtilities"; -import mecredApi, { mecredURL } from "@/axiosConfig"; +import mecredApi, { mecredURL, s3URL } from "@/axiosConfig"; import OpenInNewOutlinedIcon from "@mui/icons-material/OpenInNewOutlined"; @@ -55,7 +55,9 @@ const getDefaultThumbnail = (type) => { export default function ResourcePreview({ learningObject }) { if (!learningObject?.id) return <></>; - const uri = mecredURL + "inline/" + learningObject.id; + // const uri = mecredURL + "inline/" + learningObject.id; + + const uri = s3URL + "resource/" + learningObject.id; let content = ( <div className="relative aspect-video w-full h-full"> @@ -66,7 +68,7 @@ export default function ResourcePreview({ learningObject }) { width: "100%", objectFit: "cover", }} - src={getDefaultThumbnail(learningObject.object_type)} + src={getDefaultThumbnail(learningObject.objectTypeName)} alt={learningObject.name} /> </div> @@ -83,7 +85,7 @@ export default function ResourcePreview({ learningObject }) { className="aspect-video" ></iframe> ); - } else if (learningObject.default_mime_type === "application/pdf") { + } else if (learningObject.contentType === "application/pdf") { content = ( <object className="rounded-xl aspect-video" @@ -93,7 +95,7 @@ export default function ResourcePreview({ learningObject }) { height="100%" /> ); - } else if (videoType(learningObject?.default_mime_type)) { + } else if (videoType(learningObject?.contentType)) { content = ( <video src={uri} @@ -101,17 +103,17 @@ export default function ResourcePreview({ learningObject }) { className="flex rounded-lg justify-center items-center text-5xl aspect-video h-full w-full" /> ); - } else if (audioType(learningObject?.default_mime_type)) { + } else if (audioType(learningObject?.contentType)) { content = ( <div className="flex justify-center items-center h-full w-full"> <div> <audio preload="true" width="100%" height="100%" controls> - <source src={uri} type={learningObject.default_mime_type} /> + <source src={uri} type={learningObject.contentType} /> </audio> </div> </div> ); - } else if (imageType(learningObject?.default_mime_type)) { + } else if (imageType(learningObject?.contentType)) { content = ( <div className="relative bg-white-HC-dark aspect-video w-full h-full"> <img @@ -130,9 +132,11 @@ export default function ResourcePreview({ learningObject }) { if (typeof window !== "undefined") { let uri = mecredApi.getUri() + - `/learning_objects/${learningObject.id}/download`; - if (learningObject.default_mime_type === "application/pdf") { - uri = mecredURL + "inline/" + learningObject.id; + `public/resource/download/${learningObject.id}`; + if (learningObject.contentType === "application/pdf") { + // uri = s3URL + "inline/" + learningObject.id; + + uri = s3URL + "resource/" + learningObject.id; } window.open(uri); } @@ -147,7 +151,7 @@ export default function ResourcePreview({ learningObject }) { width: "100%", objectFit: "cover", }} - src={mecredURL + learningObject.thumbnail} + src={s3URL + `thumbnail/resource/${learningObject.id}`} alt={learningObject.name} /> diff --git a/src/app/recurso/[id]/components/specifications.js b/src/app/recurso/[id]/components/specifications.js index 552340ae2c6d1fa11d75cd3158d345bba92a55c3..eb0a093c71ed14a7faad7d8bb734b0f4187e729f 100644 --- a/src/app/recurso/[id]/components/specifications.js +++ b/src/app/recurso/[id]/components/specifications.js @@ -29,11 +29,11 @@ function formatSize(size) { export default function Specifications({ learningObject }) { const specInfo = [ - { icon: <IconLocation className='mr-2 invertLogo-HC-white'/>, enabled: true, name: "Idioma", data: learningObject.language.map((lang) => lang.name).join(", ") ?? "Não Informado" }, + { icon: <IconLocation className='mr-2 invertLogo-HC-white'/>, enabled: true, name: "Idioma", data: learningObject.languages.map((lang) => lang.name).join(", ") ?? "Não Informado" }, { icon: <IconLevel className='mr-2 invertLogo-HC-white'/>, enabled: true, name: "Nível de Ensino", data: learningObject.educational_stages.map((stage) => stage.name).join(", ") }, - { icon: <IconMedia className='invertLogo-HC-white' style={{ transform: "scale(0.85)" }}/>, enabled: true, name: "Tipo de Mídia", data: learningObject.object_type }, + { icon: <IconMedia className='invertLogo-HC-white' style={{ transform: "scale(0.85)" }}/>, enabled: true, name: "Tipo de Mídia", data: learningObject.objectTypeName }, { icon: <IconTheme className='mr-1 invertLogo-HC-white'/>, enabled: true, name: "Temática", data: learningObject.subjects.map((subject) => subject.name).join(", ") }, - { icon: <IconSize className='mr-2 invertLogo-HC-white' style={{ transform: "scale(1.15)" }}/>, enabled: !learningObject.link, name: "Tamanho", data: formatSize(learningObject?.attachments[0]?.size) }, + // { icon: <IconSize className='mr-2 invertLogo-HC-white' style={{ transform: "scale(1.15)" }}/>, enabled: !learningObject.link, name: "Tamanho", data: formatSize(learningObject?.attachments[0]?.size) }, ]; return ( <div className="flex flex-col p-1 text-darkGray-HC-white"> diff --git a/src/app/recurso/[id]/page.js b/src/app/recurso/[id]/page.js index 7e49c0965e9ec725ee0a7dee727b5739bbdef6e4..128297e40e88317264751940405bc42083ded4c5 100644 --- a/src/app/recurso/[id]/page.js +++ b/src/app/recurso/[id]/page.js @@ -33,8 +33,6 @@ export default function Recurso({ params }) { const collectionId = searchParams.get("collectionId"); const token = getStoredValue("access_token"); - const client = getStoredValue("client"); - const uid = getStoredValue("uid"); useEffect(() => { const fetchData = async () => { @@ -43,15 +41,11 @@ export default function Recurso({ params }) { if (isLoggedIn()) { headers = { - "access-token": token, - "token-type": "Bearer", - client: client, - uid: uid, - Expires: 0, + Authorization:`bearer ${token}` }; } - const response = await mecredApi.get(`learning_objects/${params.id}`, { headers }); + const response = await mecredApi.get(`public/resource/${params.id}`); setLearningObject(response.data); setState(response.data.state === "submitted"); @@ -62,7 +56,7 @@ export default function Recurso({ params }) { }; fetchData(); - }, [params.id, client, token, uid]); + }, [params.id, token]); useEffect(() => { setComplained(learningObject?.state === "suspended"); diff --git a/src/axiosConfig.js b/src/axiosConfig.js index 624c2a5a0febf2401f9821a4d75cea8c767ae369..9be313ece58b962894093d7e475408707efa3647 100644 --- a/src/axiosConfig.js +++ b/src/axiosConfig.js @@ -3,7 +3,7 @@ import { saveToLocalStorage, } from "./app/handlers/localStorageHandler"; -export const mecredURL = "https://api.mecred.c3sl.ufpr.br/"; +export const s3URL = "https://s3.c3sl.ufpr.br/mecredteste/"; export const mecredURLv1 = "https://api.mecred.c3sl.ufpr.br/v1"; const wrapper = (method) => { @@ -20,7 +20,7 @@ const wrapper = (method) => { const mecredApi = (() => { const api = axios.create({ - baseURL: "https://api.mecred.c3sl.ufpr.br/v1", + baseURL: "http://localhost:3000/", }); const wrappedApi = {