Establish a way to set profile photo and cover image for blogs, remove cover image for categories

This commit is contained in:
Barunes Padhy 2024-06-02 22:37:04 +03:00
parent 1f15181995
commit 74beddbc38
7 changed files with 79 additions and 16 deletions

View File

@ -2,7 +2,6 @@ import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import EditableDataService from '../../services/editable-data-service'; import EditableDataService from '../../services/editable-data-service';
import MediaService from '../../services/media-service';
import CardListViewer from './shared/card-list-viewer'; import CardListViewer from './shared/card-list-viewer';
import CategoryBar from './shared/category-bar'; import CategoryBar from './shared/category-bar';
import { import {
@ -20,6 +19,7 @@ import {
import { useNavigate, useParams } from 'react-router-dom'; import { useNavigate, useParams } from 'react-router-dom';
import { faLeftLong } from '@fortawesome/free-solid-svg-icons'; import { faLeftLong } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import EditableMediaService from "../../services/editable-media-service.jsx";
function BlogList(props) { function BlogList(props) {

View File

@ -1,10 +1,11 @@
import { useEffect, useState, useRef } from 'react'; import { useEffect, useState, useRef } from 'react';
import EditableDataService from '../../services/editable-data-service'; import EditableDataService from '../../services/editable-data-service';
import MediaService from '../../services/media-service' import EditableMediaService from '../../services/editable-media-service'
import CategoryBar from './shared/category-bar'; import CategoryBar from './shared/category-bar';
import EditorComponent from './shared/tiptap'; import EditorComponent from './shared/tiptap';
import ModalComponent from './shared/modal-component'; import ModalComponent from './shared/modal-component';
import MediaUpload from './shared/media-upload'
import { faLeftLong } from '@fortawesome/free-solid-svg-icons'; import { faLeftLong } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
@ -29,18 +30,22 @@ function Blog(props) {
const [blogData, setBlogData] = useState([]); const [blogData, setBlogData] = useState([]);
const [blogContent, setBlogContent] = useState(); const [blogContent, setBlogContent] = useState();
const [coverImage, setCoverImage] = useState(false)
const [modal, setModal] = useState(false); const [modal, setModal] = useState(false);
const [modalText, setModalText] = useState(false); const [modalText, setModalText] = useState(false);
const [modalTitle, setModalTitle] = useState(false); const [modalTitle, setModalTitle] = useState(false);
const [fileModal, setFileModal] = useState(false);
const toggle = () => setModal(!modal); const toggle = () => setModal(!modal);
const toggleFileModal = () => setFileModal(!fileModal);
const setInfo = (event) => { const setInfo = (event) => {
EditableDataService.updateData(`/data/blog/update/${blogID}/`,{ EditableDataService.updateData(`/data/blog/update/${blogID}/`,{
"name": nameField.current.value, "name": nameField.current.value,
"description": descriptionField.current.value, "description": descriptionField.current.value,
"tagline": tagLineField.current.value, "tagline": tagLineField.current.value,
"content_body": blogContent "content_body": blogContent,
"cover_image": coverImage ? coverImage !== '-' ? coverImage : '' : blogData.coverImage
}).then(response => { }).then(response => {
props.notificationToggler('Blog data saved!'); props.notificationToggler('Blog data saved!');
getInfo() getInfo()
@ -85,10 +90,18 @@ function Blog(props) {
getInfo() getInfo()
}, []); }, []);
useEffect(() => {
if (coverImage){
setInfo()
if (coverImage !== '-') toggleFileModal()
}
}, [coverImage])
if (GlobalTheme && ThemeConfig && blogData) { if (GlobalTheme && ThemeConfig && blogData) {
return ( return (
<Container fluid className={`${ThemeConfig[GlobalTheme].background}`}> <Container fluid className={`${ThemeConfig[GlobalTheme].background}`}>
<ModalComponent modalText={modalText} modalTitle={modalTitle} modal={modal} toggle={toggle} confirmAction={deleteResource}/> <ModalComponent modalText={modalText} modalTitle={modalTitle} modal={modal} toggle={toggle} confirmAction={deleteResource}/>
<MediaUpload setMedia={setCoverImage} notificationToggler={props.notificationToggler} modal={fileModal} toggle={toggleFileModal} resourceType='homepage' resourceId='homepage'></MediaUpload>
<Col xs="3" className="d-none d-md-block"><Button color={ThemeConfig[GlobalTheme].buttonColor} onClick={() => navigate(`/categories/${blogData.parentCategory}`)} className="ms-5" outline><FontAwesomeIcon icon={faLeftLong}/></Button></Col> <Col xs="3" className="d-none d-md-block"><Button color={ThemeConfig[GlobalTheme].buttonColor} onClick={() => navigate(`/categories/${blogData.parentCategory}`)} className="ms-5" outline><FontAwesomeIcon icon={faLeftLong}/></Button></Col>
<CategoryBar currentPage={blogData.parentCategory} GlobalTheme={GlobalTheme} ThemeConfig={ThemeConfig}/> <CategoryBar currentPage={blogData.parentCategory} GlobalTheme={GlobalTheme} ThemeConfig={ThemeConfig}/>
<Row className="mb-4"> <Row className="mb-4">
@ -96,7 +109,7 @@ function Blog(props) {
{ {
blogData.coverImage !== "" ? blogData.coverImage !== "" ?
<img <img
src={MediaService.getMedia(blogData.coverImage)} src={EditableMediaService.getMedia(blogData.coverImage)}
alt="Banner" alt="Banner"
style={{ width: '100%', height: 'auto', maxHeight: '20vh', objectFit: 'cover' }} style={{ width: '100%', height: 'auto', maxHeight: '20vh', objectFit: 'cover' }}
/>:"" />:""
@ -105,8 +118,25 @@ function Blog(props) {
</Row> </Row>
<Row className="mr-2 ml-2 mb-2 mt-1 blogContent"> <Row className="mr-2 ml-2 mb-2 mt-1 blogContent">
<Col xs="3" className="d-none d-md-block"></Col> <Col xs="3" className="d-none d-md-block"></Col>
<Col xs={`${window.screen.width >= 765 ? '6':''}`}> <Col xs={`${window.screen.width >= 765 ? '6':''}`}>
<Button color='danger' onClick={() => showModal()} className="mb-5">Delete Blog</Button> <Button color='danger' onClick={() => showModal()} className="mb-5">Delete Blog</Button>
<ButtonGroup className="mb-5 ms-5">
<Button
outline
color={ThemeConfig[GlobalTheme].buttonColor}
onClick={() => toggleFileModal()}
>
Set Profile Photo
</Button>
<Button
outline
color={ThemeConfig[GlobalTheme].buttonColor}
onClick={() => setCoverImage('-')}
>
Remove Profile Photo
</Button>
</ButtonGroup>
<InputGroup className="mb-3"> <InputGroup className="mb-3">
<InputGroupText> <InputGroupText>
Name Name

View File

@ -136,6 +136,7 @@ function Blogs(props) {
bgColor={ThemeConfig[GlobalTheme].background} bgColor={ThemeConfig[GlobalTheme].background}
borderColor={ThemeConfig[GlobalTheme].borderColor} borderColor={ThemeConfig[GlobalTheme].borderColor}
buttonColor={ThemeConfig[GlobalTheme].buttonColor} buttonColor={ThemeConfig[GlobalTheme].buttonColor}
notificationToggler={props.notificationToggler}
itemObject={item} itemObject={item}
/> />
)) : <Spinner />} )) : <Spinner />}

View File

@ -1,12 +1,15 @@
import { Container, Spinner, Input, InputGroup, InputGroupText, Button, ButtonGroup, FormFeedback } from 'reactstrap'; import { Container, Spinner, Input, InputGroup, InputGroupText, Button, ButtonGroup, FormFeedback } from 'reactstrap';
import {useEffect, useState, useRef} from 'react'; import {useEffect, useState, useRef} from 'react';
import EditorComponent from './shared/tiptap'; import EditorComponent from './shared/tiptap';
import MediaService from '../../services/media-service' import MediaUpload from './shared/media-upload'
import EditableMediaService from '../../services/editable-media-service'
function HomePage(props) { function HomePage(props) {
const [introContent, setIntroContent] = useState("") const [introContent, setIntroContent] = useState("")
const [profilePhoto, setProfilePhoto] = useState(false)
const [saveKeyReady, setSaveKeyReady] = useState(true) const [saveKeyReady, setSaveKeyReady] = useState(true)
const [nameFieldInvalid, setNameFieldInvalid] = useState(false) const [nameFieldInvalid, setNameFieldInvalid] = useState(false)
const [modal, setModal] = useState(false)
const nameField = useRef(null) const nameField = useRef(null)
const UserData = props.UserData ? props.UserData : <Spinner> Loading... </Spinner> const UserData = props.UserData ? props.UserData : <Spinner> Loading... </Spinner>
const GlobalTheme = props.GlobalTheme; const GlobalTheme = props.GlobalTheme;
@ -16,7 +19,7 @@ function HomePage(props) {
let response = await props.setInfo('/data/shared/update/user-data/', { let response = await props.setInfo('/data/shared/update/user-data/', {
"name": nameField.current.value, "name": nameField.current.value,
"intro_content": introContent, "intro_content": introContent,
"profile_photo": "" "profile_photo": profilePhoto ? profilePhoto !== '-' ? profilePhoto : '' : UserData.profilePhoto
}) })
console.log(response) console.log(response)
if (response === 200) if (response === 200)
@ -25,6 +28,8 @@ function HomePage(props) {
props.notificationToggler("Something failed!", "danger") props.notificationToggler("Something failed!", "danger")
} }
const toggle = () => {setModal(!modal)}
const showError = (elementValue, fieldType) => { const showError = (elementValue, fieldType) => {
console.log(elementValue) console.log(elementValue)
if (fieldType === 'nameField'){ if (fieldType === 'nameField'){
@ -39,11 +44,35 @@ function HomePage(props) {
setIntroContent(UserData.introContent) setIntroContent(UserData.introContent)
}, [UserData]) }, [UserData])
useEffect(() => {
if (profilePhoto){
setInfo()
if (profilePhoto !== '-') toggle()
}
}, [profilePhoto])
if (GlobalTheme && ThemeConfig) if (GlobalTheme && ThemeConfig)
return ( return (
<Container fluid className={`p-0 mt-5 ${ThemeConfig[GlobalTheme].background}`}> <Container fluid className={`p-0 mt-5 ${ThemeConfig[GlobalTheme].background}`}>
<MediaUpload setMedia={setProfilePhoto} notificationToggler={props.notificationToggler} modal={modal} toggle={toggle} resourceType='homepage' resourceId='homepage'></MediaUpload>
<div className="d-flex flex-column justify-content-center align-items-center min-vh-82"> <div className="d-flex flex-column justify-content-center align-items-center min-vh-82">
{UserData.profilePhoto !== "" ? <img style={{ width: '180px', height: '180px', objectFit: 'cover' }} className="rounded-circle" src={MediaService.getMedia(UserData.profilePhoto)} /> : ""} {UserData.profilePhoto !== "" ? <img style={{ width: '180px', height: '180px', objectFit: 'cover' }} className="rounded-circle" src={EditableMediaService.getMedia(UserData.profilePhoto)} /> : ""}
<ButtonGroup className='mt-4'>
<Button
outline
color={ThemeConfig[GlobalTheme].buttonColor}
onClick={() => toggle()}
>
Set Profile Photo
</Button>
<Button
outline
color={ThemeConfig[GlobalTheme].buttonColor}
onClick={() => setProfilePhoto('-')}
>
Remove Profile Photo
</Button>
</ButtonGroup>
<div className={`mt-5 ${ThemeConfig[GlobalTheme].textColor}`}> <div className={`mt-5 ${ThemeConfig[GlobalTheme].textColor}`}>
<> <>
<InputGroup className='mb-5'> <InputGroup className='mb-5'>

View File

@ -1,16 +1,16 @@
import { useEffect, useState, useRef } from 'react'; import { useEffect, useState, useRef } from 'react';
import MediaService from '../../../services/media-service' import EditableMediaService from '../../../services/editable-media-service'
import { import {
Spinner,
Card, Card,
CardImg, CardImg,
CardTitle, CardTitle,
CardText, CardText,
CardBody, CardBody,
Input, InputGroup, InputGroupText, FormFeedback, Button Input, InputGroup, InputGroupText, FormFeedback, Button, ButtonGroup
} from 'reactstrap'; } from 'reactstrap';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import ModalComponent from './modal-component'; import ModalComponent from './modal-component';
import MediaUpload from './media-upload.jsx'
function CardListViewer(props) { function CardListViewer(props) {
@ -52,7 +52,6 @@ function CardListViewer(props) {
"featuredBlog": "", "featuredBlog": "",
"description": descriptionField.current.value, "description": descriptionField.current.value,
"tagLine": taglineField.current.value, "tagLine": taglineField.current.value,
"coverImage": ""
}) })
} }
@ -66,7 +65,7 @@ function CardListViewer(props) {
props.deleteResource(props.id) props.deleteResource(props.id)
toggle() toggle()
} }
const itemObject = props.itemObject const itemObject = props.itemObject
if (props.totalItems > 0 && itemObject && Object.keys(itemObject).length !== 0){ if (props.totalItems > 0 && itemObject && Object.keys(itemObject).length !== 0){
@ -75,7 +74,6 @@ function CardListViewer(props) {
<> <>
<ModalComponent modalText={modalText} modalTitle={modalTitle} modal={modal} toggle={toggle} confirmAction={deleteResource}/> <ModalComponent modalText={modalText} modalTitle={modalTitle} modal={modal} toggle={toggle} confirmAction={deleteResource}/>
<Card color={props.borderColor} outline className={`my-2 ${props.bgColor}`} style={{"width": props.cardType === "smallCard" ? "18rem": "100%"}}> <Card color={props.borderColor} outline className={`my-2 ${props.bgColor}`} style={{"width": props.cardType === "smallCard" ? "18rem": "100%"}}>
{itemObject.coverImage !== "" ? <CardImg src={MediaService.getMedia(itemObject.coverImage)} style={{ "height": "180px", "objectFit": "cover" }} top width="100%" /> : ""}
<CardBody> <CardBody>
<CardTitle className={`mb-3 ${props.textColor}`} tag="h5"> <CardTitle className={`mb-3 ${props.textColor}`} tag="h5">
<InputGroup> <InputGroup>
@ -125,7 +123,7 @@ function CardListViewer(props) {
else else
return ( return (
<Card color={props.borderColor} outline className={`my-2 ${props.bgColor}`} style={{"width": props.cardType === "smallCard" ? "18rem": "100%"}}> <Card color={props.borderColor} outline className={`my-2 ${props.bgColor}`} style={{"width": props.cardType === "smallCard" ? "18rem": "100%"}}>
{itemObject.coverImage !== "" ? <CardImg src={MediaService.getMedia(itemObject.coverImage)} style={{ "height": "180px", "objectFit": "cover" }} top width="100%" /> : ""} {itemObject.coverImage !== "" ? <CardImg src={EditableMediaService.getMedia(itemObject.coverImage)} style={{ "height": "180px", "objectFit": "cover" }} top width="100%" /> : ""}
<CardBody> <CardBody>
<Link to={`/${props.resourceType}/${itemObject.id}`}> <Link to={`/${props.resourceType}/${itemObject.id}`}>
<CardTitle className={`${props.textColor}`} tag="h3"> <CardTitle className={`${props.textColor}`} tag="h3">

View File

@ -13,7 +13,7 @@ import {
Button, ButtonGroup, Label, Input Button, ButtonGroup, Label, Input
} from 'reactstrap'; } from 'reactstrap';
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import MediaService from '../../../services/media-service' import EditableMediaService from '../../../services/editable-media-service'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faSun, faMoon, faPen, faBrush } from '@fortawesome/free-solid-svg-icons'; import { faSun, faMoon, faPen, faBrush } from '@fortawesome/free-solid-svg-icons';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
@ -69,7 +69,7 @@ function Header(props) {
<img <img
style={{ width: '40px', height: '40px', objectFit: 'cover', 'marginRight': '10px' }} style={{ width: '40px', height: '40px', objectFit: 'cover', 'marginRight': '10px' }}
className="rounded-circle" className="rounded-circle"
src={MediaService.getMedia(UserData.profilePhoto)} src={EditableMediaService.getMedia(UserData.profilePhoto)}
/> : "" /> : ""
} }
<Button color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ""}`} size="lg"> <Button color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ""}`} size="lg">

View File

@ -0,0 +1,5 @@
const getMedia = (mediaPath) => {
return `${mediaPath}`;
}
export default { getMedia };