diff --git a/server/apps/research/admin/article_admin.py b/server/apps/research/admin/article_admin.py index 3bebba2..5e62d2d 100644 --- a/server/apps/research/admin/article_admin.py +++ b/server/apps/research/admin/article_admin.py @@ -1,18 +1,15 @@ from django.contrib import admin from django import forms -from django_ckeditor_5.widgets import CKEditor5Widget from apps.research.models import Article, Author +from tinymce.widgets import TinyMCE @admin.register(Article) class ArticleAdmin(admin.ModelAdmin): """Admin interface for the Article model.""" - class Media: - # Reference the JavaScript file - js = ('ckeditor/js/custom_ckeditor_admin.js',) fieldsets = [ - ('Article Details', {'fields': ['title', 'authors', 'categories', 'thumb', 'content', 'summary', 'status', 'scheduled_publish_time']}), + ('Article Details', {'fields': ['title', 'authors', 'acknowledgement', 'categories', 'thumb', 'content', 'summary', 'status', 'scheduled_publish_time']}), ] - list_display = ('title', 'display_authors', 'status', 'views', 'display_categories', 'created_at', 'scheduled_publish_time') + list_display = ('title', 'display_authors', 'status', 'views', 'display_categories', 'min_read', 'created_at', 'scheduled_publish_time') search_fields = ('title', 'authors__user__username', 'authors__twitter_username', 'content') list_per_page = 25 list_filter = ('authors', 'status', 'categories', 'created_at') @@ -20,10 +17,11 @@ class Media: list_editable = ('status',) def get_form(self, request, obj=None, **kwargs): - """Return a form with CKEditor5Widget for the content field.""" + """Return a form with TinyMCE Widget for the selected fields.""" form = super().get_form(request, obj, **kwargs) - if 'content' in form.base_fields: - form.base_fields['content'].widget = CKEditor5Widget(attrs={"class": "django_ckeditor_5"}, config_name='extends') + for field_name in ['content', 'acknowledgement']: + if field_name in form.base_fields: + form.base_fields[field_name].widget = TinyMCE(attrs={'cols': 80, 'rows': 30, 'id': f"{field_name}_richtext_field", 'placeholder': f"Enter {field_name} here"}) return form def display_authors(self, obj): diff --git a/server/apps/research/admin/author_admin.py b/server/apps/research/admin/author_admin.py index fd1cba9..1c2f670 100644 --- a/server/apps/research/admin/author_admin.py +++ b/server/apps/research/admin/author_admin.py @@ -6,9 +6,9 @@ class AuthorAdmin(admin.ModelAdmin): """Admin interface for the Author model.""" fieldsets = [ - ('Author Details', {'fields': ['user', 'bio', 'twitter_username']}), + ('Author Details', {'fields': ['user', 'full_name', 'bio', 'twitter_username']}), ] - list_display = ('user', 'bio', 'twitter_username') + list_display = ('user', 'full_name', 'bio', 'twitter_username') list_per_page = 25 search_fields = ('user__username', 'twitter_username') diff --git a/server/apps/research/migrations/0015_alter_article_options_article_acknowledgement_and_more.py b/server/apps/research/migrations/0015_alter_article_options_article_acknowledgement_and_more.py new file mode 100644 index 0000000..9746d30 --- /dev/null +++ b/server/apps/research/migrations/0015_alter_article_options_article_acknowledgement_and_more.py @@ -0,0 +1,33 @@ +# Generated by Django 5.0.8 on 2024-08-29 03:39 + +import tinymce.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('research', '0014_alter_article_title'), + ] + + operations = [ + migrations.AlterModelOptions( + name='article', + options={'ordering': ('-scheduled_publish_time',)}, + ), + migrations.AddField( + model_name='article', + name='acknowledgement', + field=models.TextField(blank=True, null=True), + ), + migrations.AddField( + model_name='author', + name='full_name', + field=models.CharField(blank=True, max_length=255, null=True), + ), + migrations.AlterField( + model_name='article', + name='content', + field=tinymce.models.HTMLField(blank=True, null=True), + ), + ] diff --git a/server/apps/research/migrations/0016_article_time_read.py b/server/apps/research/migrations/0016_article_time_read.py new file mode 100644 index 0000000..7a59bb7 --- /dev/null +++ b/server/apps/research/migrations/0016_article_time_read.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.8 on 2024-08-29 05:41 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('research', '0015_alter_article_options_article_acknowledgement_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='article', + name='time_read', + field=models.IntegerField(editable=False, null=True), + ), + ] diff --git a/server/apps/research/migrations/0017_remove_article_time_read.py b/server/apps/research/migrations/0017_remove_article_time_read.py new file mode 100644 index 0000000..26ec0bf --- /dev/null +++ b/server/apps/research/migrations/0017_remove_article_time_read.py @@ -0,0 +1,17 @@ +# Generated by Django 5.0.8 on 2024-08-29 05:57 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('research', '0016_article_time_read'), + ] + + operations = [ + migrations.RemoveField( + model_name='article', + name='time_read', + ), + ] diff --git a/server/apps/research/migrations/0018_alter_article_acknowledgement.py b/server/apps/research/migrations/0018_alter_article_acknowledgement.py new file mode 100644 index 0000000..7c74568 --- /dev/null +++ b/server/apps/research/migrations/0018_alter_article_acknowledgement.py @@ -0,0 +1,19 @@ +# Generated by Django 5.0.8 on 2024-08-29 07:19 + +import tinymce.models +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('research', '0017_remove_article_time_read'), + ] + + operations = [ + migrations.AlterField( + model_name='article', + name='acknowledgement', + field=tinymce.models.HTMLField(blank=True, null=True), + ), + ] diff --git a/server/apps/research/models/article.py b/server/apps/research/models/article.py index 5ffa30a..7fd22d5 100644 --- a/server/apps/research/models/article.py +++ b/server/apps/research/models/article.py @@ -1,12 +1,13 @@ from django.db import models from django.utils.text import slugify -from django_ckeditor_5.fields import CKEditor5Field from apps.common.models import BaseModel from apps.research.managers import ArticleObjects from .category import Category from .author import Author from django.utils import timezone from django.conf import settings +from tinymce.models import HTMLField +import math def get_default_thumb(): @@ -21,33 +22,43 @@ class Article(BaseModel): ) title = models.TextField() - content = CKEditor5Field('Text', null=True, blank=True, config_name='extends') + content = HTMLField(blank=True, null=True) summary = models.TextField(blank=True) + acknowledgement = HTMLField(blank=True, null=True) authors = models.ManyToManyField(Author, blank=True, related_name='articles') slug = models.SlugField(blank=True) categories = models.ManyToManyField(Category, blank=True, related_name='articles') thumb = models.ImageField(upload_to='images/', default=get_default_thumb, blank=True) views = models.PositiveBigIntegerField(default=0) - status = models.CharField(max_length=10, choices=options, default='draft') + status = models.CharField(max_length=10, choices=options, default='draft') scheduled_publish_time = models.DateTimeField(null=True, blank=True, db_index=True) objects = models.Manager() post_objects = ArticleObjects() class Meta: - ordering = ('-created_at',) + ordering = ('-scheduled_publish_time',) + + @property + def min_read(self): + # Compute reading time based on content length + word_count = len(self.content.split()) + words_per_minute = 300 # Average reading speed (words per minute) + minutes = max(1, round(word_count / words_per_minute)) + return minutes def __str__(self): return self.title def save(self, *args, **kwargs): """Override the save method to generate a unique slug.""" - if not self.slug: + if not self.slug or self.title_update(): self.slug = self.generate_unique_slug() - + """Override the save method to handle scheduled publishing.""" if self.scheduled_publish_time and self.status == 'draft' and timezone.now() >= self.scheduled_publish_time: self.status = 'ready' + super().save(*args, **kwargs) def generate_unique_slug(self): @@ -59,3 +70,10 @@ def generate_unique_slug(self): slug = f"{base_slug}-{num}" num += 1 return slug + + def title_update(self): + """Check if the title has changed.""" + if self.pk: + original = Article.objects.get(pk=self.pk) + return original.title != self.title + return False \ No newline at end of file diff --git a/server/apps/research/models/author.py b/server/apps/research/models/author.py index 4750dde..51a4e85 100644 --- a/server/apps/research/models/author.py +++ b/server/apps/research/models/author.py @@ -7,6 +7,7 @@ class Author(BaseModel): user = models.OneToOneField(User, on_delete=models.CASCADE) bio = models.TextField(blank=True, null=True) twitter_username = models.CharField(max_length=100, blank=True, null=True) + full_name = models.CharField(max_length=255, blank=True, null=True) class Meta: verbose_name_plural = 'Authors' diff --git a/server/apps/research/serializers/article_serializer.py b/server/apps/research/serializers/article_serializer.py index cdaef96..3efc448 100644 --- a/server/apps/research/serializers/article_serializer.py +++ b/server/apps/research/serializers/article_serializer.py @@ -14,7 +14,7 @@ class Meta: model = Article fields = [ 'id', 'slug', 'title', 'authors', 'thumb', - 'categories', 'summary', 'content', + 'categories', 'summary', 'acknowledgement', 'content', 'status', 'views', 'created_at', 'updated_at', 'scheduled_publish_time' ] @@ -25,7 +25,7 @@ class ArticleCreateUpdateSerializer(serializers.ModelSerializer): class Meta: model = Article - fields = ['title', 'categories', 'thumb', 'content', 'summary', 'status', 'authors', 'scheduled_publish_time'] + fields = ['title', 'categories', 'thumb', 'content', 'summary', 'acknowledgement', 'status', 'authors', 'scheduled_publish_time'] # TODO : Debug this method to add the logged-in user as the author when creating a new article def create(self, validated_data): diff --git a/server/apps/research/serializers/author_serializer.py b/server/apps/research/serializers/author_serializer.py index 773a854..efcf594 100644 --- a/server/apps/research/serializers/author_serializer.py +++ b/server/apps/research/serializers/author_serializer.py @@ -7,7 +7,7 @@ class AuthorSerializer(serializers.ModelSerializer): class Meta: model = Author - fields = ['id', 'username', 'bio', 'twitter_username'] + fields = ['id', 'username', 'full_name', 'bio', 'twitter_username'] def get_username(self, obj): return obj.user.username diff --git a/server/apps/research/tasks.py b/server/apps/research/tasks.py index 3d47cdc..34d25b0 100644 --- a/server/apps/research/tasks.py +++ b/server/apps/research/tasks.py @@ -8,5 +8,4 @@ def publish_scheduled_articles(): """Publish articles that are scheduled to be published.""" now = timezone.now() articles_to_publish = Article.objects.filter(status='draft', scheduled_publish_time__lte=now) - articles_to_publish = Article.objects.filter(status='draft', scheduled_publish_time__lte=now) articles_to_publish.update(status='ready') \ No newline at end of file diff --git a/server/apps/research/views.py b/server/apps/research/views.py index 15ee361..6c8b951 100644 --- a/server/apps/research/views.py +++ b/server/apps/research/views.py @@ -15,7 +15,7 @@ def index(request): class ArticleViewSet(viewsets.ModelViewSet): """API endpoint for articles.""" permission_classes = [ArticleUserWritePermission] - #serializer_class = ArticleSerializer + def get_serializer_class(self): """Return appropriate serializer class based on request method.""" diff --git a/server/core/config/base.py b/server/core/config/base.py index 1f4a1f7..c4e19ee 100644 --- a/server/core/config/base.py +++ b/server/core/config/base.py @@ -52,9 +52,8 @@ THIRD_PARTY_APPS = [ 'corsheaders', - 'ckeditor_uploader', - 'django_ckeditor_5', 'django_celery_beat', + 'tinymce', ] INSTALLED_APPS = DJANGO_APPS + LOCAL_APPS + THIRD_PARTY_APPS @@ -97,7 +96,6 @@ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [ - BASE_DIR / '../../client/build', BASE_DIR / 'templates', ], 'APP_DIRS': True, @@ -107,6 +105,9 @@ 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', + + # Tinymce Api Context + 'core.config.tinymce.tinymce_api_key', ], }, }, @@ -162,7 +163,6 @@ MEDIA_ROOT = os.path.join(BASE_DIR, 'media') STATICFILES_DIRS = [ - '../client/build/static/', os.path.join(BASE_DIR, 'static'), ] @@ -184,8 +184,9 @@ "staticfiles.W004" ] +# Tinymce API Config +TINYMCE_API_KEY = os.getenv('TINYMCE_API_KEY') + from .jazzmin import * -from .ckeditor import * from .celery_config import * -from .mail import * - +from .mail import * \ No newline at end of file diff --git a/server/core/config/ckeditor.py b/server/core/config/ckeditor.py deleted file mode 100644 index 332b566..0000000 --- a/server/core/config/ckeditor.py +++ /dev/null @@ -1,185 +0,0 @@ -# CKEDITOR CONFIGS -CKEDITOR_UPLOAD_PATH = "ckeditor_uploads/" - -iframeEditing = True -removePlugins = 'link' -allowedContent = True -htmlEncodeOutput = True -disallowedContent = {'script', 'iframe', 'javascript'} - -CKEDITOR_IMAGE_BACKEND = "pillow" - -CKEDITOR_5_ALLOW_ALL_FILE_TYPES = True - -CKEDITOR_5_CUSTOM_CSS = "custom.css" - -CKEDITOR_5_CUSTOM_JS = { - 'pastefilter': ''' - CKEDITOR.plugins.add('pastefilter', { - init: function(editor) { - editor.on('paste', function(evt) { - evt.preventDefault(); - evt.stopPropagation(); - var data = evt.data; - data.html = data.html.replace(/]*>/g, function(match) { - return match.replace('href', 'data-href'); - }); - }); - } - }); - ''' -} - -customColorPalette = [ - {"color": "hsl(4, 90%, 58%)", "label": "Red"}, - {"color": "hsl(340, 82%, 52%)", "label": "Pink"}, - {"color": "hsl(291, 64%, 42%)", "label": "Purple"}, - {"color": "hsl(262, 52%, 47%)", "label": "Deep Purple"}, - {"color": "hsl(231, 48%, 48%)", "label": "Indigo"}, - {"color": "hsl(207, 90%, 54%)", "label": "Blue"}, -] - - -CKEDITOR_5_CONFIGS = { - 'default': { - 'paste': { - 'forcePlainText': True, - 'linkCreation': False, - }, - 'htmlSupport': { - 'allow': [ - 'a', - # Other allowed HTML elements... - ], - 'disallow': [ - 'a[href]', # Disallow links with href attribute - # Other disallowed HTML elements... - ], - }, - 'extraPlugins': ','.join(['sourcearea']), - 'removePlugins': 'Link', # Disables automatic link handling - # other configurations... - 'link': { - 'addTargetToExternalLinks': False, - 'defaultProtocol': 'https://', # Prevents redirection by controlling protocol behavior - }, - "toolbar": [ - "heading", - "|", - "bold", - "italic", - "link", - "bulletedList", - "numberedList", - "blockQuote", - ], - }, - "extends": { - "blockToolbar": [ - "paragraph", - "heading1", - "heading2", - "heading3", - "|", - "bulletedList", - "numberedList", - "|", - "blockQuote", - ], - "toolbar": { - "items": [ - "heading", - "bold", - "italic", - "link", - "underline", - "strikethrough", - "horizontalLine", - "removeFormat", - "outdent", - "indent", - "code", - "subscript", - "superscript", - "highlight", - "|", - "bulletedList", - "numberedList", - "todoList", - "|", - "blockQuote", - "insertImage", - "|", - "fontSize", - "fontFamily", - "fontColor", - "fontBackgroundColor", - "insertTable", - "sourceEditing", - ], - "shouldNotGroupWhenFull": True, - }, - "image": { - "toolbar": [ - "imageTextAlternative", - "|", - "imageStyle:alignLeft", - "imageStyle:alignRight", - "imageStyle:alignCenter", - "imageStyle:side", - "|", - ], - "styles": [ - "full", - "side", - "alignLeft", - "alignRight", - "alignCenter", - ], - }, - "table": { - "contentToolbar": [ - "tableColumn", - "tableRow", - "mergeTableCells", - "tableProperties", - "tableCellProperties", - "toggleTableCaption", - ], - "tableProperties": { - "borderColors": customColorPalette, - "backgroundColors": customColorPalette, - }, - "tableCellProperties": { - "borderColors": customColorPalette, - "backgroundColors": customColorPalette, - }, - }, - "heading": { - "options": [ - { - "model": "paragraph", - "title": "Paragraph", - "class": "ck-heading_paragraph", - }, - { - "model": "heading1", - "view": "h1", - "title": "Heading 1", - "class": "ck-heading_heading1", - }, - { - "model": "heading2", - "view": "h2", - "title": "Heading 2", - "class": "ck-heading_heading2", - }, - { - "model": "heading3", - "view": "h3", - "title": "Heading 3", - "class": "ck-heading_heading3", - }, - ], - },} -} diff --git a/server/core/config/tinymce.py b/server/core/config/tinymce.py new file mode 100644 index 0000000..5f8b336 --- /dev/null +++ b/server/core/config/tinymce.py @@ -0,0 +1,4 @@ +from django.conf import settings + +def tinymce_api_key(request): + return {'TINYMCE_API_KEY': settings.TINYMCE_API_KEY} \ No newline at end of file diff --git a/server/core/urls.py b/server/core/urls.py index 43aff11..c9eb82b 100644 --- a/server/core/urls.py +++ b/server/core/urls.py @@ -13,8 +13,8 @@ path('newsletter/', include('apps.newsletter.urls')), path('get-csrf-token/', csrf_token_view, name='csrf_token'), - # Ckeditor URL - path('ckeditor5/', include('django_ckeditor_5.urls')), + # TinyMCE URL + path('tinymce/', include('tinymce.urls')), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) if settings.DEBUG: diff --git a/server/media/0-simple_web_stack.drawio.png b/server/media/0-simple_web_stack.drawio.png deleted file mode 100644 index 6484d90..0000000 Binary files a/server/media/0-simple_web_stack.drawio.png and /dev/null differ diff --git a/server/media/2077-Collective_5HVRloC.png b/server/media/2077-Collective_5HVRloC.png deleted file mode 100644 index 6b317d0..0000000 Binary files a/server/media/2077-Collective_5HVRloC.png and /dev/null differ diff --git a/server/media/2077-Collective_5HVRloC_IDm6gJP.png b/server/media/2077-Collective_5HVRloC_IDm6gJP.png deleted file mode 100644 index 6b317d0..0000000 Binary files a/server/media/2077-Collective_5HVRloC_IDm6gJP.png and /dev/null differ diff --git a/server/media/2077-Collective_CqfkYap.png b/server/media/2077-Collective_CqfkYap.png deleted file mode 100644 index 6b317d0..0000000 Binary files a/server/media/2077-Collective_CqfkYap.png and /dev/null differ diff --git a/server/media/2077-Collective_Wsvulup.png b/server/media/2077-Collective_Wsvulup.png deleted file mode 100644 index 6b317d0..0000000 Binary files a/server/media/2077-Collective_Wsvulup.png and /dev/null differ diff --git a/server/media/2077-Collective_mdnnvJM.png b/server/media/2077-Collective_mdnnvJM.png deleted file mode 100644 index 6b317d0..0000000 Binary files a/server/media/2077-Collective_mdnnvJM.png and /dev/null differ diff --git a/server/media/2077-Collective_mjXBRyf.png b/server/media/2077-Collective_mjXBRyf.png deleted file mode 100644 index 6b317d0..0000000 Binary files a/server/media/2077-Collective_mjXBRyf.png and /dev/null differ diff --git a/server/media/2077-Collective_paIEmC7.png b/server/media/2077-Collective_paIEmC7.png deleted file mode 100644 index 6b317d0..0000000 Binary files a/server/media/2077-Collective_paIEmC7.png and /dev/null differ diff --git a/server/media/firewall.png b/server/media/firewall.png deleted file mode 100644 index 0d3f12a..0000000 Binary files a/server/media/firewall.png and /dev/null differ diff --git a/server/media/firewall_AkhBjz4.png b/server/media/firewall_AkhBjz4.png deleted file mode 100644 index 0d3f12a..0000000 Binary files a/server/media/firewall_AkhBjz4.png and /dev/null differ diff --git a/server/media/firewall_BcRWora.png b/server/media/firewall_BcRWora.png deleted file mode 100644 index 0d3f12a..0000000 Binary files a/server/media/firewall_BcRWora.png and /dev/null differ diff --git a/server/media/firewall_YgCNBrw.png b/server/media/firewall_YgCNBrw.png deleted file mode 100644 index 0d3f12a..0000000 Binary files a/server/media/firewall_YgCNBrw.png and /dev/null differ diff --git a/server/media/firewall_lxFc6MN.png b/server/media/firewall_lxFc6MN.png deleted file mode 100644 index 0d3f12a..0000000 Binary files a/server/media/firewall_lxFc6MN.png and /dev/null differ diff --git a/server/media/icon_bed.png b/server/media/icon_bed.png deleted file mode 100644 index 2a63284..0000000 Binary files a/server/media/icon_bed.png and /dev/null differ diff --git a/server/media/images/0-simple_web_stack.jpg b/server/media/images/0-simple_web_stack.jpg deleted file mode 100644 index eccb12f..0000000 Binary files a/server/media/images/0-simple_web_stack.jpg and /dev/null differ diff --git a/server/media/images/2077-Collective_CmxVQmg.png b/server/media/images/2077-Collective_CmxVQmg.png deleted file mode 100644 index 6b317d0..0000000 Binary files a/server/media/images/2077-Collective_CmxVQmg.png and /dev/null differ diff --git a/server/media/2077-Collective.png b/server/media/images/2077-Collective_EYFPFdS.png similarity index 100% rename from server/media/2077-Collective.png rename to server/media/images/2077-Collective_EYFPFdS.png diff --git a/server/media/images/2077-Collective_NKzY9zM.png b/server/media/images/2077-Collective_NKzY9zM.png deleted file mode 100644 index 6b317d0..0000000 Binary files a/server/media/images/2077-Collective_NKzY9zM.png and /dev/null differ diff --git a/server/media/images/2077-Collective_Vt5LMm4.png b/server/media/images/2077-Collective_Vt5LMm4.png deleted file mode 100644 index 6b317d0..0000000 Binary files a/server/media/images/2077-Collective_Vt5LMm4.png and /dev/null differ diff --git a/server/media/images/2077-Collective_sdam6F2.png b/server/media/images/2077-Collective_sdam6F2.png deleted file mode 100644 index 6b317d0..0000000 Binary files a/server/media/images/2077-Collective_sdam6F2.png and /dev/null differ diff --git a/server/media/images/2077-Collective_yYKWZf2.png b/server/media/images/2077-Collective_yYKWZf2.png deleted file mode 100644 index 6b317d0..0000000 Binary files a/server/media/images/2077-Collective_yYKWZf2.png and /dev/null differ diff --git a/server/media/images/EIPs-for-Nerds7-EIP-7623-Increase-calldata-cost.BQmoJeoD_tf8U6.webp b/server/media/images/EIPs-for-Nerds7-EIP-7623-Increase-calldata-cost.BQmoJeoD_tf8U6.webp deleted file mode 100644 index db204a7..0000000 Binary files a/server/media/images/EIPs-for-Nerds7-EIP-7623-Increase-calldata-cost.BQmoJeoD_tf8U6.webp and /dev/null differ diff --git a/server/media/images/Screenshot_from_2024-08-01_01-19-27.png b/server/media/images/Screenshot_from_2024-08-01_01-19-27.png deleted file mode 100644 index 7144e97..0000000 Binary files a/server/media/images/Screenshot_from_2024-08-01_01-19-27.png and /dev/null differ diff --git a/server/media/images/Screenshot_from_2024-08-03_08-17-47.png b/server/media/images/Screenshot_from_2024-08-03_08-17-47.png deleted file mode 100644 index 1674ab1..0000000 Binary files a/server/media/images/Screenshot_from_2024-08-03_08-17-47.png and /dev/null differ diff --git a/server/media/images/UnderstandingBlockchainGovernance.BB5AHiNA_1c0KSU.webp b/server/media/images/UnderstandingBlockchainGovernance.BB5AHiNA_1c0KSU.webp deleted file mode 100644 index d37d20a..0000000 Binary files a/server/media/images/UnderstandingBlockchainGovernance.BB5AHiNA_1c0KSU.webp and /dev/null differ diff --git a/server/media/images/mynft.png b/server/media/images/mynft.png deleted file mode 100644 index d270697..0000000 Binary files a/server/media/images/mynft.png and /dev/null differ diff --git a/server/media/images/mynft_D0F3m8M.png b/server/media/images/mynft_D0F3m8M.png deleted file mode 100644 index d270697..0000000 Binary files a/server/media/images/mynft_D0F3m8M.png and /dev/null differ diff --git a/server/media/images/mynft_bvdjr3c.png b/server/media/images/mynft_bvdjr3c.png deleted file mode 100644 index d270697..0000000 Binary files a/server/media/images/mynft_bvdjr3c.png and /dev/null differ diff --git a/server/media/images/mynft_fXK8jpO.png b/server/media/images/mynft_fXK8jpO.png deleted file mode 100644 index d270697..0000000 Binary files a/server/media/images/mynft_fXK8jpO.png and /dev/null differ diff --git a/server/media/makeTea.png b/server/media/makeTea.png deleted file mode 100644 index f45fbd1..0000000 Binary files a/server/media/makeTea.png and /dev/null differ diff --git a/server/media/mynft.png b/server/media/mynft.png deleted file mode 100644 index d270697..0000000 Binary files a/server/media/mynft.png and /dev/null differ diff --git a/server/media/mynft_HmtNgzV.png b/server/media/mynft_HmtNgzV.png deleted file mode 100644 index d270697..0000000 Binary files a/server/media/mynft_HmtNgzV.png and /dev/null differ diff --git a/server/media/mynft_Wn4f1lp.png b/server/media/mynft_Wn4f1lp.png deleted file mode 100644 index d270697..0000000 Binary files a/server/media/mynft_Wn4f1lp.png and /dev/null differ diff --git a/server/media/mynft_zDjW1CS.png b/server/media/mynft_zDjW1CS.png deleted file mode 100644 index d270697..0000000 Binary files a/server/media/mynft_zDjW1CS.png and /dev/null differ diff --git a/server/requirements.txt b/server/requirements.txt index 0c957c7..8a2d8a8 100644 --- a/server/requirements.txt +++ b/server/requirements.txt @@ -23,6 +23,7 @@ django-jazzmin==3.0.0 django-js-asset==2.2.0 django-shortcuts==1.6 django-timezone-field==7.0 +django-tinymce==4.1.0 djangorestframework==3.15.2 drf-spectacular==0.27.2 h11==0.14.0 diff --git a/server/static/ckeditor/js/custom_ckeditor_admin.js b/server/static/ckeditor/js/custom_ckeditor_admin.js deleted file mode 100644 index 8fc5294..0000000 --- a/server/static/ckeditor/js/custom_ckeditor_admin.js +++ /dev/null @@ -1,33 +0,0 @@ -document.addEventListener("DOMContentLoaded", function () { - const editorElement = document.querySelector("#id_contents"); // Adjust to match your actual element ID - if (editorElement) { - ClassicEditor.create(editorElement, { - link: { - decorators: { - addTargetToExternalLinks: false, - }, - }, - removePlugins: ["Link"], - toolbar: { - items: [ - "heading", - "|", - "bold", - "italic", - "link", - "bulletedList", - "numberedList", - "blockQuote", - ], - }, - }) - .then((editor) => { - console.log("CKEditor5 initialized successfully"); - }) - .catch((error) => { - console.error("Error initializing CKEditor:", error); - }); - } else { - console.error("CKEditor5 element not found"); - } -}); diff --git a/server/static/images/img.webp b/server/static/images/img.webp deleted file mode 100644 index 01a3efd..0000000 Binary files a/server/static/images/img.webp and /dev/null differ diff --git a/server/templates/admin/base.html b/server/templates/admin/base.html new file mode 100644 index 0000000..b28f080 --- /dev/null +++ b/server/templates/admin/base.html @@ -0,0 +1,65 @@ +{% extends "admin/base.html" %} +{% load static %} + +{% block footer %} + {{ block.super }} + + +{% endblock %} \ No newline at end of file