Provide ability for admins to manage user organisation membership & admin rights

- Required overwriting a bunch of base code to slot in the handling
- Admins are shown with yellow text in their organisation label
This commit is contained in:
2022-02-08 18:10:20 +00:00
parent 609454def2
commit 9d62749914
14 changed files with 763 additions and 1 deletions

View File

@@ -0,0 +1,80 @@
{% extends "modals/modal.html.twig" %}
{% block modal_title %}{{translate("ORGANISATION.MANAGE")}}{% endblock %}
{% block modal_body %}
<form class="js-form" method="PUT" action="{{site.uri.public}}/api/users/u/{{user.user_name}}/organisations">
{% include "forms/csrf.html.twig" %}
<div class="js-form-alerts">
</div>
<div class="js-form-organisations">
<table class="table table-striped">
<thead>
<tr>
<th>{{translate("NAME")}}</th>
<th>{{translate("DESCRIPTION")}}</th>
<th>{{translate("REMOVE")}}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<div class="padding-bottom">
<label>{{translate("ORGANISATION.ASSIGN_NEW")}}:</label>
<select class="form-control js-select-new" type="text">
<option></option>
</select>
</div>
</div>
<br>
<div class="row">
<div class="col-xs-8 col-sm-4">
<button type="submit" class="btn btn-block btn-lg btn-success">{{translate("UPDATE")}}</button>
</div>
<div class="col-xs-4 col-sm-3 pull-right">
<button type="button" class="btn btn-block btn-lg btn-link" data-dismiss="modal">{{translate('CANCEL')}}</button>
</div>
</div>
</form>
{# This contains a series of <script> blocks, each of which is a client-side Handlebars template.
# Note that these are NOT Twig templates, although the syntax is similar. We wrap them in the `verbatim` tag,
# so that Twig will output them directly into the DOM instead of trying to treat them like Twig templates.
#
# These templates require handlebars-helpers.js, moment.js
#}
{% verbatim %}
<script id="user-organisations-select-option" type="text/x-handlebars-template">
<div>
<strong>
{{name}}
</strong>
<br>
{{description}}
</div>
</script>
<script id="user-organisations-row" type="text/x-handlebars-template">
<tr class="uf-collection-row">
<td>
{{name}}
<input type="hidden" name="organisations[{{ rownum }}][organisation_id]" value="{{id}}">
</td>
<td>
{{description}}
</td>
<td>
<input type="checkbox" name="organisations[{{ rownum }}][flag_admin]" {{#if flag_admin}}checked{{/if}}>
</td>
<td>
<button type="button" class="btn btn-link btn-trash js-delete-row pull-right" title="Delete"> <i class="fas fa-trash"></i> </button>
</td>
</tr>
</script>
{% endverbatim %}
<!-- Include validation rules -->
<script>
{% include "pages/partials/page.js.twig" %}
</script>
{% endblock %}

View File

@@ -0,0 +1,168 @@
{# This partial template renders a table of users, to be populated with rows via an AJAX request.
# This extends a generic template for paginated tables.
#
# Note that this template contains a "skeleton" table with an empty table body, and then a block of Handlebars templates which are used
# to render the table cells with the data from the AJAX request.
#}
{% extends "tables/table-paginated.html.twig" %}
{% block table %}
<table id="{{table.id}}" class="tablesorter table table-bordered table-hover table-striped" data-sortlist="{{table.sortlist}}">
<thead>
<tr>
<th class="sorter-metatext" data-column-name="name" data-column-template="#user-table-column-info" data-priority="1">{{translate('USER')}} <i class="fas fa-sort"></i></th>
<th class="filter-metatext" data-column-name="organisations" data-column-template="#user-table-column-organisations" data-priority="2">{{translate("ORGANISATION", 2)}} <i class="fas fa-sort"></i></th>
{% if 'last_activity' in table.columns %}
<th class="sorter-metanum" data-column-name="last_activity" data-column-template="#user-table-column-last-activity" data-priority="3">{{translate("ACTIVITY.LAST")}} <i class="fas fa-sort"></i></th>
{% endif %}
{% if 'via_roles' in table.columns %}
<th data-column-template="#user-table-column-via-roles" data-sorter="false" data-filter="false" data-priority="1">{{translate('PERMISSION.VIA_ROLES')}}</th>
{% endif %}
<th class="filter-select filter-metatext" data-column-name="status" data-column-template="#user-table-column-status" data-priority="2">{{translate("STATUS")}} <i class="fas fa-sort"></i></th>
<th data-column-name="actions" data-column-template="#user-table-column-actions" data-sorter="false" data-filter="false" data-priority="1">{{translate("ACTIONS")}}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
{% endblock %}
{% block table_cell_templates %}
{# This contains a series of <script> blocks, each of which is a client-side Handlebars template.
# Note that these are NOT Twig templates, although the syntax is similar. We wrap them in the `verbatim` tag,
# so that Twig will output them directly into the DOM instead of trying to treat them like Twig templates.
#
# These templates require handlebars-helpers.js, moment.js
#}
{% verbatim %}
<script id="user-table-column-info" type="text/x-handlebars-template">
<td data-text="{{row.last_name}}">
<strong>
<a href="{{site.uri.public}}/users/u/{{row.user_name}}">{{row.first_name}} {{row.last_name}} ({{row.user_name}})</a>
</strong>
<div class="js-copy-container">
<span class="js-copy-target">{{row.email}}</span>
<button class="btn btn-xs uf-copy-trigger js-copy-trigger"><i class="fas fa-copy"></i></button>
</div>
</td>
</script>
<script id="user-table-column-organisations" type="text/x-handlebars-template">
{{#if row.organisations.length }}
<td style="line-height: 2em;">
{{#each row.organisations }}
<a href="{% endverbatim %}{{site.uri.public}}{% verbatim %}/organisations/o/{{this.slug}}" class="label label-primary {{#if this.pivot.flag_admin }}organisation-admin{{/if}}" title="{{this.description}}" data-text="{{this.name}}" style="font-size: 100%;">{{this.name}}</a><br>
{{/each}}
</td>
{{ else }}
<td></td>
{{/if }}
</script>
<script id="user-table-column-last-activity" type="text/x-handlebars-template">
{{#if row.last_activity }}
<td data-num="{{dateFormat row.last_activity.occurred_at format='x'}}">
{{dateFormat row.last_activity.occurred_at format="dddd"}}<br>{{dateFormat row.last_activity.occurred_at format="MMM Do, YYYY h:mm a"}}
<br>
<i>{{row.last_activity.description}}</i>
</td>
{{ else }}
<td data-num="0">
<i>{% endverbatim %}{{translate("UNKNOWN")}}{% verbatim %}</i>
</td>
{{/if }}
</script>
<script id="user-table-column-status" type="text/x-handlebars-template">
<td
{{#ifx row.flag_enabled '==' 0 }}
data-text="disabled"
{{ else }}
{{#ifx row.flag_verified '==' 0 }}
data-text="unactivated"
{{ else }}
data-text="active"
{{/ifx }}
{{/ifx }}
>
{{#ifx row.flag_enabled '==' 0 }}
<span class="text-muted">
{% endverbatim %}{{translate("DISABLED")}}{% verbatim %}
</span>
{{ else }}
{{#ifx row.flag_verified '==' 0 }}
<span class="text-yellow">
{% endverbatim %}{{translate("UNACTIVATED")}}{% verbatim %}
</span>
{{ else }}
<span>
{% endverbatim %}{{translate("ACTIVE")}}{% verbatim %}
</span>
{{/ifx }}
{{/ifx }}
</td>
</script>
<script id="user-table-column-actions" type="text/x-handlebars-template">
<td class="uf-table-fit-width">
<div class="btn-group">
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">{% endverbatim %}{{translate("ACTIONS")}}{% verbatim %}<span class="caret"></span></button>
<ul class="dropdown-menu dropdown-menu-right-responsive" role="menu">
{{#ifx row.flag_verified '==' 0 }}
<li>
<a href="#" data-user_name="{{row.user_name}}" class="js-user-activate">
<i class="fas fa-bolt"></i> {% endverbatim %}{{translate("USER.ACTIVATE")}}{% verbatim %}
</a>
</li>
{{/ifx }}
<li>
<a href="#" data-user_name="{{row.user_name}}" class="js-user-edit">
<i class="fas fa-edit"></i> {% endverbatim %}{{translate("USER.EDIT")}}{% verbatim %}
</a>
</li>
<li>
<a href="#" data-user_name="{{row.user_name}}" class="js-user-roles">
<i class="fas fa-id-card"></i> {% endverbatim %}{{translate("ROLE.MANAGE")}}{% verbatim %}
</a>
</li>
<li>
<a href="#" data-user_name="{{row.user_name}}" class="js-user-organisations">
<i class="fas fa-sitemap"></i> {% endverbatim %}{{translate("ORGANISATION.MANAGE")}}{% verbatim %}
</a>
</li>
<li>
<a href="#" data-user_name="{{row.user_name}}" class="js-user-password">
<i class="fas fa-key"></i> {% endverbatim %}{{translate("USER.ADMIN.CHANGE_PASSWORD")}}{% verbatim %}
</a>
</li>
<li>
{{#ifx row.flag_enabled '==' 1 }}
<a href="#" data-user_name="{{row.user_name}}" class="js-user-disable">
<i class="fas fa-minus-circle"></i> {% endverbatim %}{{translate("USER.DISABLE")}}{% verbatim %}
</a>
{{ else }}
<a href="#" data-user_name="{{row.user_name}}" class="js-user-enable">
<i class="fas fa-plus-circle"></i> {% endverbatim %}{{translate("USER.ENABLE")}}{% verbatim %}
</a>
{{/ifx }}
</li>
<li>
<a href="#" data-user_name="{{row.user_name}}" class="js-user-delete">
<i class="fas fa-trash-alt"></i> {% endverbatim %}{{translate("USER.DELETE")}}{% verbatim %}
</a>
</li>
</ul>
</div>
</td>
</script>
<script id="user-table-column-via-roles" type="text/x-handlebars-template">
<td>
{{#each row.roles_via }}
<a href="{% endverbatim %}{# Handlebars can't access variables in the global scope, so we have to use Twig to insert the base url #}{{site.uri.public}}{% verbatim %}/roles/r/{{this.slug}}" class="label label-primary" title="{{this.description}}">{{this.name}}</a>
{{/each}}
</td>
</script>
{% endverbatim %}
{% endblock %}