From 2d7435314672c2f4653f600edadae1d4c0b02406 Mon Sep 17 00:00:00 2001 From: Stefano Alberto Russo <stefano.russo@gmail.com> Date: Mon, 15 Nov 2021 18:12:38 +0100 Subject: [PATCH] Moved from Text to Page models, in order to allow building a mini-website inside the platform to provide help and informations. --- .../webapp/code/rosetta/core_app/admin.py | 4 +- .../management/commands/core_app_populate.py | 83 ++++++++++++++----- .../migrations/0019_auto_20211115_1547.py | 23 +++++ .../webapp/code/rosetta/core_app/models.py | 12 +-- .../rosetta/core_app/templates/account.html | 2 +- .../core_app/templates/add_profile_conf.html | 2 +- .../core_app/templates/add_software.html | 2 +- .../rosetta/core_app/templates/computing.html | 2 +- .../rosetta/core_app/templates/error.html | 4 +- .../rosetta/core_app/templates/header.html | 6 +- .../code/rosetta/core_app/templates/main.html | 10 +-- .../rosetta/core_app/templates/new_task.html | 2 +- .../code/rosetta/core_app/templates/page.html | 28 +++++++ .../rosetta/core_app/templates/register.html | 2 +- .../rosetta/core_app/templates/software.html | 2 +- .../rosetta/core_app/templates/storage.html | 2 +- .../rosetta/core_app/templates/success.html | 4 +- .../rosetta/core_app/templates/task_log.html | 2 +- .../rosetta/core_app/templates/tasks.html | 2 +- .../webapp/code/rosetta/core_app/views.py | 35 ++++++-- services/webapp/code/rosetta/urls.py | 2 + 21 files changed, 173 insertions(+), 58 deletions(-) create mode 100644 services/webapp/code/rosetta/core_app/migrations/0019_auto_20211115_1547.py create mode 100644 services/webapp/code/rosetta/core_app/templates/page.html diff --git a/services/webapp/code/rosetta/core_app/admin.py b/services/webapp/code/rosetta/core_app/admin.py index c22b65d..b69c3b2 100644 --- a/services/webapp/code/rosetta/core_app/admin.py +++ b/services/webapp/code/rosetta/core_app/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -from .models import Profile, LoginToken, Task, Container, Computing, Storage, KeyPair, Text +from .models import Profile, LoginToken, Task, Container, Computing, Storage, KeyPair, Page admin.site.register(Profile) admin.site.register(LoginToken) @@ -9,4 +9,4 @@ admin.site.register(Container) admin.site.register(Computing) admin.site.register(Storage) admin.site.register(KeyPair) -admin.site.register(Text) +admin.site.register(Page) diff --git a/services/webapp/code/rosetta/core_app/management/commands/core_app_populate.py b/services/webapp/code/rosetta/core_app/management/commands/core_app_populate.py index 9a11444..0b3d3ec 100644 --- a/services/webapp/code/rosetta/core_app/management/commands/core_app_populate.py +++ b/services/webapp/code/rosetta/core_app/management/commands/core_app_populate.py @@ -1,6 +1,6 @@ from django.core.management.base import BaseCommand from django.contrib.auth.models import User -from ...models import Profile, Container, Computing, Storage, KeyPair, Text +from ...models import Profile, Container, Computing, Storage, KeyPair, Page class Command(BaseCommand): help = 'Adds the admin superuser with \'a\' password.' @@ -62,29 +62,70 @@ class Command(BaseCommand): #===================== - # Default home text + # Default home page #===================== - default_home_text_content = ''' -<div class="span8 offset2" style="margin: 30px auto; max-width:800px"> - Welcome to Rosetta! - <br/><br/> - This is the default home text loaded after populating the platform with the default/demo data. - To change it, head to the <a href="/admin">admin</a> page and edit the <code>Text</code> model. - <br/><br/> - The default installation provides a test user register with email <code>testuser@rosetta.platform</code> - and password <code>testpass</code>, which you can use to login on the menu on the rightand give Rosetta - a try immediately. If you run with the default docker-compose file (i.e. you just run - <code>rosetta/setup</code>), then you will also have a few demo computing resources you can play with - out-of-the-box, including a small Slurm cluster. Otherwise, you will need to setup your own computing - resources either platform-wide or as user. -</div> + default_home_page_content = ''' +<header id="top" class="header"> + <div style="display:table-row"> + <div class="text-vertical-center"> + <h1> Rosetta <img src="/static/img/emoji_u1f6f0.png" style="height:84px; width:64px; padding-bottom:20px"></h1> + <h2 style="margin-top:10px; margin-left:25px; margin-right:25px; font-weight:100; line-height: 30px;"><i>A container-centric Science Platform<br></i></h2> + </div> + </div> + <div class="container"> + <div class="dashboard"> + <div class="span8 offset2" style="margin: 30px auto; max-width:800px"> + Welcome to Rosetta! + <br/><br/> + This is the default main page content loaded after populating the platform with the default/demo data. + To change it, head to the <a href="/admin">admin</a> section and edit the <code>Page</code> model with id "main". + <br/><br/> + A test user with admin rights registered with email <code>testuser@rosetta.platform</code> and password + <code>testpass</code> has been created as well, which you can use to login on the menu on the right and give Rosetta + immediately a try. If you run with the default docker-compose file (i.e. you just run <code>rosetta/setup</code>), + then you will also have a few demo computing and storage resources (beside the internal engine) already available + and that you can play with, including a small Slurm cluster. Otherwise, you will need to setup your own ones + from the <a href="/admin">admin</a> section. + <br /> + <br /> + You can also create custom pages and access them under <code>/pages/page_id</code> should you need to provide + your users informations about the platform and its storage and computing resources. For example, see this + demo extra <a href="/pages/help">help page</a>. + </div> + </div> + </div> +</header> ''' - home_text = Text.objects.filter(id='home') - if home_text: - print('Not creating default home text as already present') + home_page = Page.objects.filter(id='main') + if home_page: + print('Not creating default main page content as already present') else: - print('Creating default home text...') - Text.objects.create(id='home', content=default_home_text_content) + print('Creating default main page content...') + Page.objects.create(id='main', content=default_home_page_content) + + extra_help_page_content = ''' +<h1>Help!</h1> +<hr> +<p> +This is a demo extra page (a help page, in this case). Here you could for example provide the instructions on how to set up SSH-based +computing resources using user keys, or who to contact to join a specific group to access its software and computing resources. +</p> + +<p> +In general, the part of the URL following the <code>/pages/</code> path is parsed as the page id, +so that if a page with that id exists in the database, its content will show up here. +You can use this system for creating a mini-website inside the platform +to provide help, news and informations on your deployment. Or you can just ignore the whole thing and leave a plain logo in the main page. +</p> +''' + + extra_help_page = Page.objects.filter(id='help') + if home_page: + print('Not creating extra help page content as already present') + else: + print('Creating extra help page content...') + Page.objects.create(id='help', content=extra_help_page_content) + #===================== diff --git a/services/webapp/code/rosetta/core_app/migrations/0019_auto_20211115_1547.py b/services/webapp/code/rosetta/core_app/migrations/0019_auto_20211115_1547.py new file mode 100644 index 0000000..49feeee --- /dev/null +++ b/services/webapp/code/rosetta/core_app/migrations/0019_auto_20211115_1547.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.1 on 2021-11-15 15:47 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core_app', '0018_delete_computinguserconf'), + ] + + operations = [ + migrations.CreateModel( + name='Page', + fields=[ + ('id', models.CharField(max_length=16, primary_key=True, serialize=False, verbose_name='Page id')), + ('content', models.TextField(blank=True, null=True, verbose_name='Page content')), + ], + ), + migrations.DeleteModel( + name='Text', + ), + ] diff --git a/services/webapp/code/rosetta/core_app/models.py b/services/webapp/code/rosetta/core_app/models.py index 0640726..01685d4 100644 --- a/services/webapp/code/rosetta/core_app/models.py +++ b/services/webapp/code/rosetta/core_app/models.py @@ -391,17 +391,17 @@ class KeyPair(models.Model): #========================= -# Texts +# Page #========================= -class Text(models.Model): - '''A model to store some text contents for the platform, like the home page text''' +class Page(models.Model): + '''A model to store pages for the platform, as custom a custom home page''' - id = models.CharField('Text id', max_length=16, primary_key=True) - content = models.TextField('Text content', blank=True, null=True) + id = models.CharField('Page id', max_length=16, primary_key=True) + content = models.TextField('Page content', blank=True, null=True) def __str__(self): - return str('Text with id "{}"'.format(self.id)) + return str('Page "{}"'.format(self.id)) diff --git a/services/webapp/code/rosetta/core_app/templates/account.html b/services/webapp/code/rosetta/core_app/templates/account.html index 42c52ea..2ca2d5a 100644 --- a/services/webapp/code/rosetta/core_app/templates/account.html +++ b/services/webapp/code/rosetta/core_app/templates/account.html @@ -1,6 +1,6 @@ {% load static %} {% include "header.html" %} -{% include "navigation.html" with main_path='/main/' %} +{% include "navigation.html" %} <br/> <br/> diff --git a/services/webapp/code/rosetta/core_app/templates/add_profile_conf.html b/services/webapp/code/rosetta/core_app/templates/add_profile_conf.html index 1b1369a..8f1135a 100644 --- a/services/webapp/code/rosetta/core_app/templates/add_profile_conf.html +++ b/services/webapp/code/rosetta/core_app/templates/add_profile_conf.html @@ -1,6 +1,6 @@ {% load static %} {% include "header.html" %} -{% include "navigation.html" with main_path='/main/' %} +{% include "navigation.html" %} <br/> <br/> diff --git a/services/webapp/code/rosetta/core_app/templates/add_software.html b/services/webapp/code/rosetta/core_app/templates/add_software.html index 300d486..668480d 100644 --- a/services/webapp/code/rosetta/core_app/templates/add_software.html +++ b/services/webapp/code/rosetta/core_app/templates/add_software.html @@ -1,6 +1,6 @@ {% load static %} {% include "header.html" %} -{% include "navigation.html" with main_path='/main/' %} +{% include "navigation.html" %} <br/> <br/> diff --git a/services/webapp/code/rosetta/core_app/templates/computing.html b/services/webapp/code/rosetta/core_app/templates/computing.html index 0edbc23..b9991ea 100644 --- a/services/webapp/code/rosetta/core_app/templates/computing.html +++ b/services/webapp/code/rosetta/core_app/templates/computing.html @@ -1,6 +1,6 @@ {% load static %} {% include "header.html" %} -{% include "navigation.html" with main_path='/main/' %} +{% include "navigation.html" %} <br/> <br/> diff --git a/services/webapp/code/rosetta/core_app/templates/error.html b/services/webapp/code/rosetta/core_app/templates/error.html index 106404a..b31a70c 100644 --- a/services/webapp/code/rosetta/core_app/templates/error.html +++ b/services/webapp/code/rosetta/core_app/templates/error.html @@ -1,6 +1,6 @@ {% load static %} {% include "header.html" %} -{% include "navigation.html" with main_path='/main/' %} +{% include "navigation.html" %} <br/> <br/> @@ -13,11 +13,9 @@ <br/> <br/><br/> <div class='centerbox-error-outer'> - <a href="/main"> <span class='centerbox-error-inner'> {{data.error}} </span> - </a> </div> <br/> diff --git a/services/webapp/code/rosetta/core_app/templates/header.html b/services/webapp/code/rosetta/core_app/templates/header.html index 46dc332..8e26792 100644 --- a/services/webapp/code/rosetta/core_app/templates/header.html +++ b/services/webapp/code/rosetta/core_app/templates/header.html @@ -12,8 +12,12 @@ {% if refresh %} <meta http-equiv="refresh" content="{{refresh}}" > {% endif %} - + + {% if title %} + <title>Rosetta - {{ title }}</title> + {% else %} <title>Rosetta</title> + {% endif %} <!-- Bootstrap Core CSS --> <link href="/static/css/bootstrap-3.3.5.min.css" rel="stylesheet"> diff --git a/services/webapp/code/rosetta/core_app/templates/main.html b/services/webapp/code/rosetta/core_app/templates/main.html index e91e4bf..eb1a989 100644 --- a/services/webapp/code/rosetta/core_app/templates/main.html +++ b/services/webapp/code/rosetta/core_app/templates/main.html @@ -2,7 +2,9 @@ {% include "header.html" %} {% include "navigation.html"%} - <!-- Header --> + {% if data.page.content %} + {{ data.page.content | safe }} + {% else %} <header id="top" class="header"> <div style="display:table-row"> <div class="text-vertical-center"> @@ -13,19 +15,17 @@ <div class="container"> <div class="dashboard"> - {% if data.home_text %} - {{ data.home_text | safe }} - {% else %} <div class="span8 offset2" style="margin: 30px auto; max-width:800px"> <br/> Welcome to Rosetta! <br/><br/> This is an empty installation. To load some demo data, run <code>rosetta/populate</code>. </div> - {% endif %} + </div> </div> </header> + {% endif %} {% include "footer.html" %} diff --git a/services/webapp/code/rosetta/core_app/templates/new_task.html b/services/webapp/code/rosetta/core_app/templates/new_task.html index fb6cd69..23db343 100644 --- a/services/webapp/code/rosetta/core_app/templates/new_task.html +++ b/services/webapp/code/rosetta/core_app/templates/new_task.html @@ -1,6 +1,6 @@ {% load static %} {% include "header.html" %} -{% include "navigation.html" with main_path='/main/' %} +{% include "navigation.html" %} <br/> <br/> diff --git a/services/webapp/code/rosetta/core_app/templates/page.html b/services/webapp/code/rosetta/core_app/templates/page.html new file mode 100644 index 0000000..9055a94 --- /dev/null +++ b/services/webapp/code/rosetta/core_app/templates/page.html @@ -0,0 +1,28 @@ +{% load static %} +{% include "header.html" with title=data.page.title %} +{% include "navigation.html"%} + +<br/> +<br/> + +<div class="container"> + <div class="dashboard"> + <div class="span8 offset2"> + <!-- <h1>Example title</h1> + <hr> --> + {{ data.page.content | safe }} + + </div> + </div> +</div> + + + + + + + +{% include "footer.html" %} + + + diff --git a/services/webapp/code/rosetta/core_app/templates/register.html b/services/webapp/code/rosetta/core_app/templates/register.html index 8a7ca29..f1439a9 100644 --- a/services/webapp/code/rosetta/core_app/templates/register.html +++ b/services/webapp/code/rosetta/core_app/templates/register.html @@ -1,6 +1,6 @@ {% load static %} {% include "header.html" %} -{% include "navigation.html" with main_path='/main/' %} +{% include "navigation.html" %} <br/> <br/> diff --git a/services/webapp/code/rosetta/core_app/templates/software.html b/services/webapp/code/rosetta/core_app/templates/software.html index 86fef6b..8be03d0 100644 --- a/services/webapp/code/rosetta/core_app/templates/software.html +++ b/services/webapp/code/rosetta/core_app/templates/software.html @@ -1,6 +1,6 @@ {% load static %} {% include "header.html" %} -{% include "navigation.html" with main_path='/main/' %} +{% include "navigation.html" %} <br/> <br/> diff --git a/services/webapp/code/rosetta/core_app/templates/storage.html b/services/webapp/code/rosetta/core_app/templates/storage.html index 9b29c54..43b0c78 100644 --- a/services/webapp/code/rosetta/core_app/templates/storage.html +++ b/services/webapp/code/rosetta/core_app/templates/storage.html @@ -1,6 +1,6 @@ {% load static %} {% include "header.html" %} -{% include "navigation.html" with main_path='/main/' %} +{% include "navigation.html" %} <br/> <br/> diff --git a/services/webapp/code/rosetta/core_app/templates/success.html b/services/webapp/code/rosetta/core_app/templates/success.html index bb1991c..7cc06a0 100644 --- a/services/webapp/code/rosetta/core_app/templates/success.html +++ b/services/webapp/code/rosetta/core_app/templates/success.html @@ -1,6 +1,6 @@ {% load static %} {% include "header.html" %} -{% include "navigation.html" with main_path='/main/' %} +{% include "navigation.html" %} <br/> <br/> @@ -12,11 +12,9 @@ <hr> <br/> <div class='centerbox-success-outer'> - <a href="/main"> <span class='centerbox-success-inner'> {{data.success}} </span> - </a> </div> diff --git a/services/webapp/code/rosetta/core_app/templates/task_log.html b/services/webapp/code/rosetta/core_app/templates/task_log.html index 2a842cb..994c254 100644 --- a/services/webapp/code/rosetta/core_app/templates/task_log.html +++ b/services/webapp/code/rosetta/core_app/templates/task_log.html @@ -1,6 +1,6 @@ {% load static %} {% include "header.html" with refresh=data.refresh %} -{% include "navigation.html" with main_path='/main/' %} +{% include "navigation.html" %} <br/> <br/> diff --git a/services/webapp/code/rosetta/core_app/templates/tasks.html b/services/webapp/code/rosetta/core_app/templates/tasks.html index fa9b554..67cec11 100644 --- a/services/webapp/code/rosetta/core_app/templates/tasks.html +++ b/services/webapp/code/rosetta/core_app/templates/tasks.html @@ -1,6 +1,6 @@ {% load static %} {% include "header.html" %} -{% include "navigation.html" with main_path='/main/' %} +{% include "navigation.html" %} <br/> <br/> diff --git a/services/webapp/code/rosetta/core_app/views.py b/services/webapp/code/rosetta/core_app/views.py index 352648d..1904a01 100644 --- a/services/webapp/code/rosetta/core_app/views.py +++ b/services/webapp/code/rosetta/core_app/views.py @@ -5,11 +5,11 @@ import subprocess from django.conf import settings from django.shortcuts import render from django.contrib.auth import authenticate, login, logout -from django.http import HttpResponse, HttpResponseRedirect +from django.http import HttpResponse, HttpResponseRedirect, HttpResponseNotFound from django.contrib.auth.models import User from django.shortcuts import redirect from django.db.models import Q -from .models import Profile, LoginToken, Task, TaskStatuses, Container, Computing, KeyPair, Text +from .models import Profile, LoginToken, Task, TaskStatuses, Container, Computing, KeyPair, Page from .utils import send_email, format_exception, timezonize, os_shell, booleanize, debug_param, get_task_tunnel_host, get_task_proxy_host, random_username, setup_tunnel_and_proxy, finalize_user_creation from .decorators import public_view, private_view from .exceptions import ErrorMessage @@ -23,6 +23,10 @@ logger = logging.getLogger(__name__) _task_cache = {} +#==================== +# Page views +#==================== + @public_view def login_view(request): @@ -186,19 +190,36 @@ def entrypoint(request): @public_view def main_view(request): - # Set data & render + # Init data data = {} - # Get homepage text if any + # Get custom home page if any try: - text = Text.objects.get(id='home') - data['home_text'] = text.content - except Text.DoesNotExist: + page = Page.objects.get(id='main') + data['page'] = page + except Page.DoesNotExist: pass return render(request, 'main.html', {'data': data}) +@public_view +def page_view(request, page_id): + + # Init data + data = {} + + # Get the page + try: + page = Page.objects.get(id=page_id) + data['page'] = page + except Page.DoesNotExist: + return HttpResponseNotFound('Page not found') + + return render(request, 'page.html', {'data': data}) + + + #==================== # Account view #==================== diff --git a/services/webapp/code/rosetta/urls.py b/services/webapp/code/rosetta/urls.py index 1015d6f..88b14fd 100644 --- a/services/webapp/code/rosetta/urls.py +++ b/services/webapp/code/rosetta/urls.py @@ -45,6 +45,8 @@ urlpatterns = [ path('login/', core_app_views.login_view), path('logout/', core_app_views.logout_view), url(r'^register/$', core_app_views.register_view), + url(r'^pages/(?P<page_id>\w{0,36})/$', core_app_views.page_view), + # Software url(r'^software/$', core_app_views.software), -- GitLab