src/templates/team.html
{% extends 'base.html' %}
{% block body %}
<ul class='tabbed-menu'>
<li><button type='button' class='btn' data-action='switch-tab' data-tabtarget='1'>{{ 'Scheduler'|trans }}</button></li>
<li><button type='button' class='btn' data-action='switch-tab' data-tabtarget='2'>{{ 'Members'|trans }}</button></li>
<li><button type='button' class='btn' data-action='switch-tab' data-tabtarget='3'>{{ 'Templates'|trans }}</button></li>
<li><button type='button' class='btn' data-action='switch-tab' data-tabtarget='4'>{{ 'Email'|trans }}</button></li>
<li><button type='button' class='btn' data-action='switch-tab' data-tabtarget='5'>{{ 'Procurement requests'|trans }}</button></li>
</ul>
{# loading spinner #}
<div class='d-flex justify-content-center' id='loading-spinner'>
<div class='lds-dual-ring'></div>
</div>
{# Modal for event click #}
<div class='modal fade' id='eventModal' tabindex='-1' role='dialog' aria-labelledby='eventModalLabel'>
<div class='modal-dialog modal-lg' role='document'>
<div class='modal-content'>
<div class='modal-header'>
<h5 class='modal-title' id='eventModalLabel'>{{ 'Edit event'|trans }}</h5>
<button type='button' class='close' data-dismiss='modal' aria-label='{{ 'Close'|trans }}'>
<span aria-hidden='true'>×</span>
</button>
</div>
<div class='modal-body' data-wait='{{ 'Please wait…'|trans }}'>
{# "placeholder" will be replaced with real title by js #}
<h3 id='eventTitle' class='editable hl-hover'>placeholder</h3>
{# START AND END TIMES #}
<div class='mt-2'>
<label for='schedulerEventModalStart'>{{ 'Start time'|trans }}</label>
<input id='schedulerEventModalStart' class='form-control' type='datetime-local' data-what='start_epoch' value='' />
<label for='schedulerEventModalEnd'>{{ 'End time'|trans }}</label>
<input id='schedulerEventModalEnd' class='form-control' type='datetime-local' data-what='end_epoch' value='' />
</div>
{# BIND EXPERIMENT #}
<div class='mt-2'>
<i class='fas fa-link mr-1'></i><h5 class='d-inline' id='bindExpInputLabel'>{{ 'Bind an experiment'|trans }}</h5>
<div id='eventBoundExp'></div>
<button data-action='scheduler-rm-bind' data-type='experiment' data-eventid='' class='btn btn-sm btn-danger mb-2' type='button'>{{ 'Unbind'|trans }}</button>
<div class='input-group mb-3'>
<div class='input-group-prepend'>
<span class='input-group-text'>{{ 'Search'|trans }}</span>
</div>
<input type='text' data-complete-target='experiments' data-identifier='binddivexp' class='form-control bindInput' aria-labelledby='bindExpInputLabel' />
<div class='input-group-append'>
<button class='btn btn-primary' data-input='bindexpinput' data-action='scheduler-bind-entity' data-type='experiment' type='button'>{{ 'Attach'|trans }}</button>
</div>
</div>
<div id='autocompleteAnchorDiv_binddivexp'></div>
</div>
{# BIND ITEM #}
<div class='mt-2'>
<i class='fas fa-link mr-1'></i><h5 class='d-inline' id='bindItemInputLabel'>{{ 'Bind a resource'|trans }}</h5>
<div id='eventBoundDb'></div>
<button data-action='scheduler-rm-bind' data-type='item_link' data-eventid='' class='btn btn-sm btn-danger mb-2' type='button'>{{ 'Unbind'|trans }}</button>
<div class='input-group mb-3'>
<div class='input-group-prepend'>
<span class='input-group-text'>{{ 'Search'|trans }}</span>
</div>
<input type='text' data-complete-target='items' data-identifier='binddivdb' class='form-control bindInput' aria-labelledby='bindItemInputLabel' />
<div class='input-group-append'>
<button class='btn btn-primary' data-input='binddbinput' data-action='scheduler-bind-entity' data-type='item_link' type='button'>{{ 'Attach'|trans }}</button>
</div>
</div>
<div id='autocompleteAnchorDiv_binddivdb'></div>
</div>
{# only show the cancel block if item is cancellable or user is admin #}
{% if bookableItemData.book_is_cancellable == 1 or App.Users.isAdmin %}
<div>
<h5>{{ 'Cancel booking slot'|trans }}</h5>
<h6><label for='cancelEventTextarea'>{{ 'Add a custom message'|trans }}</label></h6>
<textarea id='cancelEventTextarea' class='form-control'></textarea>
<label>{{ 'Send to'|trans }}</label>
<div class='form-check'>
<input class='form-check-input' type='radio' name='targetCancelEvent' data-targetid='{{ App.Request.query.get('item') }}' value='bookable_item' id='targetCancelEventUsers' checked> <label class='form-check-label' for='targetCancelEventUsers'>{{ 'Past and future users who booked this resource'|trans }}</label>
</div>
<div class='form-check'>
<input class='form-check-input' type='radio' name='targetCancelEvent' data-targetid='{{ App.teamArr.id }}' value='team' id='targetCancelEventTeam'> <label class='form-check-label' for='targetCancelEventTeam'>{{ 'Members of team %s'|trans|format(App.teamArr.name) }}</label>
</div>
{% for teamgroup in teamGroupsArr %}
<div class='form-check'>
<input class='form-check-input' type='radio' name='targetCancelEvent' data-targetid='{{ teamgroup.id }}' value='teamgroup' id='targetCancelEventTeamgroup_{{ teamgroup.id }}'> <label class='form-check-label' for='targetCancelEventTeamgroup_{{ teamgroup.id }}'>{{ 'Members of teamgroup %s'|trans|format(teamgroup.name) }}</label>
</div>
{% endfor %}
<div class='mt-2'>
<button type='button' data-action='cancel-event-with-message' data-dismiss='modal' data-id='' class='btn btn-danger cancelEventBtn'>{{ 'Send message and cancel'|trans }}</button>
<button type='button' data-action='cancel-event' data-dismiss='modal' data-id='' class='btn btn-danger cancelEventBtn'>{{ 'Cancel'|trans }}</button>
</div>
</div>
{% endif %}
</div>
<div class='modal-footer'>
<button type='button' class='btn btn-secondary' data-dismiss='modal'>{{ 'Close'|trans }}</button>
</div>
</div>
</div>
</div>
{# TAB 1 SCHEDULER #}
<div data-tabcontent='1' hidden>
<div class='d-flex mb-2'>
<div id='selectBookableWarningDiv' hidden>{{ 'Select a resource below in order to book it.'|trans }}</div>
<div class='ml-auto'>
{% include 'scope-button.html' with {'reload': 'page', 'target': 'scope_items'} %}
</div>
</div>
<div id='mainSchedulerContent'>
{% if itemsArr|length == 0 %}
{{ 'No bookable items.'|trans|msg('warning', false) }}
{% else %}
<div class='row mb-3'>
<div class='col-md-3'>
{# CATEGORY #}
<form aria-label='{{ 'Filter by category'|trans }}'>
{% if App.Config.configArr.debug -%}
<!-- [html-validate-disable-block input-missing-label, prefer-native-element, no-unused-disable: suppress errors from tom-select] -->
{%- endif %}
<select
aria-label='{{ 'Filter by category'|trans }}'
class='autosubmit mr-1 form-control'
id='schedulerSelectCat'
name='cat'
>
<option value=''>{{ 'Filter by category'|trans }}</option>
{% for category in bookableItemsTypes %}
<option value='{{ category.id }}'{{ App.Request.query.get('cat') == category.id ? ' selected' }}>
{{ category.title }}
</option>
{% endfor %}
</select>
</form>
</div>
<div class='col-md-3'>
{# ITEM LIST #}
<form aria-label='{{ 'Select a resource'|trans }}'>
{% if App.Config.configArr.debug -%}
<!-- [html-validate-disable-block input-missing-label, prefer-native-element, no-unused-disable: suppress errors from tom-select] -->
{%- endif %}
<select
aria-label='{{ 'Select a resource'|trans }}'
class='autosubmit mr-1 form-control'
id='itemSelect'
name='item'
>
<option value=''>{{ 'Select a resource'|trans }}</option>
{% for item in itemsArr %}
{# data-color is used to set the background during initial drag #}
<option data-color='{{ item.category_color }}' value='{{ item.id }}'{{ App.Request.query.get('item') == item.id ? ' selected' }}>
{{ item.category_title }} - {{ item.title }}
</option>
{% endfor %}
</select>
</form>
</div>
{% if bookableItemData %}
<div class='col-md-3 ml-auto'>
<div class='input-group justify-content-end flex-nowrap'>
<div class='input-group-prepend'>
<button class='btn btn-secondary' type='button' data-action='remove-param-reload' data-target='item'>X</button>
</div>
<a href='database.php?mode=view&id={{ bookableItemData.id }}' class='list-group-item hl-hover-gray'><span style='--bg: #{{ bookableItemData.category_color }}' class='catstat-btn category-btn mr-2'>{{ bookableItemData.category_title }}</span>{{ bookableItemData.title }}</a>
</div>
</div>
{% endif %}
</div>
{% endif %}
</div>
<div id='scheduler' data-lang='{{ App.getJsLang }}' data-render={{ itemsArr|length > 0 ? 'true' : 'false' }}></div>
</div>
{# TAB 2 INFO #}
<div data-tabcontent='2' hidden>
<div class='alert alert-success'><i class='fas fa-info-circle fa-fw color-success'></i>
{{ 'You belong to the %s team.'|trans|format(teamArr.name) }}
{{ 'Members'|trans }}: {{ teamsStats.totusers }} – {% trans %}Experiment{% plural teamStats.totxp %}Experiments{% endtrans %}: {{ teamsStats.totxp }} ({{ teamsStats.totxpts }} timestamped) – {{ 'Resources'|trans }}: {{ teamsStats.totdb }}
</div>
<h3 class='p-2 pl-3 mb-3 section-title'>{{ 'Members'|trans }}</h3>
{% include 'filter-input-snippet.html' with {'target': 'teamTable'} %}
<table class='table' aria-describedby='pageTitle' data-table-sort='true'>
<thead>
<tr>
<th scope='col'>{{ 'Name'|trans }}</th>
<th scope='col'>{{ 'Email'|trans }}</th>
<th scope='col'>ORCID</th>
</tr>
</thead>
<tbody id='teamTable'>
{# archived users are hidden on this page #}
{% for user in App.Users.readAllFromTeam()|filter(u => u.archived == 0) %}
<tr>
<td>
<a href='experiments.php?owner={{ user.userid }}'>
<span>
{{ user.fullname }}
{% if user.usergroup in range(1, 3) %}
({{ 'Admin'|trans }})
{% endif %}
</span>
</a>
</td>
<td><a href='mailto:{{ user.email|e('html_attr') }}'>{{ user.email }}</a></td>
<td>{{ user.orcid }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{# TAB 3 TEMPLATE #}
<div data-tabcontent='3' hidden>
<h3 class='p-2 pl-3 section-title'>{{ 'Experiments Templates'|trans }}</h3>
<p class='mt-3'>All the experiments templates are now visible at one place: the <a href='/ucp.php?tab=3'>Settings</a>.</p>
</div>
{# TAB 4 EMAIL #}
<div data-tabcontent='4' hidden>
<h3 class='p-2 pl-3 mb-3 section-title'>{{ 'Send an email to users'|trans }}</h3>
<form class='pl-3' method='post' action='app/controllers/TeamController.php' aria-label='{{ 'Mass email form'|trans }}'>
{{ App.Session.get('csrf')|csrf }}
<input type='hidden' name='emailUsers' />
<label>{{ 'Send to'|trans }}</label>
<div class='form-check'>
<input class='form-check-input' type='radio' name='target' value='team' id='targetTeam' checked> <label class='form-check-label' for='targetTeam'>{{ 'Members of team %s'|trans|format(App.teamArr.name) }}</label>
</div>
{% for teamgroup in teamGroupsArr %}
<div class='form-check'>
<input class='form-check-input' type='radio' name='target' value='teamgroup_{{ teamgroup.id }}' id='targetTeamgroup_{{ teamgroup.id }}'> <label class='form-check-label' for='targetTeamgroup_{{ teamgroup.id }}'>{{ 'Members of teamgroup %s'|trans|format(teamgroup.name) }}</label>
</div>
{% endfor %}
<div class='form-group'>
<label for='emailSubject'>{{ 'Subject'|trans }}</label>
<input type='text' id='emailSubject' name='subject' class='form-control' required />
<label for='emailBody'>{{ 'Content'|trans }}</label>
<textarea id='emailBody' name='body' class='form-control' rows='10' required></textarea>
</div>
<div class='mt-4 text-center'>
<button type='submit' class='btn btn-primary'>{{ 'Send'|trans }}</button>
</div>
</form>
</div>
{# TAB 5 PROCUREMENT REQUESTS #}
<div data-tabcontent='5' hidden>
<h3 class='p-2 pl-3 section-title'>{{ 'Procurement requests'|trans }}</h3>
<div class='pl-3 my-2'>
{% if teamProcurementRequestsArr %}
{# DOWNLOAD as CSV #}
<div class='mb-4 d-flex flex-row-reverse'>
<a href='/api/v2/teams/current/procurement_requests?format=csv'><button type='button' class='btn btn-secondary'>{{ 'Download'|trans }} (.csv)</button></a>
</div>
{% include 'filter-input-snippet.html' with {'target': 'procurementRequestsTable'} %}
{# MAIN TABLE #}
<table class='table' aria-label='{{ 'Procurement requests'|trans }}' data-table-sort='true'>
<thead>
<tr>
<th scope='col'>{{ 'Resource'|trans }}</th>
<th scope='col'>{{ 'Requester'|trans }}</th>
<th scope='col'>{{ 'Ordered'|trans }}</th>
<th scope='col'>{{ 'Quantity ordered'|trans }}</th>
<th scope='col'>{{ 'Total'|trans }}</th>
<th scope='col'>{{ 'Quantity received'|trans }}</th>
<th scope='col'>{{ 'Comment'|trans }}</th>
<th scope='col'>{{ 'Quote'|trans }}</th>
<th scope='col'>{{ 'State'|trans }}</th>
<th scope='col'>{{ 'Actions'|trans }}</th>
</tr>
</thead>
{# this is the element to reload after a change, don't use the full div so we keep the js working in table headers #}
<tbody id='procurementRequestsTable'>
{% for req in teamProcurementRequestsArr %}
<tr>
<td class='no-wrap' data-label='{{ 'Resource'|trans }}'>
<a href='/database.php?mode=view&id={{ req.entity_id }}'>
<span class='hl-hover-gray p-2 mr-2 rounded'><i class='fas fa-eye'></i></span>
</a>{{ req.entity_title }}</td>
{# REQUESTER #}
<td data-label='{{ 'Requester'|trans }}'>{{ req.requester_fullname }}</td>
{# CREATED AT #}
<td data-label='{{ 'Ordered'|trans }}'><span title='{{ req.created_at }}' class='relative-moment text-nowrap'></span></td>
{# QTY ORDERED #}
<td data-label='{{ 'Quantity ordered'|trans }}'>{{ req.qty_ordered }}</td>
{# TOTAL #}
<td data-label='{{ 'Total'|trans }}'>{{ req.total }} {{ req.symbol }}</td>
<td data-label='{{ 'Quantity received'|trans }}'><span class='hl-hover-gray p-1 rounded malleableColumn' data-endpoint='teams/current/procurement_requests' data-target='qty_received' data-input-type='number' data-id='{{ req.id }}'>{{ req.qty_received }}</span></td>
<td data-label='{{ 'Comment'|trans }}'><span class='hl-hover-gray p-1 rounded malleableColumn {{ not req.body ? 'font-italic' }}' data-endpoint='teams/current/procurement_requests' data-target='body' data-id='{{ req.id }}'>{{ req.body|default('unset'|trans) }}</span></td>
<td data-label='{{ 'Quote'|trans }}'>
<a target='_blank' href='/api/v2/uploads/{{ req.quote }}?format=binary'>
<span class='hl-hover-gray p-1 mr-2 rounded'>{{ req.quote ? "<i class='fas fa-download'></i>" }}</span>
</a>
</td>
<td data-label='{{ 'State'|trans }}'><span class='hl-hover-gray p-1 rounded malleableState' data-id='{{ req.id }}'>{{ req.state_human }}</span></td>
<td data-label='{{ 'Actions'|trans }}'>
<button class='btn hl-hover-gray p-1 rounded hover-danger lh-normal' title='{{ 'Cancel order'|trans }}' data-action='cancel-procurement-request' aria-label='{{ 'Cancel order'|trans }}' type='button' data-id='{{ req.id }}'>
<i class='fas fa-trash-alt'></i>
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %} {# no requests #}
{# TODO add documentation link #}
<p>{{ 'No procurement requests have been made yet.'|trans }}</p>
{% endif %}
</div>
</div>
{% endblock body %}