@ -0,0 +1,8 @@
|
||||
{
|
||||
"users": [
|
||||
"CHANGE_ME"
|
||||
],
|
||||
"teams": [
|
||||
"CHANGE_ME"
|
||||
]
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
# Generated by Django 3.1.3 on 2022-02-10 13:02
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
def migrate_actions(apps, schema_editor):
|
||||
CompensationAction = apps.get_model('compensation', 'CompensationAction')
|
||||
actions = CompensationAction.objects.all()
|
||||
|
||||
for action in actions:
|
||||
action_type = action.action_type or []
|
||||
action.action_type_tmp.set([action_type])
|
||||
action.save()
|
||||
|
||||
if not action.action_type_tmp.count() > 0:
|
||||
raise ValueError("Migration of actions did not work! Stoped before data loss!")
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('codelist', '0001_initial'),
|
||||
('compensation', '0003_auto_20220202_0846'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='compensationaction',
|
||||
name='action_type_tmp',
|
||||
field=models.ManyToManyField(blank=True, limit_choices_to={'code_lists__in': [1026], 'is_archived': False, 'is_selectable': True}, related_name='_compensationaction_action_type_+', to='codelist.KonovaCode'),
|
||||
),
|
||||
migrations.RunPython(migrate_actions),
|
||||
migrations.RemoveField(
|
||||
model_name='compensationaction',
|
||||
name='action_type',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='compensationaction',
|
||||
old_name='action_type_tmp',
|
||||
new_name='action_type',
|
||||
)
|
||||
]
|
@ -0,0 +1,46 @@
|
||||
# Generated by Django 3.1.3 on 2022-02-18 08:17
|
||||
|
||||
from django.db import migrations, models, transaction
|
||||
import django.db.models.deletion
|
||||
|
||||
from codelist.settings import CODELIST_BIOTOPES_ID, CODELIST_AFTER_STATE_BIOTOPES__ID
|
||||
|
||||
|
||||
def migrate_entries_974_to_654(apps, schema_editor):
|
||||
CompensationState = apps.get_model("compensation", "CompensationState")
|
||||
KonovaCode = apps.get_model("codelist", "KonovaCode")
|
||||
all_states = CompensationState.objects.all()
|
||||
|
||||
with transaction.atomic():
|
||||
for state in all_states:
|
||||
code_from_654 = KonovaCode.objects.get(
|
||||
short_name=state.biotope_type.short_name,
|
||||
code_lists__in=[CODELIST_BIOTOPES_ID],
|
||||
is_archived=False,
|
||||
is_leaf=True,
|
||||
)
|
||||
state.biotope_type = code_from_654
|
||||
state.save()
|
||||
|
||||
old_list_states = CompensationState.objects.filter(
|
||||
biotope_type__code_lists__in=[CODELIST_AFTER_STATE_BIOTOPES__ID]
|
||||
)
|
||||
if old_list_states.count() > 0:
|
||||
raise Exception("Still unmigrated values!")
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('codelist', '0001_initial'),
|
||||
('compensation', '0004_auto_20220210_1402'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(migrate_entries_974_to_654),
|
||||
migrations.AlterField(
|
||||
model_name='compensationstate',
|
||||
name='biotope_type',
|
||||
field=models.ForeignKey(blank=True, limit_choices_to={'code_lists__in': [654], 'is_archived': False, 'is_selectable': True}, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='codelist.konovacode'),
|
||||
),
|
||||
]
|
@ -0,0 +1,19 @@
|
||||
# Generated by Django 3.1.3 on 2022-02-18 09:13
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('user', '0003_team'),
|
||||
('compensation', '0005_auto_20220218_0917'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='ecoaccount',
|
||||
name='teams',
|
||||
field=models.ManyToManyField(help_text='Teams having access (data shared with)', to='user.Team'),
|
||||
),
|
||||
]
|
@ -0,0 +1,19 @@
|
||||
# Generated by Django 3.1.3 on 2022-02-18 09:13
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('user', '0003_team'),
|
||||
('ema', '0002_auto_20220114_0936'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='ema',
|
||||
name='teams',
|
||||
field=models.ManyToManyField(help_text='Teams having access (data shared with)', to='user.Team'),
|
||||
),
|
||||
]
|
@ -0,0 +1,19 @@
|
||||
# Generated by Django 3.1.3 on 2022-02-18 09:13
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('user', '0003_team'),
|
||||
('intervention', '0002_auto_20220114_0936'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='intervention',
|
||||
name='teams',
|
||||
field=models.ManyToManyField(help_text='Teams having access (data shared with)', to='user.Team'),
|
||||
),
|
||||
]
|
@ -0,0 +1,40 @@
|
||||
# Generated by Django 3.1.3 on 2022-02-16 07:56
|
||||
|
||||
from django.db import migrations, transaction
|
||||
|
||||
from codelist.settings import CODELIST_BIOTOPES_ID, CODELIST_AFTER_STATE_BIOTOPES__ID
|
||||
|
||||
|
||||
def migrate_biotopes_from_974_to_654(apps, schema_editor):
|
||||
KonovaCode = apps.get_model("codelist", "KonovaCode")
|
||||
CompensationState = apps.get_model("compensation", "CompensationState")
|
||||
all_states = CompensationState.objects.all()
|
||||
|
||||
with transaction.atomic():
|
||||
for state in all_states:
|
||||
new_biotope_code = KonovaCode.objects.get(
|
||||
code_lists__in=[CODELIST_BIOTOPES_ID],
|
||||
is_selectable=True,
|
||||
is_archived=False,
|
||||
short_name=state.biotope_type.short_name,
|
||||
)
|
||||
state.biotope_type = new_biotope_code
|
||||
state.save()
|
||||
|
||||
all_states = CompensationState.objects.all()
|
||||
after_state_list_elements = all_states.filter(
|
||||
biotope_type__code_lists__in=[CODELIST_AFTER_STATE_BIOTOPES__ID]
|
||||
)
|
||||
if after_state_list_elements.count() > 0:
|
||||
raise Exception("Still states with wrong codelist entries!")
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('konova', '0004_auto_20220209_0839'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(migrate_biotopes_from_974_to_654),
|
||||
]
|
@ -0,0 +1,21 @@
|
||||
{% load l10n fontawesome_5 %}
|
||||
|
||||
{% for code in codes %}
|
||||
<div class="ml-4 tree-element">
|
||||
<label class="tree-label" role="{% if not code.is_leaf%}button{% endif %}" for="input_{{code.pk|unlocalize}}" id="{{code.pk|unlocalize}}" data-toggle="collapse" data-target="#children_{{code.pk|unlocalize}}" aria-expanded="true" aria-controls="children_{{code.pk|unlocalize}}">
|
||||
{% if code.is_leaf%}
|
||||
<input class="tree-input" id="input_{{code.pk|unlocalize}}" name="{{ widget.name }}" type="checkbox" value="{{code.pk|unlocalize}}" {% if code.pk|unlocalize in widget.value %}checked{% endif %}/>
|
||||
{% else %}
|
||||
{% fa5_icon 'angle-right' %}
|
||||
{% endif %}
|
||||
{{code.long_name}}
|
||||
</label>
|
||||
{% if not code.is_leaf %}
|
||||
<div id="children_{{code.pk|unlocalize}}" data-toggle="collapse" class="collapse tree-element-children">
|
||||
{% with code.children as codes %}
|
||||
{% include 'konova/widgets/checkbox-tree-select-content.html' %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
@ -0,0 +1,68 @@
|
||||
{% load i18n %}
|
||||
|
||||
<div class="ml-4 mb-4">
|
||||
<input id="tree-search-input" class="form-control" type="text" placeholder="{% trans 'Search' %}"/>
|
||||
</div>
|
||||
|
||||
<div id="tree-root">
|
||||
{% include 'konova/widgets/checkbox-tree-select-content.html' %}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function toggleSelectedCssClass(element){
|
||||
element = $(element);
|
||||
var cssClass = "badge rlp-r"
|
||||
|
||||
var directParent = element.closest(".tree-element-children")
|
||||
var root = element.parents(".tree-element-children")
|
||||
|
||||
var otherCheckedInputsOfParent = directParent.find('.tree-input:checked');
|
||||
var otherCheckedInputsOfRoot = root.find('.tree-input:checked');
|
||||
|
||||
if(otherCheckedInputsOfParent.length == 0){
|
||||
var parentLabel = directParent.siblings(".tree-label");
|
||||
parentLabel.removeClass(cssClass)
|
||||
if(otherCheckedInputsOfRoot.length == 0){
|
||||
var rootLabel = root.siblings(".tree-label")
|
||||
rootLabel.removeClass(cssClass)
|
||||
}
|
||||
}else{
|
||||
var rootAndParentLabel = root.siblings(".tree-label");
|
||||
rootAndParentLabel.addClass(cssClass);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function changeHandler(event){
|
||||
toggleSelectedCssClass(this);
|
||||
}
|
||||
|
||||
function searchInputHandler(event){
|
||||
var elem = $(this);
|
||||
var val = elem.val()
|
||||
var allTreeElements = $(".tree-element")
|
||||
var allTreeElementsContain = $(".tree-element").filter(function(){
|
||||
var reg = new RegExp(val, "i");
|
||||
return reg.test($(this).text());
|
||||
}
|
||||
);
|
||||
if(val.length > 0){
|
||||
allTreeElements.hide()
|
||||
allTreeElementsContain.show()
|
||||
}else{
|
||||
allTreeElements.show()
|
||||
}
|
||||
}
|
||||
|
||||
// Add event listener on search input
|
||||
$("#tree-search-input").keyup(searchInputHandler)
|
||||
|
||||
// Add event listener on changed checkboxes
|
||||
$(".tree-input").change(changeHandler);
|
||||
|
||||
// initialize all pre-checked checkboxes (e.g. on an edit form)
|
||||
var preCheckedElements = $(".tree-input:checked");
|
||||
preCheckedElements.each(function (index, element){
|
||||
toggleSelectedCssClass(element);
|
||||
})
|
||||
</script>
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,28 @@
|
||||
{% load i18n %}
|
||||
|
||||
<div>
|
||||
<h2>{% trans 'Shared data checked' %}</h2>
|
||||
<h4>{{obj_identifier}}</h4>
|
||||
<hr>
|
||||
<article>
|
||||
{% trans 'Hello team' %} {{team.name}},
|
||||
<br>
|
||||
{% trans 'the following dataset has just been checked' %}
|
||||
<br>
|
||||
<strong>{{obj_identifier}}</strong>
|
||||
<br>
|
||||
<strong>{{obj_title}}</strong>
|
||||
<br>
|
||||
{% trans 'This means, the responsible registration office just confirmed the correctness of this dataset.' %}
|
||||
<br>
|
||||
<br>
|
||||
{% trans 'Best regards' %}
|
||||
<br>
|
||||
KSP
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
{% include 'email/signature.html' %}
|
||||
</article>
|
||||
</div>
|
||||
|
@ -0,0 +1,28 @@
|
||||
{% load i18n %}
|
||||
|
||||
<div>
|
||||
<h2>{% trans 'Shared data deleted' %}</h2>
|
||||
<h4>{{obj_identifier}}</h4>
|
||||
<hr>
|
||||
<article>
|
||||
{% trans 'Hello team' %} {{team.name}},
|
||||
<br>
|
||||
{% trans 'the following dataset has just been deleted' %}
|
||||
<br>
|
||||
<strong>{{obj_identifier}}</strong>
|
||||
<br>
|
||||
<strong>"{{obj_title}}"</strong>
|
||||
<br>
|
||||
{% trans 'If this should not have been happened, please contact us. See the signature for details.' %}
|
||||
<br>
|
||||
<br>
|
||||
{% trans 'Best regards' %}
|
||||
<br>
|
||||
KSP
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
{% include 'email/signature.html' %}
|
||||
</article>
|
||||
</div>
|
||||
|
@ -0,0 +1,33 @@
|
||||
{% load i18n %}
|
||||
|
||||
<div>
|
||||
<h2>{% trans 'Shared data recorded' %}</h2>
|
||||
<h4>{{obj_identifier}}</h4>
|
||||
<hr>
|
||||
<article>
|
||||
{% trans 'Hello team' %} {{team.name}},
|
||||
<br>
|
||||
{% trans 'the following dataset has just been recorded' %}
|
||||
<br>
|
||||
<strong>{{obj_identifier}}</strong>
|
||||
<br>
|
||||
<strong>"{{obj_title}}"</strong>
|
||||
<br>
|
||||
{% trans 'This means the data is now publicly available, e.g. in LANIS' %}
|
||||
<br>
|
||||
<br>
|
||||
{% trans 'Best regards' %}
|
||||
<br>
|
||||
KSP
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<small>
|
||||
{% trans 'Please note: Recorded intervention means the compensations are recorded as well.' %}
|
||||
</small>
|
||||
<br>
|
||||
<br>
|
||||
{% include 'email/signature.html' %}
|
||||
</article>
|
||||
</div>
|
||||
|
@ -0,0 +1,33 @@
|
||||
{% load i18n %}
|
||||
|
||||
<div>
|
||||
<h2>{% trans 'Shared data unrecorded' %}</h2>
|
||||
<h4>{{obj_identifier}}</h4>
|
||||
<hr>
|
||||
<article>
|
||||
{% trans 'Hello team' %} {{team.name}},
|
||||
<br>
|
||||
{% trans 'the following dataset has just been unrecorded' %}
|
||||
<br>
|
||||
<strong>{{obj_identifier}}</strong>
|
||||
<br>
|
||||
<strong>"{{obj_title}}"</strong>
|
||||
<br>
|
||||
{% trans 'This means the data is no longer publicly available.' %}
|
||||
<br>
|
||||
<br>
|
||||
{% trans 'Best regards' %}
|
||||
<br>
|
||||
KSP
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<small>
|
||||
{% trans 'Please note: Unrecorded intervention means the compensations are unrecorded as well.' %}
|
||||
</small>
|
||||
<br>
|
||||
<br>
|
||||
{% include 'email/signature.html' %}
|
||||
</article>
|
||||
</div>
|
||||
|
@ -0,0 +1,34 @@
|
||||
{% load i18n %}
|
||||
|
||||
<div>
|
||||
<h2>{% trans 'Access shared' %}</h2>
|
||||
<h4>{{obj_identifier}}</h4>
|
||||
<hr>
|
||||
<article>
|
||||
{% trans 'Hello team' %} {{team.name}},
|
||||
<br>
|
||||
{% trans 'the following dataset has just been shared with your team' %}
|
||||
<br>
|
||||
<strong>{{obj_identifier}}</strong>
|
||||
<br>
|
||||
<strong>"{{obj_title}}"</strong>
|
||||
<br>
|
||||
{% trans 'This means you can now edit this dataset.' %}
|
||||
{% trans 'The shared dataset appears now by default on your overview for this dataset type.' %}
|
||||
<br>
|
||||
<br>
|
||||
{% trans 'Best regards' %}
|
||||
<br>
|
||||
KSP
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<small>
|
||||
{% trans 'Please note: Shared access on an intervention means you automatically have editing access to related compensations.' %}
|
||||
</small>
|
||||
<br>
|
||||
<br>
|
||||
{% include 'email/signature.html' %}
|
||||
</article>
|
||||
</div>
|
||||
|
@ -0,0 +1,29 @@
|
||||
{% load i18n %}
|
||||
|
||||
<div>
|
||||
<h2>{% trans 'Shared access removed' %}</h2>
|
||||
<h4>{{obj_identifier}}</h4>
|
||||
<hr>
|
||||
<article>
|
||||
{% trans 'Hello team' %} {{team.name}},
|
||||
<br>
|
||||
{% trans 'your teams shared access, including editing, has been revoked for the dataset ' %}
|
||||
<br>
|
||||
<strong>{{obj_identifier}}</strong>
|
||||
<br>
|
||||
<strong>"{{obj_title}}"</strong>
|
||||
<br>
|
||||
{% trans 'However, you are still able to view the dataset content.' %}
|
||||
{% trans 'Please use the provided search filter on the dataset`s overview pages to find them.' %}
|
||||
<br>
|
||||
<br>
|
||||
{% trans 'Best regards' %}
|
||||
<br>
|
||||
KSP
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
{% include 'email/signature.html' %}
|
||||
</article>
|
||||
</div>
|
||||
|
@ -0,0 +1,29 @@
|
||||
# Generated by Django 3.1.3 on 2022-02-17 10:22
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('user', '0002_user_api_token'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Team',
|
||||
fields=[
|
||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||
('name', models.CharField(blank=True, max_length=500, null=True)),
|
||||
('description', models.TextField(blank=True, null=True)),
|
||||
('admin', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
|
||||
('users', models.ManyToManyField(blank=True, related_name='teams', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
@ -0,0 +1,95 @@
|
||||
from django.db import models
|
||||
|
||||
from konova.models import UuidModel
|
||||
from konova.utils.mailer import Mailer
|
||||
|
||||
|
||||
class Team(UuidModel):
|
||||
""" Groups users in self managed teams. Can be used for multi-sharing of data
|
||||
|
||||
"""
|
||||
name = models.CharField(max_length=500, null=True, blank=True)
|
||||
description = models.TextField(null=True, blank=True)
|
||||
users = models.ManyToManyField("user.User", blank=True, related_name="teams")
|
||||
admin = models.ForeignKey("user.User", blank=True, null=True, related_name="+", on_delete=models.SET_NULL)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def send_mail_shared_access_given_team(self, obj_identifier, obj_title):
|
||||
""" Sends a mail to the team members in case of given shared access
|
||||
|
||||
Args:
|
||||
obj_identifier ():
|
||||
obj_title ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
mailer = Mailer()
|
||||
mailer.send_mail_shared_access_given_team(obj_identifier, obj_title, self)
|
||||
|
||||
def send_mail_shared_access_removed(self, obj_identifier, obj_title):
|
||||
""" Sends a mail to the team members in case of removed shared access
|
||||
|
||||
Args:
|
||||
obj_identifier ():
|
||||
obj_title ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
mailer = Mailer()
|
||||
mailer.send_mail_shared_access_removed_team(obj_identifier, obj_title, self)
|
||||
|
||||
def send_mail_shared_data_unrecorded(self, obj_identifier, obj_title):
|
||||
""" Sends a mail to the team members in case of unrecorded data
|
||||
|
||||
Args:
|
||||
obj_identifier ():
|
||||
obj_title ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
mailer = Mailer()
|
||||
mailer.send_mail_shared_data_unrecorded_team(obj_identifier, obj_title, self)
|
||||
|
||||
def send_mail_shared_data_recorded(self, obj_identifier, obj_title):
|
||||
""" Sends a mail to the team members in case of unrecorded data
|
||||
|
||||
Args:
|
||||
obj_identifier ():
|
||||
obj_title ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
mailer = Mailer()
|
||||
mailer.send_mail_shared_data_recorded_team(obj_identifier, obj_title, self)
|
||||
|
||||
def send_mail_shared_data_checked(self, obj_identifier, obj_title):
|
||||
""" Sends a mail to the team members in case of checked data
|
||||
|
||||
Args:
|
||||
obj_identifier ():
|
||||
obj_title ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
mailer = Mailer()
|
||||
mailer.send_mail_shared_data_checked_team(obj_identifier, obj_title, self)
|
||||
|
||||
def send_mail_shared_data_deleted(self, obj_identifier, obj_title):
|
||||
""" Sends a mail to the team members in case of deleted data
|
||||
|
||||
Args:
|
||||
obj_identifier ():
|
||||
obj_title ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
mailer = Mailer()
|
||||
mailer.send_mail_shared_data_deleted_team(obj_identifier, obj_title, self)
|
@ -1,6 +1,6 @@
|
||||
{% load fontawesome_5 i18n %}
|
||||
|
||||
<button class="btn btn-default btn-modal" data-form-url="{% url 'user:contact' user.id %}" title="{% trans 'Show contact data' %}">
|
||||
{% fa5_icon 'id-card' %}
|
||||
{% fa5_icon 'user' %}
|
||||
<span>{{user.username}}</span>
|
||||
</button>
|
@ -0,0 +1,6 @@
|
||||
{% load fontawesome_5 i18n %}
|
||||
|
||||
<button class="btn btn-default btn-modal" data-form-url="{% url 'user:team-data' team.id %}" title="{% trans 'Show team data' %}">
|
||||
{% fa5_icon 'users' %}
|
||||
<span>{{team.name}}</span>
|
||||
</button>
|
@ -0,0 +1,69 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n fontawesome_5 %}
|
||||
|
||||
{% block head %}
|
||||
|
||||
{% comment %}
|
||||
dal documentation (django-autocomplete-light) states using form.media for adding needed scripts.
|
||||
This does not work properly with modal forms, as the scripts are not loaded properly inside the modal.
|
||||
Therefore the script linkages from form.media have been extracted and put inside dal/scripts.html to ensure
|
||||
these scripts are loaded when needed.
|
||||
{% endcomment %}
|
||||
{% include 'dal/scripts.html' %}
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="container">
|
||||
<h4>{% trans 'Teams' %}</h4>
|
||||
<div class="col-md">
|
||||
<button class="btn rlp-r btn-modal" data-form-url="{% url 'user:team-new' %}" title="{% trans 'Add new team' %}">
|
||||
{% fa5_icon 'plus' %}
|
||||
{% trans 'New' %}
|
||||
</button>
|
||||
</div>
|
||||
<div class="table-container">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="align-middle">{% trans 'Name' %}</th>
|
||||
<th scope="col" class="align-middle w-20">{% trans 'Description' %}</th>
|
||||
<th scope="col" class="align-middle">{% trans 'Members' %}</th>
|
||||
<th scope="col" class="align-middle">{% trans 'Action' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for team in teams %}
|
||||
<tr>
|
||||
<td>{{team.name}}</td>
|
||||
<td>
|
||||
<div class="scroll-150">
|
||||
{{team.description}}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{% for member in team.users.all %}
|
||||
<span class="badge badge-pill rlp-r">{{member.username}}</span>
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td>
|
||||
{% if team.admin == user %}
|
||||
<button class="btn rlp-r btn-modal" data-form-url="{% url 'user:team-edit' team.id %}" title="{% trans 'Edit team' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
<button class="btn rlp-r btn-modal" data-form-url="{% url 'user:team-remove' team.id %}" title="{% trans 'Remove team' %}">
|
||||
{% fa5_icon 'trash' %}
|
||||
</button>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% with 'btn-modal' as btn_class %}
|
||||
{% include 'modal/modal_form_script.html' %}
|
||||
{% endwith %}
|
||||
|
||||
{% endblock %}
|
Loading…
Reference in New Issue