diff --git a/backend/apimanager/serializers.py b/backend/apimanager/serializers.py index 8151936..dac94e8 100644 --- a/backend/apimanager/serializers.py +++ b/backend/apimanager/serializers.py @@ -96,5 +96,5 @@ class MediaSerializer(serializers.Serializer): media = serializers.ListField( child=serializers.FileField(max_length=100000, allow_empty_file=False, use_url=False) ) - resource_type = serializers.CharField(allow_blank=False) - resource_id = serializers.CharField(allow_blank=False) \ No newline at end of file + resource_type = serializers.CharField(max_length=255, allow_blank=False) + resource_id = serializers.CharField(max_length=255, allow_blank=False) \ No newline at end of file diff --git a/backend/apimanager/views.py b/backend/apimanager/views.py index 29ec7fb..eae401d 100644 --- a/backend/apimanager/views.py +++ b/backend/apimanager/views.py @@ -1,17 +1,10 @@ #######################Django related imports#################### -import os -import subprocess -import ast -import shutil -from django.shortcuts import render -from django.contrib.auth.models import User -from django.http import HttpResponseRedirect from rest_framework.views import APIView from rest_framework.response import Response -from rest_framework.decorators import api_view -from rest_framework.generics import GenericAPIView from rest_framework.parsers import MultiPartParser, FormParser -from rest_framework import generics, permissions, views, serializers, status +from django.core.files.storage import default_storage +from rest_framework import generics, status +import random ################################################################# #API related imports from .models import ( @@ -110,24 +103,22 @@ class BlogDeleteAPIView(generics.DestroyAPIView): lookup_field = 'blog_id' #################################################################### -''' -class MediaView(APIView): + +class MediaUpload(APIView): parser_classes = (MultiPartParser, FormParser) def post(self, request, *args, **kwargs): - file_serializer = FileSerializer(data=request.data) + file_serializer = MediaSerializer(data=request.data) if file_serializer.is_valid(): - files = dict((f, f) for f in request.FILES.getlist('file')) - nodeName = file_serializer.validated_data['nodeName'] - preferredFormat = file_serializer.validated_data['preferredFormat'] - for f in files.values(): - fileHandlerObject = FileHandler(f, preferredFormat, nodeName) - fileProcessed = fileHandlerObject.handleUploadedFile() - if not fileProcessed[0]: - return Response(file_serializer.errors, status=status.HTTP_400_BAD_REQUEST) - else: - return Response(file_serializer.data, status=status.HTTP_201_CREATED) + files = request.FILES.getlist('media') + resource_type = file_serializer.validated_data['resource_type'] + resource_id = file_serializer.validated_data['resource_id'] + file_path_base = f'static/rangolio_data' + for f in files: + file_unique_slug = ''.join(random.choices('ABCDEabcde1234', k=5)) + file_path = f"{file_path_base}/{resource_type}/{resource_id}/media/{file_unique_slug+resource_id+f.name}" + default_storage.save(file_path, f) return Response(file_serializer.data, status=status.HTTP_201_CREATED) else: @@ -135,6 +126,7 @@ class MediaView(APIView): +''' class ETLFunctions(GenericAPIView): serializer_class = ETLData diff --git a/backend/backend/urls.py b/backend/backend/urls.py index 4073d56..8a81dab 100644 --- a/backend/backend/urls.py +++ b/backend/backend/urls.py @@ -32,6 +32,7 @@ from apimanager.views import ( BlogRetrieveAPIView, BlogDeleteAPIView, BlogsByCategoryAPIView, + MediaUpload ) urlpatterns = [ @@ -49,4 +50,5 @@ urlpatterns = [ path('data/blog//', BlogRetrieveAPIView.as_view(), name='blog-retrieve-view'), path('data/blog/update//', BlogUpdateAPIView.as_view(), name='blog-update-view'), path('data/blog/delete//', BlogDeleteAPIView.as_view(), name='blog-delete-view'), + path('data/upload/', MediaUpload.as_view(), name='media-upload'), ] \ No newline at end of file diff --git a/backend/resourceType/resourceId/Screenshot_20240324_111611_Firefox.jpg b/backend/resourceType/resourceId/Screenshot_20240324_111611_Firefox.jpg new file mode 100644 index 0000000..1e79f22 Binary files /dev/null and b/backend/resourceType/resourceId/Screenshot_20240324_111611_Firefox.jpg differ diff --git a/backend/static/json/data/blogs/72e4d550-a19b-4b62-bf5a-13f98813d31a/blog-data.json b/backend/static/json/data/blogs/72e4d550-a19b-4b62-bf5a-13f98813d31a/blog-data.json deleted file mode 100644 index c26b260..0000000 --- a/backend/static/json/data/blogs/72e4d550-a19b-4b62-bf5a-13f98813d31a/blog-data.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "id": "72e4d550-a19b-4b62-bf5a-13f98813d31a", - "name": "Blog 1", - "description": "A subtitle for Blog 1", - "tagLine": "Read blog", - "coverImage": "blogs/72e4d550-a19b-4b62-bf5a-13f98813d31a/media/blog1.png", - "parentCategory": "520b7982-069e-4a48-9ef3-64507d86a579", - "contentBody": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec non ipsum in nunc pretium gravida id ut lectus. Duis ligula nisl, egestas a tortor nec, scelerisque hendrerit urna. Nullam gravida, ante id aliquet ultrices, justo metus aliquet augue, vestibulum posuere massa lacus at est. Cras vitae dolor euismod, volutpat quam eu, cursus enim. Maecenas in magna ut augue ultrices laoreet. Maecenas sapien sem, mollis sed ipsum nec, viverra vehicula quam. Sed et pulvinar justo. Quisque et vestibulum dui. Aliquam laoreet tempus neque, et eleifend nulla vestibulum eget. Cras tempus justo at nunc facilisis auctor. Duis facilisis tortor eu risus aliquam dapibus nec sit amet est. Maecenas ante lectus, sagittis eu facilisis sit amet, convallis eu ex. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean imperdiet vulputate ipsum sed scelerisque. Donec sit amet rutrum est. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Etiam gravida augue sem, quis aliquet justo varius non. Nam tortor nulla, bibendum sit amet finibus sed, ultricies non tellus. Aliquam condimentum risus ut felis porta iaculis. Nullam gravida mauris lacinia finibus hendrerit. Sed nec consectetur erat, sed tincidunt velit. Donec sit amet nulla at sem blandit imperdiet ut eu nisl. Sed condimentum, lectus quis sodales commodo, arcu turpis sodales ex, ac placerat mi turpis sit amet mi. Nullam lorem velit, porta eu quam eu, hendrerit egestas nibh. Sed non pellentesque arcu. Nam felis lectus, scelerisque in semper a, faucibus sit amet nibh. Cras est ligula, pretium id maximus nec, hendrerit eu ante. Maecenas tincidunt est ante, sed vestibulum mauris dignissim nec. Phasellus varius varius leo in pharetra. Aenean vestibulum id dui cursus lobortis. Mauris vel orci massa. Nullam vitae lorem mattis, lobortis dui in, pharetra velit. Aenean non urna ac felis volutpat consequat sit amet sed nisi. Quisque rutrum nisi ac erat ultricies tempor. Etiam nec pellentesque metus. Nulla tempus mi a ex rutrum, ut luctus tellus porta. Interdum et malesuada fames ac ante ipsum primis in faucibus. Phasellus et quam sit amet arcu mattis commodo quis non risus. Sed luctus non dui ullamcorper consectetur. Duis eros magna, tempus ut aliquam sit amet, tempor vel nibh. Vestibulum hendrerit odio convallis elit pretium dictum. Proin ligula dolor, finibus eget lacus sed, facilisis fringilla lorem. Quisque quis lacus sit amet massa blandit fringilla vel vitae tortor. Vivamus dictum nibh vel justo ullamcorper faucibus. Nullam vitae augue pretium erat semper rhoncus. Etiam tempus, arcu feugiat hendrerit pretium, nisi justo sollicitudin velit, sagittis elementum ante metus sed ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Etiam quis ligula euismod, venenatis arcu vitae, condimentum arcu. Donec vitae nisl aliquam, rutrum arcu vel, sollicitudin justo. Vestibulum nec sagittis massa. Etiam maximus, erat vitae dapibus vulputate, velit lectus imperdiet est, sed lobortis ante erat lobortis arcu. Maecenas mollis nunc ut nisi tristique tempus. Nulla tempor est non dui scelerisque, eget semper augue consequat." -} \ No newline at end of file diff --git a/backend/static/json/data/blogs/b4d9e1a0-4a77-48eb-a04b-06ec23e2b73e/blog-data.json b/backend/static/json/data/blogs/b4d9e1a0-4a77-48eb-a04b-06ec23e2b73e/blog-data.json deleted file mode 100644 index 2944507..0000000 --- a/backend/static/json/data/blogs/b4d9e1a0-4a77-48eb-a04b-06ec23e2b73e/blog-data.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "id": "b4d9e1a0-4a77-48eb-a04b-06ec23e2b73e", - "name": "Blog 2", - "description": "A subtitle for Blog 2", - "tagLine": "Read blog", - "coverImage": "blogs/b4d9e1a0-4a77-48eb-a04b-06ec23e2b73e/media/blog2.png", - "parentCategory": "520b7982-069e-4a48-9ef3-64507d86a579", - "contentBody": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec non ipsum in nunc pretium gravida id ut lectus. Duis ligula nisl, egestas a tortor nec, scelerisque hendrerit urna. Nullam gravida, ante id aliquet ultrices, justo metus aliquet augue, vestibulum posuere massa lacus at est. Cras vitae dolor euismod, volutpat quam eu, cursus enim. Maecenas in magna ut augue ultrices laoreet. Maecenas sapien sem, mollis sed ipsum nec, viverra vehicula quam. Sed et pulvinar justo. Quisque et vestibulum dui. Aliquam laoreet tempus neque, et eleifend nulla vestibulum eget. Cras tempus justo at nunc facilisis auctor. Duis facilisis tortor eu risus aliquam dapibus nec sit amet est. Maecenas ante lectus, sagittis eu facilisis sit amet, convallis eu ex. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean imperdiet vulputate ipsum sed scelerisque. Donec sit amet rutrum est. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Etiam gravida augue sem, quis aliquet justo varius non. Nam tortor nulla, bibendum sit amet finibus sed, ultricies non tellus. Aliquam condimentum risus ut felis porta iaculis. Nullam gravida mauris lacinia finibus hendrerit. Sed nec consectetur erat, sed tincidunt velit. Donec sit amet nulla at sem blandit imperdiet ut eu nisl. Sed condimentum, lectus quis sodales commodo, arcu turpis sodales ex, ac placerat mi turpis sit amet mi. Nullam lorem velit, porta eu quam eu, hendrerit egestas nibh. Sed non pellentesque arcu. Nam felis lectus, scelerisque in semper a, faucibus sit amet nibh. Cras est ligula, pretium id maximus nec, hendrerit eu ante. Maecenas tincidunt est ante, sed vestibulum mauris dignissim nec. Phasellus varius varius leo in pharetra. Aenean vestibulum id dui cursus lobortis. Mauris vel orci massa. Nullam vitae lorem mattis, lobortis dui in, pharetra velit. Aenean non urna ac felis volutpat consequat sit amet sed nisi. Quisque rutrum nisi ac erat ultricies tempor. Etiam nec pellentesque metus. Nulla tempus mi a ex rutrum, ut luctus tellus porta. Interdum et malesuada fames ac ante ipsum primis in faucibus. Phasellus et quam sit amet arcu mattis commodo quis non risus. Sed luctus non dui ullamcorper consectetur. Duis eros magna, tempus ut aliquam sit amet, tempor vel nibh. Vestibulum hendrerit odio convallis elit pretium dictum. Proin ligula dolor, finibus eget lacus sed, facilisis fringilla lorem. Quisque quis lacus sit amet massa blandit fringilla vel vitae tortor. Vivamus dictum nibh vel justo ullamcorper faucibus. Nullam vitae augue pretium erat semper rhoncus. Etiam tempus, arcu feugiat hendrerit pretium, nisi justo sollicitudin velit, sagittis elementum ante metus sed ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Etiam quis ligula euismod, venenatis arcu vitae, condimentum arcu. Donec vitae nisl aliquam, rutrum arcu vel, sollicitudin justo. Vestibulum nec sagittis massa. Etiam maximus, erat vitae dapibus vulputate, velit lectus imperdiet est, sed lobortis ante erat lobortis arcu. Maecenas mollis nunc ut nisi tristique tempus. Nulla tempor est non dui scelerisque, eget semper augue consequat." -} \ No newline at end of file diff --git a/backend/static/json/data/category/520b7982-069e-4a48-9ef3-64507d86a579/blog-metadata.json b/backend/static/json/data/category/520b7982-069e-4a48-9ef3-64507d86a579/blog-metadata.json deleted file mode 100644 index f3f1037..0000000 --- a/backend/static/json/data/category/520b7982-069e-4a48-9ef3-64507d86a579/blog-metadata.json +++ /dev/null @@ -1,18 +0,0 @@ -[ - { - "id": "72e4d550-a19b-4b62-bf5a-13f98813d31a", - "name": "Blog 1", - "description": "A subtitle for Blog 1", - "coverImage": "blogs/72e4d550-a19b-4b62-bf5a-13f98813d31a/media/blog1.png", - "tagLine": "Read more", - "parentCategory": "520b7982-069e-4a48-9ef3-64507d86a579" - }, - { - "id": "b4d9e1a0-4a77-48eb-a04b-06ec23e2b73e", - "name": "Blog 2", - "description": "A subtitle for Blog 2", - "coverImage": "blogs/b4d9e1a0-4a77-48eb-a04b-06ec23e2b73e/media/blog2.png", - "tagLine": "Read more", - "parentCategory": "520b7982-069e-4a48-9ef3-64507d86a579" - } -] \ No newline at end of file diff --git a/backend/static/json/data/category/520b7982-069e-4a48-9ef3-64507d86a579/category-data.json b/backend/static/json/data/category/520b7982-069e-4a48-9ef3-64507d86a579/category-data.json deleted file mode 100644 index 476aad9..0000000 --- a/backend/static/json/data/category/520b7982-069e-4a48-9ef3-64507d86a579/category-data.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "id": "520b7982-069e-4a48-9ef3-64507d86a579", - "name": "Technology", - "coverImage": "category/520b7982-069e-4a48-9ef3-64507d86a579/media/technology.png", - "tagLine": "Read articles about tech", - "description": "I have been working in tech for long, and here are my thoughts of random stuff", - "featuredBlog": "b4d9e1a0-4a77-48eb-a04b-06ec23e2b73e" -} \ No newline at end of file diff --git a/backend/static/json/data/category/b9e0d686-351d-49af-8e3d-b62023f44dbe/blog-metadata.json b/backend/static/json/data/category/b9e0d686-351d-49af-8e3d-b62023f44dbe/blog-metadata.json deleted file mode 100644 index 367e8fa..0000000 --- a/backend/static/json/data/category/b9e0d686-351d-49af-8e3d-b62023f44dbe/blog-metadata.json +++ /dev/null @@ -1,3 +0,0 @@ -[{ - -}] \ No newline at end of file diff --git a/backend/static/json/data/category/b9e0d686-351d-49af-8e3d-b62023f44dbe/category-data.json b/backend/static/json/data/category/b9e0d686-351d-49af-8e3d-b62023f44dbe/category-data.json deleted file mode 100644 index 8f1143e..0000000 --- a/backend/static/json/data/category/b9e0d686-351d-49af-8e3d-b62023f44dbe/category-data.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "id": "b9e0d686-351d-49af-8e3d-b62023f44dbe", - "name": "Gaming", - "coverImage": "category/b9e0d686-351d-49af-8e3d-b62023f44dbe/media/game.png", - "tagLine": "Read articles about games", - "description": "I like to game, and here are my thoughts on games" -} diff --git a/backend/static/json/data/category/category-metadata.json b/backend/static/json/data/category/category-metadata.json deleted file mode 100644 index c795a13..0000000 --- a/backend/static/json/data/category/category-metadata.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "id": "520b7982-069e-4a48-9ef3-64507d86a579", - "name": "Technology", - "coverImage": "category/520b7982-069e-4a48-9ef3-64507d86a579/media/technology.png", - "tagLine": "Read articles about tech", - "description": "I have been working in tech for long, and here are my thoughts of random stuff" - }, - { - "id": "b9e0d686-351d-49af-8e3d-b62023f44dbe", - "name": "Gaming", - "coverImage": "category/b9e0d686-351d-49af-8e3d-b62023f44dbe/media/game.png", - "tagLine": "Read articles about games", - "description": "I like to game, and here are my thoughts on games" - } -] diff --git a/backend/static/json/data/shared/theme-config.json b/backend/static/json/data/shared/theme-config.json deleted file mode 100644 index 5005f9e..0000000 --- a/backend/static/json/data/shared/theme-config.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "darkTheme": { - "theme": "Dark Mode", - "background": "bg-dark", - "textColor": "text-white", - "captionColor": "#8a8a8a", - "fontAwesomeIcon": "faSun", - "borderColor": "white", - "categoryNavigator": "light", - "navBar": { - "navBarTheme": "navbar-dark", - "background": "bg-secondary", - "buttonColor": "light" - }, - "footer": { - "background": "bg-secondary", - "text": "bg-white" - } - }, - "lightTheme":{ - "theme": "Light Mode", - "background": "bg-light", - "textColor": "text-black", - "captionColor": "#605f5f", - "fontAwesomeIcon": "faMoon", - "borderColor": "black", - "categoryNavigator": "dark", - "navBar": { - "navBarTheme": "navbar-light", - "background": "bg-secondary", - "buttonColor": "light" - }, - "footer": { - "background": "bg-secondary", - "text": "bg-white" - } - } -} \ No newline at end of file diff --git a/backend/static/json/data/shared/user-data.json b/backend/static/json/data/shared/user-data.json deleted file mode 100644 index 2644d70..0000000 --- a/backend/static/json/data/shared/user-data.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "John Doe", - "greetingLine": "Hi! My name is", - "tagLine": "Me like tech. Checkout my blog where I have nice stuff!", - "profilePhoto": "homepage/media/profile.png", - "links": { - "instagram": "" - }, - "contact":{ - "email":"", - "phone": "" - } -} diff --git a/frontend/src/components/editable/blog.jsx b/frontend/src/components/editable/blog.jsx index 862d62c..9f09a03 100755 --- a/frontend/src/components/editable/blog.jsx +++ b/frontend/src/components/editable/blog.jsx @@ -138,7 +138,7 @@ function Blog(props) { - + diff --git a/frontend/src/components/editable/shared/file-component.jsx b/frontend/src/components/editable/shared/file-component.jsx new file mode 100644 index 0000000..4014b18 --- /dev/null +++ b/frontend/src/components/editable/shared/file-component.jsx @@ -0,0 +1,46 @@ +import React, { useState } from 'react'; +import { Button, Label, Input } from 'reactstrap'; +import EditableDataService from '../../../services/editable-data-service'; + +function FileComponent(props) { + const [file, setFile] = useState(null); + const [resourceType, setResourceType] = useState(''); + const [resourceId, setResourceId] = useState(''); + + const handleFileChange = (event) => { + setFile(event.target.files[0]); // Assuming single file upload + }; + + const handleUpload = async (event) => { + event.preventDefault(); + + const formData = new FormData(); + formData.append('media', file); + formData.append('resource_type', props.resourceType); + formData.append('resource_id', props.resourceId); + + try { + const response = await EditableDataService.createData('/data/upload/', formData); + props.notificationToggler('Media uploaded successfully') + } catch (error) { + props.notificationToggler('Media upload failed', 'danger') + } + }; + + return ( +
+ + + +
+ ); +} + +export default FileComponent; diff --git a/frontend/src/components/editable/shared/media-upload.jsx b/frontend/src/components/editable/shared/media-upload.jsx new file mode 100644 index 0000000..171dfc4 --- /dev/null +++ b/frontend/src/components/editable/shared/media-upload.jsx @@ -0,0 +1,59 @@ +import React, { useState } from 'react'; +import FileComponent from './file-component.jsx'; +import { Button, ButtonGroup, Modal, ModalHeader, ModalBody, ModalFooter} from 'reactstrap'; + +function MediaUpload(props) { + + const [action, setAction] = useState('insert') + const toggleAction = () =>{ + if (action === 'insert') + setAction('upload') + if (action === 'upload') + setAction('insert') + } + + return ( +
+ + {props.modalTitle} + + + + + +
+ { action === 'insert' ? +
+

+ Choose media to insert +

+
: +
+ +
+ } +
+
+ + + +
+
+ ); +} + +export default MediaUpload; \ No newline at end of file diff --git a/frontend/src/components/editable/shared/tiptap-custom-extensions/custom-image-extension.jsx b/frontend/src/components/editable/shared/tiptap-custom-extensions/custom-image-extension.jsx new file mode 100644 index 0000000..706635a --- /dev/null +++ b/frontend/src/components/editable/shared/tiptap-custom-extensions/custom-image-extension.jsx @@ -0,0 +1,52 @@ +/* + + 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 { NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react'; +import { + Button +} from 'reactstrap'; + +function ImageNode(props) { + const { src, alt } = props.node.attrs + const { updateAttributes } = props + const onEditAlt = () => { + const newAlt = prompt('Set alt text:', alt || '') + updateAttributes({ alt: newAlt }) + } + + let className = 'image' + if (props.selected) { className += ' ProseMirror-selectednode'} + + return ( + +
+ onEditAlt()} className='mx-auto d-block' src={src} alt={alt} /> +
+ + { alt ? + : + ! + } + { alt ? + Alt text: "{alt}".: + Alt text missing. + } + + +
+
+
+ ) +} + +export default Image.extend({ + addNodeView() { + return ReactNodeViewRenderer(ImageNode) + } +}) \ No newline at end of file diff --git a/frontend/src/components/editable/shared/tiptap.jsx b/frontend/src/components/editable/shared/tiptap.jsx index 25ca9dc..849a7e5 100755 --- a/frontend/src/components/editable/shared/tiptap.jsx +++ b/frontend/src/components/editable/shared/tiptap.jsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect } from 'react' +import React, { useCallback, useEffect, useState } from 'react' import { Button, ButtonGroup, Label, Input } from 'reactstrap'; import { Color } from '@tiptap/extension-color' @@ -8,7 +8,6 @@ import Highlight from '@tiptap/extension-highlight' import TextAlign from '@tiptap/extension-text-align' import Underline from '@tiptap/extension-underline' import Blockquote from '@tiptap/extension-blockquote' -import Image from '@tiptap/extension-image' import Link from '@tiptap/extension-link' import { EditorProvider, useCurrentEditor } from '@tiptap/react' import StarterKit from '@tiptap/starter-kit' @@ -21,7 +20,11 @@ import { faBold, faItalic, faListUl, faLink, faListOl, faQuoteLeft, faQuoteRight, faRulerHorizontal, - faRotateLeft, faRotateRight } from '@fortawesome/free-solid-svg-icons'; + faRotateLeft, faRotateRight, faImage } from '@fortawesome/free-solid-svg-icons'; + + +import CustomImageExtension from './tiptap-custom-extensions/custom-image-extension.jsx' +import MediaUpload from './media-upload.jsx' const MenuBar = (props) => { const { editor } = useCurrentEditor() @@ -310,6 +313,14 @@ const MenuBar = (props) => {
+ ) } @@ -329,12 +340,7 @@ const extensions = [ }), Underline, Blockquote, - Image.configure({ - allowBase64: true, - HTMLAttributes: { - class: 'mx-auto d-block', - }, - }), + CustomImageExtension, TextAlign.configure({ types: ['heading', 'paragraph'], }), @@ -349,8 +355,14 @@ export default (props) => { const GlobalTheme = props.GlobalTheme; const ThemeConfig = props.ThemeConfig; + const [modal, setModal] = useState(false); + const toggle = () => setModal(!modal); + if (props.content && GlobalTheme && ThemeConfig) return ( - } extensions={extensions} content={props.content}> + <> + + } extensions={extensions} content={props.content}> + ) } \ No newline at end of file diff --git a/frontend/src/index.css b/frontend/src/index.css index dc1dac1..a8c4035 100755 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -1,12 +1,12 @@ a { - text-decoration: none !important; /* Removes underline */ - color: inherit !important; /* Inherits color from parent */ - border: none !important; /* Removes any borders */ + text-decoration: none !important; + color: inherit !important; + border: none !important; } .app-container { display: grid; - grid-template-rows: auto 1fr auto; /* Header size, flexible content, footer size */ + grid-template-rows: auto 1fr auto; height: 100vh; } @@ -42,7 +42,27 @@ a { .blogContent img { display: flex; - justify-content: center; /* Center horizontally */ + justify-content: center; align-items: center; - width: 50%; -} \ No newline at end of file + width: 70%; +} + +.image-container { + position: relative; + display: inline-block; +} + +.image-overlay { + position: absolute; + bottom: 0; + left: 0; + right: 0; + text-align: center; + color: white; + background: rgba(0, 0, 0, 0.5); +} + +.image-text { + display: block; + padding: 5px 0; +}