bro got linted
This commit is contained in:
parent
2369d5c8e6
commit
d41d3501c3
34
frontend/editable-ui/.eslintrc
Normal file
34
frontend/editable-ui/.eslintrc
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"es2021": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:react/recommended"
|
||||||
|
],
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaFeatures": {
|
||||||
|
"jsx": true
|
||||||
|
},
|
||||||
|
"ecmaVersion": 12,
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
"react"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"indent": [
|
||||||
|
"error",
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"react/react-in-jsx-scope": "off",
|
||||||
|
"react/prop-types": "off",
|
||||||
|
"react/display-name": "off",
|
||||||
|
"quotes": [
|
||||||
|
"error",
|
||||||
|
"single"
|
||||||
|
],
|
||||||
|
"no-console": "error"
|
||||||
|
}
|
||||||
|
}
|
||||||
3226
frontend/editable-ui/package-lock.json
generated
3226
frontend/editable-ui/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -43,9 +43,11 @@
|
|||||||
"@types/react-dom": "^18.2.22",
|
"@types/react-dom": "^18.2.22",
|
||||||
"@vitejs/plugin-react": "^4.2.1",
|
"@vitejs/plugin-react": "^4.2.1",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
|
"eslint-config-react-app": "^7.0.1",
|
||||||
"eslint-plugin-react": "^7.34.1",
|
"eslint-plugin-react": "^7.34.1",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"eslint-plugin-react-refresh": "^0.4.6",
|
"eslint-plugin-react-refresh": "^0.4.6",
|
||||||
"vite": "^5.2.0"
|
"vite": "^5.2.0",
|
||||||
|
"vite-plugin-eslint": "^1.8.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,9 +21,9 @@ import EditableDataService from './services/editable-data-service'
|
|||||||
function App() {
|
function App() {
|
||||||
const [userData, setUserData] = useState(null);
|
const [userData, setUserData] = useState(null);
|
||||||
const [themeConfig, setThemeConfig] = useState(null);
|
const [themeConfig, setThemeConfig] = useState(null);
|
||||||
const [globalTheme, setGlobalTheme] = useState("lightTheme");
|
const [globalTheme, setGlobalTheme] = useState('lightTheme');
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [notificationMessage, setNotificationMessage] = useState("")
|
const [notificationMessage, setNotificationMessage] = useState('')
|
||||||
|
|
||||||
const notificationToggler = (message, color) => {
|
const notificationToggler = (message, color) => {
|
||||||
setIsOpen(true)
|
setIsOpen(true)
|
||||||
@ -47,23 +47,22 @@ function App() {
|
|||||||
EditableDataService.getData('/data/shared/user-data/').then( response => {
|
EditableDataService.getData('/data/shared/user-data/').then( response => {
|
||||||
let responseData = response.data[0]
|
let responseData = response.data[0]
|
||||||
setUserData({
|
setUserData({
|
||||||
"name": responseData["name"],
|
'name': responseData['name'],
|
||||||
"introContent": responseData["intro_content"],
|
'introContent': responseData['intro_content'],
|
||||||
"profilePhoto": responseData["profile_photo"],
|
'profilePhoto': responseData['profile_photo'],
|
||||||
"builtWith": responseData["built_with"]
|
'builtWith': responseData['built_with']
|
||||||
})
|
})
|
||||||
document.title = responseData.name
|
document.title = responseData.name
|
||||||
}
|
})
|
||||||
)
|
|
||||||
EditableDataService.getData('/data/shared/theme-config/').then( response =>{
|
EditableDataService.getData('/data/shared/theme-config/').then( response =>{
|
||||||
let responseData = response.data[0]
|
let responseData = response.data[0]
|
||||||
setThemeConfig({
|
setThemeConfig({
|
||||||
"defaultTheme": responseData["default_theme"],
|
'defaultTheme': responseData['default_theme'],
|
||||||
"darkTheme": JSON.parse(responseData["dark_theme"]),
|
'darkTheme': JSON.parse(responseData['dark_theme']),
|
||||||
"lightTheme": JSON.parse(responseData["light_theme"])
|
'lightTheme': JSON.parse(responseData['light_theme'])
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -76,19 +75,19 @@ function App() {
|
|||||||
|
|
||||||
if (themeConfig && userData && globalTheme)
|
if (themeConfig && userData && globalTheme)
|
||||||
return (
|
return (
|
||||||
<div className="app-container">
|
<div className='app-container'>
|
||||||
<Router>
|
<Router>
|
||||||
<Header className="header" ThemeSwitcher={themeSwitcher} GlobalTheme={globalTheme} ThemeConfig={themeConfig} UserData={userData} notificationToggler={notificationToggler} setInfo={setInfo} />
|
<Header className='header' ThemeSwitcher={themeSwitcher} GlobalTheme={globalTheme} ThemeConfig={themeConfig} UserData={userData} notificationToggler={notificationToggler} setInfo={setInfo} />
|
||||||
<div className={`p-0 ${themeConfig[globalTheme].background}`}>
|
<div className={`p-0 ${themeConfig[globalTheme].background}`}>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<Home notificationToggler={notificationToggler} GlobalTheme={globalTheme} ThemeConfig={themeConfig} UserData={userData} setInfo={setInfo} />} />
|
<Route path='/' element={<Home notificationToggler={notificationToggler} GlobalTheme={globalTheme} ThemeConfig={themeConfig} UserData={userData} setInfo={setInfo} />} />
|
||||||
<Route path="/categories" element={<CategoryList notificationToggler={notificationToggler} GlobalTheme={globalTheme} ThemeConfig={themeConfig} />} />
|
<Route path='/categories' element={<CategoryList notificationToggler={notificationToggler} GlobalTheme={globalTheme} ThemeConfig={themeConfig} />} />
|
||||||
<Route path="/categories/:categoryID" element={<BlogList notificationToggler={notificationToggler} GlobalTheme={globalTheme} ThemeConfig={themeConfig} />} />
|
<Route path='/categories/:categoryID' element={<BlogList notificationToggler={notificationToggler} GlobalTheme={globalTheme} ThemeConfig={themeConfig} />} />
|
||||||
<Route path="/blog/:blogID" element={<Blog notificationToggler={notificationToggler} GlobalTheme={globalTheme} ThemeConfig={themeConfig} />} />
|
<Route path='/blog/:blogID' element={<Blog notificationToggler={notificationToggler} GlobalTheme={globalTheme} ThemeConfig={themeConfig} />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
<Footer notificationToggler={notificationToggler} setInfo={setInfo} className="footer" ThemeSwitcher={themeSwitcher} GlobalTheme={globalTheme} ThemeConfig={themeConfig} UserData={userData} />
|
<Footer notificationToggler={notificationToggler} setInfo={setInfo} className='footer' ThemeSwitcher={themeSwitcher} GlobalTheme={globalTheme} ThemeConfig={themeConfig} UserData={userData} />
|
||||||
<Notification style={{width: '20%'}} className="fixed-top" isOpen={isOpen} message={notificationMessage} />
|
<Notification style={{width: '20%'}} className='fixed-top' isOpen={isOpen} message={notificationMessage} />
|
||||||
</Router>
|
</Router>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -29,33 +29,32 @@ function BlogList(props) {
|
|||||||
const [featuredBlogData, setFeaturedBlogData] = useState(null);
|
const [featuredBlogData, setFeaturedBlogData] = useState(null);
|
||||||
|
|
||||||
const loadBlogs = () => {
|
const loadBlogs = () => {
|
||||||
EditableDataService.getData(`/data/category/${categoryID}/`).then(response => {
|
EditableDataService.getData(`/data/category/${categoryID}/`).then( response => {
|
||||||
let responseData = response.data
|
let responseData = response.data
|
||||||
let blogMetadata = []
|
let blogMetadata = []
|
||||||
let localCategoryData = {
|
let localCategoryData = {
|
||||||
"id": responseData["category_id"],
|
'id': responseData['category_id'],
|
||||||
"name": responseData["name"],
|
'name': responseData['name'],
|
||||||
"coverImage": responseData["cover_image"],
|
'coverImage': responseData['cover_image'],
|
||||||
"tagLine": responseData["tagline"],
|
'tagLine': responseData['tagline'],
|
||||||
"description": responseData["description"],
|
'description': responseData['description'],
|
||||||
"featuredBlog": responseData["featured_id"],
|
'featuredBlog': responseData['featured_id'],
|
||||||
"blogMetadata": responseData["blog_metadata"]
|
'blogMetadata': responseData['blog_metadata']
|
||||||
}
|
}
|
||||||
for (let eachBlog of responseData["blog_metadata"]){
|
for (let eachBlog of responseData['blog_metadata']){
|
||||||
blogMetadata.push({
|
blogMetadata.push({
|
||||||
"id": eachBlog["blog_id"],
|
'id': eachBlog['blog_id'],
|
||||||
"name": eachBlog["name"],
|
'name': eachBlog['name'],
|
||||||
"description": eachBlog["description"],
|
'description': eachBlog['description'],
|
||||||
"tagLine": eachBlog["tagline"],
|
'tagLine': eachBlog['tagline'],
|
||||||
"coverImage": eachBlog["cover_image"],
|
'coverImage': eachBlog['cover_image'],
|
||||||
"parentCategory": eachBlog["parent_category"]
|
'parentCategory': eachBlog['parent_category']
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
localCategoryData.blogMetadata = blogMetadata
|
localCategoryData.blogMetadata = blogMetadata
|
||||||
setCategoryData(localCategoryData)
|
setCategoryData(localCategoryData)
|
||||||
setFeaturedBlogData(blogMetadata.find(blog => blog.id === localCategoryData.featuredBlog))
|
setFeaturedBlogData(blogMetadata.find(blog => blog.id === localCategoryData.featuredBlog))
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -63,23 +62,23 @@ function BlogList(props) {
|
|||||||
}, [categoryID]);
|
}, [categoryID]);
|
||||||
|
|
||||||
const addNewBlog = () => {
|
const addNewBlog = () => {
|
||||||
EditableDataService.createData(`/data/blog/create/`, {
|
EditableDataService.createData('/data/blog/create/', {
|
||||||
"name": "Enter a blog name",
|
'name': 'Enter a blog name',
|
||||||
"description": "Enter a description",
|
'description': 'Enter a description',
|
||||||
"tagline": "Enter a tagline",
|
'tagline': 'Enter a tagline',
|
||||||
"cover_image": "",
|
'cover_image': '',
|
||||||
"content_body": "<p></p>",
|
'content_body': '<p></p>',
|
||||||
"parent_category": categoryID
|
'parent_category': categoryID
|
||||||
}).then(response => {
|
}).then(() => {
|
||||||
props.notificationToggler("New blog created")
|
props.notificationToggler('New blog created')
|
||||||
loadBlogs()
|
loadBlogs()
|
||||||
}).catch(error => {
|
}).catch(() => {
|
||||||
props.notificationToggler('Failed to add a new blog', 'danger');
|
props.notificationToggler('Failed to add a new blog', 'danger');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateFeaturedBlog = (featuredId) => {
|
const updateFeaturedBlog = (featuredId) => {
|
||||||
EditableDataService.updateData(`/data/category/update/${categoryID}/`, {"featured_id": featuredId}).then(response=>{
|
EditableDataService.updateData(`/data/category/update/${categoryID}/`, {'featured_id': featuredId}).then(() =>{
|
||||||
if (featuredId)
|
if (featuredId)
|
||||||
props.notificationToggler('Blog set as featured')
|
props.notificationToggler('Blog set as featured')
|
||||||
else props.notificationToggler('Featured blog removed')
|
else props.notificationToggler('Featured blog removed')
|
||||||
@ -88,30 +87,30 @@ function BlogList(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (GlobalTheme && ThemeConfig) {
|
if (GlobalTheme && ThemeConfig) {
|
||||||
return (
|
return (
|
||||||
<Container fluid className={`mb-2 p-0 ${ThemeConfig[GlobalTheme].background}`}>
|
<Container fluid className={`mb-2 p-0 ${ThemeConfig[GlobalTheme].background}`}>
|
||||||
<Col className="d-md-block"><Button color={ThemeConfig[GlobalTheme].buttonColor} onClick={() => navigate(`/categories/`)} className="ms-5 mt-5" outline><FontAwesomeIcon icon={faLeftLong}/></Button></Col>
|
<Col className='d-md-block'><Button color={ThemeConfig[GlobalTheme].buttonColor} onClick={() => navigate('/categories/')} className='ms-5 mt-5' outline><FontAwesomeIcon icon={faLeftLong}/></Button></Col>
|
||||||
<CategoryBar currentPage={categoryID} GlobalTheme={GlobalTheme} ThemeConfig={ThemeConfig} />
|
<CategoryBar currentPage={categoryID} GlobalTheme={GlobalTheme} ThemeConfig={ThemeConfig} />
|
||||||
<Row className="justify-content-center align-items-center">
|
<Row className='justify-content-center align-items-center'>
|
||||||
<Col className="d-flex flex-column align-items-center">
|
<Col className='d-flex flex-column align-items-center'>
|
||||||
<div className="w-100">
|
<div className='w-100'>
|
||||||
<Card className={`my-2 ${ThemeConfig[GlobalTheme].background}`} style={{ width: "100%", border: "none" }}>
|
<Card className={`my-2 ${ThemeConfig[GlobalTheme].background}`} style={{ width: '100%', border: 'none' }}>
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<CardTitle style={{ display: "grid" }} className={`${ThemeConfig[GlobalTheme].textColor} justify-content-center`} tag="h1">
|
<CardTitle style={{ display: 'grid' }} className={`${ThemeConfig[GlobalTheme].textColor} justify-content-center`} tag='h1'>
|
||||||
{`Blogs in ${categoryData.name}`}
|
{`Blogs in ${categoryData.name}`}
|
||||||
<Button className='mt-2' color={ThemeConfig[GlobalTheme].buttonColor} outline onClick={() => addNewBlog()}>Add New</Button>
|
<Button className='mt-2' color={ThemeConfig[GlobalTheme].buttonColor} outline onClick={() => addNewBlog()}>Add New</Button>
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
<div className="container">
|
<div className='container'>
|
||||||
{
|
{
|
||||||
featuredBlogData ?
|
featuredBlogData ?
|
||||||
<CardListViewer
|
<CardListViewer
|
||||||
key={featuredBlogData.id}
|
key={featuredBlogData.id}
|
||||||
totalItems={featuredBlogData === 'nodata' ? 0 : 1}
|
totalItems={featuredBlogData === 'nodata' ? 0 : 1}
|
||||||
cardType={"longCard"}
|
cardType={'longCard'}
|
||||||
resourceType={"blog"}
|
resourceType={'blog'}
|
||||||
textColor={ThemeConfig[GlobalTheme].textColor}
|
textColor={ThemeConfig[GlobalTheme].textColor}
|
||||||
bgColor={ThemeConfig[GlobalTheme].background}
|
bgColor={ThemeConfig[GlobalTheme].background}
|
||||||
borderColor={ThemeConfig[GlobalTheme].borderColor}
|
borderColor={ThemeConfig[GlobalTheme].borderColor}
|
||||||
@ -119,16 +118,16 @@ return (
|
|||||||
/> : ''
|
/> : ''
|
||||||
}
|
}
|
||||||
<Row>
|
<Row>
|
||||||
{categoryData === 'loading' ? <Spinner /> :
|
{ categoryData === 'loading' ? <Spinner /> :
|
||||||
categoryData.blogMetadata.map((item, index) => (
|
categoryData.blogMetadata.map((item) => (
|
||||||
<Col key={item.blog_id}>
|
<Col key={item.blog_id}>
|
||||||
<div className={`p-2 ml-2 ${ThemeConfig[GlobalTheme].textColor}`}>
|
<div className={`p-2 ml-2 ${ThemeConfig[GlobalTheme].textColor}`}>
|
||||||
<CardListViewer
|
<CardListViewer
|
||||||
totalItems={categoryData.blogMetadata.length}
|
totalItems={categoryData.blogMetadata.length}
|
||||||
featuredBlog={categoryData.featuredBlog}
|
featuredBlog={categoryData.featuredBlog}
|
||||||
updateFeaturedBlog={updateFeaturedBlog}
|
updateFeaturedBlog={updateFeaturedBlog}
|
||||||
cardType={"smallCard"}
|
cardType={'smallCard'}
|
||||||
resourceType={"blog"}
|
resourceType={'blog'}
|
||||||
textColor={ThemeConfig[GlobalTheme].textColor}
|
textColor={ThemeConfig[GlobalTheme].textColor}
|
||||||
bgColor={ThemeConfig[GlobalTheme].background}
|
bgColor={ThemeConfig[GlobalTheme].background}
|
||||||
borderColor={ThemeConfig[GlobalTheme].borderColor}
|
borderColor={ThemeConfig[GlobalTheme].borderColor}
|
||||||
@ -143,11 +142,9 @@ return (
|
|||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BlogList
|
export default BlogList
|
||||||
@ -11,7 +11,7 @@ import { faLeftLong } from '@fortawesome/free-solid-svg-icons';
|
|||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Container,Row, Col,Spinner, UncontrolledCollapse, Button, ButtonGroup, Card, CardBody, Input, InputGroup, InputGroupText
|
Container,Row, Col,Spinner, Button, ButtonGroup, Input, InputGroup, InputGroupText
|
||||||
} from 'reactstrap';
|
} from 'reactstrap';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
|
|
||||||
@ -39,17 +39,17 @@ function Blog(props) {
|
|||||||
const toggle = () => setModal(!modal);
|
const toggle = () => setModal(!modal);
|
||||||
const toggleFileModal = () => setFileModal(!fileModal);
|
const toggleFileModal = () => setFileModal(!fileModal);
|
||||||
|
|
||||||
const setInfo = (event) => {
|
const setInfo = () => {
|
||||||
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
|
'cover_image': coverImage ? coverImage !== '-' ? coverImage : '' : blogData.coverImage
|
||||||
}).then(response => {
|
}).then(() => {
|
||||||
props.notificationToggler('Blog data saved!');
|
props.notificationToggler('Blog data saved!');
|
||||||
getInfo()
|
getInfo()
|
||||||
}).catch(error => {
|
}).catch(() => {
|
||||||
props.notificationToggler('Failed to update blog!', 'danger');
|
props.notificationToggler('Failed to update blog!', 'danger');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -61,10 +61,10 @@ function Blog(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const deleteResource = () => {
|
const deleteResource = () => {
|
||||||
EditableDataService.deleteData(`/data/blog/delete/${blogData.id}/`).then(response => {
|
EditableDataService.deleteData(`/data/blog/delete/${blogData.id}/`).then(() => {
|
||||||
props.notificationToggler('Blog successfully deleted')
|
props.notificationToggler('Blog successfully deleted')
|
||||||
navigate(`/categories/${blogData.parentCategory}`);
|
navigate(`/categories/${blogData.parentCategory}`);
|
||||||
}).catch(error => {
|
}).catch(() => {
|
||||||
props.notificationToggler('Failed to delete blog', 'danger');
|
props.notificationToggler('Failed to delete blog', 'danger');
|
||||||
});
|
});
|
||||||
toggle()
|
toggle()
|
||||||
@ -74,16 +74,15 @@ function Blog(props) {
|
|||||||
EditableDataService.getData(`/data/blog/${blogID}/`).then(response => {
|
EditableDataService.getData(`/data/blog/${blogID}/`).then(response => {
|
||||||
let responseData = response.data
|
let responseData = response.data
|
||||||
setBlogData({
|
setBlogData({
|
||||||
"id": responseData["blog_id"],
|
'id': responseData['blog_id'],
|
||||||
"name": responseData["name"],
|
'name': responseData['name'],
|
||||||
"description": responseData["description"],
|
'description': responseData['description'],
|
||||||
"tagLine": responseData["tagline"],
|
'tagLine': responseData['tagline'],
|
||||||
"coverImage": responseData["cover_image"],
|
'coverImage': responseData['cover_image'],
|
||||||
"parentCategory": responseData["parent_category"]
|
'parentCategory': responseData['parent_category']
|
||||||
})
|
})
|
||||||
setBlogContent(responseData["content_body"])
|
setBlogContent(responseData['content_body'])
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -102,25 +101,25 @@ function Blog(props) {
|
|||||||
<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='blog' resourceId={blogData.id}></MediaUpload>
|
<MediaUpload setMedia={setCoverImage} notificationToggler={props.notificationToggler} modal={fileModal} toggle={toggleFileModal} resourceType='blog' resourceId={blogData.id}></MediaUpload>
|
||||||
<Col xs="3" className="d-md-block"><Button color={ThemeConfig[GlobalTheme].buttonColor} onClick={() => navigate(`/categories/${blogData.parentCategory}`)} className="ms-5 mt-5" outline><FontAwesomeIcon icon={faLeftLong}/></Button></Col>
|
<Col xs='3' className='d-md-block'><Button color={ThemeConfig[GlobalTheme].buttonColor} onClick={() => navigate(`/categories/${blogData.parentCategory}`)} className='ms-5 mt-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'>
|
||||||
<Col className="p-0">
|
<Col className='p-0'>
|
||||||
{
|
{
|
||||||
blogData.coverImage !== "" ?
|
blogData.coverImage !== '' ?
|
||||||
<img
|
<img
|
||||||
src={EditableMediaService.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' }}
|
||||||
/>:""
|
/>:''
|
||||||
}
|
}
|
||||||
</Col>
|
</Col>
|
||||||
</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">
|
<ButtonGroup className='mb-5 ms-5'>
|
||||||
<Button
|
<Button
|
||||||
outline
|
outline
|
||||||
color={ThemeConfig[GlobalTheme].buttonColor}
|
color={ThemeConfig[GlobalTheme].buttonColor}
|
||||||
@ -136,39 +135,33 @@ function Blog(props) {
|
|||||||
Remove Cover Image
|
Remove Cover Image
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
<InputGroup className="mb-3">
|
<InputGroup className='mb-3'>
|
||||||
<InputGroupText>
|
<InputGroupText>Name</InputGroupText>
|
||||||
Name
|
|
||||||
</InputGroupText>
|
|
||||||
<Input innerRef={nameField} defaultValue={blogData.name} />
|
<Input innerRef={nameField} defaultValue={blogData.name} />
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
<InputGroup className="mb-3">
|
<InputGroup className='mb-3'>
|
||||||
<InputGroupText>
|
<InputGroupText>Description</InputGroupText>
|
||||||
Description
|
|
||||||
</InputGroupText>
|
|
||||||
<Input innerRef={descriptionField} defaultValue={blogData.description} />
|
<Input innerRef={descriptionField} defaultValue={blogData.description} />
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
<InputGroup>
|
<InputGroup>
|
||||||
<InputGroupText>
|
<InputGroupText>Tagline</InputGroupText>
|
||||||
Tagline
|
|
||||||
</InputGroupText>
|
|
||||||
<Input innerRef={tagLineField} defaultValue={blogData.tagLine} />
|
<Input innerRef={tagLineField} defaultValue={blogData.tagLine} />
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs="3" className="d-none d-md-block"></Col>
|
<Col xs='3' className='d-none d-md-block'></Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Row className={`my-2 ${ThemeConfig[GlobalTheme].background}`}>
|
<Row className={`my-2 ${ThemeConfig[GlobalTheme].background}`}>
|
||||||
<Col>
|
<Col>
|
||||||
<hr style={{"borderColor": `${ThemeConfig[GlobalTheme].borderColor}`}} />
|
<hr style={{'borderColor': `${ThemeConfig[GlobalTheme].borderColor}`}} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Row className="mr-2 ml-2 mt-1">
|
<Row className='mr-2 ml-2 mt-1'>
|
||||||
<Col xs="3" className="d-none d-md-block"></Col>
|
<Col xs='3' className='d-none d-md-block'></Col>
|
||||||
<Col className={`blogContent ${ThemeConfig[GlobalTheme].textColor}`} style={{marginBottom: '25px'}}>
|
<Col className={`blogContent ${ThemeConfig[GlobalTheme].textColor}`} style={{marginBottom: '25px'}}>
|
||||||
<EditorComponent notificationToggler={props.notificationToggler} setContent={setBlogContent} GlobalTheme={GlobalTheme} ThemeConfig={ThemeConfig} content={blogContent} resourceType='blog' resourceId={blogData.id}/>
|
<EditorComponent notificationToggler={props.notificationToggler} setContent={setBlogContent} GlobalTheme={GlobalTheme} ThemeConfig={ThemeConfig} content={blogContent} resourceType='blog' resourceId={blogData.id}/>
|
||||||
<Button className='mt-3 mb-2' onClick={(event) => setInfo(event)} color={ThemeConfig[GlobalTheme].buttonColor} outline>Save Data</Button>
|
<Button className='mt-3 mb-2' onClick={(event) => setInfo(event)} color={ThemeConfig[GlobalTheme].buttonColor} outline>Save Data</Button>
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs="3" className="d-none d-md-block"></Col>
|
<Col xs='3' className='d-none d-md-block'></Col>
|
||||||
</Row>
|
</Row>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -12,12 +12,9 @@ import {
|
|||||||
Col,
|
Col,
|
||||||
Container,
|
Container,
|
||||||
Card,
|
Card,
|
||||||
CardImg,
|
|
||||||
CardTitle,
|
CardTitle,
|
||||||
CardText,
|
|
||||||
CardBody,
|
CardBody,
|
||||||
Button,
|
Button,
|
||||||
ButtonGroup
|
|
||||||
} from 'reactstrap';
|
} from 'reactstrap';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { faLeftLong } from '@fortawesome/free-solid-svg-icons';
|
import { faLeftLong } from '@fortawesome/free-solid-svg-icons';
|
||||||
@ -42,61 +39,58 @@ function Blogs(props) {
|
|||||||
let localCategoryMetadata = []
|
let localCategoryMetadata = []
|
||||||
for (let eachResponse of responseData){
|
for (let eachResponse of responseData){
|
||||||
localCategoryMetadata.push({
|
localCategoryMetadata.push({
|
||||||
"id": eachResponse["category_id"],
|
'id': eachResponse['category_id'],
|
||||||
"name": eachResponse["name"],
|
'name': eachResponse['name'],
|
||||||
"featuredBlog": eachResponse["featured_id"],
|
'featuredBlog': eachResponse['featured_id'],
|
||||||
"description": eachResponse["description"],
|
'description': eachResponse['description'],
|
||||||
"tagLine": eachResponse["tagline"],
|
'tagLine': eachResponse['tagline'],
|
||||||
"coverImage": eachResponse["cover_image"]
|
'coverImage': eachResponse['cover_image']
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
setCategoryMetadata(localCategoryMetadata)
|
setCategoryMetadata(localCategoryMetadata)
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const addToIdsToUpdate = (resourceObject) => {
|
const addToIdsToUpdate = (resourceObject) => {
|
||||||
let localIdsToUpdate = {...idsToUpdate}
|
let localIdsToUpdate = {...idsToUpdate}
|
||||||
localIdsToUpdate[resourceObject.id]={
|
localIdsToUpdate[resourceObject.id]={
|
||||||
"name": resourceObject.name,
|
'name': resourceObject.name,
|
||||||
"featured_blog": resourceObject.featuredBlog,
|
'featured_blog': resourceObject.featuredBlog,
|
||||||
"description": resourceObject.description,
|
'description': resourceObject.description,
|
||||||
"tagline": resourceObject.tagLine,
|
'tagline': resourceObject.tagLine,
|
||||||
"cover_image": resourceObject.coverImage
|
'cover_image': resourceObject.coverImage
|
||||||
}
|
}
|
||||||
setIdsToUpdate(localIdsToUpdate)
|
setIdsToUpdate(localIdsToUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteResource = (id) => {
|
const deleteResource = (id) => {
|
||||||
EditableDataService.deleteData(`/data/category/delete/${id}/`).then(response => {
|
EditableDataService.deleteData(`/data/category/delete/${id}/`).then(() => {
|
||||||
props.notificationToggler('Category successfully deleted')
|
props.notificationToggler('Category successfully deleted')
|
||||||
setCategoryData()
|
setCategoryData()
|
||||||
}).catch(error => {
|
}).catch(() => {
|
||||||
props.notificationToggler('Failed to delete category', 'danger');
|
props.notificationToggler('Failed to delete category', 'danger');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const addNewCategory = () => {
|
const addNewCategory = () => {
|
||||||
EditableDataService.createData('/data/category/create/', {
|
EditableDataService.createData('/data/category/create/', {
|
||||||
"name": "Enter name",
|
'name': 'Enter name',
|
||||||
"featured_id": "",
|
'featured_id': '',
|
||||||
"description": "Enter description",
|
'description': 'Enter description',
|
||||||
"tagline": "Enter tagline",
|
'tagline': 'Enter tagline',
|
||||||
"cover_image": ""
|
'cover_image': ''
|
||||||
}).then(response => {
|
}).then(() => {
|
||||||
props.notificationToggler('Category created successfully')
|
props.notificationToggler('Category created successfully')
|
||||||
setCategoryData()
|
setCategoryData()}).catch(() => {
|
||||||
}
|
|
||||||
).catch(error => {
|
|
||||||
props.notificationToggler('Failed to add category', 'danger');
|
props.notificationToggler('Failed to add category', 'danger');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateInfo = () => {
|
const updateInfo = () => {
|
||||||
for (let id of Object.keys(idsToUpdate)) {
|
for (let id of Object.keys(idsToUpdate)) {
|
||||||
EditableDataService.updateData(`/data/category/update/${id}/`, idsToUpdate[id]).then(response=>{
|
EditableDataService.updateData(`/data/category/update/${id}/`, idsToUpdate[id]).then( () =>{
|
||||||
props.notificationToggler('Category data updated successfully')
|
props.notificationToggler('Category data updated successfully')
|
||||||
}).catch(error => {
|
}).catch( () => {
|
||||||
props.notificationToggler('Failed to update category data', 'danger');
|
props.notificationToggler('Failed to update category data', 'danger');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -106,32 +100,30 @@ function Blogs(props) {
|
|||||||
if (GlobalTheme && ThemeConfig) {
|
if (GlobalTheme && ThemeConfig) {
|
||||||
return (
|
return (
|
||||||
<Container fluid className={`p-0 mb-2 ${ThemeConfig[GlobalTheme].background}`}>
|
<Container fluid className={`p-0 mb-2 ${ThemeConfig[GlobalTheme].background}`}>
|
||||||
<Col xs="3" className="d-md-block"><Button color={ThemeConfig[GlobalTheme].buttonColor} onClick={() => navigate(`/`)} className="ms-5 mt-5" outline><FontAwesomeIcon icon={faLeftLong}/></Button></Col>
|
<Col xs='3' className='d-md-block'><Button color={ThemeConfig[GlobalTheme].buttonColor} onClick={() => navigate('/')} className='ms-5 mt-5' outline><FontAwesomeIcon icon={faLeftLong}/></Button></Col>
|
||||||
<Row className="justify-content-center align-items-center">
|
<Row className='justify-content-center align-items-center'>
|
||||||
<Col className="d-flex flex-column align-items-center">
|
<Col className='d-flex flex-column align-items-center'>
|
||||||
<div className="w-100">
|
<div className='w-100'>
|
||||||
<Card className={`my-2 ${ThemeConfig[GlobalTheme].background}`} style={{width: "100%", border: "none"}}>
|
<Card className={`my-2 ${ThemeConfig[GlobalTheme].background}`} style={{width: '100%', border: 'none'}}>
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<CardTitle style={{ display: "grid" }} className={`${ThemeConfig[GlobalTheme].textColor} justify-content-center`} tag="h1">
|
<CardTitle style={{ display: 'grid' }} className={`${ThemeConfig[GlobalTheme].textColor} justify-content-center`} tag='h1'>
|
||||||
{"Categories"}
|
{'Categories'}
|
||||||
<Button className='mt-2' color={ThemeConfig[GlobalTheme].buttonColor} outline onClick={() => addNewCategory()}>Add New</Button>
|
<Button className='mt-2' color={ThemeConfig[GlobalTheme].buttonColor} outline onClick={() => addNewCategory()}>Add New</Button>
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
<div className='' style={{ width: '70%', margin: 'auto' }}>
|
||||||
<div className="" style={{ width: '70%', margin: 'auto' }}>
|
|
||||||
|
|
||||||
{categoryMetadata.length > 0 ?
|
{categoryMetadata.length > 0 ?
|
||||||
categoryMetadata.map((item, index) => (
|
categoryMetadata.map((item) => (
|
||||||
<CardListViewer
|
<CardListViewer
|
||||||
key={item.id}
|
key={item.id}
|
||||||
id = {item.id}
|
id = {item.id}
|
||||||
totalItems={categoryMetadata.length}
|
totalItems={categoryMetadata.length}
|
||||||
addToIdsToUpdate={addToIdsToUpdate}
|
addToIdsToUpdate={addToIdsToUpdate}
|
||||||
cardType={"longCard"}
|
cardType={'longCard'}
|
||||||
deleteResource={deleteResource}
|
deleteResource={deleteResource}
|
||||||
resourceType={"categories"}
|
resourceType={'categories'}
|
||||||
textColor={ThemeConfig[GlobalTheme].textColor}
|
textColor={ThemeConfig[GlobalTheme].textColor}
|
||||||
bgColor={ThemeConfig[GlobalTheme].background}
|
bgColor={ThemeConfig[GlobalTheme].background}
|
||||||
borderColor={ThemeConfig[GlobalTheme].borderColor}
|
borderColor={ThemeConfig[GlobalTheme].borderColor}
|
||||||
@ -143,7 +135,6 @@ function Blogs(props) {
|
|||||||
<Button className='mt-3 mb-2' onClick={() => updateInfo()} color={ThemeConfig[GlobalTheme].buttonColor} outline>Save Data</Button>
|
<Button className='mt-3 mb-2' onClick={() => updateInfo()} color={ThemeConfig[GlobalTheme].buttonColor} outline>Save Data</Button>
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
</Row>
|
</Row>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import MediaUpload from './shared/media-upload'
|
|||||||
import EditableMediaService from '../services/editable-media-service'
|
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 [profilePhoto, setProfilePhoto] = useState(false)
|
||||||
const [nameFieldInvalid, setNameFieldInvalid] = useState(false)
|
const [nameFieldInvalid, setNameFieldInvalid] = useState(false)
|
||||||
const [modal, setModal] = useState(false)
|
const [modal, setModal] = useState(false)
|
||||||
@ -16,21 +16,19 @@ function HomePage(props) {
|
|||||||
|
|
||||||
const setInfo = async () => {
|
const setInfo = async () => {
|
||||||
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": profilePhoto ? profilePhoto !== '-' ? profilePhoto : '' : UserData.profilePhoto
|
'profile_photo': profilePhoto ? profilePhoto !== '-' ? profilePhoto : '' : UserData.profilePhoto
|
||||||
})
|
})
|
||||||
console.log(response)
|
|
||||||
if (response === 200)
|
if (response === 200)
|
||||||
props.notificationToggler("Data saved successfully!")
|
props.notificationToggler('Data saved successfully!')
|
||||||
if ([500, 404, 403, 400].includes(response))
|
if ([500, 404, 403, 400].includes(response))
|
||||||
props.notificationToggler("Something failed!", "danger")
|
props.notificationToggler('Something failed!', 'danger')
|
||||||
}
|
}
|
||||||
|
|
||||||
const toggle = () => {setModal(!modal)}
|
const toggle = () => {setModal(!modal)}
|
||||||
|
|
||||||
const showError = (elementValue, fieldType) => {
|
const showError = (elementValue, fieldType) => {
|
||||||
console.log(elementValue)
|
|
||||||
if (fieldType === 'nameField'){
|
if (fieldType === 'nameField'){
|
||||||
if (elementValue === '')
|
if (elementValue === '')
|
||||||
setNameFieldInvalid(true)
|
setNameFieldInvalid(true)
|
||||||
@ -54,15 +52,15 @@ function HomePage(props) {
|
|||||||
return (
|
return (
|
||||||
<Container fluid className={`${ThemeConfig[GlobalTheme].textColor} ${ThemeConfig[GlobalTheme].background}`}>
|
<Container fluid className={`${ThemeConfig[GlobalTheme].textColor} ${ThemeConfig[GlobalTheme].background}`}>
|
||||||
<MediaUpload setMedia={setProfilePhoto} notificationToggler={props.notificationToggler} modal={modal} toggle={toggle} resourceType='homepage' resourceId='homepage' />
|
<MediaUpload setMedia={setProfilePhoto} notificationToggler={props.notificationToggler} modal={modal} toggle={toggle} resourceType='homepage' resourceId='homepage' />
|
||||||
<Row className="mb-4">
|
<Row className='mb-4'>
|
||||||
<Col xs="3" className="d-none d-md-block"></Col>
|
<Col xs='3' className='d-none d-md-block'></Col>
|
||||||
<Col className="p-0">
|
<Col className='p-0'>
|
||||||
<Row className='d-md-block'>
|
<Row className='d-md-block'>
|
||||||
<Col xs="4" className="d-none d-md-block"></Col>
|
<Col xs='4' className='d-none d-md-block'></Col>
|
||||||
{UserData.profilePhoto !== "" && (
|
{UserData.profilePhoto !== '' && (
|
||||||
<center><img style={{ width: '180px', height: '180px', objectFit: 'cover' }} className="mt-5 mb-2 rounded-circle" src={EditableMediaService.getMedia(UserData.profilePhoto)} alt="Profile Photo" /></center>
|
<center><img style={{ width: '180px', height: '180px', objectFit: 'cover' }} className='mt-5 mb-2 rounded-circle' src={EditableMediaService.getMedia(UserData.profilePhoto)} alt='Profile Photo' /></center>
|
||||||
)}
|
)}
|
||||||
<Col xs="4" className="d-none d-md-block"></Col>
|
<Col xs='4' className='d-none d-md-block'></Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<ButtonGroup className='mt-4'>
|
<ButtonGroup className='mt-4'>
|
||||||
@ -83,25 +81,23 @@ function HomePage(props) {
|
|||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
</Row>
|
</Row>
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs="3" className="d-none d-md-block"></Col>
|
<Col xs='3' className='d-none d-md-block'></Col>
|
||||||
</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 md="6" xs="12">
|
<Col md='6' xs='12'>
|
||||||
<InputGroup className='mb-5'>
|
<InputGroup className='mb-5'>
|
||||||
<InputGroupText>Name</InputGroupText>
|
<InputGroupText>Name</InputGroupText>
|
||||||
<Input invalid={nameFieldInvalid} innerRef={nameField} defaultValue={UserData.name} onChange={() => showError(nameField.current.value, 'nameField')}/>
|
<Input invalid={nameFieldInvalid} innerRef={nameField} defaultValue={UserData.name} onChange={() => showError(nameField.current.value, 'nameField')}/>
|
||||||
{nameFieldInvalid && <FormFeedback tooltip className="mt-1">
|
{nameFieldInvalid && <FormFeedback tooltip className='mt-1'>
|
||||||
This field cannot be empty
|
This field cannot be empty
|
||||||
</FormFeedback>}
|
</FormFeedback>}
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
<EditorComponent notificationToggler={props.notificationToggler} GlobalTheme={GlobalTheme} ThemeConfig={ThemeConfig} content={UserData.introContent} setContent={setIntroContent} resourceType='homepage' resourceId='homepage' />
|
<EditorComponent notificationToggler={props.notificationToggler} GlobalTheme={GlobalTheme} ThemeConfig={ThemeConfig} content={UserData.introContent} setContent={setIntroContent} resourceType='homepage' resourceId='homepage' />
|
||||||
<Button className='mt-3 mb-2' onClick={() => setInfo()} color={ThemeConfig[GlobalTheme].buttonColor} outline>Save Data</Button>
|
<Button className='mt-3 mb-2' onClick={() => setInfo()} color={ThemeConfig[GlobalTheme].buttonColor} outline>Save Data</Button>
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs="3" className="d-none d-md-block"></Col>
|
<Col xs='3' className='d-none d-md-block'></Col>
|
||||||
|
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,11 +46,11 @@ function CardListViewer(props) {
|
|||||||
setTaglineFieldInvalid(false)
|
setTaglineFieldInvalid(false)
|
||||||
}
|
}
|
||||||
props.addToIdsToUpdate({
|
props.addToIdsToUpdate({
|
||||||
"id": props.id,
|
'id': props.id,
|
||||||
"name": nameField.current.value,
|
'name': nameField.current.value,
|
||||||
"featuredBlog": "",
|
'featuredBlog': '',
|
||||||
"description": descriptionField.current.value,
|
'description': descriptionField.current.value,
|
||||||
"tagLine": taglineField.current.value,
|
'tagLine': taglineField.current.value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,15 +72,15 @@ function CardListViewer(props) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<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%'}}>
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<CardTitle className={`mb-3 ${props.textColor}`} tag="h5">
|
<CardTitle className={`mb-3 ${props.textColor}`} tag='h5'>
|
||||||
<InputGroup>
|
<InputGroup>
|
||||||
<InputGroupText>
|
<InputGroupText>
|
||||||
Name
|
Name
|
||||||
</InputGroupText>
|
</InputGroupText>
|
||||||
<Input defaultValue={itemObject.name} invalid={nameFieldInvalid} innerRef={nameField} onChange={() => handleInputUpdate(nameField.current.value, 'nameField')}/>
|
<Input defaultValue={itemObject.name} invalid={nameFieldInvalid} innerRef={nameField} onChange={() => handleInputUpdate(nameField.current.value, 'nameField')}/>
|
||||||
{nameFieldInvalid ? <FormFeedback tooltip className="mt-1">
|
{nameFieldInvalid ? <FormFeedback tooltip className='mt-1'>
|
||||||
This field cannot be empty
|
This field cannot be empty
|
||||||
</FormFeedback>:''}
|
</FormFeedback>:''}
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
@ -91,7 +91,7 @@ function CardListViewer(props) {
|
|||||||
Description
|
Description
|
||||||
</InputGroupText>
|
</InputGroupText>
|
||||||
<Input defaultValue={itemObject.description} invalid={descriptionFieldInvalid} innerRef={descriptionField} onChange={() => handleInputUpdate(descriptionField.current.value, 'descriptionField')}/>
|
<Input defaultValue={itemObject.description} invalid={descriptionFieldInvalid} innerRef={descriptionField} onChange={() => handleInputUpdate(descriptionField.current.value, 'descriptionField')}/>
|
||||||
{descriptionFieldInvalid ? <FormFeedback tooltip className="mt-1">
|
{descriptionFieldInvalid ? <FormFeedback tooltip className='mt-1'>
|
||||||
This field cannot be empty
|
This field cannot be empty
|
||||||
</FormFeedback>:''}
|
</FormFeedback>:''}
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
@ -103,7 +103,7 @@ function CardListViewer(props) {
|
|||||||
Tagline
|
Tagline
|
||||||
</InputGroupText>
|
</InputGroupText>
|
||||||
<Input defaultValue={itemObject.tagLine} invalid={taglineFieldInvalid} innerRef={taglineField} onChange={() => handleInputUpdate(taglineField.current.value, 'taglineField')} />
|
<Input defaultValue={itemObject.tagLine} invalid={taglineFieldInvalid} innerRef={taglineField} onChange={() => handleInputUpdate(taglineField.current.value, 'taglineField')} />
|
||||||
{taglineFieldInvalid ? <FormFeedback tooltip className="mt-1">
|
{taglineFieldInvalid ? <FormFeedback tooltip className='mt-1'>
|
||||||
This field cannot be empty
|
This field cannot be empty
|
||||||
</FormFeedback>:''}
|
</FormFeedback>:''}
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
@ -113,7 +113,7 @@ function CardListViewer(props) {
|
|||||||
<Link className={`${props.textColor}`} to={`/${props.resourceType}/${itemObject.id}`}>
|
<Link className={`${props.textColor}`} to={`/${props.resourceType}/${itemObject.id}`}>
|
||||||
Open this resource
|
Open this resource
|
||||||
</Link>
|
</Link>
|
||||||
<Button color='danger' onClick={() => showModal()} className="m-2">Delete Category</Button>
|
<Button color='danger' onClick={() => showModal()} className='m-2'>Delete Category</Button>
|
||||||
</CardText>
|
</CardText>
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
@ -121,17 +121,17 @@ 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={EditableMediaService.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'>
|
||||||
{itemObject.name}
|
{itemObject.name}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardText className={`${props.textColor}`} tag="h5">
|
<CardText className={`${props.textColor}`} tag='h5'>
|
||||||
{itemObject.description}
|
{itemObject.description}
|
||||||
</CardText>
|
</CardText>
|
||||||
<CardText tag="h6">
|
<CardText tag='h6'>
|
||||||
<small className={`${props.textColor}`}>
|
<small className={`${props.textColor}`}>
|
||||||
{itemObject.tagLine}
|
{itemObject.tagLine}
|
||||||
</small>
|
</small>
|
||||||
@ -158,6 +158,6 @@ function CardListViewer(props) {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
return(<h3 className={`${props.textColor}`}>No items found in this section</h3>)
|
return(<h3 className={`${props.textColor}`}>No items found in this section</h3>)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CardListViewer
|
export default CardListViewer
|
||||||
@ -13,12 +13,12 @@ function CategoryBar(props) {
|
|||||||
let localCategoryMetadata = []
|
let localCategoryMetadata = []
|
||||||
for (let eachResponse of responseData){
|
for (let eachResponse of responseData){
|
||||||
localCategoryMetadata.push({
|
localCategoryMetadata.push({
|
||||||
"id": eachResponse["category_id"],
|
'id': eachResponse['category_id'],
|
||||||
"name": eachResponse["name"],
|
'name': eachResponse['name'],
|
||||||
"featuredBlog": eachResponse["featured_id"],
|
'featuredBlog': eachResponse['featured_id'],
|
||||||
"description": eachResponse["description"],
|
'description': eachResponse['description'],
|
||||||
"tagLine": eachResponse["tagline"],
|
'tagLine': eachResponse['tagline'],
|
||||||
"coverImage": eachResponse["cover_image"]
|
'coverImage': eachResponse['cover_image']
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
setCategoryMetadata(localCategoryMetadata)
|
setCategoryMetadata(localCategoryMetadata)
|
||||||
@ -46,15 +46,15 @@ function CategoryBar(props) {
|
|||||||
<Col>
|
<Col>
|
||||||
<ButtonGroup style={{marginTop: '15px', marginBottom: '15px'}}>
|
<ButtonGroup style={{marginTop: '15px', marginBottom: '15px'}}>
|
||||||
{categoryMetadata.length > 0 ?
|
{categoryMetadata.length > 0 ?
|
||||||
categoryMetadata.map((item, index) => (
|
categoryMetadata.map((item) => (
|
||||||
<Button
|
<Button
|
||||||
key={item.id}
|
key={item.id}
|
||||||
className="btn-lg"
|
className='btn-lg'
|
||||||
color={`${ThemeConfig[GlobalTheme].buttonColor}`}
|
color={`${ThemeConfig[GlobalTheme].buttonColor}`}
|
||||||
outline
|
outline
|
||||||
active={props.currentPage === item.id}
|
active={props.currentPage === item.id}
|
||||||
>
|
>
|
||||||
<Link className="p-3" to={`/categories/${item.id}`}>
|
<Link className='p-3' to={`/categories/${item.id}`}>
|
||||||
{item.name}
|
{item.name}
|
||||||
</Link></Button>
|
</Link></Button>
|
||||||
)) : <Spinner />
|
)) : <Spinner />
|
||||||
@ -65,6 +65,6 @@ function CategoryBar(props) {
|
|||||||
</Row>
|
</Row>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
export default CategoryBar;
|
export default CategoryBar;
|
||||||
@ -4,8 +4,6 @@ import EditableDataService from '../../services/editable-data-service';
|
|||||||
|
|
||||||
function FileComponent(props) {
|
function FileComponent(props) {
|
||||||
const [file, setFile] = useState(null);
|
const [file, setFile] = useState(null);
|
||||||
const [resourceType, setResourceType] = useState('');
|
|
||||||
const [resourceId, setResourceId] = useState('');
|
|
||||||
|
|
||||||
const handleFileChange = (event) => {
|
const handleFileChange = (event) => {
|
||||||
setFile(event.target.files[0]); // Assuming single file upload
|
setFile(event.target.files[0]); // Assuming single file upload
|
||||||
@ -20,7 +18,7 @@ function FileComponent(props) {
|
|||||||
formData.append('resource_id', props.resourceId);
|
formData.append('resource_id', props.resourceId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await EditableDataService.createData('/data/upload/', formData);
|
await EditableDataService.createData('/data/upload/', formData);
|
||||||
props.notificationToggler('Media uploaded successfully')
|
props.notificationToggler('Media uploaded successfully')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
props.notificationToggler('Media upload failed', 'danger')
|
props.notificationToggler('Media upload failed', 'danger')
|
||||||
|
|||||||
@ -4,14 +4,12 @@ import {
|
|||||||
Container,
|
Container,
|
||||||
Row,
|
Row,
|
||||||
Col,
|
Col,
|
||||||
Nav,
|
|
||||||
NavLink,
|
|
||||||
Spinner,
|
Spinner,
|
||||||
Button,
|
Button,
|
||||||
ButtonGroup
|
ButtonGroup
|
||||||
} from 'reactstrap';
|
} from 'reactstrap';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { faSun, faMoon, faPen, faBrush } from '@fortawesome/free-solid-svg-icons';
|
import { faBrush } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
const Footer = (props) => {
|
const Footer = (props) => {
|
||||||
const GlobalTheme = props.GlobalTheme;
|
const GlobalTheme = props.GlobalTheme;
|
||||||
@ -21,23 +19,23 @@ const Footer = (props) => {
|
|||||||
const setInfo = async (colorArea, color) => {
|
const setInfo = async (colorArea, color) => {
|
||||||
let localThemeConfig = {...ThemeConfig}
|
let localThemeConfig = {...ThemeConfig}
|
||||||
localThemeConfig[GlobalTheme].footer[colorArea] = `${color}`
|
localThemeConfig[GlobalTheme].footer[colorArea] = `${color}`
|
||||||
let response = await props.setInfo('/data/shared/update/theme-config/', GlobalTheme === "darkTheme" ? {
|
let response = await props.setInfo('/data/shared/update/theme-config/', GlobalTheme === 'darkTheme' ? {
|
||||||
"dark_theme": JSON.stringify(localThemeConfig[GlobalTheme]),
|
'dark_theme': JSON.stringify(localThemeConfig[GlobalTheme]),
|
||||||
}:{
|
}:{
|
||||||
"light_theme": JSON.stringify(localThemeConfig[GlobalTheme]),
|
'light_theme': JSON.stringify(localThemeConfig[GlobalTheme]),
|
||||||
})
|
})
|
||||||
if (response === 200)
|
if (response === 200)
|
||||||
props.notificationToggler(`Color set for ${ThemeConfig[GlobalTheme].theme} successfully!`)
|
props.notificationToggler(`Color set for ${ThemeConfig[GlobalTheme].theme} successfully!`)
|
||||||
if ([500, 404, 403].includes(response))
|
if ([500, 404, 403].includes(response))
|
||||||
props.notificationToggler("Something failed!", "danger")
|
props.notificationToggler('Something failed!', 'danger')
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className={`footer p-4 ${ThemeConfig ? ThemeConfig[GlobalTheme].footer['background'] + ' ' + ThemeConfig[GlobalTheme].footer['text'] : ""}`} id="site-footer">
|
<footer className={`footer p-4 ${ThemeConfig ? ThemeConfig[GlobalTheme].footer['background'] + ' ' + ThemeConfig[GlobalTheme].footer['text'] : ''}`} id='site-footer'>
|
||||||
<Container className='p-1'>
|
<Container className='p-1'>
|
||||||
<Row>
|
<Row>
|
||||||
<ButtonGroup style={{marginTop: '15px', marginBottom: '15px', marginRight: '15px'}}>
|
<ButtonGroup style={{marginTop: '15px', marginBottom: '15px', marginRight: '15px'}}>
|
||||||
<Button disabled color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ""}`}>
|
<Button disabled color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ''}`}>
|
||||||
<FontAwesomeIcon icon={faBrush} /> Set color
|
<FontAwesomeIcon icon={faBrush} /> Set color
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
@ -66,7 +64,7 @@ const Footer = (props) => {
|
|||||||
onClick={() => setInfo('background', 'bg-dark')}/>
|
onClick={() => setInfo('background', 'bg-dark')}/>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
<ButtonGroup style={{marginTop: '15px', marginBottom: '15px'}}>
|
<ButtonGroup style={{marginTop: '15px', marginBottom: '15px'}}>
|
||||||
<Button disabled color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ""}`}>
|
<Button disabled color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ''}`}>
|
||||||
<FontAwesomeIcon icon={faBrush} /> Set footer text color
|
<FontAwesomeIcon icon={faBrush} /> Set footer text color
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
@ -76,12 +74,12 @@ const Footer = (props) => {
|
|||||||
color='dark'
|
color='dark'
|
||||||
onClick={() => setInfo('text', 'text-black')}>Black</Button>
|
onClick={() => setInfo('text', 'text-black')}>Black</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
<Col md="12">
|
<Col md='12'>
|
||||||
<div className="blogContent text-center text-md-left mt-3">
|
<div className='blogContent text-center text-md-left mt-3'>
|
||||||
{new Date().getFullYear()}, <a className={`${ThemeConfig[GlobalTheme].linkBackground} ${ThemeConfig[GlobalTheme].linkTextColor}`} href="/">{ UserData ? UserData.name : <Spinner> Loading... </Spinner> }</a>
|
{new Date().getFullYear()}, <a className={`${ThemeConfig[GlobalTheme].linkBackground} ${ThemeConfig[GlobalTheme].linkTextColor}`} href='/'>{ UserData ? UserData.name : <Spinner> Loading... </Spinner> }</a>
|
||||||
<br />
|
<br />
|
||||||
<div className='m-2'>
|
<div className='m-2'>
|
||||||
{ UserData.builtWith ? <span>Built with <a target="_blank" className={`${ThemeConfig[GlobalTheme].linkBackground} ${ThemeConfig[GlobalTheme].linkTextColor}`} href="https://github.com/barunespadhy/rangolio">Rangolio</a></span>:""}
|
{ UserData.builtWith ? <span>Built with <a target='_blank' className={`${ThemeConfig[GlobalTheme].linkBackground} ${ThemeConfig[GlobalTheme].linkTextColor}`} href='https://github.com/barunespadhy/rangolio' rel="noreferrer">Rangolio</a></span>:''}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
|
|||||||
@ -27,7 +27,7 @@ function MediaLister(props) {
|
|||||||
props.notificationToggler('Media deleted')
|
props.notificationToggler('Media deleted')
|
||||||
fetchMedia()
|
fetchMedia()
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(() => {
|
||||||
props.notificationToggler('Error deleting media', 'danger')
|
props.notificationToggler('Error deleting media', 'danger')
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -21,9 +21,7 @@ function Header(props) {
|
|||||||
const ThemeConfig = props.ThemeConfig;
|
const ThemeConfig = props.ThemeConfig;
|
||||||
const UserData = props.UserData;
|
const UserData = props.UserData;
|
||||||
|
|
||||||
const [collapseClasses, setCollapseClasses] = useState('');
|
|
||||||
const [themeSelected, setThemeSelected] = useState('lightTheme');
|
const [themeSelected, setThemeSelected] = useState('lightTheme');
|
||||||
const [defaultThemeConfig, setDefaultThemeConfig] = useState('lightTheme');
|
|
||||||
const [modal, setModal] = useState(false)
|
const [modal, setModal] = useState(false)
|
||||||
|
|
||||||
const toggle = () => {setModal(!modal)}
|
const toggle = () => {setModal(!modal)}
|
||||||
@ -34,17 +32,17 @@ function Header(props) {
|
|||||||
if (colorArea && color)
|
if (colorArea && color)
|
||||||
localThemeConfig[GlobalTheme].navBar[colorArea] = `${color}`
|
localThemeConfig[GlobalTheme].navBar[colorArea] = `${color}`
|
||||||
|
|
||||||
let response = await props.setInfo('/data/shared/update/theme-config/', GlobalTheme === "darkTheme" ? {
|
let response = await props.setInfo('/data/shared/update/theme-config/', GlobalTheme === 'darkTheme' ? {
|
||||||
"default_theme": defaultThemeConfig,
|
'default_theme': defaultThemeConfig,
|
||||||
"dark_theme": JSON.stringify(localThemeConfig[GlobalTheme]),
|
'dark_theme': JSON.stringify(localThemeConfig[GlobalTheme]),
|
||||||
}:{
|
}:{
|
||||||
"default_theme": defaultThemeConfig,
|
'default_theme': defaultThemeConfig,
|
||||||
"light_theme": JSON.stringify(localThemeConfig[GlobalTheme]),
|
'light_theme': JSON.stringify(localThemeConfig[GlobalTheme]),
|
||||||
})
|
})
|
||||||
if (response === 200)
|
if (response === 200)
|
||||||
props.notificationToggler(`Color set for ${ThemeConfig[GlobalTheme].theme} successfully!`)
|
props.notificationToggler(`Color set for ${ThemeConfig[GlobalTheme].theme} successfully!`)
|
||||||
if ([500, 404, 403].includes(response))
|
if ([500, 404, 403].includes(response))
|
||||||
props.notificationToggler("Something failed!", "danger")
|
props.notificationToggler('Something failed!', 'danger')
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -53,41 +51,40 @@ function Header(props) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setThemeSelected(props.ThemeConfig.defaultTheme)
|
setThemeSelected(props.ThemeConfig.defaultTheme)
|
||||||
setDefaultThemeConfig(props.ThemeConfig.defaultTheme)
|
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
if (GlobalTheme && ThemeConfig && UserData)
|
if (GlobalTheme && ThemeConfig && UserData)
|
||||||
return (
|
return (
|
||||||
<header className="header-global" id="site-header">
|
<header className='header-global' id='site-header'>
|
||||||
<Navbar className={`navbar-horizontal ${ThemeConfig[GlobalTheme].navBar['navBarTheme']} ${ThemeConfig[GlobalTheme].navBar['background']}`}
|
<Navbar className={`navbar-horizontal ${ThemeConfig[GlobalTheme].navBar['navBarTheme']} ${ThemeConfig[GlobalTheme].navBar['background']}`}
|
||||||
expand="lg">
|
expand='lg'>
|
||||||
<Container>
|
<Container>
|
||||||
<Publish notificationToggler={props.notificationToggler} modal={modal} toggle={toggle} />
|
<Publish notificationToggler={props.notificationToggler} modal={modal} toggle={toggle} />
|
||||||
<NavbarBrand>
|
<NavbarBrand>
|
||||||
<Link to="/">
|
<Link to='/'>
|
||||||
{
|
{
|
||||||
UserData.profilePhoto !== "" ?
|
UserData.profilePhoto !== '' ?
|
||||||
<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={EditableMediaService.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'>
|
||||||
{ UserData ? UserData.name : <Spinner> Loading... </Spinner> }
|
{ UserData ? UserData.name : <Spinner> Loading... </Spinner> }
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</NavbarBrand>
|
</NavbarBrand>
|
||||||
<Nav className="ml-lg-auto" navbar>
|
<Nav className='ml-lg-auto' navbar>
|
||||||
<NavItem>
|
<NavItem>
|
||||||
<ButtonGroup style={{marginTop: '15px', marginBottom: '15px', marginRight: '15px'}}>
|
<ButtonGroup style={{marginTop: '15px', marginBottom: '15px', marginRight: '15px'}}>
|
||||||
<Button color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ""}`}>
|
<Button color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ''}`}>
|
||||||
<Link to="/categories">
|
<Link to='/categories'>
|
||||||
<FontAwesomeIcon icon={faPen} /> Blogs
|
<FontAwesomeIcon icon={faPen} /> Blogs
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ""}`}
|
color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ''}`}
|
||||||
outline
|
outline
|
||||||
onClick={() => {setThemeSelected('lightTheme')}}
|
onClick={() => {setThemeSelected('lightTheme')}}
|
||||||
active={themeSelected === 'lightTheme'}
|
active={themeSelected === 'lightTheme'}
|
||||||
@ -95,7 +92,7 @@ function Header(props) {
|
|||||||
<FontAwesomeIcon icon={faSun} /> Light Theme
|
<FontAwesomeIcon icon={faSun} /> Light Theme
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ""}`}
|
color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ''}`}
|
||||||
outline
|
outline
|
||||||
onClick={() => {setThemeSelected('darkTheme')}}
|
onClick={() => {setThemeSelected('darkTheme')}}
|
||||||
active={themeSelected === 'darkTheme'}
|
active={themeSelected === 'darkTheme'}
|
||||||
@ -105,7 +102,7 @@ function Header(props) {
|
|||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
|
|
||||||
<ButtonGroup style={{marginTop: '15px', marginBottom: '15px', marginRight: '15px'}}>
|
<ButtonGroup style={{marginTop: '15px', marginBottom: '15px', marginRight: '15px'}}>
|
||||||
<Button disabled color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ""}`}>
|
<Button disabled color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ''}`}>
|
||||||
<FontAwesomeIcon icon={faBrush} /> Set color
|
<FontAwesomeIcon icon={faBrush} /> Set color
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
@ -134,7 +131,7 @@ function Header(props) {
|
|||||||
onClick={() => setInfo('background', 'bg-dark', ThemeConfig['defaultTheme'])}/>
|
onClick={() => setInfo('background', 'bg-dark', ThemeConfig['defaultTheme'])}/>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
<ButtonGroup style={{marginTop: '15px', marginBottom: '15px'}}>
|
<ButtonGroup style={{marginTop: '15px', marginBottom: '15px'}}>
|
||||||
<Button disabled color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ""}`}>
|
<Button disabled color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ''}`}>
|
||||||
<FontAwesomeIcon icon={faBrush} /> Set button color
|
<FontAwesomeIcon icon={faBrush} /> Set button color
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
@ -145,20 +142,20 @@ function Header(props) {
|
|||||||
onClick={() => setInfo('buttonColor', 'black', ThemeConfig['defaultTheme'])}>Black</Button>
|
onClick={() => setInfo('buttonColor', 'black', ThemeConfig['defaultTheme'])}>Black</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
<ButtonGroup style={{marginTop: '15px', marginBottom: '15px'}}>
|
<ButtonGroup style={{marginTop: '15px', marginBottom: '15px'}}>
|
||||||
<Button disabled color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ""}`}>
|
<Button disabled color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ''}`}>
|
||||||
<FontAwesomeIcon icon={faBrush} /> Default Theme
|
<FontAwesomeIcon icon={faBrush} /> Default Theme
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ""}`}
|
color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ''}`}
|
||||||
outline
|
outline
|
||||||
onClick={() => setInfo(null, null, 'lightTheme')}>Light Theme</Button>
|
onClick={() => setInfo(null, null, 'lightTheme')}>Light Theme</Button>
|
||||||
<Button
|
<Button
|
||||||
color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ""}`}
|
color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ''}`}
|
||||||
outline
|
outline
|
||||||
onClick={() => setInfo(null, null, 'darkTheme')}>Dark Theme</Button>
|
onClick={() => setInfo(null, null, 'darkTheme')}>Dark Theme</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
<Button
|
<Button
|
||||||
color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ""}`}
|
color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ''}`}
|
||||||
className='ms-5'
|
className='ms-5'
|
||||||
outline
|
outline
|
||||||
onClick={() => toggle()}
|
onClick={() => toggle()}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Collapse, Button, CardBody, Card, Alert } from 'reactstrap';
|
import { Collapse, CardBody, Card, Alert } from 'reactstrap';
|
||||||
|
|
||||||
function Notification(props) {
|
function Notification(props) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -16,8 +16,8 @@ function Publish(props) {
|
|||||||
let publishMethods = []
|
let publishMethods = []
|
||||||
Object.entries(response.data).map(([key, value]) => (
|
Object.entries(response.data).map(([key, value]) => (
|
||||||
publishMethods.push({
|
publishMethods.push({
|
||||||
"key_name": key,
|
'key_name': key,
|
||||||
"name": value["name"]
|
'name': value['name']
|
||||||
})
|
})
|
||||||
))
|
))
|
||||||
setPublishMethods(publishMethods)
|
setPublishMethods(publishMethods)
|
||||||
@ -29,7 +29,7 @@ function Publish(props) {
|
|||||||
const publishData = async (deploy_method) => {
|
const publishData = async (deploy_method) => {
|
||||||
try {
|
try {
|
||||||
setPublishSpinner(true)
|
setPublishSpinner(true)
|
||||||
const response = await EditableDataService.getData(`/data/publish/${deploy_method}/`);
|
await EditableDataService.getData(`/data/publish/${deploy_method}/`);
|
||||||
props.notificationToggler('Deployment Sucess')
|
props.notificationToggler('Deployment Sucess')
|
||||||
setPublishSpinner(false)
|
setPublishSpinner(false)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -37,39 +37,30 @@ function Publish(props) {
|
|||||||
setPublishSpinner(false)
|
setPublishSpinner(false)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Modal isOpen={props.modal} toggle={props.toggle}>
|
<Modal isOpen={props.modal} toggle={props.toggle}>
|
||||||
<ModalHeader toggle={props.toggle}>Publish Website</ModalHeader>
|
<ModalHeader toggle={props.toggle}>Publish Website</ModalHeader>
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<h4>
|
<h4>Select a publish method</h4>
|
||||||
Select a publish method
|
|
||||||
</h4>
|
|
||||||
{
|
{
|
||||||
publishMethods ?
|
publishMethods ?
|
||||||
publishMethods.map((item) =>
|
publishMethods.map((item) =>
|
||||||
<div className='mb-3'>
|
<div key={item.key_name} className='mb-3'>
|
||||||
<Button
|
<Button
|
||||||
key={item.key_name}
|
|
||||||
color='danger'
|
color='danger'
|
||||||
onClick={() => publishData(item.key_name)}
|
onClick={() => publishData(item.key_name)}
|
||||||
>
|
>
|
||||||
{item.name}
|
{item.name}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>):''
|
||||||
):""
|
|
||||||
}
|
}
|
||||||
{ publishSpinner ?
|
{ publishSpinner ?
|
||||||
<h5>
|
<h5>Publishing <Spinner /></h5> : ''
|
||||||
Publishing <Spinner />
|
|
||||||
</h5> : ""
|
|
||||||
}
|
}
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
<ModalFooter>
|
<ModalFooter>
|
||||||
<Button color="secondary" onClick={props.toggle}>
|
<Button color='secondary' onClick={props.toggle}>Cancel</Button>
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
|
||||||
extension credits: Angelika Tyborska: https://angelika.me/2023/02/26/how-to-add-editing-image-alt-text-tiptap/
|
extension credits: Angelika Tyborska: https://angelika.me/2023/02/26/how-to-add-editing-image-alt-text-tiptap/
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Image from '@tiptap/extension-image'
|
import Image from '@tiptap/extension-image'
|
||||||
@ -32,7 +30,7 @@ function ImageNode(props) {
|
|||||||
<span>!</span>
|
<span>!</span>
|
||||||
}
|
}
|
||||||
{ alt ?
|
{ alt ?
|
||||||
<span className="text">Alt text: "{alt}".</span>:
|
<span className="text">Alt text: “{alt}“.</span>:
|
||||||
<span className="text">Alt text missing.</span>
|
<span className="text">Alt text missing.</span>
|
||||||
}
|
}
|
||||||
<Button className="edit" type="button" onClick={onEditAlt}>
|
<Button className="edit" type="button" onClick={onEditAlt}>
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import React, { useCallback, useEffect, useState } from 'react'
|
import React, { useCallback, useEffect, useState } from 'react'
|
||||||
import {
|
import { Button, ButtonGroup } from 'reactstrap';
|
||||||
Button, ButtonGroup, Label, Input } from 'reactstrap';
|
|
||||||
import { Color } from '@tiptap/extension-color'
|
import { Color } from '@tiptap/extension-color'
|
||||||
import ListItem from '@tiptap/extension-list-item'
|
import ListItem from '@tiptap/extension-list-item'
|
||||||
import TextStyle from '@tiptap/extension-text-style'
|
import TextStyle from '@tiptap/extension-text-style'
|
||||||
@ -87,8 +86,7 @@ const MenuBar = (props) => {
|
|||||||
<Button
|
<Button
|
||||||
color={ThemeConfig[GlobalTheme].buttonColor}
|
color={ThemeConfig[GlobalTheme].buttonColor}
|
||||||
onClick={() => editor.chain().focus().setTextAlign('left').run()}
|
onClick={() => editor.chain().focus().setTextAlign('left').run()}
|
||||||
outline
|
outline active={editor.isActive('left')}
|
||||||
active={editor.isActive('left')}
|
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={faAlignLeft}/>
|
<FontAwesomeIcon icon={faAlignLeft}/>
|
||||||
</Button>
|
</Button>
|
||||||
@ -103,8 +101,7 @@ const MenuBar = (props) => {
|
|||||||
<Button
|
<Button
|
||||||
color={ThemeConfig[GlobalTheme].buttonColor}
|
color={ThemeConfig[GlobalTheme].buttonColor}
|
||||||
onClick={() => editor.chain().focus().setTextAlign('right').run()}
|
onClick={() => editor.chain().focus().setTextAlign('right').run()}
|
||||||
outline
|
outline active={editor.isActive('right')}
|
||||||
active={editor.isActive('right')}
|
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={faAlignRight}/>
|
<FontAwesomeIcon icon={faAlignRight}/>
|
||||||
</Button>
|
</Button>
|
||||||
@ -116,7 +113,7 @@ const MenuBar = (props) => {
|
|||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={faAlignJustify}/>
|
<FontAwesomeIcon icon={faAlignJustify}/>
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonGroup >
|
</ButtonGroup>
|
||||||
<ButtonGroup className='mt-2' style={{marginLeft: '10px'}}>
|
<ButtonGroup className='mt-2' style={{marginLeft: '10px'}}>
|
||||||
<Button
|
<Button
|
||||||
color={ThemeConfig[GlobalTheme].buttonColor}
|
color={ThemeConfig[GlobalTheme].buttonColor}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React, { Suspense, lazy } from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom/client'
|
import ReactDOM from 'react-dom/client'
|
||||||
import './index.css'
|
import './index.css'
|
||||||
import App from './App'
|
import App from './App'
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
import axios from 'axios'
|
|
||||||
|
|
||||||
const getData = (endPoint) => {
|
|
||||||
return axios.get(`/data/${endPoint}.json`)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default { getData }
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
const getMedia = (mediaPath) => {
|
|
||||||
return `/data/${mediaPath}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default { getMedia };
|
|
||||||
@ -1,9 +1,10 @@
|
|||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import react from '@vitejs/plugin-react'
|
import react from '@vitejs/plugin-react'
|
||||||
|
import eslint from 'vite-plugin-eslint';
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [react(), eslint()],
|
||||||
base: '/static/',
|
base: '/static/',
|
||||||
server: {
|
server: {
|
||||||
proxy: {
|
proxy: {
|
||||||
|
|||||||
34
frontend/viewable-ui/.eslintrc
Normal file
34
frontend/viewable-ui/.eslintrc
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"es2021": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:react/recommended"
|
||||||
|
],
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaFeatures": {
|
||||||
|
"jsx": true
|
||||||
|
},
|
||||||
|
"ecmaVersion": 12,
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
"react"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"indent": [
|
||||||
|
"error",
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"react/react-in-jsx-scope": "off",
|
||||||
|
"react/prop-types": "off",
|
||||||
|
"react/display-name": "off",
|
||||||
|
"quotes": [
|
||||||
|
"error",
|
||||||
|
"single"
|
||||||
|
],
|
||||||
|
"no-console": "error"
|
||||||
|
}
|
||||||
|
}
|
||||||
3226
frontend/viewable-ui/package-lock.json
generated
3226
frontend/viewable-ui/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -46,9 +46,11 @@
|
|||||||
"@vitejs/plugin-react": "^4.2.1",
|
"@vitejs/plugin-react": "^4.2.1",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
|
"eslint-config-react-app": "^7.0.1",
|
||||||
"eslint-plugin-react": "^7.34.1",
|
"eslint-plugin-react": "^7.34.1",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"eslint-plugin-react-refresh": "^0.4.6",
|
"eslint-plugin-react-refresh": "^0.4.6",
|
||||||
"vite": "^5.2.0"
|
"vite": "^5.2.0",
|
||||||
|
"vite-plugin-eslint": "^1.8.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,9 +22,9 @@ import DataService from './services/data-service'
|
|||||||
function App() {
|
function App() {
|
||||||
const [userData, setUserData] = useState(null);
|
const [userData, setUserData] = useState(null);
|
||||||
const [themeConfig, setThemeConfig] = useState(null);
|
const [themeConfig, setThemeConfig] = useState(null);
|
||||||
const [globalTheme, setGlobalTheme] = useState("lightTheme");
|
const [globalTheme, setGlobalTheme] = useState('lightTheme');
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [notificationMessage, setNotificationMessage] = useState("")
|
const [notificationMessage, setNotificationMessage] = useState('')
|
||||||
|
|
||||||
const notificationToggler = (message) => {
|
const notificationToggler = (message) => {
|
||||||
setIsOpen(true)
|
setIsOpen(true)
|
||||||
@ -38,13 +38,11 @@ function App() {
|
|||||||
DataService.getData('shared/user-data').then( response =>{
|
DataService.getData('shared/user-data').then( response =>{
|
||||||
setUserData(response.data)
|
setUserData(response.data)
|
||||||
document.title = response.data.name
|
document.title = response.data.name
|
||||||
}
|
})
|
||||||
)
|
|
||||||
DataService.getData('shared/theme-config').then( response =>{
|
DataService.getData('shared/theme-config').then( response =>{
|
||||||
setThemeConfig(response.data)
|
setThemeConfig(response.data)
|
||||||
setGlobalTheme(response.data.defaultTheme)
|
setGlobalTheme(response.data.defaultTheme)
|
||||||
}
|
})
|
||||||
)
|
|
||||||
},[])
|
},[])
|
||||||
|
|
||||||
const themeSwitcher = (theme) => {
|
const themeSwitcher = (theme) => {
|
||||||
@ -53,20 +51,20 @@ function App() {
|
|||||||
|
|
||||||
if (themeConfig)
|
if (themeConfig)
|
||||||
return (
|
return (
|
||||||
<div className="app-container">
|
<div className='app-container'>
|
||||||
<Router>
|
<Router>
|
||||||
<Header className="header" ThemeSwitcher={themeSwitcher} GlobalTheme={globalTheme} ThemeConfig={themeConfig} UserData={userData} />
|
<Header className='header' ThemeSwitcher={themeSwitcher} GlobalTheme={globalTheme} ThemeConfig={themeConfig} UserData={userData} />
|
||||||
<div className={`p-0 ${themeConfig[globalTheme].background}`}>
|
<div className={`p-0 ${themeConfig[globalTheme].background}`}>
|
||||||
<Notification isOpen={isOpen} message={notificationMessage} />
|
<Notification isOpen={isOpen} message={notificationMessage} />
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<Home GlobalTheme={globalTheme} ThemeConfig={themeConfig} UserData={userData} />} />
|
<Route path='/' element={<Home GlobalTheme={globalTheme} ThemeConfig={themeConfig} UserData={userData} />} />
|
||||||
<Route path="/categories" element={<CategoryList notificationToggler={notificationToggler} GlobalTheme={globalTheme} ThemeConfig={themeConfig} />} />
|
<Route path='/categories' element={<CategoryList notificationToggler={notificationToggler} GlobalTheme={globalTheme} ThemeConfig={themeConfig} />} />
|
||||||
<Route path="/categories/:categoryID" element={<BlogList notificationToggler={notificationToggler} GlobalTheme={globalTheme} ThemeConfig={themeConfig} />} />
|
<Route path='/categories/:categoryID' element={<BlogList notificationToggler={notificationToggler} GlobalTheme={globalTheme} ThemeConfig={themeConfig} />} />
|
||||||
<Route path="/blog/:blogID" element={<Blog notificationToggler={notificationToggler} GlobalTheme={globalTheme} ThemeConfig={themeConfig} />} />
|
<Route path='/blog/:blogID' element={<Blog notificationToggler={notificationToggler} GlobalTheme={globalTheme} ThemeConfig={themeConfig} />} />
|
||||||
<Route path="*" element={<NotFound validRoutes={['categories', 'blog']} GlobalTheme={globalTheme} ThemeConfig={themeConfig}/>} />
|
<Route path='*' element={<NotFound validRoutes={['categories', 'blog']} GlobalTheme={globalTheme} ThemeConfig={themeConfig}/>} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
<Footer className="footer" ThemeSwitcher={themeSwitcher} GlobalTheme={globalTheme} ThemeConfig={themeConfig} UserData={userData} />
|
<Footer className='footer' ThemeSwitcher={themeSwitcher} GlobalTheme={globalTheme} ThemeConfig={themeConfig} UserData={userData} />
|
||||||
</Router>
|
</Router>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -28,41 +28,39 @@ function BlogList(props) {
|
|||||||
|
|
||||||
const [categoryData, setCategoryData] = useState(null);
|
const [categoryData, setCategoryData] = useState(null);
|
||||||
const [featuredBlogData, setFeaturedBlogData] = useState('loading');
|
const [featuredBlogData, setFeaturedBlogData] = useState('loading');
|
||||||
const [currentPage, setCurrentPage] = useState('loading');
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
DataService.getData(`category/${categoryID}/category-data`).then(response =>{
|
DataService.getData(`category/${categoryID}/category-data`).then(response =>{
|
||||||
setCategoryData(response.data);
|
setCategoryData(response.data);
|
||||||
setFeaturedBlogData(response.data.blogMetadata.find(blog => blog.id === response.data.featuredBlog))
|
setFeaturedBlogData(response.data.blogMetadata.find(blog => blog.id === response.data.featuredBlog))
|
||||||
document.title = 'Blogs in ' + response.data.name
|
document.title = 'Blogs in ' + response.data.name
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}, [categoryID]);
|
}, [categoryID]);
|
||||||
|
|
||||||
if (GlobalTheme && ThemeConfig) {
|
if (GlobalTheme && ThemeConfig) {
|
||||||
return (
|
return (
|
||||||
<Container fluid className={`mb-2 p-0 ${ThemeConfig[GlobalTheme].background}`}>
|
<Container fluid className={`mb-2 p-0 ${ThemeConfig[GlobalTheme].background}`}>
|
||||||
<Col className="d-md-block"><Button color={ThemeConfig[GlobalTheme].buttonColor} onClick={() => navigate(`/categories/`)} className="ms-5 mt-5" outline><FontAwesomeIcon icon={faLeftLong}/></Button></Col>
|
<Col className="d-md-block"><Button color={ThemeConfig[GlobalTheme].buttonColor} onClick={() => navigate('/categories/')} className="ms-5 mt-5" outline><FontAwesomeIcon icon={faLeftLong}/></Button></Col>
|
||||||
<CategoryBar currentPage={categoryID} GlobalTheme={GlobalTheme} ThemeConfig={ThemeConfig} />
|
<CategoryBar currentPage={categoryID} GlobalTheme={GlobalTheme} ThemeConfig={ThemeConfig} />
|
||||||
<Row className="justify-content-center align-items-center">
|
<Row className="justify-content-center align-items-center">
|
||||||
<Col className="d-flex flex-column align-items-center">
|
<Col className="d-flex flex-column align-items-center">
|
||||||
<div className="w-100">
|
<div className="w-100">
|
||||||
<Card className={`my-2 ${ThemeConfig[GlobalTheme].background}`} style={{ width: "100%", border: "none" }}>
|
<Card className={`my-2 ${ThemeConfig[GlobalTheme].background}`} style={{ width: '100%', border: 'none' }}>
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<CardTitle style={{ display: "grid" }} className={`${ThemeConfig[GlobalTheme].textColor} justify-content-center`} tag="h1">
|
<CardTitle style={{ display: 'grid' }} className={`${ThemeConfig[GlobalTheme].textColor} justify-content-center`} tag='h1'>
|
||||||
{categoryData ? `Blogs in ${categoryData.name}`:`Loading blogs ${<Spinner/>}`}
|
{categoryData ? `Blogs in ${categoryData.name}`:`Loading blogs ${<Spinner/>}`}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
<div className="container">
|
<div className='container'>
|
||||||
{
|
{
|
||||||
featuredBlogData ?
|
featuredBlogData ?
|
||||||
<CardListViewer
|
<CardListViewer
|
||||||
key={featuredBlogData.id}
|
key={featuredBlogData.id}
|
||||||
totalItems={featuredBlogData === 'nodata' ? 0 : 1}
|
totalItems={featuredBlogData === 'nodata' ? 0 : 1}
|
||||||
cardType={"longCard"}
|
cardType={'longCard'}
|
||||||
resourceType={"blog"}
|
resourceType={'blog'}
|
||||||
textColor={ThemeConfig[GlobalTheme].textColor}
|
textColor={ThemeConfig[GlobalTheme].textColor}
|
||||||
bgColor={ThemeConfig[GlobalTheme].background}
|
bgColor={ThemeConfig[GlobalTheme].background}
|
||||||
borderColor={ThemeConfig[GlobalTheme].borderColor}
|
borderColor={ThemeConfig[GlobalTheme].borderColor}
|
||||||
@ -71,14 +69,14 @@ function BlogList(props) {
|
|||||||
}
|
}
|
||||||
<Row>
|
<Row>
|
||||||
{categoryData ?
|
{categoryData ?
|
||||||
categoryData.blogMetadata.map((item, index) => (
|
categoryData.blogMetadata.map((item) => (
|
||||||
<Col key={item.blog_id}>
|
<Col key={item.blog_id}>
|
||||||
<div className={`p-2 ml-2 ${ThemeConfig[GlobalTheme].textColor}`}>
|
<div className={`p-2 ml-2 ${ThemeConfig[GlobalTheme].textColor}`}>
|
||||||
<CardListViewer
|
<CardListViewer
|
||||||
totalItems={categoryData.blogMetadata.length}
|
totalItems={categoryData.blogMetadata.length}
|
||||||
featuredBlog={categoryData.featuredBlog}
|
featuredBlog={categoryData.featuredBlog}
|
||||||
cardType={"smallCard"}
|
cardType={'smallCard'}
|
||||||
resourceType={"blog"}
|
resourceType={'blog'}
|
||||||
textColor={ThemeConfig[GlobalTheme].textColor}
|
textColor={ThemeConfig[GlobalTheme].textColor}
|
||||||
bgColor={ThemeConfig[GlobalTheme].background}
|
bgColor={ThemeConfig[GlobalTheme].background}
|
||||||
borderColor={ThemeConfig[GlobalTheme].borderColor}
|
borderColor={ThemeConfig[GlobalTheme].borderColor}
|
||||||
|
|||||||
@ -34,7 +34,7 @@ function Blog(props) {
|
|||||||
node.attribs.target = '_blank';
|
node.attribs.target = '_blank';
|
||||||
}
|
}
|
||||||
if (node.name === 'img') {
|
if (node.name === 'img') {
|
||||||
const newClasses = `img-fluid mt-2 mb-2 rounded mx-auto d-block`;
|
const newClasses = 'img-fluid mt-2 mb-2 rounded mx-auto d-block';
|
||||||
const existingClasses = node.attribs.class ? `${node.attribs.class} ` : '';
|
const existingClasses = node.attribs.class ? `${node.attribs.class} ` : '';
|
||||||
node.attribs.class = `${existingClasses}${newClasses}`;
|
node.attribs.class = `${existingClasses}${newClasses}`;
|
||||||
}
|
}
|
||||||
@ -47,8 +47,7 @@ function Blog(props) {
|
|||||||
const parsedContent = parse(response.data.contentBody, { replace });
|
const parsedContent = parse(response.data.contentBody, { replace });
|
||||||
setBlogContent(parsedContent);
|
setBlogContent(parsedContent);
|
||||||
document.title = response.data.name
|
document.title = response.data.name
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -71,7 +70,7 @@ function Blog(props) {
|
|||||||
src={MediaService.getMedia(blogData.coverImage)}
|
src={MediaService.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' }}
|
||||||
/>:""
|
/>:''
|
||||||
}
|
}
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
@ -101,7 +100,7 @@ function Blog(props) {
|
|||||||
<Link className="p-3" to="#" onClick={(e) => {
|
<Link className="p-3" to="#" onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
navigator.clipboard.writeText(window.location.href).then(() => {
|
navigator.clipboard.writeText(window.location.href).then(() => {
|
||||||
props.notificationToggler("Link copied")
|
props.notificationToggler('Link copied')
|
||||||
})
|
})
|
||||||
return false;
|
return false;
|
||||||
}}>
|
}}>
|
||||||
@ -145,7 +144,7 @@ function Blog(props) {
|
|||||||
</Row>
|
</Row>
|
||||||
<Row className={`my-2 ${ThemeConfig[GlobalTheme].background}`}>
|
<Row className={`my-2 ${ThemeConfig[GlobalTheme].background}`}>
|
||||||
<Col>
|
<Col>
|
||||||
<hr style={{"borderColor": `${ThemeConfig[GlobalTheme].borderColor}`}} />
|
<hr style={{'borderColor': `${ThemeConfig[GlobalTheme].borderColor}`}} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
|
|||||||
@ -12,9 +12,7 @@ import {
|
|||||||
Col,
|
Col,
|
||||||
Container,
|
Container,
|
||||||
Card,
|
Card,
|
||||||
CardImg,
|
|
||||||
CardTitle,
|
CardTitle,
|
||||||
CardText,
|
|
||||||
CardBody,
|
CardBody,
|
||||||
Button
|
Button
|
||||||
} from 'reactstrap';
|
} from 'reactstrap';
|
||||||
@ -40,28 +38,28 @@ function Blogs(props) {
|
|||||||
return (
|
return (
|
||||||
<Container fluid className={`p-0 mb-2 ${ThemeConfig[GlobalTheme].background}`}>
|
<Container fluid className={`p-0 mb-2 ${ThemeConfig[GlobalTheme].background}`}>
|
||||||
|
|
||||||
<Row className="justify-content-center align-items-center">
|
<Row className='justify-content-center align-items-center'>
|
||||||
<Col className="d-flex flex-column align-items-center">
|
<Col className='d-flex flex-column align-items-center'>
|
||||||
{/* Top Section - Categories */}
|
{/* Top Section - Categories */}
|
||||||
<div className="w-100">
|
<div className='w-100'>
|
||||||
<Col xs="3" className="d-md-block"><Button color={ThemeConfig[GlobalTheme].buttonColor} onClick={() => navigate(`/`)} className="ms-5 mt-5" outline><FontAwesomeIcon icon={faLeftLong}/></Button></Col>
|
<Col xs='3' className='d-md-block'><Button color={ThemeConfig[GlobalTheme].buttonColor} onClick={() => navigate('/')} className='ms-5 mt-5' outline><FontAwesomeIcon icon={faLeftLong}/></Button></Col>
|
||||||
<Card className={`my-2 ${ThemeConfig[GlobalTheme].background}`} style={{width: "100%", border: "none"}}>
|
<Card className={`my-2 ${ThemeConfig[GlobalTheme].background}`} style={{width: '100%', border: 'none'}}>
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<CardTitle style={{ display: "grid" }} className={`${ThemeConfig[GlobalTheme].textColor} justify-content-center`} tag="h1">
|
<CardTitle style={{ display: 'grid' }} className={`${ThemeConfig[GlobalTheme].textColor} justify-content-center`} tag='h1'>
|
||||||
{"Categories"}
|
{'Categories'}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
{/* Bottom Section - Category Metadata or Spinner */}
|
{/* Bottom Section - Category Metadata or Spinner */}
|
||||||
<div className="" style={{ width: '70%', margin: 'auto' }}>
|
<div className='' style={{ width: '70%', margin: 'auto' }}>
|
||||||
{categoryMetadata ?
|
{categoryMetadata ?
|
||||||
categoryMetadata.length > 0 ? categoryMetadata.map((item, index) => (
|
categoryMetadata.length > 0 ? categoryMetadata.map((item) => (
|
||||||
<CardListViewer
|
<CardListViewer
|
||||||
key={item.id}
|
key={item.id}
|
||||||
totalItems={categoryMetadata.length}
|
totalItems={categoryMetadata.length}
|
||||||
cardType={"longCard"}
|
cardType={'longCard'}
|
||||||
resourceType={"categories"}
|
resourceType={'categories'}
|
||||||
textColor={ThemeConfig[GlobalTheme].textColor}
|
textColor={ThemeConfig[GlobalTheme].textColor}
|
||||||
bgColor={ThemeConfig[GlobalTheme].background}
|
bgColor={ThemeConfig[GlobalTheme].background}
|
||||||
borderColor={ThemeConfig[GlobalTheme].borderColor}
|
borderColor={ThemeConfig[GlobalTheme].borderColor}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ function HomePage(props) {
|
|||||||
node.attribs.target = '_blank';
|
node.attribs.target = '_blank';
|
||||||
}
|
}
|
||||||
if (node.name === 'img') {
|
if (node.name === 'img') {
|
||||||
const newClasses = `img-fluid mt-2 mb-2 rounded mx-auto d-block`;
|
const newClasses = 'img-fluid mt-2 mb-2 rounded mx-auto d-block';
|
||||||
const existingClasses = node.attribs.class ? `${node.attribs.class} ` : '';
|
const existingClasses = node.attribs.class ? `${node.attribs.class} ` : '';
|
||||||
node.attribs.class = `${existingClasses}${newClasses}`;
|
node.attribs.class = `${existingClasses}${newClasses}`;
|
||||||
}
|
}
|
||||||
@ -29,25 +29,25 @@ function HomePage(props) {
|
|||||||
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;
|
||||||
const ThemeConfig = props.ThemeConfig;
|
const ThemeConfig = props.ThemeConfig;
|
||||||
const introContent = props.UserData ? parse(props.UserData.introContent, { replace }) : ""
|
const introContent = props.UserData ? parse(props.UserData.introContent, { replace }) : ''
|
||||||
|
|
||||||
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}`}>
|
||||||
<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'>
|
||||||
<Row className="mb-4">
|
<Row className='mb-4'>
|
||||||
<Col xs="3" className="d-none d-md-block"></Col>
|
<Col xs='3' className='d-none d-md-block'></Col>
|
||||||
<Col className="p-0">
|
<Col className='p-0'>
|
||||||
{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={MediaService.getMedia(UserData.profilePhoto)} /> : ''}
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs="3" className="d-none d-md-block"></Col>
|
<Col xs='3' className='d-none d-md-block'></Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Row className={`mb-5 mt-2 ${ThemeConfig[GlobalTheme].textColor}`}>
|
<Row className={`mb-5 mt-2 ${ThemeConfig[GlobalTheme].textColor}`}>
|
||||||
<Col xs="3" className="d-none d-md-block"></Col>
|
<Col xs='3' className='d-none d-md-block'></Col>
|
||||||
<Col className="p-4 blogContent">
|
<Col className='p-4 blogContent'>
|
||||||
<div className={`blogContent ${ThemeConfig[GlobalTheme].textColor}`}>{introContent}</div>
|
<div className={`blogContent ${ThemeConfig[GlobalTheme].textColor}`}>{introContent}</div>
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs="3" className="d-none d-md-block"></Col>
|
<Col xs='3' className='d-none d-md-block'></Col>
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@ -10,17 +10,15 @@ import { Link } from 'react-router-dom';
|
|||||||
|
|
||||||
function CardListViewer(props) {
|
function CardListViewer(props) {
|
||||||
|
|
||||||
|
|
||||||
const itemObject = props.itemObject
|
const itemObject = props.itemObject
|
||||||
console.log(itemObject)
|
|
||||||
|
|
||||||
if (props.totalItems > 0 && itemObject && Object.keys(itemObject).length !== 0)
|
if (props.totalItems > 0 && itemObject && Object.keys(itemObject).length !== 0)
|
||||||
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={MediaService.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="h5">
|
<CardTitle className={`${props.textColor}`} tag='h5'>
|
||||||
{itemObject.name}
|
{itemObject.name}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardText className={`${props.textColor}`}>
|
<CardText className={`${props.textColor}`}>
|
||||||
@ -35,7 +33,7 @@ function CardListViewer(props) {
|
|||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
return(<h3 className={`${props.textColor}`}>No items found in this section</h3>)
|
return(<h3 className={`${props.textColor}`}>No items found in this section</h3>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import DataService from '../../services/data-service';
|
import DataService from '../../services/data-service';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Container, Row, Col, Button, Spinner, ListGroup, ListGroupItem, ButtonGroup } from 'reactstrap';
|
import { Container, Row, Col, Button, Spinner, ButtonGroup } from 'reactstrap';
|
||||||
|
|
||||||
function CategoryBar(props) {
|
function CategoryBar(props) {
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ function CategoryBar(props) {
|
|||||||
<Col>
|
<Col>
|
||||||
<ButtonGroup style={{marginTop: '15px', marginBottom: '15px'}}>
|
<ButtonGroup style={{marginTop: '15px', marginBottom: '15px'}}>
|
||||||
{categoryMetadata.length > 0 ?
|
{categoryMetadata.length > 0 ?
|
||||||
categoryMetadata.map((item, index) => (
|
categoryMetadata.map((item) => (
|
||||||
<Button
|
<Button
|
||||||
key={item.id}
|
key={item.id}
|
||||||
className="btn-lg"
|
className="btn-lg"
|
||||||
@ -49,6 +49,6 @@ function CategoryBar(props) {
|
|||||||
</Row>
|
</Row>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
export default CategoryBar;
|
export default CategoryBar;
|
||||||
@ -14,7 +14,7 @@ const Footer = (props) => {
|
|||||||
|
|
||||||
if (UserData)
|
if (UserData)
|
||||||
return (
|
return (
|
||||||
<footer className={`footer p-4 ${ThemeConfig ? ThemeConfig[GlobalTheme].footer['background'] + ' ' + ThemeConfig[GlobalTheme].footer['text'] : ""}`} id="site-footer">
|
<footer className={`footer p-4 ${ThemeConfig ? ThemeConfig[GlobalTheme].footer['background'] + ' ' + ThemeConfig[GlobalTheme].footer['text'] : ''}`} id="site-footer">
|
||||||
<Container className='p-1'>
|
<Container className='p-1'>
|
||||||
<Row>
|
<Row>
|
||||||
<Col md="12">
|
<Col md="12">
|
||||||
@ -22,7 +22,7 @@ const Footer = (props) => {
|
|||||||
{new Date().getFullYear()}, <a className={`${ThemeConfig[GlobalTheme].linkBackground} ${ThemeConfig[GlobalTheme].linkTextColor}`} href="/">{ UserData ? UserData.name : <Spinner> Loading... </Spinner> }</a>
|
{new Date().getFullYear()}, <a className={`${ThemeConfig[GlobalTheme].linkBackground} ${ThemeConfig[GlobalTheme].linkTextColor}`} href="/">{ UserData ? UserData.name : <Spinner> Loading... </Spinner> }</a>
|
||||||
<br />
|
<br />
|
||||||
<div className='m-2'>
|
<div className='m-2'>
|
||||||
{ UserData.builtWith ? <span>Built with <a target="_blank" className={`${ThemeConfig[GlobalTheme].linkBackground} ${ThemeConfig[GlobalTheme].linkTextColor}`} href="https://github.com/barunespadhy/rangolio">Rangolio</a></span>:""}
|
{ UserData.builtWith ? <span>Built with <a target="_blank" className={`${ThemeConfig[GlobalTheme].linkBackground} ${ThemeConfig[GlobalTheme].linkTextColor}`} href="https://github.com/barunespadhy/rangolio" rel="noreferrer">Rangolio</a></span>:''}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
@ -30,6 +30,6 @@ const Footer = (props) => {
|
|||||||
</Container>
|
</Container>
|
||||||
</footer>
|
</footer>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
export default Footer;
|
export default Footer;
|
||||||
@ -2,15 +2,11 @@
|
|||||||
import {
|
import {
|
||||||
Navbar,
|
Navbar,
|
||||||
NavbarBrand,
|
NavbarBrand,
|
||||||
UncontrolledCollapse,
|
|
||||||
Row,
|
|
||||||
Col,
|
|
||||||
Nav,
|
Nav,
|
||||||
NavItem,
|
NavItem,
|
||||||
NavLink,
|
|
||||||
Container,
|
Container,
|
||||||
Spinner,
|
Spinner,
|
||||||
Button, ButtonGroup, Label, Input
|
Button, ButtonGroup
|
||||||
} from 'reactstrap';
|
} from 'reactstrap';
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import MediaService from '../../services/media-service'
|
import MediaService from '../../services/media-service'
|
||||||
@ -23,8 +19,6 @@ function Header(props) {
|
|||||||
const GlobalTheme = props.GlobalTheme;
|
const GlobalTheme = props.GlobalTheme;
|
||||||
const ThemeConfig = props.ThemeConfig;
|
const ThemeConfig = props.ThemeConfig;
|
||||||
const UserData = props.UserData;
|
const UserData = props.UserData;
|
||||||
|
|
||||||
const [collapseClasses, setCollapseClasses] = useState('');
|
|
||||||
const [themeSelected, setThemeSelected] = useState('lightTheme');
|
const [themeSelected, setThemeSelected] = useState('lightTheme');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -37,35 +31,35 @@ function Header(props) {
|
|||||||
|
|
||||||
if (GlobalTheme && ThemeConfig && UserData)
|
if (GlobalTheme && ThemeConfig && UserData)
|
||||||
return (
|
return (
|
||||||
<header className="header-global" id="site-header">
|
<header className='header-global' id='site-header'>
|
||||||
<Navbar className={`navbar-horizontal ${ThemeConfig[GlobalTheme].navBar['navBarTheme']} ${ThemeConfig[GlobalTheme].navBar['background']}`}
|
<Navbar className={`navbar-horizontal ${ThemeConfig[GlobalTheme].navBar['navBarTheme']} ${ThemeConfig[GlobalTheme].navBar['background']}`}
|
||||||
expand="lg">
|
expand='lg'>
|
||||||
<Container>
|
<Container>
|
||||||
<NavbarBrand>
|
<NavbarBrand>
|
||||||
<Link to="/">
|
<Link to='/'>
|
||||||
{
|
{
|
||||||
UserData.profilePhoto !== "" ?
|
UserData.profilePhoto !== '' ?
|
||||||
<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={MediaService.getMedia(UserData.profilePhoto)}
|
||||||
/> : ""
|
/> : ''
|
||||||
}
|
}
|
||||||
<Button color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ""}`} size="lg">
|
<Button color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ''}`} size='lg'>
|
||||||
{ UserData ? UserData.name : <Spinner> Loading... </Spinner> }
|
{ UserData ? UserData.name : <Spinner> Loading... </Spinner> }
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</NavbarBrand>
|
</NavbarBrand>
|
||||||
<Nav className="ml-lg-auto" navbar>
|
<Nav className='ml-lg-auto' navbar>
|
||||||
<NavItem>
|
<NavItem>
|
||||||
<ButtonGroup style={{marginTop: '15px', marginBottom: '15px'}}>
|
<ButtonGroup style={{marginTop: '15px', marginBottom: '15px'}}>
|
||||||
<Button color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ""}`}>
|
<Button color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ''}`}>
|
||||||
<Link to="/categories">
|
<Link to='/categories'>
|
||||||
<FontAwesomeIcon icon={faPen} /> Blogs
|
<FontAwesomeIcon icon={faPen} /> Blogs
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ""}`}
|
color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ''}`}
|
||||||
outline
|
outline
|
||||||
onClick={() => {setThemeSelected('lightTheme')}}
|
onClick={() => {setThemeSelected('lightTheme')}}
|
||||||
active={themeSelected === 'lightTheme'}
|
active={themeSelected === 'lightTheme'}
|
||||||
@ -73,7 +67,7 @@ function Header(props) {
|
|||||||
<FontAwesomeIcon icon={faSun} /> Light Theme
|
<FontAwesomeIcon icon={faSun} /> Light Theme
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ""}`}
|
color={`${ThemeConfig ? ThemeConfig[GlobalTheme].navBar['buttonColor'] : ''}`}
|
||||||
outline
|
outline
|
||||||
onClick={() => {setThemeSelected('darkTheme')}}
|
onClick={() => {setThemeSelected('darkTheme')}}
|
||||||
active={themeSelected === 'darkTheme'}
|
active={themeSelected === 'darkTheme'}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Collapse, Button, CardBody, Card, Alert } from 'reactstrap';
|
import { Collapse, CardBody, Card, Alert } from 'reactstrap';
|
||||||
|
|
||||||
function Notification(props) {
|
function Notification(props) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React, { Suspense, lazy } from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom/client'
|
import ReactDOM from 'react-dom/client'
|
||||||
import './index.css'
|
import './index.css'
|
||||||
import App from './App.jsx'
|
import App from './App.jsx'
|
||||||
|
|||||||
@ -1,17 +1,18 @@
|
|||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import react from '@vitejs/plugin-react'
|
import react from '@vitejs/plugin-react'
|
||||||
|
import eslint from 'vite-plugin-eslint';
|
||||||
|
|
||||||
console.log(process.env.BUILD_ENV)
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [
|
plugins: [
|
||||||
react(),
|
react(),
|
||||||
|
eslint(),
|
||||||
process.env.BUILD_ENV === 'ghpages' ? {
|
process.env.BUILD_ENV === 'ghpages' ? {
|
||||||
name: 'inject-ghpages-fix',
|
name: 'inject-ghpages-fix',
|
||||||
transformIndexHtml(html) {
|
transformIndexHtml(html) {
|
||||||
return html.replace(
|
return html.replace(
|
||||||
'<div id="root"></div>',
|
'<div id="root"></div>',
|
||||||
"<div id='root'></div><script type='text/javascript'>(function(l) {if (l.search[1] === '/' ) {var decoded = l.search.slice(1).split('&').map(function(s) {return s.replace(/~and~/g, '&')}).join('?');window.history.replaceState(null, null,l.pathname.slice(0, -1) + decoded + l.hash);}}(window.location))</script>"
|
'<div id="root"></div><script type="text/javascript">(function(l) {if (l.search[1] === "/" ) {var decoded = l.search.slice(1).split("&").map(function(s) {return s.replace(/~and~/g, "&")}).join("?");window.history.replaceState(null, null,l.pathname.slice(0, -1) + decoded + l.hash);}}(window.location))</script>'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} : ''
|
} : ''
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user