musician webapp visualization and firsts edits

This commit is contained in:
Jorge Pastor 2024-04-23 21:06:48 +02:00
parent bb4fc5e267
commit 3c3e15d1c5
9 changed files with 326 additions and 2 deletions

View file

@ -9,6 +9,7 @@ from orchestra.contrib.domains.models import Domain, Record
from orchestra.contrib.mailboxes.models import Address, Mailbox
from orchestra.contrib.systemusers.models import WebappUsers, SystemUser
from orchestra.contrib.musician.validators import ValidateZoneMixin
from orchestra.contrib.webapps.models import WebApp, WebAppOption
from . import api
@ -201,3 +202,20 @@ class SystemUsersChangePasswordForm(ChangePasswordForm):
class Meta:
fields = ("password",)
model = SystemUser
class WebappOptionCreateForm(forms.ModelForm):
class Meta:
model = WebAppOption
fields = ("name", "value")
def __init__(self, *args, **kwargs):
self.webapp = kwargs.pop('webapp')
super().__init__(*args, **kwargs)
def save(self, commit=True):
instance = super().save(commit=False)
instance.webapp = self.webapp
if commit:
super().save(commit=True)
return instance

View file

@ -0,0 +1,42 @@
{% extends "musician/base.html" %}
{% load i18n %}
{% block content %}
<a class="btn-arrow-left" href="{% url 'musician:webapp-list' %}">{% trans "Go back" %}</a>
<h1 class="service-name">
{% trans "PHP settings for" %} <span class="font-weight-light">{{ object.name }}</span>
</h1>
<p class="service-description">{% trans "PHP settings page description." %}</p>
<table class="table service-list">
<colgroup>
<col span="1" style="width: 12%;">
<col span="1" style="width: 10%;">
<col span="1" style="width: 78%;">
</colgroup>
<thead class="thead-dark">
<tr>
<th scope="col">{% trans "Type" %}</th>
<th scope="col">{% trans "Value" %}</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
{% for option in object.options.all %}
<tr>
<td>{{ option.name }}</td>
<td>{{ option.value }}</td>
<td class="text-right">
<a href="{% url 'musician:webapp-delete-option' object.pk option.pk %}">
<i class="ml-3 text-danger fas fa-trash"></i></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<a class="btn btn-primary mt-4 mb-4" href="{% url 'musician:webapp-add-option' object.pk %}">{% trans "Add new option" %}</a></td>
{% endblock %}

View file

@ -0,0 +1,20 @@
{% extends "musician/base.html" %}
{% load bootstrap4 i18n %}
{% block content %}
<h1 class="service-name">{{ service.verbose_name }}</h1>
<form method="post">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<a class="btn btn-light mr-2" href="{% url 'musician:address-list' %}">{% trans "Cancel" %}</a>
<button type="submit" class="btn btn-secondary">{% trans "Save" %}</button>
{% if form.instance.pk %}
<div class="float-right">
<a class="btn btn-danger" href="{% url 'musician:address-delete' view.kwargs.pk %}">{% trans "Delete" %}</a>
</div>
{% endif %}
{% endbuttons %}
</form>
{% endblock %}

View file

@ -0,0 +1,57 @@
{% extends "musician/base.html" %}
{% load bootstrap4 i18n %}
{% block content %}
<p>
Una Webapp es el diectorio donde se almacena su web,
mediante SFTP podras acceder a este directorio y subir/editar/eliminar los archivos
</p>
<p>
Cada Webapp tiene su propio usuario SFTP, este se creara automaticamente al crear la Webapp
</p>
<table class="table service-list">
<colgroup>
<col span="1" style="width: 19%;">
<col span="1" style="width: 19%;">
<col span="1" style="width: 19%;">
<col span="1" style="width: 19%;">
<col span="1" style="width: 19%;">
<col span="1" style="width: 5%;">
</colgroup>
<thead class="thead-dark">
<tr>
<th scope="col">{% trans "Name" %}</th>
<th scope="col">{% trans "Type" %}</th>
<th scope="col">{% trans "Version" %}</th>
<th scope="col">{% trans "SFTP User" %}</th>
<th scope="col">{% trans "Server" %}</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
{% for webapp in object_list %}
<tr>
<td>{{ webapp.name }}</td>
<td>{{ webapp.type }}</td>
<td>{{ webapp.type_instance.get_detail }}</td>
<td>
{% if webapp.sftpuser %}
<a href="{% url 'musician:webappuser-list'%}">{{ webapp.sftpuser }}</a>
{% else %}
<a href="{% url 'musician:systemuser-list'%}">{{ webapp.account.main_systemuser }}</a>
{% endif %}
</td>
<td>{{ webapp.target_server }}</td>
<td>
<a class="btn btn-outline-warning" href="{% url 'musician:webapp-detail' webapp.id %}">
<i class="fas fa-tools"></i></a>
</td>
</tr>
{% endfor %}
</tbody>
{% include "musician/components/table_paginator.html" %}
</table>
{% endblock %}

