diff --git a/backend/settings.py b/backend/settings.py index 8ff6fb99..05ea5cdd 100644 --- a/backend/settings.py +++ b/backend/settings.py @@ -79,7 +79,7 @@ "djangocms_frontend.contrib.image", "djangocms_frontend.contrib.tabs", "djangocms_frontend.contrib.utilities", - "publications", + "zotero_publications_app", ] MIDDLEWARE = [ diff --git a/backend/urls.py b/backend/urls.py index 9233cf2b..f3c66eca 100644 --- a/backend/urls.py +++ b/backend/urls.py @@ -6,7 +6,7 @@ urlpatterns = [ path("admin/", admin.site.urls), - path("publications/", include("publications.urls")), + path("zotero_publications_app/", include("zotero_publications_app.urls")), ] # if settings.DEBUG: diff --git a/publications/apps.py b/publications/apps.py deleted file mode 100644 index 0081d991..00000000 --- a/publications/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class PublicationsConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'publications' diff --git a/publications/migrations/0002_auto_20240318_1924.py b/publications/migrations/0002_auto_20240318_1924.py deleted file mode 100644 index 65ac02a2..00000000 --- a/publications/migrations/0002_auto_20240318_1924.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 3.2 on 2024-03-18 19:24 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('cms', '0022_auto_20180620_1551'), - ('publications', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='ZoteroPublications', - fields=[ - ('cmsplugin_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='publications_zoteropublications', serialize=False, to='cms.cmsplugin')), - ('api_key', models.CharField(default='', max_length=200)), - ('library_type', models.CharField(default='', max_length=200)), - ('library_id', models.CharField(default='', max_length=200)), - ('collection_id', models.CharField(blank=True, default='', max_length=200)), - ('style', models.CharField(default='apa', max_length=200)), - ], - options={ - 'abstract': False, - }, - bases=('cms.cmsplugin',), - ), - migrations.DeleteModel( - name='ZoteroBibliographyResource', - ), - ] diff --git a/publications/templates/publications/base.html b/publications/templates/publications/base.html deleted file mode 100644 index 39085cbc..00000000 --- a/publications/templates/publications/base.html +++ /dev/null @@ -1,72 +0,0 @@ - - -{% load cms_tags sekizai_tags %} - - -{% addtoblock "js" %} - - -{% endaddtoblock %} - -{% addtoblock "css" %} - -{% endaddtoblock %} - -{% block content %} - -

No publications found

- - -{% endblock %} - - - diff --git a/publications/templates/publications/publications.html b/publications/templates/publications/publications.html deleted file mode 100644 index 543517c5..00000000 --- a/publications/templates/publications/publications.html +++ /dev/null @@ -1,165 +0,0 @@ -{% load sekizai_tags %} -{% load cms_tags %} - - {% csrf_token %} - - - -{% addtoblock "js" %} - - -{% endaddtoblock %} - -{% addtoblock "css" %} - -{% endaddtoblock %} - -{% block content %} - -
- -{% endblock %} diff --git a/publications/tests.py b/publications/tests.py deleted file mode 100644 index 7ce503c2..00000000 --- a/publications/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/publications/urls.py b/publications/urls.py deleted file mode 100644 index d2b24678..00000000 --- a/publications/urls.py +++ /dev/null @@ -1,8 +0,0 @@ -from django.urls import re_path - - -from .views import base_view, publications_view - -urlpatterns = [ - re_path(r"^publications-api/$", publications_view, name="publications"), -] diff --git a/publications/__init__.py b/zotero_publications_app/__init__.py similarity index 100% rename from publications/__init__.py rename to zotero_publications_app/__init__.py diff --git a/publications/admin.py b/zotero_publications_app/admin.py similarity index 100% rename from publications/admin.py rename to zotero_publications_app/admin.py diff --git a/zotero_publications_app/apps.py b/zotero_publications_app/apps.py new file mode 100644 index 00000000..3c1d2bef --- /dev/null +++ b/zotero_publications_app/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class ZoteroPublicationsAppConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "zotero_publications_app" diff --git a/publications/cms_apps.py b/zotero_publications_app/cms_apps.py similarity index 63% rename from publications/cms_apps.py rename to zotero_publications_app/cms_apps.py index 279e390e..01157fa4 100644 --- a/publications/cms_apps.py +++ b/zotero_publications_app/cms_apps.py @@ -3,9 +3,9 @@ @apphook_pool.register # register the application -class PublicationsApphook(CMSApp): - app_name = "publications" +class ZoteroPublicationsAppApphook(CMSApp): + app_name = "zotero_publications_app" name = "Zotero Publications Application" def get_urls(self, page=None, language=None, **kwargs): - return ["publications.urls"] + return ["zotero_publications_app.urls"] diff --git a/publications/cms_plugins.py b/zotero_publications_app/cms_plugins.py similarity index 93% rename from publications/cms_plugins.py rename to zotero_publications_app/cms_plugins.py index 3ab13428..4d2a62ae 100644 --- a/publications/cms_plugins.py +++ b/zotero_publications_app/cms_plugins.py @@ -13,7 +13,7 @@ class ZoteroPlugin(CMSPluginBase): model = ZoteroPublications name = _("Zotero Publications Plugin") - render_template = "publications/publications.html" + render_template = "zotero-publications.html" cache = False # This is key in order to call the API every time the page renders diff --git a/publications/migrations/0001_initial.py b/zotero_publications_app/migrations/0001_initial.py similarity index 81% rename from publications/migrations/0001_initial.py rename to zotero_publications_app/migrations/0001_initial.py index 5729a29d..e6fa19cd 100644 --- a/publications/migrations/0001_initial.py +++ b/zotero_publications_app/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2 on 2024-03-18 18:10 +# Generated by Django 3.2 on 2024-03-19 16:07 from django.db import migrations, models import django.db.models.deletion @@ -14,9 +14,9 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='ZoteroBibliographyResource', + name='ZoteroPublications', fields=[ - ('cmsplugin_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='publications_zoterobibliographyresource', serialize=False, to='cms.cmsplugin')), + ('cmsplugin_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='zotero_publications_app_zoteropublications', serialize=False, to='cms.cmsplugin')), ('api_key', models.CharField(default='', max_length=200)), ('library_type', models.CharField(default='', max_length=200)), ('library_id', models.CharField(default='', max_length=200)), diff --git a/publications/migrations/__init__.py b/zotero_publications_app/migrations/__init__.py similarity index 100% rename from publications/migrations/__init__.py rename to zotero_publications_app/migrations/__init__.py diff --git a/publications/models.py b/zotero_publications_app/models.py similarity index 64% rename from publications/models.py rename to zotero_publications_app/models.py index 36099edb..690ae960 100644 --- a/publications/models.py +++ b/zotero_publications_app/models.py @@ -1,16 +1,5 @@ from cms.models.pluginmodel import CMSPlugin -from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models -from pyzotero import zotero -from hs_restclient import HydroShare, HydroShareAuthBasic -import requests - -# from datetime import datetime -import time - -import datetime -import uuid -from django.db.models.signals import pre_save, post_save from django.dispatch import receiver import logging diff --git a/zotero_publications_app/static/css/publications.css b/zotero_publications_app/static/css/publications.css new file mode 100644 index 00000000..7ad781fa --- /dev/null +++ b/zotero_publications_app/static/css/publications.css @@ -0,0 +1,61 @@ + +/* https://cloudcannon.com/blog/how-the-facebook-content-placeholder-works/ */ +/* https://codepen.io/nurulishlah/pen/beEGVE */ +@import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap'); +@import url('https://fonts.googleapis.com/css?family=Raleway:300,400,700&display=swap'); +@import url('https://fonts.googleapis.com/css?family=Roboto:300,400,700&display=swap'); + + +.csl-entry { + word-wrap: break-word; + margin: 0 !important; +} +.csl-entry, +.csl-entry * { + box-sizing: content-box; +} +.csl-bib-body{ + line-height: 2; + padding-left: 1em; + text-indent:-1.5em !important; + padding-bottom:0.5em; +} +.wrapper-publication-set{ + color: #1c1e21; + font-size: 16px; +} +.year-style{ + padding-top: 1rem; +} + +.hidden { + display: none; +} + + +@keyframes placeHolderShimmer{ + 0%{ + background-position: -468px 0 + } + 100%{ + background-position: 468px 0 + } +} + +.animated-background { + animation-duration: 1.25s; + animation-fill-mode: forwards; + animation-iteration-count: infinite; + animation-name: placeHolderShimmer; + animation-timing-function: linear; +} +.year-loading-background{ + background: #cbcbcb; + background: linear-gradient(to right, #cbcbcb 8%, #bbbbbb 18%, #cbcbcb 33%); +} +.publication-background{ + background: linear-gradient(to right, #eeeeee 8%, #dddddd 18%, #eeeeee 33%); +} +#placeholder-publications{ + margin-top: 20px ; +} \ No newline at end of file diff --git a/zotero_publications_app/static/js/publications.js b/zotero_publications_app/static/js/publications.js new file mode 100644 index 00000000..090b2da8 --- /dev/null +++ b/zotero_publications_app/static/js/publications.js @@ -0,0 +1,61 @@ + + +const getCSRFToken = () => { + // Attempt to retrieve the CSRF token from the meta tag + const token = document.querySelector('meta[name="csrf-token"]').getAttribute('content'); + return token; +} + +const fetchPublications = () => { + // Assuming your Django server is running on localhost:8000 + // Update the URL if your setup is different or if you are using a production server + fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': getCSRFToken(), // Include the CSRF token in the request headers + }, + body: JSON.stringify(requestData), + }) + .then(response => { + document.getElementById('placeholder-publications').classList.add('hidden'); // Hide spinner + document.getElementById('publications-html').classList.remove('hidden'); // Show content + + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.json(); // Assuming the response is JSON + }) + .then(data => { + let publicationsHTML = `` + for (const [key, value] of Object.entries(data)) { + //add the year title + publicationsHTML += `

${key}

` + //add the publications + value.forEach((publication) => { + publicationsHTML += publication + }) + } + document.getElementById('publications-html').innerHTML = publicationsHTML; + + // For example, you could iterate over the data and append it to an element in your HTML + }) + .catch(error => { + console.error('There was a problem with the fetch operation:', error); + }); + } +const create_placeholders = () => { + let placeholdersHtmlElement = document.getElementById('placeholder-publications'); + let htmlPlaceholders = ''; + for(var i = 0; i < 10; i++){ + htmlPlaceholders+=`

` + for(var j = 0; j < 5; j++){ + htmlPlaceholders+= `
` + } + htmlPlaceholders+=`
` + } + placeholdersHtmlElement.innerHTML = htmlPlaceholders; +} + +create_placeholders(); +fetchPublications(); diff --git a/zotero_publications_app/templates/zotero-publications-base.html b/zotero_publications_app/templates/zotero-publications-base.html new file mode 100644 index 00000000..bae07810 --- /dev/null +++ b/zotero_publications_app/templates/zotero-publications-base.html @@ -0,0 +1,16 @@ +{% extends CMS_TEMPLATE %} + +{% load sekizai_tags static cms_tags %} + +{% addtoblock "js" %} + +{% endaddtoblock %} + +{% addtoblock "css" %} + + +{% endaddtoblock %} + +{% block content %} + +{% endblock %} diff --git a/zotero_publications_app/templates/zotero-publications.html b/zotero_publications_app/templates/zotero-publications.html new file mode 100644 index 00000000..b423d4f1 --- /dev/null +++ b/zotero_publications_app/templates/zotero-publications.html @@ -0,0 +1,31 @@ + +{% load sekizai_tags static cms_tags %} + + {% csrf_token %} + + + +{% addtoblock "js" %} + + +{% endaddtoblock %} + +{% addtoblock "css" %} + + +{% endaddtoblock %} + +{% block content %} +
+ +{% endblock %} diff --git a/zotero_publications_app/urls.py b/zotero_publications_app/urls.py new file mode 100644 index 00000000..775766de --- /dev/null +++ b/zotero_publications_app/urls.py @@ -0,0 +1,11 @@ +from django.urls import re_path + + +from .views import base_view, publications_view + +urlpatterns = [ + re_path(r"^$", base_view, name="base"), + re_path( + r"^zotero-publications-api/$", publications_view, name="zotero-publications-api" + ), +] diff --git a/publications/views.py b/zotero_publications_app/views.py similarity index 91% rename from publications/views.py rename to zotero_publications_app/views.py index e2d92500..7cbf9ff1 100644 --- a/publications/views.py +++ b/zotero_publications_app/views.py @@ -1,7 +1,6 @@ from django.shortcuts import render from django.http import JsonResponse from pyzotero import zotero -from .models import ZoteroPublications import logging import json @@ -9,10 +8,9 @@ def base_view(request): - # This dictionary can pass variables to the template. - logging.warning("base_view") + context = {} - return render(request, "publications/base.html", context) + return render(request, "zotero-publications-base.html", context) def publications_view(request):