diff --git a/services/webapp/code/rosetta/core_app/admin.py b/services/webapp/code/rosetta/core_app/admin.py index c22b65d72d4704efdd5b46076c44fbb56cc36493..b69c3b232dc099e5e241bd162bf974503d6dd1eb 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 9a114448956ff84e23a6ac882a2ebaa016a58dbe..0b3d3ec80dcbeaae259a95b2889aa54aa9b56169 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 0000000000000000000000000000000000000000..49feeee42065a0ab922f4068ba49b3a36623a524 --- /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 0640726b52279ce9a426cc0fcb98522ab1b70726..01685d41007675d516c2a10827d0ddf7f8383a0c 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 42c52eafa46c949f3687331d117097951fd853c2..2ca2d5ab1cc38894e6763fd3a1c5944df689abcd 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 1b1369a316ac04e149095106a025108fbce36776..8f1135ac06d46b411cb7852bab5fc68169b95e6b 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 300d4861184d5fc4340f4308fca42c36fdb51e98..668480db5ab5e5ec987492fe8ca9f9a5496bea49 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 0edbc23bfd12baa277de39f02f6b1a6f35c771b9..b9991eac9fea69ed5d349133b4f2bace795b059d 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 106404a13bd0c6ca940ef3f9fbb7d0f775b2a3c9..b31a70cc94821d6ea80031d59b2c3868b223ff54 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 46dc332be2c73b1d07c06ede73972f34dba44848..8e26792a0292ecbfb444143b5e07f8ce2fadb85c 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 e91e4bfcc1d58be4eca4754e627adb9c850db786..eb1a989fe6fe1868345cdafaf7d9d50a5311c621 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 fb6cd695805a86eab79aa7e606eb1523931cd5ef..23db343aefb01a77fe92c45076ade8a1de3436fc 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 0000000000000000000000000000000000000000..9055a9494fc8b31d92a3eb196ee4a590308b02b1 --- /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 8a7ca29c40c387d7f64a2b5241ff8bb868d2218f..f1439a9fbe0e5e5d3f45457d53dfd66ac310afda 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 86fef6be8ef08f46beaaf23638ef8df66a961e41..8be03d0b5deed876bd26394f2d26f618dc23ec76 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 9b29c546610e94c4a0fcf915b9792a86cd33296b..43b0c7803c7d67f44335ee954f7aacb373e1fb5e 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 bb1991c49179029bb0a8d4655162eb5b9f9df2de..7cc06a0a06acfe43be5964067c460c836016588d 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 2a842cb789fc7613d907922f7337bc34bcf189e1..994c254396065df1f8ff057436a19b6956299940 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 fa9b5545a7f74a72ff94132a2a02d68d51f93dc8..67cec1136a78be71decc8d7628fadbca60d8b413 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 352648d1a958fb5a5583be00215bf6cbb20466f2..1904a01e646efc125756f96a8a1f07f0ce2b8a3c 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 1015d6ffadc416c6afe9bfe98b30aa7b0fbf09f7..88b14fd804ba57754aa91480e8a23e497740d3d1 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),