View file

@ -0,0 +1,20 @@
{% extends "musician/base.html" %}
{% load bootstrap4 i18n %}
{% block content %}
<a class="btn-arrow-left" href="{% url 'musician:webapp-detail' view.kwargs.pk %}">{% trans "Go back" %}</a>
<h1 class="service-name">
{% if form.instance.pk %}{% trans "Update record of" %}{% else %}{% trans "Add record to" %}{% endif %}
<span class="font-weight-light">{{ form.webapp.name }}</span>
</h1>
<form method="post">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<a class="btn btn-light mr-2" href="{% url 'musician:webapp-detail' view.kwargs.pk %}">{% trans "Cancel" %}</a>
<button type="submit" class="btn btn-secondary">{% trans "Save" %}</button>
{% endbuttons %}
</form>
{% endblock %}

View file

@ -0,0 +1,13 @@
{% extends "musician/base.html" %}
{% load i18n %}
{% block content %}
<form method="post">
{% csrf_token %}
<p>{% blocktrans %}Are you sure that you want remove the following option"?{% endblocktrans %}</p>
<pre>{{ object.name}} {{ object.value}}</pre>
<p class="alert alert-warning"><strong>{% trans 'WARNING: This action cannot be undone.' %}</strong></p>
<input class="btn btn-danger" type="submit" value="{% trans 'Delete' %}">
<a class="btn btn-secondary" href="{% url 'musician:webapp-detail' view.kwargs.pk %}">{% trans 'Cancel' %}</a>
</form>
{% endblock %}

View file

@ -0,0 +1,103 @@
{% extends "musician/base.html" %}
{% load bootstrap4 i18n %}
{% block content %}
<table class="table service-list table-hover">
<colgroup>
<col span="1" style="width: 15%;">
<col span="1" style="width: 25%;">
<col span="1" style="width: 40%;">
<col span="1" style="width: 10%;">
<col span="1" style="width: 10%;">
</colgroup>
<thead class="thead-dark">
<tr>
<th scope="col">{% trans "Name" %}</th>
<th scope="col">{% trans "Url" %}</th>
<th scope="col">{% trans "Server" %}</th>
<th scope="col">{% trans "Is active?" %}</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
{% for website in object_list %}
<tr class="fila-principal" data-toggle="collapse" data-target=".detalles{{ website.id }}">
<td>{{ website.name }}</td>
<td>
{% for domain in website.domains.all %}
<a href="{{ website.get_protocol }}://{{ domain }}">{{ website.get_protocol }}://{{ domain }}</a><br>
{% endfor %}
</td>
<td>{{ website.target_server }}</td>
<td class="text-{{website.is_active|yesno:'success,danger'}}">
<i class="fa fa-{{ website.is_active|yesno:'check,times' }}"></i>
<span class="sr-only">{{ website.is_active|yesno }}</span>
</td>
<td>
<a class="btn btn-outline-warning" href="#">
<i class="fas fa-tools"></i></a>
</td>
</tr>
<!-- Fila oculta de webapp -->
<tr class="collapse detalles{{ website.id }}">
<td colspan="12"class="p-5">
<table class="table">
<tbody>
{% for content in website.content_set.all %}
<tr class="table-active">
<td>Webapp Dir</td>
<td>/home/{{ content.webapp.account }}/webapps/{{ content.webapp }}</td>
<td class="text-right">
<a class="btn btn-outline-secondary" href="#">
<i class="fas fa-tools"></i></a>
</td>
</tr>
<tr>
<td>Url</td>
{% if website.domains.first %}
<td><a href="{{ website.get_protocol }}://{{ website.domains.first }}{{ content.path }}">
{{ website.get_protocol }}://{{ website.domains.first }}{{ content.path }}</a>
</td>
{% else %}
<td></td>
{% endif %}
<td></td>
</tr>
<tr>
<td>Type</td>
{% if content.webapp.type == "php" %}
<td>PHP {{ content.webapp.type_instance.get_detail }}</td>
{% else %}
<td>{{ content.webapp.type }}</td>
{% endif %}
<td></td>
</tr>
<tr>
{% if content.webapp.sftpuser %}
<td>SFTP user</td>
<td>{{ content.webapp.sftpuser }}</td>
<td class="text-right">
<a class="btn btn-outline-warning" href="{% url 'musician:webappuser-password' content.webapp.sftpuser.id %}">
<i class="fas fa-key"></i> {% trans "Update password" %}</a>
</td>
{% else %}
<td>FTP user</td>
<td>{{ content.webapp.account.main_systemuser }}</td>
<td class="text-right">
<a class="btn btn-outline-warning" href="{% url 'musician:systemuser-password' content.webapp.account.main_systemuser.id %}">
<i class="fas fa-key"></i> {% trans "Update password" %}</a>
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</td>
</tr>
{% endfor %}
</tbody>
{% include "musician/components/table_paginator.html" %}
</table>
{% endblock %}

