5b544ceed2
* Add is_present field for csv import of users. * Refactor JS functions get_full_name and get_short_name (Fixes #2136). - Show participant number in get_full_name() output. - Sort users by first or last name. - Extend config option to sort users. - Mark unused Python methods get_short_name and get_full_name.
227 lines
9.5 KiB
HTML
227 lines
9.5 KiB
HTML
<div class="header">
|
|
<div class="title">
|
|
<div class="submenu">
|
|
<a ui-sref="users.user.list" class="btn btn-sm btn-default">
|
|
<i class="fa fa-angle-double-left fa-lg"></i>
|
|
<translate>Back to overview</translate>
|
|
</a>
|
|
</div>
|
|
<h1 translate>Import participants</h1>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="details">
|
|
<h2 translate>Import by copy/paste</h2>
|
|
<p translate>Copy and paste your participant names in this textbox.
|
|
Keep each person in a single line.</p>
|
|
|
|
<div class="row">
|
|
<div class="form-group col-sm-6">
|
|
<textarea ng-model="userlist" rows="5" class="form-control" ng-list="/\n/"></textarea>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="clearfix">
|
|
<button ng-click="importByLine()" class="btn btn-primary pull-left" translate>Import</button>
|
|
<div class="col-xs-5" ng-if="usernames">
|
|
<progressbar animate="false" type="success" max="usernames.length" value="importcounter">
|
|
<i>{{ importcounter }} / {{ usernames.length }} {{ "imported" | translate }}</i>
|
|
</progressbar>
|
|
</div>
|
|
</div>
|
|
<div class="spacer">
|
|
<a ng-if="importcounter > 0 && importcounter == usernames.length" ui-sref="users.user.list"
|
|
class="btn btn-default">
|
|
<i class="fa fa-angle-double-left fa-lg"></i>
|
|
<translate>Back to users overview</translate>
|
|
</a>
|
|
</div>
|
|
|
|
<hr>
|
|
|
|
<h2 translate>Import by CSV file</h2>
|
|
|
|
<div class="block row">
|
|
<div class="title">
|
|
<h3 translate>Select a CSV file
|
|
</div>
|
|
<div class="block right import">
|
|
<label class="label" for="inputSeparator" translate>Separator</label>
|
|
<input type="text" ng-model="separator" ng-change="setSeparator()" ng-init="separator=separator" id="inputSeparator">
|
|
<br>
|
|
<label class="label" for="selectEncoding" translate>Encoding</label>
|
|
<select ng-model="encoding" ng-options="enc as enc for enc in encodingOptions"
|
|
ng-selected="setEncoding()" ng-init="encoding=encoding" id="selectEncoding"></select>
|
|
<ng-csv-import
|
|
content="csv.content"
|
|
header="csv.header"
|
|
header-visible="csv.headerVisible"
|
|
separator="csv.separator"
|
|
separator-visible="csv.separatorVisible"
|
|
result="csv.result"
|
|
accept="csv.accept"
|
|
encoding="csv.encoding"
|
|
encoding-visible="csv.encodingVisible"></ng-csv-import>
|
|
</div>
|
|
</div>
|
|
|
|
<h4 translate>Please note:</h4>
|
|
<ul class="indentation">
|
|
<li><translate>Required comma or semicolon separated values with these column header names in the first row</translate>:<br>
|
|
<code>title, first_name, last_name, structure_level, number, groups, comment, is_active, is_present, is_committee</code>
|
|
<li><translate>Default groups</translate>:
|
|
<translate>Delegates</translate> <code>2</code>,
|
|
<translate>Staff</translate> <code>3</code>
|
|
<translate>Committees</translate> <code>4</code>
|
|
<li translate>At least first name or last name have to be filled in. All
|
|
other fields are optional and may be empty.
|
|
<li translate>Only double quotes are accepted as text delimiter (no single quotes).
|
|
<li><a id="downloadLink" href="" ng-click="downloadCSVExample()" translate>Download CSV example file</a>
|
|
</ul>
|
|
|
|
<div ng-show="csv.result">
|
|
<h3 translate>Preview</h3>
|
|
<table class="table table-striped table-bordered table-condensed">
|
|
<thead>
|
|
<tr>
|
|
<th>
|
|
<th>#
|
|
<th translate>Title
|
|
<th translate>First name
|
|
<th translate>Last name
|
|
<th translate>Structure level
|
|
<th translate>Participant number
|
|
<th translate>Groups
|
|
<th translate>Comment
|
|
<th translate>Is active
|
|
<th translate>Is present
|
|
<th translate>Is committee</th>
|
|
<th ng-if="duplicates > 0">
|
|
<i class="fa fa-exclamation-triangle text-danger"></i>
|
|
<strong class="text-danger" ng-if="duplicates == 1">1 <translate>duplicate</translate></strong>
|
|
<strong class="text-danger" ng-if="duplicates > 1">{{ duplicates }} <translate>duplicates</translate></strong>
|
|
|
|
<div uib-dropdown>
|
|
<button type="button" class="btn btn-default btn-danger btn-sm" uib-dropdown-toggle>
|
|
<translate>Set global action</translate>
|
|
<span class="caret"></span>
|
|
</button>
|
|
<ul class="dropdown-menu dropdown-entries">
|
|
<li role="menuitem" ng-repeat="action in duplicateActions" class="pointer"
|
|
ng-click="setGlobalAction(action)">
|
|
{{ action | translate }}
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</th>
|
|
<tbody>
|
|
<tr ng-repeat="user in users | limitTo : itemsPerPage : limitBegin">
|
|
<td class="minimum"
|
|
ng-class="{ 'text-danger': (user.importerror || user.duplicateAction == duplicateActions[0]), 'text-success': user.imported }">
|
|
<span ng-if="user.importerror || user.duplicateAction == duplicateActions[0]">
|
|
<i class="fa fa-exclamation-triangle fa-lg"></i>
|
|
</span>
|
|
<span ng-if="!user.importerror && !user.imported && user.duplicateAction != duplicateActions[0]">
|
|
<i class="fa fa-check-circle-o fa-lg"></i>
|
|
</span>
|
|
<span ng-if="user.imported">
|
|
<i class="fa fa-check-circle fa-lg"></i>
|
|
</span>
|
|
<td>
|
|
{{ (currentPage - 1) * itemsPerPage + $index + 1 }}
|
|
<td>
|
|
{{ user.title }}
|
|
<td ng-class="{ 'text-danger': user.name_error }">
|
|
<span ng-if="!user.first_name && user.name_error" title="{{ user.name_error | translate }}">
|
|
<i class="fa fa-exclamation-triangle"></i>
|
|
</span>
|
|
{{ user.first_name }}
|
|
<td ng-class="{ 'text-danger': user.name_error }">
|
|
<span ng-if="!user.last_name && user.name_error" title="{{ user.name_error | translate }}">
|
|
<i class="fa fa-exclamation-triangle"></i>
|
|
</span>
|
|
{{ user.last_name }}
|
|
<td>
|
|
{{ user.structure_level }}
|
|
<td>
|
|
{{ user.number }}
|
|
<td>
|
|
<div ng-repeat="groupname in user.groupnames">
|
|
{{ groupname | translate }}
|
|
</div>
|
|
<td style="max-width: 130px;">
|
|
<span uib-tooltip="{{ user.comment }}">
|
|
{{ user.comment | limitTo: 30 }}{{ user.comment.length > 30 ? '...' : '' }}
|
|
</span>
|
|
<td>
|
|
<i class="fa pointer" ng-class="user.is_active ? 'fa-check-square-o' : 'fa-square-o'"
|
|
ng-click="user.is_active = !user.is_active"></i>
|
|
<td>
|
|
<i class="fa pointer" ng-class="user.is_present ? 'fa-check-square-o' : 'fa-square-o'"
|
|
ng-click="user.is_present = !user.is_present"></i>
|
|
<td>
|
|
<i class="fa pointer" ng-class="user.is_committee ? 'fa-check-square-o' : 'fa-square-o'"
|
|
ng-click="user.is_committee = !user.is_committee"></i>
|
|
<td ng-if="duplicates > 0">
|
|
<div ng-if="user.duplicate" uib-tooltip="{{ user.duplicate_info }}" uib-dropdown>
|
|
<button type="button" class="btn btn-default btn-sm"
|
|
uib-dropdown-toggle ng-class="user.duplicateAction == duplicateActions[0] ? 'btn-warning' : (user.duplicateAction == duplicateActions[1] ? 'btn-danger' : 'btn-success')">
|
|
{{ user.duplicateAction | translate }}
|
|
<span class="caret"></span>
|
|
</button>
|
|
<ul class="dropdown-menu dropdown-entries">
|
|
<li role="menuitem" ng-repeat="action in duplicateActions" class="pointer"
|
|
ng-click="user.duplicateAction = action; calcStats()">
|
|
<i class="fa fa-check" ng-if="user.duplicateAction == action"></i>
|
|
{{ action | translate }}
|
|
</li>
|
|
</ul>
|
|
</table>
|
|
<ul uib-pagination
|
|
ng-show="users.length > itemsPerPage"
|
|
total-items="users.length"
|
|
items-per-page="itemsPerPage"
|
|
ng-model="currentPage"
|
|
ng-change="pageChanged()"
|
|
class="pagination-sm"
|
|
direction-links="false"
|
|
boundary-links="true"
|
|
first-text="«"
|
|
last-text="»">
|
|
</ul>
|
|
|
|
<div class="text-danger">
|
|
<i class="fa fa-exclamation-triangle"></i>
|
|
{{ usersWillNotBeImported }}
|
|
<translate>participants will be not imported.</translate>
|
|
</div>
|
|
<div>
|
|
<i class="fa fa-check-circle-o fa-lg"></i>
|
|
{{ usersWillBeImported }}
|
|
<translate>participants will be imported.</translate>
|
|
</div>
|
|
<div ng-repeat="user in usersImported = (users | filter:{imported:true})"></div>
|
|
<div ng-if="usersImported.length > 0" class="text-success">
|
|
<hr class="smallhr">
|
|
<i class="fa fa-check-circle fa-lg"></i>
|
|
{{ usersImported.length }}
|
|
<translate>participants were successfully imported.</translate>
|
|
</div>
|
|
|
|
<div class="spacer">
|
|
<button ng-click="clear()" class="btn btn-default" translate>
|
|
Clear preview
|
|
</button>
|
|
<button ng-if="!csvImporting" ng-click="import()" class="btn btn-primary" translate>
|
|
Import {{ usersWillBeImported }} participants
|
|
</button>
|
|
</div>
|
|
<div class="spacer">
|
|
<a ng-if="csvimported" ui-sref="users.user.list" class="btn btn-default">
|
|
<i class="fa fa-angle-double-left fa-lg"></i>
|
|
<translate>Back to users overview</translate>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|