View file

@ -45,4 +45,9 @@ urlpatterns = [
path('systemusers/', views.SystemUserListView.as_view(), name='systemuser-list'),
path('systemuser/<int:pk>/change-password/', views.SystemUserChangePasswordView.as_view(), name='systemuser-password'),
path('websites/', views.WebsiteListView.as_view(), name='website-list'),
path('webapps/', views.WebappListView.as_view(), name='webapp-list'),
path('webapps/<int:pk>/', views.WebappDetailView.as_view(), name='webapp-detail'),
path('webapps/<int:pk>/add-option/', views.WebappAddOptionView.as_view(), name='webapp-add-option'),
path('webapps/<int:pk>/option/<int:option_pk>/delete/', views.WebappDeleteOptionView.as_view(), name='webapp-delete-option'),
]

View file

@ -34,13 +34,14 @@ from orchestra.contrib.resources.models import Resource, ResourceData
from orchestra.contrib.saas.models import SaaS
from orchestra.contrib.systemusers.models import WebappUsers, SystemUser
from orchestra.contrib.websites.models import Website
from orchestra.contrib.webapps.models import WebApp, WebAppOption
from orchestra.utils.html import html_to_pdf
from .auth import logout as auth_logout
from .forms import (LoginForm, MailboxChangePasswordForm, MailboxCreateForm,
MailboxSearchForm, MailboxUpdateForm, MailForm,
RecordCreateForm, RecordUpdateForm, WebappUsersChangePasswordForm,
SystemUsersChangePasswordForm)
SystemUsersChangePasswordForm, WebappOptionCreateForm)
from .mixins import (CustomContextMixin, ExtendedPaginationMixin,
UserTokenRequiredMixin)
from .models import Address as AddressService
@ -659,3 +660,48 @@ class WebsiteListView(ServiceListView):
# Translators: This message appears on the page title
'title': _('Websites'),
}
class WebappListView(ServiceListView):
model = WebApp
template_name = "musician/webapp_list.html"
extra_context = {
# Translators: This message appears on the page title
'title': _('Webapps'),
}
class WebappDetailView(CustomContextMixin, UserTokenRequiredMixin, DetailView):
template_name = "musician/webapp_detail.html"
extra_context = {
# Translators: This message appears on the page title
'title': _('webapp details'),
}
def get_queryset(self):
return WebApp.objects.filter(account=self.request.user)
class WebappAddOptionView(CustomContextMixin, UserTokenRequiredMixin, CreateView):
model = WebAppOption
form_class = WebappOptionCreateForm
template_name = "musician/webapp_option_form.html"
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
webapp = get_object_or_404(WebApp, account=self.request.user, pk=self.kwargs["pk"])
kwargs['webapp'] = webapp
return kwargs
def get_success_url(self):
return reverse_lazy("musician:webapp-detail", kwargs={"pk": self.kwargs["pk"]})
class WebappDeleteOptionView(CustomContextMixin, UserTokenRequiredMixin, DeleteView):
model = WebAppOption
template_name = "musician/webappoption_check_delete.html"
pk_url_kwarg = "option_pk"
def get_queryset(self):
qs = WebAppOption.objects.filter(webapp__account=self.request.user, webapp=self.kwargs["pk"])
return qs
def get_success_url(self):
return reverse_lazy("musician:webapp-detail", kwargs={"pk": self.kwargs["pk"]})