Merge pull request #2688 from FinnStutzenstein/AssignmentsTable
New assignment and mediafile tables and table generics
This commit is contained in:
commit
17c464bafa
@ -259,8 +259,11 @@ angular.module('OpenSlidesApp.assignments.site', [
|
|||||||
'AssignmentCatalogContentProvider',
|
'AssignmentCatalogContentProvider',
|
||||||
'PdfMakeDocumentProvider',
|
'PdfMakeDocumentProvider',
|
||||||
'User',
|
'User',
|
||||||
|
'osTableFilter',
|
||||||
|
'osTableSort',
|
||||||
function($scope, ngDialog, AssignmentForm, Assignment, Tag, Agenda, phases, Projector, ProjectionDefault,
|
function($scope, ngDialog, AssignmentForm, Assignment, Tag, Agenda, phases, Projector, ProjectionDefault,
|
||||||
gettextCatalog, AssignmentContentProvider, AssignmentCatalogContentProvider, PdfMakeDocumentProvider, User) {
|
gettextCatalog, AssignmentContentProvider, AssignmentCatalogContentProvider, PdfMakeDocumentProvider,
|
||||||
|
User, osTableFilter, osTableSort) {
|
||||||
Assignment.bindAll({}, $scope, 'assignments');
|
Assignment.bindAll({}, $scope, 'assignments');
|
||||||
Tag.bindAll({}, $scope, 'tags');
|
Tag.bindAll({}, $scope, 'tags');
|
||||||
$scope.$watch(function () {
|
$scope.$watch(function () {
|
||||||
@ -274,72 +277,76 @@ angular.module('OpenSlidesApp.assignments.site', [
|
|||||||
$scope.phases = phases;
|
$scope.phases = phases;
|
||||||
$scope.alert = {};
|
$scope.alert = {};
|
||||||
|
|
||||||
// setup table sorting
|
// Filtering
|
||||||
$scope.sortColumn = 'title';
|
$scope.filter = osTableFilter.createInstance();
|
||||||
$scope.filterPresent = '';
|
$scope.filter.multiselectFilters = {
|
||||||
$scope.reverse = false;
|
tag: [],
|
||||||
// function to sort by clicked column
|
phase: [],
|
||||||
$scope.toggleSort = function (column) {
|
};
|
||||||
if ( $scope.sortColumn === column ) {
|
$scope.filter.propertyList = ['title', 'description'];
|
||||||
$scope.reverse = !$scope.reverse;
|
$scope.filter.propertyFunctionList = [
|
||||||
|
function (assignment) {
|
||||||
|
return gettextCatalog.getString($scope.phases[assignment.phase].display_name);
|
||||||
|
},
|
||||||
|
];
|
||||||
|
$scope.filter.propertyDict = {
|
||||||
|
'assignment_related_users': function (candidate) {
|
||||||
|
return candidate.user.get_short_name();
|
||||||
|
},
|
||||||
|
'tags': function (tag) {
|
||||||
|
return tag.name;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
$scope.getItemId = {
|
||||||
|
tag: function (assignment) {return assignment.tags_id;},
|
||||||
|
phase: function (assignment) {return assignment.phase;},
|
||||||
|
};
|
||||||
|
// Sorting
|
||||||
|
$scope.sort = osTableSort.createInstance();
|
||||||
|
$scope.sort.column = 'title';
|
||||||
|
$scope.sortOptions = [
|
||||||
|
{name: 'agenda_item.getItemNumberWithAncestors()',
|
||||||
|
display_name: 'Item'},
|
||||||
|
{name: 'title',
|
||||||
|
display_name: 'Title'},
|
||||||
|
{name: 'open_posts',
|
||||||
|
display_name: 'Open posts'},
|
||||||
|
{name: 'phase',
|
||||||
|
display_name: 'Phase'},
|
||||||
|
];
|
||||||
|
$scope.hasTag = function (assignment, tag) {
|
||||||
|
return _.indexOf(assignment.tags_id, tag.id) > -1;
|
||||||
|
};
|
||||||
|
$scope.toggleTag = function (assignment, tag) {
|
||||||
|
if ($scope.hasTag(assignment, tag)) {
|
||||||
|
assignment.tags_id = _.filter(assignment.tags_id, function (tag_id){
|
||||||
|
return tag_id != tag.id;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
assignment.tags_id.push(tag.id);
|
||||||
}
|
}
|
||||||
$scope.sortColumn = column;
|
Assignment.save(assignment);
|
||||||
};
|
};
|
||||||
// define custom search filter string
|
// update phase
|
||||||
$scope.getFilterString = function (assignment) {
|
$scope.updatePhase = function (assignment, phase_id) {
|
||||||
return [
|
assignment.phase = phase_id;
|
||||||
assignment.title,
|
Assignment.save(assignment);
|
||||||
assignment.description,
|
|
||||||
$scope.phases[assignment.phase].display_name,
|
|
||||||
_.map(assignment.assignment_related_users,
|
|
||||||
function (candidate) {
|
|
||||||
return candidate.user.get_short_name();
|
|
||||||
}
|
|
||||||
).join(" "),
|
|
||||||
_.map(assignment.tags,
|
|
||||||
function (tag) {
|
|
||||||
return tag.name;
|
|
||||||
}
|
|
||||||
).join(" "),
|
|
||||||
].join(" ");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// open new/edit dialog
|
// open new/edit dialog
|
||||||
$scope.openDialog = function (assignment) {
|
$scope.openDialog = function (assignment) {
|
||||||
ngDialog.open(AssignmentForm.getDialog(assignment));
|
ngDialog.open(AssignmentForm.getDialog(assignment));
|
||||||
};
|
};
|
||||||
// cancel QuickEdit mode
|
// *** select mode functions ***
|
||||||
$scope.cancelQuickEdit = function (assignment) {
|
$scope.isSelectMode = false;
|
||||||
// revert all changes by restore (refresh) original assignment object from server
|
|
||||||
Assignment.refresh(assignment);
|
|
||||||
assignment.quickEdit = false;
|
|
||||||
};
|
|
||||||
// save changed assignment
|
|
||||||
$scope.save = function (assignment) {
|
|
||||||
Assignment.save(assignment).then(
|
|
||||||
function(success) {
|
|
||||||
assignment.quickEdit = false;
|
|
||||||
$scope.alert.show = false;
|
|
||||||
},
|
|
||||||
function(error) {
|
|
||||||
var message = '';
|
|
||||||
for (var e in error.data) {
|
|
||||||
message += e + ': ' + error.data[e] + ' ';
|
|
||||||
}
|
|
||||||
$scope.alert = { type: 'danger', msg: message, show: true };
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// *** delete mode functions ***
|
|
||||||
$scope.isDeleteMode = false;
|
|
||||||
// check all checkboxes
|
// check all checkboxes
|
||||||
$scope.checkAll = function () {
|
$scope.checkAll = function () {
|
||||||
angular.forEach($scope.assignments, function (assignment) {
|
angular.forEach($scope.assignments, function (assignment) {
|
||||||
assignment.selected = $scope.selectedAll;
|
assignment.selected = $scope.selectedAll;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
// uncheck all checkboxes if isDeleteMode is closed
|
// uncheck all checkboxes if isSelectMode is closed
|
||||||
$scope.uncheckAll = function () {
|
$scope.uncheckAll = function () {
|
||||||
if (!$scope.isDeleteMode) {
|
if (!$scope.isSelectMode) {
|
||||||
$scope.selectedAll = false;
|
$scope.selectedAll = false;
|
||||||
angular.forEach($scope.assignments, function (assignment) {
|
angular.forEach($scope.assignments, function (assignment) {
|
||||||
assignment.selected = false;
|
assignment.selected = false;
|
||||||
@ -352,7 +359,7 @@ angular.module('OpenSlidesApp.assignments.site', [
|
|||||||
if (assignment.selected)
|
if (assignment.selected)
|
||||||
Assignment.destroy(assignment.id);
|
Assignment.destroy(assignment.id);
|
||||||
});
|
});
|
||||||
$scope.isDeleteMode = false;
|
$scope.isSelectMode = false;
|
||||||
$scope.uncheckAll();
|
$scope.uncheckAll();
|
||||||
};
|
};
|
||||||
// delete single assignment
|
// delete single assignment
|
||||||
|
@ -9,10 +9,6 @@
|
|||||||
<i class="fa fa-tags fa-lg"></i>
|
<i class="fa fa-tags fa-lg"></i>
|
||||||
<translate>Tags</translate>
|
<translate>Tags</translate>
|
||||||
</a>
|
</a>
|
||||||
<a href="" ng-click="makePDF_assignmentList()" class="btn btn-default btn-sm">
|
|
||||||
<i class="fa fa-file-pdf-o fa-lg"></i>
|
|
||||||
<translate>PDF</translate>
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
<h1 translate>Elections</h1>
|
<h1 translate>Elections</h1>
|
||||||
</div>
|
</div>
|
||||||
@ -20,31 +16,35 @@
|
|||||||
|
|
||||||
<div class="details">
|
<div class="details">
|
||||||
<div class="row form-group">
|
<div class="row form-group">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-12">
|
||||||
<form class="form-inline">
|
<!-- delete mode -->
|
||||||
<!-- delete mode -->
|
<button os-perms="assignments.can_manage" class="btn"
|
||||||
<button os-perms="assignments.can_manage" class="btn"
|
ng-class="$parent.isSelectMode ? 'btn-primary' : 'btn-default'"
|
||||||
ng-class="$parent.isDeleteMode ? 'btn-primary' : 'btn-default'"
|
ng-click="$parent.isSelectMode = !$parent.isSelectMode; uncheckAll()">
|
||||||
ng-click="$parent.isDeleteMode = !$parent.isDeleteMode; uncheckAll()">
|
<i class="fa fa-check-square-o"></i>
|
||||||
<i class="fa fa-check-square-o"></i>
|
<translate>Select ...</translate>
|
||||||
<translate>Select ...</translate>
|
</button>
|
||||||
</button>
|
<!-- export dropdown -->
|
||||||
</form>
|
<div class="dropdown pull-right" uib-dropdown>
|
||||||
</div>
|
<button type="button" class="btn btn-default" id="dropdownExport" uib-dropdown-toggle>
|
||||||
<div class="col-sm-6">
|
<i class="fa fa-upload"></i>
|
||||||
<div class="form-inline text-right">
|
<span ng-if="assignmentsFiltered.length == assignments.length" translate>
|
||||||
<div class="form-group">
|
Export all
|
||||||
<div class="input-group">
|
</span>
|
||||||
<div class="input-group-addon"><i class="fa fa-search"></i></div>
|
<span ng-if="assignmentsFiltered.length != assignments.length" translate>
|
||||||
<input type="text" ng-model="filter.search" class="form-control"
|
Export filtered
|
||||||
placeholder="{{ 'Search' | translate}}">
|
</span>
|
||||||
</div>
|
<span class="caret"></span>
|
||||||
</div>
|
|
||||||
<button class="btn btn-default" ng-click="isFilterOpen = !isFilterOpen"
|
|
||||||
ng-class="isFilterOpen ? 'btn-primary' : 'btn-default'">
|
|
||||||
<i class="fa fa-filter"></i>
|
|
||||||
<translate>Filter ...</translate>
|
|
||||||
</button>
|
</button>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownExport">
|
||||||
|
<!-- PDF export -->
|
||||||
|
<li>
|
||||||
|
<a href="" ng-click="makePDF_assignmentList()">
|
||||||
|
<i class="fa fa-file-pdf-o fa-lg"></i>
|
||||||
|
<translate>PDF</translate>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -58,10 +58,10 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div uib-collapse="!isDeleteMode" class="row spacer">
|
<div uib-collapse="!isSelectMode" class="row spacer">
|
||||||
<div class="col-sm-12 text-left">
|
<div class="col-sm-12 text-left">
|
||||||
<!-- delete button -->
|
<!-- delete button -->
|
||||||
<a ng-show="isDeleteMode" os-perms="assignments.can_manage"
|
<a ng-show="isSelectMode" os-perms="assignments.can_manage"
|
||||||
ng-bootbox-confirm="{{ 'Are you sure you want to delete all selected elections?' | translate }}"
|
ng-bootbox-confirm="{{ 'Are you sure you want to delete all selected elections?' | translate }}"
|
||||||
ng-bootbox-confirm-action="deleteMultiple()"
|
ng-bootbox-confirm-action="deleteMultiple()"
|
||||||
class="btn btn-primary">
|
class="btn btn-primary">
|
||||||
@ -76,134 +76,247 @@
|
|||||||
{{ assignments.length }} {{ "elections" | translate }}<span ng-if="(assignments|filter:{selected:true}).length > 0">,
|
{{ assignments.length }} {{ "elections" | translate }}<span ng-if="(assignments|filter:{selected:true}).length > 0">,
|
||||||
{{(assignments|filter:{selected:true}).length}} {{ "selected" | translate }}</span>
|
{{(assignments|filter:{selected:true}).length}} {{ "selected" | translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
<table class="table table-striped table-bordered table-hover">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<!-- projector column -->
|
|
||||||
<th ng-show="!isDeleteMode" os-perms="core.can_manage_projector" class="minimum">
|
|
||||||
|
|
||||||
<!-- delete selection column -->
|
<div class="os-table container-fluid">
|
||||||
<th ng-show="isDeleteMode" os-perms="assignments.can_manage" class="minimum deleteColumn">
|
<div class="row header-row">
|
||||||
<input type="checkbox" ng-model="$parent.selectedAll" ng-change="checkAll()">
|
<div class="col-xs-1 centered" ng-show="isSelectMode">
|
||||||
|
<i class="fa text-danger pointer" ng-class=" selectedAll ? 'fa-check-square-o' : 'fa-square-o'"
|
||||||
<!-- agenda item column -->
|
ng-click="checkAll()"></i>
|
||||||
<th ng-click="toggleSort('agenda_item.item_number')" class="sortable">
|
</div>
|
||||||
<translate translate-comment="short form of agenda item">Item</translate>
|
<div class="col-xs-11 main-header">
|
||||||
<i class="pull-right fa" ng-show="sortColumn === 'agenda_item.item_number' && header.sortable != false"
|
<span class="form-inline text-right pull-right">
|
||||||
ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
|
<!-- clear all filters -->
|
||||||
</i>
|
<span class="sort-spacer pointer" ng-click="filter.reset()"
|
||||||
|
ng-if="filter.areFiltersSet()" ng-disabled="isSelectMode"
|
||||||
<!-- title column -->
|
ng-class="{'disabled': isSelectMode}">
|
||||||
<th ng-click="toggleSort('title')" class="sortable">
|
<i class="fa fa-times-circle"></i>
|
||||||
<translate>Title</translate>
|
<translate>Filter</translate>
|
||||||
<i class="pull-right fa" ng-show="sortColumn === 'title' && header.sortable != false"
|
|
||||||
ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
|
|
||||||
</i>
|
|
||||||
|
|
||||||
<!-- candicates / posts column -->
|
|
||||||
<th ng-click="toggleSort('open_posts')" class="sortable optional">
|
|
||||||
<translate>Candidates</translate> · <translate>Posts</translate>
|
|
||||||
<i class="pull-right fa" ng-show="sortColumn === 'open_posts' && header.sortable != false"
|
|
||||||
ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
|
|
||||||
</i>
|
|
||||||
|
|
||||||
<!-- phase column -->
|
|
||||||
<th ng-click="toggleSort('phase')" class="sortable optional">
|
|
||||||
<translate>Phase</translate>
|
|
||||||
<i class="pull-right fa" ng-show="sortColumn === 'phase' && header.sortable != false"
|
|
||||||
ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
|
|
||||||
</i>
|
|
||||||
<tbody>
|
|
||||||
<tr ng-repeat="assignment in assignmentsFiltered = (assignments | osFilter: filter.search : getFilterString |
|
|
||||||
filter: {phase: phaseFilter} | orderBy: sortColumn:reverse)"
|
|
||||||
class="animate-item"
|
|
||||||
ng-class="{ 'activeline': assignment.isProjected().length, 'selected': assignment.selected }">
|
|
||||||
|
|
||||||
<!-- projector -->
|
|
||||||
<td ng-show="!isDeleteMode" os-perms="core.can_manage_projector">
|
|
||||||
<projector-button model="assignment" default-projector-id="defaultProjectorId">
|
|
||||||
</projector-button>
|
|
||||||
|
|
||||||
<!-- delete selection -->
|
|
||||||
<td ng-show="isDeleteMode" os-perms="assignments.can_manage" class="deleteColumn">
|
|
||||||
<input type="checkbox" ng-model="assignment.selected">
|
|
||||||
|
|
||||||
<!-- agenda item number -->
|
|
||||||
<td ng-if="!assignment.quickEdit">
|
|
||||||
{{ assignment.agenda_item.item_number }}
|
|
||||||
|
|
||||||
<!-- title -->
|
|
||||||
<td ng-if="!assignment.quickEdit" ng-mouseover="assignment.hover=true" ng-mouseleave="assignment.hover=false">
|
|
||||||
<strong><a ui-sref="assignments.assignment.detail({id: assignment.id})">{{ assignment.title }}</a></strong>
|
|
||||||
<span ng-repeat="tag in assignment.tags" class="label label-default">
|
|
||||||
{{ tag.name }}
|
|
||||||
</span>
|
</span>
|
||||||
<div os-perms="assignments.can_manage" class="hoverActions" ng-class="{'hiddenDiv': !assignment.hover}">
|
<!-- Tag filter -->
|
||||||
<a href="" ng-click="openDialog(assignment)" translate>Edit</a> |
|
<span uib-dropdown ng-if="tags.length > 0">
|
||||||
<a href="" ng-click="assignment.quickEdit=true" translate>QuickEdit</a> |
|
<span class="pointer" id="dropdownTag" uib-dropdown-toggle
|
||||||
<a href="" class="text-danger"
|
ng-class="{'bold': filter.multiselectFilters.tag.length > 0, 'disabled': isSelectMode}"
|
||||||
|
ng-disabled="isSelectMode">
|
||||||
|
<translate>Tag</translate>
|
||||||
|
<span class="caret"></span>
|
||||||
|
</span>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-right"
|
||||||
|
aria-labelledby="dropdownTag">
|
||||||
|
<li ng-repeat="tag in tags">
|
||||||
|
<a href ng-click="filter.operateMultiselectFilter('tag', tag.id, isSelectMode)">
|
||||||
|
<i class="fa fa-check" ng-if="filter.MultiselectFilters.tag.indexOf(tag.id) > -1"></i>
|
||||||
|
{{ tag.name }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="divider"></li>
|
||||||
|
<li>
|
||||||
|
<a href ng-click="filter.operateMultiselectFilter('tag', -1, isSelectMode)">
|
||||||
|
<i class="fa fa-check" ng-if="filter.multiselectFilters.tag.indexOf(-1) > -1"></i>
|
||||||
|
<translate>No tag set</translate>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</span>
|
||||||
|
<!-- Phase filter -->
|
||||||
|
<span uib-dropdown>
|
||||||
|
<span class="pointer" id="dropdownPhase" uib-dropdown-toggle
|
||||||
|
ng-class="{'bold': filter.multiselectFilters.phase.length > 0, 'disabled': isSelectMode}"
|
||||||
|
ng-disabled="isSelectMode">
|
||||||
|
<translate>Phase</translate>
|
||||||
|
<span class="caret"></span>
|
||||||
|
</span>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-right"
|
||||||
|
aria-labelledby="dropdownPhase">
|
||||||
|
<li ng-repeat="phase in phases">
|
||||||
|
<a href ng-click="filter.operateMultiselectFilter('phase', phase.value, isSelectMode)">
|
||||||
|
<i class="fa fa-check" ng-if="filter.multiselectFilters.phase.indexOf(phase.value) > -1"></i>
|
||||||
|
{{ phase.display_name | translate }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</span>
|
||||||
|
<!-- dropdown sort -->
|
||||||
|
<span uib-dropdown>
|
||||||
|
<span class="pointer" id="dropdownSort" uib-dropdown-toggle
|
||||||
|
ng-class="{'disabled': isSelectMode}"
|
||||||
|
ng-disabled="isSelectMode">
|
||||||
|
<translate>Sort</translate>
|
||||||
|
<span class="caret"></span>
|
||||||
|
</span>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownSort">
|
||||||
|
<!-- all sortOptions -->
|
||||||
|
<li ng-repeat="option in sortOptions">
|
||||||
|
<a ng-click="sort.toggle(option.name)">
|
||||||
|
{{ option.display_name | translate }}
|
||||||
|
<span class="spacer-right pull-right"></span>
|
||||||
|
<i class="pull-right fa"
|
||||||
|
ng-style="{'visibility': sort.column === option.name ? 'visible' : 'hidden'}"
|
||||||
|
ng-class="sort.reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
|
||||||
|
</i>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</span>
|
||||||
|
<!-- search field -->
|
||||||
|
<span class="form-group">
|
||||||
|
<span class="input-group">
|
||||||
|
<span class="input-group-addon"><i class="fa fa-search"></i></span>
|
||||||
|
<input type="text" ng-model="filter.filterString" class="form-control"
|
||||||
|
placeholder="{{ 'Search' | translate}}">
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
<!-- show all selected multiselectoptions -->
|
||||||
|
<span ng-repeat="tag in tags" class="pointer spacer-left-lg"
|
||||||
|
ng-if="filter.multiselectFilters.tag.indexOf(tag.id) > -1"
|
||||||
|
ng-click="filter.operateMultiselectFilter('tag', tag.id, isSelectMode)"
|
||||||
|
ng-class="{'disabled': isSelectMode}">
|
||||||
|
<span class="nobr">
|
||||||
|
<i class="fa fa-times-circle"></i>
|
||||||
|
{{ tag.name }}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span ng-if="filter.multiselectFilters.tag.indexOf(-1) > -1" class="pointer spacer-left-lg"
|
||||||
|
ng-click="filter.operateMultiselectFilter('tag', -1, isSelectMode)"
|
||||||
|
ng-class="{'disabled': isSelectMode}">
|
||||||
|
<i class="fa fa-times-circle"></i>
|
||||||
|
<translate>No tag set</translate>
|
||||||
|
</span>
|
||||||
|
<span ng-repeat="phase in phases" class="pointer spacer-left-lg"
|
||||||
|
ng-if="filter.multiselectFilters.phase.indexOf(phase.value) > -1"
|
||||||
|
ng-click="filter.operateMultiselectFilter('phase', phase.value, isSelectMode)"
|
||||||
|
ng-class="{'disabled': isSelectMode}">
|
||||||
|
<span class="nobr">
|
||||||
|
<i class="fa fa-times-circle"></i>
|
||||||
|
{{ phase.display_name | translate }}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- main table -->
|
||||||
|
<div class="row data-row" ng-mouseover="assignment.hover=true"
|
||||||
|
ng-mouseleave="assignment.hover=false"
|
||||||
|
ng-class="{'projected': assignment.isProjected().length}"
|
||||||
|
ng-repeat="assignment in assignmentsFiltered = (assignments
|
||||||
|
| osFilter: filter.filterString : filter.getObjectQueryString
|
||||||
|
| MultiselectFilter: filter.multiselectFilters.tag : getItemId.tag
|
||||||
|
| MultiselectFilter: filter.multiselectFilters.phase : getItemId.phase
|
||||||
|
| orderBy: sort.column : sort.reverse)">
|
||||||
|
|
||||||
|
<!-- select column -->
|
||||||
|
<div ng-show="isSelectMode" os-perms="assignments.can_manage" class="col-xs-1 centered">
|
||||||
|
<i class="fa text-danger pointer" ng-click="assignment.selected=!assignment.selected"
|
||||||
|
ng-class="assignment.selected ? 'fa-check-square-o' : 'fa-square-o'"></i>
|
||||||
|
</div>
|
||||||
|
<!-- projector column -->
|
||||||
|
<div class="col-xs-1 centered projector" os-perms="core.can_manage_projector">
|
||||||
|
<projector-button model="assignment", default-projector-id="defaultProjectorId">
|
||||||
|
</projector-button>
|
||||||
|
</div>
|
||||||
|
<!-- main contant column -->
|
||||||
|
<div class="col-xs-6 content">
|
||||||
|
<div class="title-col">
|
||||||
|
<!-- title and phase -->
|
||||||
|
<div>
|
||||||
|
<strong>
|
||||||
|
<a ui-sref="assignments.assignment.detail({id: assignment.id})">{{ assignment.title }}</a>
|
||||||
|
</strong>
|
||||||
|
<span style="padding: 5px;" ng-mouseover="assignment.phaseHover=true" ng-mouseleave="assignment.phaseHover=false">
|
||||||
|
<span class="label" ng-class="{'label-primary': assignment.phase == 0,
|
||||||
|
'label-warning': assignment.phase == 1,
|
||||||
|
'label-success': assignment.phase == 2 }">
|
||||||
|
{{ phases[assignment.phase].display_name | translate }}
|
||||||
|
</span>
|
||||||
|
<span os-perms="assignments.can_manage" ng-class="{'hiddenDiv': !assignment.phaseHover}" uib-dropdown>
|
||||||
|
<i class="fa fa-cog pointer" uib-dropdown-toggle id="phaseDropdown{{ assignment.id }}"></i>
|
||||||
|
<ul uib-dropdown-menu aria-labelledby="phaseDropdown{{ assignment.id }}"
|
||||||
|
class="dropdown-menu">
|
||||||
|
<li ng-repeat="phase in phases">
|
||||||
|
<a href>
|
||||||
|
<i class="fa fa-check" ng-if="assignment.phase == phase.value"></i>
|
||||||
|
<span class="pointer" ng-click="updatePhase(assignment, phase.value)">{{ phase.display_name | translate }}</a>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<!-- hover menu -->
|
||||||
|
<div os-perms="assignments.can_manage" ng-class="{'hiddenDiv': !assignment.hover}">
|
||||||
|
<small>
|
||||||
|
<a href="" ng-click="openDialog(assignment)" translate>Edit</a> ·
|
||||||
|
<a href="" class="text-danger"
|
||||||
ng-bootbox-confirm="{{ 'Are you sure you want to delete this entry?' | translate }}<br>
|
ng-bootbox-confirm="{{ 'Are you sure you want to delete this entry?' | translate }}<br>
|
||||||
<b>{{ assignment.title }}</b>"
|
<b>{{ assignment.title }}</b>"
|
||||||
ng-bootbox-confirm-action="delete(assignment)" translate>Delete</a>
|
ng-bootbox-confirm-action="delete(assignment)" translate>Delete</a>
|
||||||
|
</small>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- candidates / posts -->
|
<!-- additional content column -->
|
||||||
<td ng-if="!assignment.quickEdit" class="optional">
|
<div class="col-xs-4 content" ng-style="{'width': isSelectMode ? 'calc(50% - 120px)' : 'calc(50% - 70px)'}">
|
||||||
<span class="badge">{{ assignment.assignment_related_users.length }}</span>
|
<div style="width: 60%;" class="optional">
|
||||||
/
|
<small>
|
||||||
<span class="badge">{{ assignment.open_posts }}</span>
|
<!-- Tag dropdown for manage user -->
|
||||||
|
<div os-perms="assignments.can_manage" ng-show="tags.length > 0"
|
||||||
|
ng-mouseover="assignment.tagHover=true"
|
||||||
|
ng-mouseleave="assignment.tagHover=false">
|
||||||
|
<span uib-dropdown>
|
||||||
|
<span id="dropdownTags{{ assignment.id }}" class="pointer"
|
||||||
|
uib-dropdown-toggle uib-tooltip="{{ 'Add a tag' | translate }}"
|
||||||
|
tooltip-class="nobr">
|
||||||
|
<span ng-if="assignment.tags.length == 0" ng-show="assignment.hover">
|
||||||
|
<i class="fa fa-tags"></i>
|
||||||
|
<i class="fa fa-plus"></i>
|
||||||
|
</span>
|
||||||
|
<span ng-if="assignment.tags.length > 0">
|
||||||
|
<i class="fa fa-tags"></i>
|
||||||
|
<span ng-repeat="tag in assignment.tags">
|
||||||
|
{{ tag.name }}<span ng-if="!$last">,</span>
|
||||||
|
</span>
|
||||||
|
<i class="fa fa-cog fa-lg spacer-left" ng-show="assignment.tagHover"></i>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="dropdownTags{{ assignment.id }}">
|
||||||
|
<li ng-repeat="tag in tags">
|
||||||
|
<a href ng-click="toggleTag(assignment, tag)">
|
||||||
|
<i class="fa fa-check" ng-if="hasTag(assignment, tag)"></i>
|
||||||
|
{{ tag.name }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<!-- Tag string for normal user -->
|
||||||
|
<div os-perms="!assignments.can_manage" ng-show="assignment.tags.length > 0">
|
||||||
|
<i class="fa fa-tags spacer-right"></i>
|
||||||
|
<span ng-repeat="tag in assignment.tags">
|
||||||
|
{{ tag.name }}<span ng-if="!$last">,</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- phase -->
|
<div style="width: 20%;" class="pull-right nobr optional centered">
|
||||||
<td ng-if="!assignment.quickEdit" class="optional">
|
<span class="badge"
|
||||||
<span class="label" ng-class="{'label-primary': assignment.phase == 0,
|
uib-tooltip="{{ assignment.assignment_related_users.length }} {{ 'Candidates' | translate }}
|
||||||
'label-warning': assignment.phase == 1,
|
{{ (assignment.open_posts - assignment.assignment_related_users.length) > 0 ? '(' + (assignment.open_posts - assignment.assignment_related_users.length) + ' ' + ('needed' | translate) + ')' : '' }}"
|
||||||
'label-success': assignment.phase == 2 }">
|
tooltip-class="nobr"
|
||||||
{{ phases[assignment.phase].display_name | translate }}
|
ng-class="{'badge-info': assignment.assignment_related_users.length < assignment.open_posts}">
|
||||||
|
{{ assignment.assignment_related_users.length }}
|
||||||
</span>
|
</span>
|
||||||
|
</div>
|
||||||
|
<div style="width: 20%;" class="pull-right nobr">
|
||||||
|
<div class="centered">{{ assignment.agenda_item.getItemNumberWithAncestors() }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div> <!-- main table -->
|
||||||
|
</div> <!-- end container -->
|
||||||
|
|
||||||
<!-- quickEdit columns -->
|
|
||||||
<td ng-if="assignment.quickEdit" colspan="4">
|
|
||||||
<h4>{{ assignment.title }} <span class="text-muted">– Quick Edit</span></h4>
|
|
||||||
<div uib-alert ng-show="alert.show" ng-class="'alert-' + (alert.type || 'warning')" ng-click="alert={}" close="alert={}">
|
|
||||||
{{ alert.msg }}
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-xs-6">
|
|
||||||
<label for="inputTitle" translate>Title</label>
|
|
||||||
<input type="text" ng-model="assignment.title" class="form-control input-sm" id="inputTitle">
|
|
||||||
</div>
|
|
||||||
<div class="col-xs-6">
|
|
||||||
<label for="inputPosts" translate>Number of members to be elected</label>
|
|
||||||
<input type="number" ng-model="assignment.open_posts" class="form-control input-sm" id="inputPosts">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-xs-6">
|
|
||||||
<label for="selectPhase" translate>Phase</label>
|
|
||||||
<select ng-options="phase.value as phase.display_name | translate for phase in phases"
|
|
||||||
ng-model="assignment.phase" class="form-control" id="selectPhase">
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-xs-6">
|
|
||||||
<label for="selectTags" translate>Tags</label>
|
|
||||||
<select multiple chosen
|
|
||||||
ng-model="assignment.tags_id"
|
|
||||||
ng-options="tag.id as tag.name for tag in tags"
|
|
||||||
search-contains="true"
|
|
||||||
id="selectTag"
|
|
||||||
class="form-control">
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="spacer">
|
|
||||||
<button ng-click="cancelQuickEdit(assignment)" class="btn btn-default pull-left" translate>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
<button ng-click="save(assignment)" class="btn btn-primary" translate>
|
|
||||||
Update
|
|
||||||
</button>
|
|
||||||
<a href="" ng-click="openDialog(assignment)"
|
|
||||||
class="pull-right" translate>Edit election ...</a>
|
|
||||||
</div>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -877,23 +877,6 @@ img {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Motion **/
|
/** Motion **/
|
||||||
#motion-os-table .identifier-col {
|
|
||||||
width: 50px;
|
|
||||||
min-height: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#motion-os-table .identifier-col > div {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#motion-os-table .title-col {
|
|
||||||
width: calc(100% - 50px);
|
|
||||||
}
|
|
||||||
|
|
||||||
#motion-os-table .title-col, .os-table small {
|
|
||||||
color: #555;
|
|
||||||
}
|
|
||||||
|
|
||||||
.motion-toolbar, .speakers-toolbar {
|
.motion-toolbar, .speakers-toolbar {
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
border-bottom: 1px solid #ddd;
|
border-bottom: 1px solid #ddd;
|
||||||
@ -913,6 +896,9 @@ img {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** OS-Table **/
|
/** OS-Table **/
|
||||||
|
.os-table small {
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
.os-table .row {
|
.os-table .row {
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
border-top: 0px;
|
border-top: 0px;
|
||||||
@ -926,6 +912,11 @@ img {
|
|||||||
padding: 10px 0px 10px 0px;
|
padding: 10px 0px 10px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.os-table .id-col {
|
||||||
|
width: 50px;
|
||||||
|
min-height: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
.os-table .header-row {
|
.os-table .header-row {
|
||||||
border-top: 1px solid #ddd;
|
border-top: 1px solid #ddd;
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
@ -973,17 +964,13 @@ img {
|
|||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.os-table .dropdown {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.os-table .header-row .dropdown > span, .os-table .sort-spacer {
|
.os-table .header-row .dropdown > span, .os-table .sort-spacer {
|
||||||
padding: 5px 10px 5px 10px;
|
padding: 5px 10px 5px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.os-table .title {
|
.os-table .title {
|
||||||
font-size: 115%;
|
font-size: 115%;
|
||||||
margin-right: 10px;
|
margin-right: 5px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
@ -1092,16 +1079,6 @@ img {
|
|||||||
margin-left: 0px !important;
|
margin-left: 0px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-entries {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-entries > li {
|
|
||||||
padding: 5px 10px 5px 10px;
|
|
||||||
width: 100%;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slimDropDown {
|
.slimDropDown {
|
||||||
padding-left: 4px !important;
|
padding-left: 4px !important;
|
||||||
padding-right: 4px !important;
|
padding-right: 4px !important;
|
||||||
@ -1560,6 +1537,8 @@ tr.selected td {
|
|||||||
|
|
||||||
#chatbox { width: 100%; top: 40px; }
|
#chatbox { width: 100%; top: 40px; }
|
||||||
|
|
||||||
|
.badge { font-size: 10px; }
|
||||||
|
|
||||||
/* show replacement elements, if any */
|
/* show replacement elements, if any */
|
||||||
.optional-show { display: block !important; }
|
.optional-show { display: block !important; }
|
||||||
|
|
||||||
|
@ -796,19 +796,6 @@ angular.module('OpenSlidesApp.core', [
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
.filter('osFilter', [
|
|
||||||
function () {
|
|
||||||
return function (array, string, getFilterString) {
|
|
||||||
if (!string) {
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
return Array.prototype.filter.call(array, function (item) {
|
|
||||||
return getFilterString(item).toLowerCase().indexOf(string.toLowerCase()) > -1;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
])
|
|
||||||
|
|
||||||
// mark HTML as "trusted"
|
// mark HTML as "trusted"
|
||||||
.filter('trusted', [
|
.filter('trusted', [
|
||||||
'$sce',
|
'$sce',
|
||||||
@ -838,7 +825,6 @@ angular.module('OpenSlidesApp.core', [
|
|||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
// Make sure that the DS factories are loaded by making them a dependency
|
// Make sure that the DS factories are loaded by making them a dependency
|
||||||
.run([
|
.run([
|
||||||
'ChatMessage',
|
'ChatMessage',
|
||||||
|
@ -342,61 +342,107 @@ angular.module('OpenSlidesApp.core.site', [
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
.factory('Multiselect', [
|
/* This factory handles the filtering of the OS-data-tables. It contains
|
||||||
|
* all logic needed for the table header filtering. Things to configure:
|
||||||
|
* - multiselectFilters: A dict associating the filter name to a list (empty per default). E.g.
|
||||||
|
* { tag: [],
|
||||||
|
* category: [], }
|
||||||
|
* - booleanFilters: A dict containing a dict for every filter. The value property is a must.
|
||||||
|
* For displaying properties like displayName, choiceYes and choiceNo could be usefull. E.g.
|
||||||
|
* { isPresent: {
|
||||||
|
* value: undefined,
|
||||||
|
* displayName: gettext('Is present'), } }
|
||||||
|
* - propertyList, propertyFunctionList, propertyDict: See function getObjectQueryString
|
||||||
|
*/
|
||||||
|
.factory('osTableFilter', [
|
||||||
function () {
|
function () {
|
||||||
var instance = function () {
|
var createInstance = function () {
|
||||||
var areFiltersSet = function () {
|
var self = {
|
||||||
var areFiltersSet = false;
|
multiselectFilters: {},
|
||||||
_.forEach(self.filters, function (filterList, filter) {
|
booleanFilters: {},
|
||||||
if (filterList.length > 0) {
|
filterString: '',
|
||||||
areFiltersSet = true;
|
};
|
||||||
|
self.areFiltersSet = function () {
|
||||||
|
var areFiltersSet = _.find(self.multiselectFilters, function (filterList) {
|
||||||
|
return filterList.length > 0;
|
||||||
|
});
|
||||||
|
areFiltersSet = areFiltersSet || _.find(self.booleanFilters, function (filterDict) {
|
||||||
|
return filterDict.value !== undefined;
|
||||||
|
});
|
||||||
|
areFiltersSet = areFiltersSet || (self.filterString !== '');
|
||||||
|
return areFiltersSet !== false;
|
||||||
|
};
|
||||||
|
self.reset = function () {
|
||||||
|
_.forEach(self.multiselectFilters, function (filterList, filter) {
|
||||||
|
self.multiselectFilters[filter] = [];
|
||||||
|
});
|
||||||
|
_.forEach(self.booleanFilters, function (filterDict, filter) {
|
||||||
|
self.booleanFilters[filter].value = undefined;
|
||||||
|
});
|
||||||
|
self.filterString = '';
|
||||||
|
};
|
||||||
|
self.operateMultiselectFilter = function (filter, id, danger) {
|
||||||
|
if (!danger) {
|
||||||
|
if (_.indexOf(self.multiselectFilters[filter], id) > -1) {
|
||||||
|
// remove id
|
||||||
|
self.multiselectFilters[filter].splice(_.indexOf(self.multiselectFilters[filter], id), 1);
|
||||||
|
} else {
|
||||||
|
// add id
|
||||||
|
self.multiselectFilters[filter].push(id);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
return areFiltersSet;
|
|
||||||
};
|
|
||||||
var resetFilters = function () {
|
|
||||||
_.forEach(self.filters, function (filterList, filter) {
|
|
||||||
self.filters[filter] = [];
|
|
||||||
});
|
|
||||||
};
|
|
||||||
var getFilterString = function (obj) {
|
|
||||||
var newList = [];
|
|
||||||
_.forEach(self.propertyList, function (property) {
|
|
||||||
newList.push(obj[property]);
|
|
||||||
});
|
|
||||||
_.forEach(self.propertyFunctionList, function (fn) {
|
|
||||||
newList.push(fn(obj));
|
|
||||||
});
|
|
||||||
_.forEach(self.propertyDict, function (idFunction, property) {
|
|
||||||
newList.push(_.map(obj[property], idFunction).join(' '));
|
|
||||||
});
|
|
||||||
return newList.join(' ');
|
|
||||||
};
|
|
||||||
var operate = function (filter, id) {
|
|
||||||
if (_.indexOf(self.filters[filter], id) > -1) {
|
|
||||||
// remove id
|
|
||||||
self.filters[filter] = _.filter(self.filters[filter], function (_id) {
|
|
||||||
return _id != id;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// add id
|
|
||||||
self.filters[filter].push(id);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
/* Three things are could be given to create the query string:
|
||||||
var self = {
|
* - propertyList: Just a list of object's properties like ['title', 'name']
|
||||||
filters: {},
|
* - propertyFunktionList: A list of functions returning a property (e.g. [function(motion) {return motion.getTitle();}] for retrieving the motions title)
|
||||||
areFiltersSet: areFiltersSet,
|
* - propertyDict: A dict association properties that are lists to functions on how to handle them.
|
||||||
resetFilters: resetFilters,
|
* E.g.: {'tags': function (tag) {return tag.name;}, }
|
||||||
operate: operate,
|
* The list of tags will be mapped with this function to a list of strings (tag names).
|
||||||
getFilterString: getFilterString,
|
*/
|
||||||
|
self.getObjectQueryString = function (obj) {
|
||||||
|
var stringList = [];
|
||||||
|
_.forEach(self.propertyList, function (property) {
|
||||||
|
stringList.push(obj[property]);
|
||||||
|
});
|
||||||
|
_.forEach(self.propertyFunctionList, function (fn) {
|
||||||
|
stringList.push(fn(obj));
|
||||||
|
});
|
||||||
|
_.forEach(self.propertyDict, function (idFunction, property) {
|
||||||
|
stringList.push(_.map(obj[property], idFunction).join(' '));
|
||||||
|
});
|
||||||
|
return stringList.join(' ');
|
||||||
};
|
};
|
||||||
resetFilters(); //Initiate filters
|
|
||||||
return self;
|
return self;
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
instance: instance
|
createInstance: createInstance
|
||||||
|
};
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
/* This factory takes care of the sorting of OS-data-tables. Things to configure:
|
||||||
|
* - column: the default column which is the list sorted by (e.g.
|
||||||
|
* instance.column='title')
|
||||||
|
*/
|
||||||
|
.factory('osTableSort', [
|
||||||
|
function () {
|
||||||
|
var createInstance = function () {
|
||||||
|
var self = {
|
||||||
|
column: '',
|
||||||
|
reverse: false,
|
||||||
|
};
|
||||||
|
self.toggle = function (column) {
|
||||||
|
if (self.column === column) {
|
||||||
|
self.reverse = !self.reverse;
|
||||||
|
}
|
||||||
|
self.column = column;
|
||||||
|
};
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
createInstance: createInstance
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
@ -407,6 +453,9 @@ angular.module('OpenSlidesApp.core.site', [
|
|||||||
* Then, all items in the array are passed, if the item_id (get with id_function) matches
|
* Then, all items in the array are passed, if the item_id (get with id_function) matches
|
||||||
* one of the ids in filterArray. id_function could also return a list of ids. Example:
|
* one of the ids in filterArray. id_function could also return a list of ids. Example:
|
||||||
* Item 1 has two tags with ids [1, 4]. filterArray == [3, 4] --> match
|
* Item 1 has two tags with ids [1, 4]. filterArray == [3, 4] --> match
|
||||||
|
*
|
||||||
|
* If -1 is in the array items without an id will not be filtered. This is for implementing
|
||||||
|
* a filter option like: "All items without a category"
|
||||||
*/
|
*/
|
||||||
.filter('MultiselectFilter', [
|
.filter('MultiselectFilter', [
|
||||||
function () {
|
function () {
|
||||||
@ -414,12 +463,13 @@ angular.module('OpenSlidesApp.core.site', [
|
|||||||
if (filterArray.length === 0) {
|
if (filterArray.length === 0) {
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
var itemsWithoutProperty = _.indexOf(filterArray, -1) > -1;
|
||||||
return Array.prototype.filter.call(array, function (item) {
|
return Array.prototype.filter.call(array, function (item) {
|
||||||
var id = idFunction(item);
|
var id = idFunction(item);
|
||||||
if (!id) {
|
if (typeof id === 'number') {
|
||||||
return false;
|
|
||||||
} else if (typeof id === 'number') {
|
|
||||||
id = [id];
|
id = [id];
|
||||||
|
} else if (id === null || !id.length) {
|
||||||
|
return itemsWithoutProperty;
|
||||||
}
|
}
|
||||||
return _.intersection(id, filterArray).length > 0;
|
return _.intersection(id, filterArray).length > 0;
|
||||||
});
|
});
|
||||||
@ -427,6 +477,19 @@ angular.module('OpenSlidesApp.core.site', [
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
.filter('osFilter', [
|
||||||
|
function () {
|
||||||
|
return function (array, string, getFilterString) {
|
||||||
|
if (!string) {
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
return Array.prototype.filter.call(array, function (item) {
|
||||||
|
return getFilterString(item).toLowerCase().indexOf(string.toLowerCase()) > -1;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
// Load the django url patterns
|
// Load the django url patterns
|
||||||
.run([
|
.run([
|
||||||
'runtimeStates',
|
'runtimeStates',
|
||||||
|
@ -57,7 +57,10 @@ angular.module('OpenSlidesApp.mediafiles.site', ['ngFileUpload', 'OpenSlidesApp.
|
|||||||
'User',
|
'User',
|
||||||
'Projector',
|
'Projector',
|
||||||
'ProjectionDefault',
|
'ProjectionDefault',
|
||||||
function($scope, $http, ngDialog, Mediafile, MediafileForm, User, Projector, ProjectionDefault) {
|
'osTableFilter',
|
||||||
|
'osTableSort',
|
||||||
|
'gettext',
|
||||||
|
function($scope, $http, ngDialog, Mediafile, MediafileForm, User, Projector, ProjectionDefault, osTableFilter, osTableSort, gettext) {
|
||||||
Mediafile.bindAll({}, $scope, 'mediafiles');
|
Mediafile.bindAll({}, $scope, 'mediafiles');
|
||||||
User.bindAll({}, $scope, 'users');
|
User.bindAll({}, $scope, 'users');
|
||||||
$scope.$watch(function() {
|
$scope.$watch(function() {
|
||||||
@ -95,44 +98,61 @@ angular.module('OpenSlidesApp.mediafiles.site', ['ngFileUpload', 'OpenSlidesApp.
|
|||||||
|
|
||||||
updatePresentedMediafiles();
|
updatePresentedMediafiles();
|
||||||
|
|
||||||
// setup table sorting
|
// Filtering
|
||||||
$scope.sortColumn = 'title';
|
$scope.filter = osTableFilter.createInstance();
|
||||||
$scope.filterPresent = '';
|
$scope.filter.booleanFilters = {
|
||||||
$scope.reverse = false;
|
isPrivate: {
|
||||||
|
value: undefined,
|
||||||
// function to sort by clicked column
|
displayName: gettext('Private'),
|
||||||
$scope.toggleSort = function ( column ) {
|
choiceYes: gettext('Is private'),
|
||||||
if ( $scope.sortColumn === column ) {
|
choiceNo: gettext('Is not private'),
|
||||||
$scope.reverse = !$scope.reverse;
|
needExtraPermission: true,
|
||||||
}
|
},
|
||||||
$scope.sortColumn = column;
|
isPdf: {
|
||||||
};
|
value: undefined,
|
||||||
// define custom search filter string
|
displayName: gettext('Is PDF'),
|
||||||
$scope.getFilterString = function (mediafile) {
|
choiceYes: gettext('Is PDF file'),
|
||||||
return [
|
choiceNo: gettext('Is no PDF file'),
|
||||||
mediafile.title,
|
},
|
||||||
mediafile.mediafile.type,
|
|
||||||
mediafile.mediafile.name,
|
|
||||||
mediafile.uploader.get_short_name()
|
|
||||||
].join(" ");
|
|
||||||
};
|
};
|
||||||
|
$scope.filter.propertyList = ['title_or_filename'];
|
||||||
|
$scope.filter.propertyFunctionList = [
|
||||||
|
function (mediafile) {return mediafile.uploader.get_short_name();},
|
||||||
|
function (mediafile) {return mediafile.mediafile.type;},
|
||||||
|
function (mediafile) {return mediafile.mediafile.name;},
|
||||||
|
];
|
||||||
|
// Sorting
|
||||||
|
$scope.sort = osTableSort.createInstance();
|
||||||
|
$scope.sort.column = 'title_or_filename';
|
||||||
|
$scope.sortOptions = [
|
||||||
|
{name: 'title_or_filename',
|
||||||
|
display_name: 'Title'},
|
||||||
|
{name: 'timestamp',
|
||||||
|
display_name: 'UploadTime'},
|
||||||
|
{name: 'uploader.get_short_name()',
|
||||||
|
display_name: 'Uploader'},
|
||||||
|
{name: 'mediafile.type',
|
||||||
|
display_name: 'Type'},
|
||||||
|
{name: 'filesize',
|
||||||
|
display_name: 'Filesize'},
|
||||||
|
];
|
||||||
|
|
||||||
// open new/edit dialog
|
// open new/edit dialog
|
||||||
$scope.openDialog = function (mediafile) {
|
$scope.openDialog = function (mediafile) {
|
||||||
ngDialog.open(MediafileForm.getDialog(mediafile));
|
ngDialog.open(MediafileForm.getDialog(mediafile));
|
||||||
};
|
};
|
||||||
|
|
||||||
// *** delete mode functions ***
|
// *** select mode functions ***
|
||||||
$scope.isDeleteMode = false;
|
$scope.isSelectMode = false;
|
||||||
// check all checkboxes
|
// check all checkboxes
|
||||||
$scope.checkAll = function () {
|
$scope.checkAll = function () {
|
||||||
angular.forEach($scope.mediafiles, function (mediafile) {
|
angular.forEach($scope.mediafiles, function (mediafile) {
|
||||||
mediafile.selected = $scope.selectedAll;
|
mediafile.selected = $scope.selectedAll;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
// uncheck all checkboxes if isDeleteMode is closed
|
// uncheck all checkboxes if SelectMode is closed
|
||||||
$scope.uncheckAll = function () {
|
$scope.uncheckAll = function () {
|
||||||
if (!$scope.isDeleteMode) {
|
if (!$scope.isSelectMode) {
|
||||||
$scope.selectedAll = false;
|
$scope.selectedAll = false;
|
||||||
angular.forEach($scope.mediafiles, function (mediafile) {
|
angular.forEach($scope.mediafiles, function (mediafile) {
|
||||||
mediafile.selected = false;
|
mediafile.selected = false;
|
||||||
@ -145,7 +165,7 @@ angular.module('OpenSlidesApp.mediafiles.site', ['ngFileUpload', 'OpenSlidesApp.
|
|||||||
if (mediafile.selected)
|
if (mediafile.selected)
|
||||||
Mediafile.destroy(mediafile.id);
|
Mediafile.destroy(mediafile.id);
|
||||||
});
|
});
|
||||||
$scope.isDeleteMode = false;
|
$scope.isSelectMode = false;
|
||||||
$scope.uncheckAll();
|
$scope.uncheckAll();
|
||||||
};
|
};
|
||||||
// delete single mediafile
|
// delete single mediafile
|
||||||
|
@ -115,44 +115,21 @@
|
|||||||
<div class="row form-group">
|
<div class="row form-group">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<form class="form-inline">
|
<form class="form-inline">
|
||||||
<!-- delete mode -->
|
<!-- select mode -->
|
||||||
<button os-perms="mediafiles.can_manage" class="btn"
|
<button os-perms="mediafiles.can_manage" class="btn"
|
||||||
ng-class="$parent.isDeleteMode ? 'btn-primary' : 'btn-default'"
|
ng-class="$parent.isSelectMode ? 'btn-primary' : 'btn-default'"
|
||||||
ng-click="$parent.isDeleteMode = !$parent.isDeleteMode; uncheckAll()">
|
ng-click="$parent.isSelectMode = !$parent.isSelectMode; uncheckAll()">
|
||||||
<i class="fa fa-check-square-o"></i>
|
<i class="fa fa-check-square-o"></i>
|
||||||
<translate>Select ...</translate>
|
<translate>Select ...</translate>
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6"></div>
|
||||||
<div class="form-inline text-right">
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="input-group">
|
|
||||||
<div class="input-group-addon"><i class="fa fa-search"></i></div>
|
|
||||||
<input type="text" ng-model="filter.search" class="form-control"
|
|
||||||
placeholder="{{ 'Search' | translate}}">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button class="btn btn-default" ng-click="isFilterOpen = !isFilterOpen"
|
|
||||||
ng-class="isFilterOpen ? 'btn-primary' : 'btn-default'">
|
|
||||||
<i class="fa fa-filter"></i>
|
|
||||||
<translate>Filter ...</translate>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div uib-collapse="!isFilterOpen" class="row">
|
<div uib-collapse="!isSelectMode" class="row spacer">
|
||||||
<div class="col-sm-6 text-right"></div>
|
|
||||||
<div class="col-sm-6 text-right">
|
|
||||||
<!-- pdf filter -->
|
|
||||||
<input type="checkbox" ng-model="filter.showPDFs" ng-true-value="'application/pdf'" ng-false-value=''>
|
|
||||||
<translate> Show PDF files only</translate>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div uib-collapse="!isDeleteMode" class="row spacer">
|
|
||||||
<div class="col-sm-12 text-left">
|
<div class="col-sm-12 text-left">
|
||||||
<!-- delete button -->
|
<!-- delete button -->
|
||||||
<a ng-show="isDeleteMode"
|
<a ng-show="isSelectMode"
|
||||||
os-perms="mediafiles.can_manage" ng-click="deleteMultiple()"
|
os-perms="mediafiles.can_manage" ng-click="deleteMultiple()"
|
||||||
class="btn btn-primary">
|
class="btn btn-primary">
|
||||||
<i class="fa fa-trash fa-lg"></i>
|
<i class="fa fa-trash fa-lg"></i>
|
||||||
@ -166,87 +143,180 @@
|
|||||||
{{ mediafiles.length }} {{ "files" | translate }}<span ng-if="(mediafiles|filter:{selected:true}).length > 0">,
|
{{ mediafiles.length }} {{ "files" | translate }}<span ng-if="(mediafiles|filter:{selected:true}).length > 0">,
|
||||||
{{(mediafiles|filter:{selected:true}).length}} {{ "selected" | translate }}</span>
|
{{(mediafiles|filter:{selected:true}).length}} {{ "selected" | translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
<table class="table table-striped table-bordered table-hover">
|
|
||||||
<thead>
|
<div class="os-table container-fluid">
|
||||||
<tr>
|
<div class="row header-row">
|
||||||
<!-- projector column -->
|
<div class="col-xs-1 centered" ng-show="isSelectMode" os-perms="mediafiles.can_manage">
|
||||||
<th ng-show="!isDeleteMode" os-perms="core.can_manage_projector" class="minimum">
|
<i class="fa text-danger pointer" ng-class="selectedAll ? 'fa-check-square-o' : 'fa-square-o'"
|
||||||
<!-- delete selection column -->
|
ng-click="checkAll()"></i>
|
||||||
<th ng-show="isDeleteMode" os-perms="mediafiles.can_manage" class="minimum deleteColumn">
|
</div>
|
||||||
<input type="checkbox" ng-model="$parent.selectedAll" ng-change="checkAll()">
|
<div class="col-xs-11 main-header">
|
||||||
<!-- title -->
|
<span class="form-inline text-right pull-right">
|
||||||
<th ng-click="toggleSort('title_or_filename')" class="sortable">
|
<!-- reset Filters -->
|
||||||
<translate>Title</translate>
|
<span class="sort-spacer pointer" ng-click="filter.reset()"
|
||||||
<i class="pull-right fa" ng-show="sortColumn === 'title_or_filename' && header.sortable != false"
|
ng-if="filter.areFiltersSet()" ng-disabled="isSelectMode"
|
||||||
ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
|
ng-class="{'disabled': isSelectMode}">
|
||||||
</i>
|
<i class="fa fa-times-circle"></i>
|
||||||
<!-- upload time -->
|
<translate>Filter</translate>
|
||||||
<th ng-click="toggleSort('timestamp')" class="sortable optional">
|
</span>
|
||||||
<translate>Upload time</translate>
|
<!-- boolean Filters -->
|
||||||
<i class="pull-right fa" ng-show="sortColumn === 'timestamp' && header.sortable != false"
|
<span ng-repeat="(name, booleanFilter) in filter.booleanFilters"
|
||||||
ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
|
ng-if="!booleanFilter.needExtraPermission || operator.hasPerms('mediafiles.can_see_private')" uib-dropdown>
|
||||||
</i>
|
<span class="pointer" id="dropdown{{ name }}" uib-dropdown-toggle
|
||||||
<!-- uploaded by -->
|
ng-class="{'bold': booleanFilter.value !== undefined, 'disabled': isSelectMode}"
|
||||||
<th ng-click="toggleSort('uploader')" class="sortable">
|
ng-disabled="isSelectMode">
|
||||||
<translate>Uploaded by</translate>
|
{{ booleanFilter.displayName }}
|
||||||
<i class="pull-right fa" ng-show="sortColumn === 'uploader' && header.sortable != false"
|
|
||||||
ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
|
|
||||||
</i>
|
|
||||||
</tr>
|
|
||||||
<tbody>
|
|
||||||
<tr ng-repeat="mediafile in mediafilesFiltered = (mediafiles | privateFilter | osFilter: filter.search : getFilterString |
|
|
||||||
filter: {filetype: filter.showPDFs} | orderBy: sortColumn:reverse )"
|
|
||||||
class="animate-item"
|
|
||||||
ng-class="{ 'activeline': mediafile.isProjected().length, 'selected': mediafile.selected }">
|
|
||||||
<!-- projector column -->
|
|
||||||
<td ng-show="!isDeleteMode"
|
|
||||||
os-perms="core.can_manage_projector">
|
|
||||||
<div class="btn-group" style="min-width:{{ projectors.length > 1 ? '54' : '34' }}px;" uib-dropdown
|
|
||||||
ng-if="mediafile.is_presentable"
|
|
||||||
uib-tooltip="{{ 'Projector' | translate }} {{ mediafile.isProjected()[0] || '' }}"
|
|
||||||
tooltip-enable="mediafile.isProjected().length">
|
|
||||||
<button type="button" class="btn btn-default btn-sm"
|
|
||||||
ng-click="showMediafile(defaultProjectorId, mediafile)"
|
|
||||||
ng-class="{ 'btn-primary': inArray(mediafile.isProjected(), defaultProjectorId) }">
|
|
||||||
<i class="fa fa-video-camera"></i>
|
|
||||||
</button>
|
|
||||||
<button type="button" class="btn btn-default btn-sm slimDropDown"
|
|
||||||
ng-class="{ 'btn-primary': (mediafile.isProjected().length && !inArray(mediafile.isProjected(), defaultProjectorId) ) }"
|
|
||||||
ng-if="projectors.length > 1"
|
|
||||||
uib-dropdown-toggle>
|
|
||||||
<span class="caret"></span>
|
<span class="caret"></span>
|
||||||
</button>
|
</span>
|
||||||
<ul class="dropdown-menu" ng-if="projectors.length > 1">
|
<ul class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdown{{ name }}">
|
||||||
<li role="menuitem" ng-repeat="projector in projectors">
|
<li>
|
||||||
<a href="" ng-click="showMediafile(projector.id, mediafile)"
|
<a href ng-click="booleanFilter.value = (booleanFilter.value ? undefined : true)">
|
||||||
ng-class="{ 'projected': inArray(mediafile.isProjected(), projector.id) }">
|
<i class="fa" ng-class="{'fa-check': booleanFilter.value === true}"></i>
|
||||||
<i class="fa fa-video-camera" ng-show="inArray(mediafile.isProjected(), projector.id) "></i>
|
{{ booleanFilter.choiceYes }}
|
||||||
{{ projector.name }}
|
</a>
|
||||||
<span ng-if="defaultProjectorId == projector.id">(<translate>Default</translate>)</span>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href ng-click="booleanFilter.value = (booleanFilter.value === false) ? undefined : false">
|
||||||
|
<i class="fa" ng-class="{'fa-check': booleanFilter.value === false}"></i>
|
||||||
|
{{ booleanFilter.choiceNo }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
</span>
|
||||||
|
<!-- dropdown sort -->
|
||||||
|
<span uib-dropdown>
|
||||||
|
<span class="pointer" id="dropdownSort" uib-dropdown-toggle
|
||||||
|
ng-class="{'disabled': isSelectMode}"
|
||||||
|
ng-disabled="isSelectMode">
|
||||||
|
<translate>Sort</translate>
|
||||||
|
<span class="caret"></span>
|
||||||
|
</span>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownSort">
|
||||||
|
<li ng-repeat="option in sortOptions">
|
||||||
|
<a href ng-click="sort.toggle(option.name)">
|
||||||
|
{{ option.display_name | translate }}
|
||||||
|
<span class="spacer-right pull-right"></span>
|
||||||
|
<i class="pull-right fa"
|
||||||
|
ng-style="{'visibility': sort.column === option.name ? 'visible' : 'hidden'}"
|
||||||
|
ng-class="sort.reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
|
||||||
|
</i>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</span>
|
||||||
|
<!-- search field -->
|
||||||
|
<span class="form-group">
|
||||||
|
<span class="input-group">
|
||||||
|
<span class="input-group-addon"><i class="fa fa-search"></i></span>
|
||||||
|
<input type="text" ng-model="filter.filterString" class="form-control"
|
||||||
|
placeholder="{{ 'Search' | translate}}" ng-disabled="isSelectMode">
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<!-- show all selected multiselectoptions -->
|
||||||
|
<span>
|
||||||
|
<!-- for all boolean Filters -->
|
||||||
|
<span ng-repeat="(name, booleanFilter) in filter.booleanFilters"
|
||||||
|
ng-hide="booleanFilter.value === undefined"
|
||||||
|
class="pointer spacer-left-lg"
|
||||||
|
ng-click="booleanFilter.value = undefined;"
|
||||||
|
ng-class="{'disabled': isSelectMode}">
|
||||||
|
<span class="nobr">
|
||||||
|
<i class="fa fa-times-circle"></i>
|
||||||
|
{{ booleanFilter.value ? booleanFilter.choiceYes : booleanFilter.choiceNo | translate }}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- main table -->
|
||||||
|
<div class="row data-row" ng-mouseover="mediafile.hover=true"
|
||||||
|
ng-mouseleave="mediafile.hover=false"
|
||||||
|
ng-class="{'projected': mediafile.isProjected().length}"
|
||||||
|
ng-repeat="mediafile in mediafilesFiltered = (mediafiles
|
||||||
|
| privateFilter
|
||||||
|
| osFilter: filter.filterString : filter.getObjectQueryString
|
||||||
|
| filter: {filetype: (filter.booleanFilters.isPdf.value ? 'application/pdf' : (filter.booleanFilters.isPdf.value === false ? '!application/pdf' : ''))}
|
||||||
|
| filter: {private: filter.booleanFilters.isPrivate.value}
|
||||||
|
| orderBy: sort.column : sort.reverse )">
|
||||||
|
|
||||||
|
<!-- select column -->
|
||||||
|
<div ng-show="isSelectMode" os-perms="mediafiles.can_manage" class="col-xs-1 centered">
|
||||||
|
<i class="fa text-danger pointer" ng-click="mediafile.selected=!mediafile.selected"
|
||||||
|
ng-class="mediafile.selected ? 'fa-check-square-o' : 'fa-square-o'"></i>
|
||||||
|
</div>
|
||||||
|
<!-- projector column -->
|
||||||
|
<div class="col-xs-1 centered projector" os-perms="core.can_manage_projector">
|
||||||
|
<div class="btn-group" style="min-width:{{ projectors.length > 1 ? '54' : '34' }}px;" uib-dropdown
|
||||||
|
ng-if="mediafile.is_presentable"
|
||||||
|
uib-tooltip="{{ 'Projector' | translate }} {{ mediafile.isProjected()[0] || '' }}"
|
||||||
|
tooltip-enable="mediafile.isProjected().length">
|
||||||
|
<button type="button" class="btn btn-default btn-sm"
|
||||||
|
ng-click="showMediafile(defaultProjectorId, mediafile)"
|
||||||
|
ng-class="{ 'btn-primary': inArray(mediafile.isProjected(), defaultProjectorId) }">
|
||||||
|
<i class="fa fa-video-camera"></i>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-default btn-sm slimDropDown"
|
||||||
|
ng-class="{ 'btn-primary': (mediafile.isProjected().length && !inArray(mediafile.isProjected(), defaultProjectorId) ) }"
|
||||||
|
ng-if="projectors.length > 1"
|
||||||
|
uib-dropdown-toggle>
|
||||||
|
<span class="caret"></span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu" ng-if="projectors.length > 1">
|
||||||
|
<li role="menuitem" ng-repeat="projector in projectors">
|
||||||
|
<a href="" ng-click="showMediafile(projector.id, mediafile)"
|
||||||
|
ng-class="{ 'projected': inArray(mediafile.isProjected(), projector.id) }">
|
||||||
|
<i class="fa fa-video-camera" ng-show="inArray(mediafile.isProjected(), projector.id) "></i>
|
||||||
|
{{ projector.name }}
|
||||||
|
<span ng-if="defaultProjectorId == projector.id">(<translate>Default</translate>)</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- main content column -->
|
||||||
|
<div class="col-xs-6 content">
|
||||||
|
<div class="spacer-right"> <!-- horizontal block -->
|
||||||
|
<strong>
|
||||||
|
<i ng-style="{'visibility': mediafile.private ? 'visible' : 'hidden'}" class="fa fa-lock fa-lg"
|
||||||
|
title="{{ 'Is private' | translate }}"></i>
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div> <!-- vertical block -->
|
||||||
|
<strong>
|
||||||
|
<a ng-href="{{ mediafile.mediafileUrl }}" target="_blank">{{ mediafile.title_or_filename }}</a>
|
||||||
|
</strong>
|
||||||
</div>
|
</div>
|
||||||
<!-- delete selection column -->
|
<div><small>{{ mediafile.uploader.get_full_name() }}</small></div>
|
||||||
<td ng-show="isDeleteMode" os-perms="mediafiles.can_manage" class="deleteColumn">
|
<div os-perms="mediafiles.can_manage" ng-class="{'hiddenDiv': !mediafile.hover}">
|
||||||
<input type="checkbox" ng-model="mediafile.selected">
|
<small>
|
||||||
<!-- mediafile data colums -->
|
<a href="" ng-click="openDialog(mediafile)" translate>Edit</a> ·
|
||||||
<td ng-mouseover="mediafile.hover=true" ng-mouseleave="mediafile.hover=false">
|
<a href="" class="text-danger"
|
||||||
<strong><a ng-href="{{ mediafile.mediafileUrl }}" target="_blank">{{ mediafile.title_or_filename }}</a></strong>
|
|
||||||
<br><small><i class="fa fa-file"></i> {{ mediafile.filetype }}
|
|
||||||
<span ng-if="mediafile.mediafile.encrypted">(<translate>Encrypted</translate>)</span>
|
|
||||||
</small>
|
|
||||||
<br><small><i class="fa fa-database"></i> {{ mediafile.filesize }}</small>
|
|
||||||
<span ng-if="mediafile.private"><br><small><i class="fa fa-lock"></i> <translate>Private</translate></small></span>
|
|
||||||
<div os-perms="mediafiles.can_manage" class="hoverActions" ng-class="{'hiddenDiv': !mediafile.hover}">
|
|
||||||
<a href="" ng-click="openDialog(mediafile)" translate>Edit</a> |
|
|
||||||
<a href="" class="text-danger"
|
|
||||||
ng-bootbox-confirm="{{ 'Are you sure you want to delete this file?' | translate }}<br>
|
ng-bootbox-confirm="{{ 'Are you sure you want to delete this file?' | translate }}<br>
|
||||||
<b>{{ mediafile.title }} [{{ mediafile.mediafile.name }}]</b>"
|
<b>{{ mediafile.title }} [{{ mediafile.mediafile.name }}]</b>"
|
||||||
ng-bootbox-confirm-action="delete(mediafile)" translate>Delete</a>
|
ng-bootbox-confirm-action="delete(mediafile)" translate>Delete</a>
|
||||||
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<td class="optional">{{ mediafile.timestamp | date:'yyyy-MM-dd HH:mm:ss' }}
|
</div>
|
||||||
<td>{{ mediafile.uploader.get_full_name() }}
|
</div>
|
||||||
</tbody>
|
|
||||||
</table>
|
<!-- additional content column -->
|
||||||
|
<div class="col-xs-4 content" ng-style="{'width': isSelectMode ? 'calc(50% - 120px)' : 'calc(50% - 70px)'}">
|
||||||
|
<div style="width: 60%;" class="optional">
|
||||||
|
<small>
|
||||||
|
<div>
|
||||||
|
<i class="fa fa-file"></i> {{ mediafile.filetype }}
|
||||||
|
<span ng-if="mediafile.mediafile.encrypted">(<translate>Encrypted</translate>)</span>
|
||||||
|
</div>
|
||||||
|
<div><i class="fa fa-database"></i> {{ mediafile.filesize }}</div>
|
||||||
|
<div><i class="fa fa-upload"></i> {{ mediafile.timestamp | date:'yyyy-MM-dd HH:mm:ss' }}</div>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
<div style="width: 40%;" class="pull-right optional"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div><!-- end data row -->
|
||||||
|
</div><!-- end os-table -->
|
||||||
</div>
|
</div>
|
||||||
|
@ -804,10 +804,11 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
'Projector',
|
'Projector',
|
||||||
'ProjectionDefault',
|
'ProjectionDefault',
|
||||||
'MotionCsvExport',
|
'MotionCsvExport',
|
||||||
'Multiselect',
|
'osTableFilter',
|
||||||
|
'osTableSort',
|
||||||
function($scope, $state, $http, ngDialog, MotionForm, Motion, Category, Tag, Workflow, User, Agenda, MotionBlock,
|
function($scope, $state, $http, ngDialog, MotionForm, Motion, Category, Tag, Workflow, User, Agenda, MotionBlock,
|
||||||
MotionDocxExport, MotionContentProvider, MotionCatalogContentProvider, PdfMakeConverter, PdfMakeDocumentProvider,
|
MotionDocxExport, MotionContentProvider, MotionCatalogContentProvider, PdfMakeConverter, PdfMakeDocumentProvider,
|
||||||
gettextCatalog, HTMLValidizer, Projector, ProjectionDefault, MotionCsvExport, Multiselect) {
|
gettextCatalog, HTMLValidizer, Projector, ProjectionDefault, MotionCsvExport, osTableFilter, osTableSort) {
|
||||||
Motion.bindAll({}, $scope, 'motions');
|
Motion.bindAll({}, $scope, 'motions');
|
||||||
Category.bindAll({}, $scope, 'categories');
|
Category.bindAll({}, $scope, 'categories');
|
||||||
MotionBlock.bindAll({}, $scope, 'motionBlocks');
|
MotionBlock.bindAll({}, $scope, 'motionBlocks');
|
||||||
@ -825,22 +826,23 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
});
|
});
|
||||||
$scope.alert = {};
|
$scope.alert = {};
|
||||||
|
|
||||||
$scope.multiselect = Multiselect.instance();
|
// Filtering
|
||||||
$scope.multiselect.filters = {
|
$scope.filter = osTableFilter.createInstance();
|
||||||
|
$scope.filter.multiselectFilters = {
|
||||||
state: [],
|
state: [],
|
||||||
category: [],
|
category: [],
|
||||||
motionBlock: [],
|
motionBlock: [],
|
||||||
tag: []
|
tag: []
|
||||||
};
|
};
|
||||||
$scope.multiselect.propertyList = ['identifier', 'origin'];
|
$scope.filter.propertyList = ['identifier', 'origin'];
|
||||||
$scope.multiselect.propertyFunctionList = [
|
$scope.filter.propertyFunctionList = [
|
||||||
function (motion) {return motion.getTitle();},
|
function (motion) {return motion.getTitle();},
|
||||||
function (motion) {return motion.getText();},
|
function (motion) {return motion.getText();},
|
||||||
function (motion) {return motion.getReason();},
|
function (motion) {return motion.getReason();},
|
||||||
function (motion) {return motion.category ? motion.category.name : '';},
|
function (motion) {return motion.category ? motion.category.name : '';},
|
||||||
function (motion) {return motion.motionBlock ? motion.motionBlock.name : '';},
|
function (motion) {return motion.motionBlock ? motion.motionBlock.name : '';},
|
||||||
];
|
];
|
||||||
$scope.multiselect.PropertyDict = {
|
$scope.filter.propertyDict = {
|
||||||
'submitters' : function (submitter) {
|
'submitters' : function (submitter) {
|
||||||
return submitter.get_short_name();
|
return submitter.get_short_name();
|
||||||
},
|
},
|
||||||
@ -857,7 +859,9 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
motionBlock: function (motion) {return motion.motion_block_id;},
|
motionBlock: function (motion) {return motion.motion_block_id;},
|
||||||
tag: function (motion) {return motion.tags_id;}
|
tag: function (motion) {return motion.tags_id;}
|
||||||
};
|
};
|
||||||
// setup table sorting
|
// Sorting
|
||||||
|
$scope.sort = osTableSort.createInstance();
|
||||||
|
$scope.sort.column = 'identifier';
|
||||||
$scope.sortOptions = [
|
$scope.sortOptions = [
|
||||||
{name: 'identifier',
|
{name: 'identifier',
|
||||||
display_name: 'Identifier'},
|
display_name: 'Identifier'},
|
||||||
@ -876,34 +880,6 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
{name: 'log_messages[0].time',
|
{name: 'log_messages[0].time',
|
||||||
display_name: 'Last modified'},
|
display_name: 'Last modified'},
|
||||||
];
|
];
|
||||||
$scope.sortColumn = 'identifier';
|
|
||||||
$scope.filterPresent = '';
|
|
||||||
$scope.reverse = false;
|
|
||||||
|
|
||||||
// function to operate the multiselectFilter
|
|
||||||
$scope.operateMultiselectFilter = function (filter, id) {
|
|
||||||
if (!$scope.isDeleteMode) {
|
|
||||||
$scope.multiselect.operate(filter, id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// function to sort by clicked column
|
|
||||||
$scope.toggleSort = function (column) {
|
|
||||||
if ( $scope.sortColumn === column ) {
|
|
||||||
$scope.reverse = !$scope.reverse;
|
|
||||||
}
|
|
||||||
$scope.sortColumn = column;
|
|
||||||
};
|
|
||||||
// for reset-button
|
|
||||||
$scope.resetFilters = function () {
|
|
||||||
$scope.multiselect.resetFilters();
|
|
||||||
if ($scope.filter) {
|
|
||||||
$scope.filter.search = '';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
$scope.areFiltersSet = function () {
|
|
||||||
return $scope.multiselect.areFiltersSet() ||
|
|
||||||
($scope.filter ? $scope.filter.search : false);
|
|
||||||
};
|
|
||||||
|
|
||||||
// collect all states of all workflows
|
// collect all states of all workflows
|
||||||
// TODO: regard workflows only which are used by motions
|
// TODO: regard workflows only which are used by motions
|
||||||
@ -930,7 +906,7 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
$http.put('/rest/motions/motion/' + motion.id + '/set_state/', {});
|
$http.put('/rest/motions/motion/' + motion.id + '/set_state/', {});
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.has_tag = function (motion, tag) {
|
$scope.hasTag = function (motion, tag) {
|
||||||
return _.indexOf(motion.tags_id, tag.id) > -1;
|
return _.indexOf(motion.tags_id, tag.id) > -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -942,8 +918,8 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
motion.reason = motion.getReason(-1);
|
motion.reason = motion.getReason(-1);
|
||||||
Motion.save(motion);
|
Motion.save(motion);
|
||||||
};
|
};
|
||||||
$scope.toggle_tag = function (motion, tag) {
|
$scope.toggleTag = function (motion, tag) {
|
||||||
if ($scope.has_tag(motion, tag)) {
|
if ($scope.hasTag(motion, tag)) {
|
||||||
// remove
|
// remove
|
||||||
motion.tags_id = _.filter(motion.tags_id, function (tag_id){
|
motion.tags_id = _.filter(motion.tags_id, function (tag_id){
|
||||||
return tag_id != tag.id;
|
return tag_id != tag.id;
|
||||||
@ -953,7 +929,7 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
}
|
}
|
||||||
save(motion);
|
save(motion);
|
||||||
};
|
};
|
||||||
$scope.toggle_category = function (motion, category) {
|
$scope.toggleCategory = function (motion, category) {
|
||||||
if (motion.category_id == category.id) {
|
if (motion.category_id == category.id) {
|
||||||
motion.category_id = null;
|
motion.category_id = null;
|
||||||
} else {
|
} else {
|
||||||
@ -961,7 +937,7 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
}
|
}
|
||||||
save(motion);
|
save(motion);
|
||||||
};
|
};
|
||||||
$scope.toggle_motionBlock = function (motion, block) {
|
$scope.toggleMotionBlock = function (motion, block) {
|
||||||
if (motion.motion_block_id == block.id) {
|
if (motion.motion_block_id == block.id) {
|
||||||
motion.motion_block_id = null;
|
motion.motion_block_id = null;
|
||||||
} else {
|
} else {
|
||||||
@ -1015,8 +991,8 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
MotionDocxExport.export($scope.motionsFiltered, $scope.categories);
|
MotionDocxExport.export($scope.motionsFiltered, $scope.categories);
|
||||||
};
|
};
|
||||||
|
|
||||||
// *** delete mode functions ***
|
// *** select mode functions ***
|
||||||
$scope.isDeleteMode = false;
|
$scope.isSelectMode = false;
|
||||||
// check all checkboxes from filtered motions
|
// check all checkboxes from filtered motions
|
||||||
$scope.checkAll = function () {
|
$scope.checkAll = function () {
|
||||||
$scope.selectedAll = !$scope.selectedAll;
|
$scope.selectedAll = !$scope.selectedAll;
|
||||||
@ -1024,9 +1000,9 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
motion.selected = $scope.selectedAll;
|
motion.selected = $scope.selectedAll;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
// uncheck all checkboxes if isDeleteMode is closed
|
// uncheck all checkboxes if isSelectMode is closed
|
||||||
$scope.uncheckAll = function () {
|
$scope.uncheckAll = function () {
|
||||||
if (!$scope.isDeleteMode) {
|
if (!$scope.isSelectMode) {
|
||||||
$scope.selectedAll = false;
|
$scope.selectedAll = false;
|
||||||
angular.forEach($scope.motions, function (motion) {
|
angular.forEach($scope.motions, function (motion) {
|
||||||
motion.selected = false;
|
motion.selected = false;
|
||||||
@ -1039,7 +1015,7 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
if (motion.selected)
|
if (motion.selected)
|
||||||
Motion.destroy(motion.id);
|
Motion.destroy(motion.id);
|
||||||
});
|
});
|
||||||
$scope.isDeleteMode = false;
|
$scope.isSelectMode = false;
|
||||||
$scope.uncheckAll();
|
$scope.uncheckAll();
|
||||||
};
|
};
|
||||||
// delete single motion
|
// delete single motion
|
||||||
|
@ -29,16 +29,16 @@
|
|||||||
<div class="details">
|
<div class="details">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<!-- delete mode -->
|
<!-- select mode -->
|
||||||
<button os-perms="motions.can_manage" class="btn"
|
<button os-perms="motions.can_manage" class="btn"
|
||||||
ng-class="$parent.isDeleteMode ? 'btn-primary' : 'btn-default'"
|
ng-class="$parent.isSelectMode ? 'btn-primary' : 'btn-default'"
|
||||||
ng-click="$parent.isDeleteMode = !$parent.isDeleteMode; uncheckAll()">
|
ng-click="$parent.isSelectMode = !$parent.isSelectMode; uncheckAll()">
|
||||||
<i class="fa fa-check-square-o"></i>
|
<i class="fa fa-check-square-o"></i>
|
||||||
<translate>Select ...</translate>
|
<translate>Select ...</translate>
|
||||||
</button>
|
</button>
|
||||||
<!-- Export dropdown -->
|
<!-- Export dropdown -->
|
||||||
<div class="dropdown pull-right" uib-dropdown>
|
<div class="dropdown pull-right" uib-dropdown>
|
||||||
<button type=button" class="btn btn-default" id="dropdownExport" uib-dropdown-toggle>
|
<button type="button" class="btn btn-default" id="dropdownExport" uib-dropdown-toggle>
|
||||||
<i class="fa fa-upload"></i>
|
<i class="fa fa-upload"></i>
|
||||||
<span ng-if="motionsFiltered.length == motions.length" translate>
|
<span ng-if="motionsFiltered.length == motions.length" translate>
|
||||||
Export all
|
Export all
|
||||||
@ -76,10 +76,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div uib-collapse="!isDeleteMode" class="row spacer">
|
<div uib-collapse="!isSelectMode" class="row spacer">
|
||||||
<div class="col-sm-12 text-left">
|
<div class="col-sm-12 text-left">
|
||||||
<!-- delete button -->
|
<!-- delete button -->
|
||||||
<a ng-show="isDeleteMode" os-perms="motions.can_manage"
|
<a ng-show="isSelectMode" os-perms="motions.can_manage"
|
||||||
ng-bootbox-confirm="{{ 'Are you sure you want to delete all selected motions?' | translate }}"
|
ng-bootbox-confirm="{{ 'Are you sure you want to delete all selected motions?' | translate }}"
|
||||||
ng-bootbox-confirm-action="deleteMultiple()"
|
ng-bootbox-confirm-action="deleteMultiple()"
|
||||||
class="btn btn-primary">
|
class="btn btn-primary">
|
||||||
@ -95,125 +95,144 @@
|
|||||||
{{(motions|filter:{selected:true}).length}} {{ "selected" | translate }}</span>
|
{{(motions|filter:{selected:true}).length}} {{ "selected" | translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="motion-os-table" class="os-table container-fluid">
|
<div class="os-table container-fluid">
|
||||||
<div class="row header-row">
|
<div class="row header-row">
|
||||||
<div class="col-xs-1 centered" ng-show="isDeleteMode">
|
<div class="col-xs-1 centered" ng-show="isSelectMode">
|
||||||
<i class="fa text-danger pointer" ng-class=" selectedAll ? 'fa-check-square-o' : 'fa-square-o'"
|
<i class="fa text-danger pointer" ng-class=" selectedAll ? 'fa-check-square-o' : 'fa-square-o'"
|
||||||
ng-click="checkAll()"></i>
|
ng-click="checkAll()"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-11 main-header">
|
<div class="col-xs-11 main-header">
|
||||||
<span class="form-inline text-right pull-right">
|
<span class="form-inline text-right pull-right">
|
||||||
<span class="sort-spacer pointer" ng-click="resetFilters()"
|
<!-- clear all filters -->
|
||||||
ng-if="areFiltersSet()" ng-disabled="isDeleteMode"
|
<span class="sort-spacer pointer" ng-click="filter.reset()"
|
||||||
ng-class="{'disabled': isDeleteMode}">
|
ng-if="filter.areFiltersSet()" ng-disabled="isSelectMode"
|
||||||
|
ng-class="{'disabled': isSelectMode}">
|
||||||
<i class="fa fa-times-circle"></i>
|
<i class="fa fa-times-circle"></i>
|
||||||
<translate>Filter</translate>
|
<translate>Filter</translate>
|
||||||
</span>
|
</span>
|
||||||
<!-- State filter -->
|
<!-- State filter -->
|
||||||
<span class="dropdown" uib-dropdown>
|
<span uib-dropdown>
|
||||||
<span class="pointer" id="dropdownState" uib-dropdown-toggle
|
<span class="pointer" id="dropdownState" uib-dropdown-toggle
|
||||||
ng-class="{'bold': multiselect.filters.state.length > 0, 'disabled': isDeleteMode}"
|
ng-class="{'bold': filter.multiselectFilters.state.length > 0, 'disabled': isSelectMode}"
|
||||||
ng-disabled="isDeleteMode">
|
ng-disabled="isSelectMode">
|
||||||
<translate>State</translate>
|
<translate>State</translate>
|
||||||
<span class="caret"></span>
|
<span class="caret"></span>
|
||||||
</span>
|
</span>
|
||||||
<ul class="dropdown-menu dropdown-menu-right dropdown-entries" aria-labelledby="dropdownState">
|
<ul class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownState">
|
||||||
<li ng-repeat="state in states" ng-class="state.workflowHeader ? 'dropdown-header' : ''">
|
<li ng-repeat="state in states" ng-class="state.workflowHeader ? 'dropdown-header' : ''">
|
||||||
<div ng-if="state.workflowHeader">
|
<a ng-if="state.workflowHeader">
|
||||||
{{ state.name | translate }}
|
{{ state.name | translate }}
|
||||||
</div>
|
</a>
|
||||||
<div ng-if="!state.workflowHeader"
|
<a href ng-if="!state.workflowHeader"
|
||||||
ng-click="operateMultiselectFilter('state', state.id)">
|
ng-click="filter.operateMultiselectFilter('state', state.id, isSelectMode)">
|
||||||
<i class="fa fa-check" ng-if="multiselect.filters.state.indexOf(state.id) > -1"></i>
|
<i class="fa fa-check" ng-if="filter.multiselectFilters.state.indexOf(state.id) > -1"></i>
|
||||||
{{ state.name | translate }}
|
{{ state.name | translate }}
|
||||||
</div>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</span>
|
</span>
|
||||||
<!-- Category filter -->
|
<!-- Category filter -->
|
||||||
<span class="dropdown" uib-dropdown ng-if="categories.length > 0">
|
<span uib-dropdown ng-if="categories.length > 0">
|
||||||
<span class="pointer" id="dropdownCategory" uib-dropdown-toggle
|
<span class="pointer" id="dropdownCategory" uib-dropdown-toggle
|
||||||
ng-class="{'bold': multiselect.filters.category.length > 0, 'disabled': isDeleteMode}"
|
ng-class="{'bold': filter.multiselectFilters.category.length > 0, 'disabled': isSelectMode}"
|
||||||
ng-disabled="isDeleteMode">
|
ng-disabled="isSelectMode">
|
||||||
<translate>Category</translate>
|
<translate>Category</translate>
|
||||||
<span class="caret"></span>
|
<span class="caret"></span>
|
||||||
</span>
|
</span>
|
||||||
<ul class="dropdown-menu dropdown-menu-right dropdown-entries"
|
<ul class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownCategory">
|
||||||
aria-labelledby="dropdownCategory">
|
|
||||||
<li ng-repeat="category in categories">
|
<li ng-repeat="category in categories">
|
||||||
<div ng-click="operateMultiselectFilter('category', category.id)">
|
<a href ng-click="filter.operateMultiselectFilter('category', category.id, isSelectMode)">
|
||||||
<i class="fa fa-check" ng-if="multiselect.filters.category.indexOf(category.id) > -1"></i>
|
<i class="fa fa-check" ng-if="filter.multiselectFilters.category.indexOf(category.id) > -1"></i>
|
||||||
{{ category.name }}
|
{{ category.name }}
|
||||||
</div>
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="divider"></li>
|
||||||
|
<li>
|
||||||
|
<a href ng-click="filter.operateMultiselectFilter('category', -1, isSelectMode)">
|
||||||
|
<i class="fa fa-check" ng-if="filter.multiselectFilters.category.indexOf(-1) > -1"></i>
|
||||||
|
<translate>No category set</translate>
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</span>
|
</span>
|
||||||
<!-- Motion block filter -->
|
<!-- Motion block filter -->
|
||||||
<span class="dropdown" uib-dropdown ng-if="motionBlocks.length > 0">
|
<span uib-dropdown ng-if="motionBlocks.length > 0">
|
||||||
<span class="pointer" id="dropdownBlock" uib-dropdown-toggle
|
<span class="pointer" id="dropdownBlock" uib-dropdown-toggle
|
||||||
ng-class="{'bold': multiselect.filters.motionBlock.length > 0, 'disabled': isDeleteMode}"
|
ng-class="{'bold': filter.multiselectFilters.motionBlock.length > 0, 'disabled': isSelectMode}"
|
||||||
ng-disabled="isDeleteMode">
|
ng-disabled="isSelectMode">
|
||||||
<translate>Motion block</translate>
|
<translate>Motion block</translate>
|
||||||
<span class="caret"></span>
|
<span class="caret"></span>
|
||||||
</span>
|
</span>
|
||||||
<ul class="dropdown-menu dropdown-menu-right dropdown-entries"
|
<ul class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownBlock">
|
||||||
aria-labelledby="dropdownBlock">
|
|
||||||
<li ng-repeat="block in motionBlocks">
|
<li ng-repeat="block in motionBlocks">
|
||||||
<div ng-click="operateMultiselectFilter('motionBlock', block.id)">
|
<a href ng-click="filter.operateMultiselectFilter('motionBlock', block.id, isSelectMode)">
|
||||||
<i class="fa fa-check" ng-if="multiselect.filters.motionBlock.indexOf(block.id) > -1"></i>
|
<i class="fa fa-check" ng-if="filter.multiselectFilters.motionBlock.indexOf(block.id) > -1"></i>
|
||||||
{{ block.title }}
|
{{ block.title }}
|
||||||
</div>
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="divider"></li>
|
||||||
|
<li>
|
||||||
|
<a href ng-click="filter.operateMultiselectFilter('motionBlock', -1, isSelectMode)">
|
||||||
|
<i class="fa fa-check" ng-if="filter.multiselectFilters.motionBlock.indexOf(-1) > -1"></i>
|
||||||
|
<translate>No motion block set</translate>
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</span>
|
</span>
|
||||||
<!-- Tag filter -->
|
<!-- Tag filter -->
|
||||||
<span class="dropdown" uib-dropdown ng-if="tags.length > 0">
|
<span uib-dropdown ng-if="tags.length > 0">
|
||||||
<span class="pointer" id="dropdownTag" uib-dropdown-toggle
|
<span class="pointer" id="dropdownTag" uib-dropdown-toggle
|
||||||
ng-class="{'bold': multiselect.filters.tag.length > 0, 'disabled': isDeleteMode}"
|
ng-class="{'bold': filter.multiselectFilters.tag.length > 0, 'disabled': isSelectMode}"
|
||||||
ng-disabled="isDeleteMode">
|
ng-disabled="isSelectMode">
|
||||||
<translate>Tag</translate>
|
<translate>Tag</translate>
|
||||||
<span class="caret"></span>
|
<span class="caret"></span>
|
||||||
</span>
|
</span>
|
||||||
<ul class="dropdown-menu dropdown-menu-right dropdown-entries"
|
<ul class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownTag">
|
||||||
aria-labelledby="dropdownTag">
|
|
||||||
<li ng-repeat="tag in tags">
|
<li ng-repeat="tag in tags">
|
||||||
<div ng-click="operateMultiselectFilter('tag', tag.id)">
|
<a href ng-click="filter.operateMultiselectFilter('tag', tag.id, isSelectMode)">
|
||||||
<i class="fa fa-check" ng-if="multiselect.filters.tag.indexOf(tag.id) > -1"></i>
|
<i class="fa fa-check" ng-if="filter.multiselectFilters.tag.indexOf(tag.id) > -1"></i>
|
||||||
{{ tag.name }}
|
{{ tag.name }}
|
||||||
</div>
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="divider"></li>
|
||||||
|
<li>
|
||||||
|
<a href ng-click="filter.operateMultiselectFilter('tag', -1, isSelectMode)">
|
||||||
|
<i class="fa fa-check" ng-if="filter.multiselectFilters.tag.indexOf(-1) > -1"></i>
|
||||||
|
<translate>No tag set</translate>
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</span>
|
</span>
|
||||||
<!-- dropdown sort -->
|
<!-- dropdown sort -->
|
||||||
<span class="dropdown" uib-dropdown>
|
<span uib-dropdown>
|
||||||
<span class="pointer" id="dropdownSort" uib-dropdown-toggle
|
<span class="pointer" id="dropdownSort" uib-dropdown-toggle
|
||||||
ng-class="{'disabled': isDeleteMode}"
|
ng-class="{'disabled': isSelectMode}"
|
||||||
ng-disabled="isDeleteMode">
|
ng-disabled="isSelectMode">
|
||||||
<translate>Sort</translate>
|
<translate>Sort</translate>
|
||||||
<span class="caret"></span>
|
<span class="caret"></span>
|
||||||
</span>
|
</span>
|
||||||
<ul class="dropdown-menu dropdown-menu-right dropdown-entries" aria-labelledby="dropdownSort">
|
<ul class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownSort">
|
||||||
<!-- item -->
|
<!-- item -->
|
||||||
<li>
|
<li>
|
||||||
<div ng-click="toggleSort('agenda_item.getItemNumberWithAncestors()')">
|
<a href ng-click="sort.toggle('agenda_item.getItemNumberWithAncestors()')">
|
||||||
<translate translate-comment="short form of agenda item">Item</translate>
|
<translate translate-comment="short form of agenda item">Item</translate>
|
||||||
<span class="spacer-right pull-right"></span>
|
<span class="spacer-right pull-right"></span>
|
||||||
<i class="pull-right fa"
|
<i class="pull-right fa"
|
||||||
ng-style="{'visibility': sortColumn === 'agenda_item.getItemNumberWithAncestors()' ? 'visible' : 'hidden'}"
|
ng-style="{'visibility': sort.column === 'agenda_item.getItemNumberWithAncestors()' ? 'visible' : 'hidden'}"
|
||||||
ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
|
ng-class="sort.reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
|
||||||
</i>
|
</i>
|
||||||
</div>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<!-- all other sortOptions -->
|
<!-- all other sortOptions -->
|
||||||
<li ng-repeat="option in sortOptions">
|
<li ng-repeat="option in sortOptions">
|
||||||
<div ng-click="toggleSort(option.name)">
|
<a href ng-click="sort.toggle(option.name)">
|
||||||
{{ option.display_name | translate }}
|
{{ option.display_name | translate }}
|
||||||
<span class="spacer-right pull-right"></span>
|
<span class="spacer-right pull-right"></span>
|
||||||
<i class="pull-right fa"
|
<i class="pull-right fa"
|
||||||
ng-style="{'visibility': sortColumn === option.name ? 'visible' : 'hidden'}"
|
ng-style="{'visibility': sort.column === option.name ? 'visible' : 'hidden'}"
|
||||||
ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
|
ng-class="sort.reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
|
||||||
</i>
|
</i>
|
||||||
</div>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</span>
|
</span>
|
||||||
@ -221,49 +240,71 @@
|
|||||||
<span class="form-group">
|
<span class="form-group">
|
||||||
<span class="input-group">
|
<span class="input-group">
|
||||||
<span class="input-group-addon"><i class="fa fa-search"></i></span>
|
<span class="input-group-addon"><i class="fa fa-search"></i></span>
|
||||||
<input type="text" ng-model="filter.search" class="form-control"
|
<input type="text" ng-model="filter.filterString" class="form-control"
|
||||||
placeholder="{{ 'Search' | translate}}" ng-disabled="isDeleteMode">
|
placeholder="{{ 'Search' | translate}}" ng-disabled="isSelectMode">
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<!-- show all selected multiselectoptions -->
|
<!-- show all selected multiselectoptions -->
|
||||||
<span>
|
<span>
|
||||||
|
<!-- state -->
|
||||||
<span ng-repeat="state in states" class="pointer spacer-left-lg"
|
<span ng-repeat="state in states" class="pointer spacer-left-lg"
|
||||||
ng-if="!state.workflowHeader && multiselect.filters.state.indexOf(state.id) > -1"
|
ng-if="!state.workflowHeader && filter.multiselectFilters.state.indexOf(state.id) > -1"
|
||||||
ng-click="operateMultiselectFilter('state', state.id)"
|
ng-click="filter.operateMultiselectFilter('state', state.id, isSelectMode)"
|
||||||
ng-class="{'disabled': isDeleteMode}">
|
ng-class="{'disabled': isSelectMode}">
|
||||||
<span class="nobr">
|
<span class="nobr">
|
||||||
<i class="fa fa-times-circle"></i>
|
<i class="fa fa-times-circle"></i>
|
||||||
{{ state.name | translate }}
|
{{ state.name | translate }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
<!-- category -->
|
||||||
<span ng-repeat="category in categories" class="pointer spacer-left-lg"
|
<span ng-repeat="category in categories" class="pointer spacer-left-lg"
|
||||||
ng-if="multiselect.filters.category.indexOf(category.id) > -1"
|
ng-if="filter.multiselectFilters.category.indexOf(category.id) > -1"
|
||||||
ng-click="operateMultiselectFilter('category', category.id)"
|
ng-click="filter.operateMultiselectFilter('category', category.id, isSelectMode)"
|
||||||
ng-class="{'disabled': isDeleteMode}">
|
ng-class="{'disabled': isSelectMode}">
|
||||||
<span class="nobr">
|
<span class="nobr">
|
||||||
<i class="fa fa-times-circle"></i>
|
<i class="fa fa-times-circle"></i>
|
||||||
{{ category.name }}
|
{{ category.name }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
<span ng-if="filter.multiselectFilters.category.indexOf(-1) > -1" class="pointer spacer-left-lg"
|
||||||
|
ng-click="filter.operateMultiselectFilter('category', -1, isSelectMode)"
|
||||||
|
ng-class="{'disabled': isSelectMode}">
|
||||||
|
<i class="fa fa-times-circle"></i>
|
||||||
|
<translate>No category set</translate>
|
||||||
|
</span>
|
||||||
|
<!-- motion block -->
|
||||||
<span ng-repeat="motionBlock in motionBlocks" class="pointer spacer-left-lg"
|
<span ng-repeat="motionBlock in motionBlocks" class="pointer spacer-left-lg"
|
||||||
ng-if="multiselect.filters.motionBlock.indexOf(motionBlock.id) > -1"
|
ng-if="filter.multiselectFilters.motionBlock.indexOf(motionBlock.id) > -1"
|
||||||
ng-click="operateMultiselectFilter('motionBlock', motionBlock.id)"
|
ng-click="filter.operateMultiselectFilter('motionBlock', motionBlock.id, isSelectMode)"
|
||||||
ng-class="{'disabled': isDeleteMode}">
|
ng-class="{'disabled': isSelectMode}">
|
||||||
<span class="nobr">
|
<span class="nobr">
|
||||||
<i class="fa fa-times-circle"></i>
|
<i class="fa fa-times-circle"></i>
|
||||||
{{ motionBlock.title }}
|
{{ motionBlock.title }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
<span ng-if="filter.multiselectFilters.motionBlock.indexOf(-1) > -1" class="pointer spacer-left-lg"
|
||||||
|
ng-click="filter.operateMultiselectFilter('motionBlock', -1, isSelectMode)"
|
||||||
|
ng-class="{'disabled': isSelectMode}">
|
||||||
|
<i class="fa fa-times-circle"></i>
|
||||||
|
<translate>No motion block set</translate>
|
||||||
|
</span>
|
||||||
|
<!-- tags -->
|
||||||
<span ng-repeat="tag in tags" class="pointer spacer-left-lg"
|
<span ng-repeat="tag in tags" class="pointer spacer-left-lg"
|
||||||
ng-if="multiselect.flters.tag.indexOf(tag.id) > -1"
|
ng-if="filter.multiselectFilters.tag.indexOf(tag.id) > -1"
|
||||||
ng-click="operateMultiselectFilter('tag', tag.id)"
|
ng-click="filter.operateMultiselectFilter('tag', tag.id, isSelectMode)"
|
||||||
ng-class="{'disabled': isDeleteMode}">
|
ng-class="{'disabled': isSelectMode}">
|
||||||
<span class="nobr">
|
<span class="nobr">
|
||||||
<i class="fa fa-times-circle"></i>
|
<i class="fa fa-times-circle"></i>
|
||||||
{{ tag.name }}
|
{{ tag.name }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
<span ng-if="filter.multiselectFilters.tag.indexOf(-1) > -1" class="pointer spacer-left-lg"
|
||||||
|
ng-click="filter.operateMultiselectFilter('tag', -1, isSelectMode)"
|
||||||
|
ng-class="{'disabled': isSelectMode}">
|
||||||
|
<i class="fa fa-times-circle"></i>
|
||||||
|
<translate>No tag set</translate>
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -273,16 +314,16 @@
|
|||||||
ng-mouseleave="motion.hover=false"
|
ng-mouseleave="motion.hover=false"
|
||||||
ng-class="{'projected': motion.isProjected().length}"
|
ng-class="{'projected': motion.isProjected().length}"
|
||||||
ng-repeat="motion in motionsFiltered = (motions
|
ng-repeat="motion in motionsFiltered = (motions
|
||||||
| osFilter: filter.search : multiselect.getFilterString
|
| osFilter: filter.filterString : filter.getObjectQueryString
|
||||||
| MultiselectFilter: multiselect.filters.state : getItemId.state
|
| MultiselectFilter: filter.multiselectFilters.state : getItemId.state
|
||||||
| MultiselectFilter: multiselect.filters.category : getItemId.category
|
| MultiselectFilter: filter.multiselectFilters.category : getItemId.category
|
||||||
| MultiselectFilter: multiselect.filters.motionBlock : getItemId.motionBlock
|
| MultiselectFilter: filter.multiselectFilters.motionBlock : getItemId.motionBlock
|
||||||
| MultiselectFilter: multiselect.filters.tag : getItemId.tag
|
| MultiselectFilter: filter.multiselectFilters.tag : getItemId.tag
|
||||||
| toArray
|
| toArray
|
||||||
| orderBy: sortColumn : reverse)">
|
| orderBy: sort.column : sort.reverse)">
|
||||||
|
|
||||||
<!-- select column -->
|
<!-- select column -->
|
||||||
<div ng-show="isDeleteMode" os-perms="motions.can_manage" class="col-xs-1 centered">
|
<div ng-show="isSelectMode" os-perms="motions.can_manage" class="col-xs-1 centered">
|
||||||
<i class="fa text-danger pointer" ng-click="motion.selected=!motion.selected"
|
<i class="fa text-danger pointer" ng-click="motion.selected=!motion.selected"
|
||||||
ng-class="motion.selected ? 'fa-check-square-o' : 'fa-square-o'"></i>
|
ng-class="motion.selected ? 'fa-check-square-o' : 'fa-square-o'"></i>
|
||||||
</div>
|
</div>
|
||||||
@ -293,12 +334,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- main content column -->
|
<!-- main content column -->
|
||||||
<div class="col-xs-6 content">
|
<div class="col-xs-6 content">
|
||||||
<div class="identifier-col">
|
<div class="id-col">
|
||||||
<span ng-show="motion.identifier">
|
<span ng-show="motion.identifier">
|
||||||
{{ motion.identifier }}
|
{{ motion.identifier }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="title-col">
|
<div>
|
||||||
<!-- ID and title -->
|
<!-- ID and title -->
|
||||||
<div>
|
<div>
|
||||||
<strong>
|
<strong>
|
||||||
@ -310,8 +351,8 @@
|
|||||||
{{ motion.getStateName() }}
|
{{ motion.getStateName() }}
|
||||||
</span>
|
</span>
|
||||||
<span os-perms="motions.can_manage" ng-class="{'hiddenDiv': !motion.stateHover}" uib-dropdown>
|
<span os-perms="motions.can_manage" ng-class="{'hiddenDiv': !motion.stateHover}" uib-dropdown>
|
||||||
<i class="fa fa-cog pointer" uib-dropdown-toggle id="state-dropdown{{ motion.id }}"></i>
|
<i class="fa fa-cog pointer" uib-dropdown-toggle id="stateDropdown{{ motion.id }}"></i>
|
||||||
<ul uib-dropdown-menu aria-labelledby="state-dropdown{{ motion.id }}">
|
<ul class="dropdown-menu" aria-labelledby="stateDropdown{{ motion.id }}">
|
||||||
<li ng-repeat="state in motion.state.getNextStates()">
|
<li ng-repeat="state in motion.state.getNextStates()">
|
||||||
<a href ng-click="updateState(motion, state.id)">{{ state.action_word | translate }}</a>
|
<a href ng-click="updateState(motion, state.id)">{{ state.action_word | translate }}</a>
|
||||||
</li>
|
</li>
|
||||||
@ -353,12 +394,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- additional content column -->
|
<!-- additional content column -->
|
||||||
<style>
|
<div class="col-xs-4 content" ng-style="{'width': isSelectMode ? 'calc(50% - 120px)' : 'calc(50% - 70px)'}">
|
||||||
#motion-table .row .col-xs-4 {
|
|
||||||
width: calc(50% - {{ isDeleteMode ? '120' : '70' }}px);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<div class="col-xs-4 content">
|
|
||||||
<div style="width: 60%;" class="optional">
|
<div style="width: 60%;" class="optional">
|
||||||
<small>
|
<small>
|
||||||
<!-- Category dropdown for manage user -->
|
<!-- Category dropdown for manage user -->
|
||||||
@ -366,7 +402,7 @@
|
|||||||
ng-mouseover="motion.categoryHover=true"
|
ng-mouseover="motion.categoryHover=true"
|
||||||
ng-mouseleave="motion.categoryHover=false">
|
ng-mouseleave="motion.categoryHover=false">
|
||||||
<span uib-dropdown>
|
<span uib-dropdown>
|
||||||
<span id="dropdown-category{{ motion.id }}" class="pointer"
|
<span id="dropdownCategory{{ motion.id }}" class="pointer"
|
||||||
uib-dropdown-toggle uib-tooltip="{{ 'Set a category' | translate }}"
|
uib-dropdown-toggle uib-tooltip="{{ 'Set a category' | translate }}"
|
||||||
tooltip-class="nobr">
|
tooltip-class="nobr">
|
||||||
<span ng-if="motion.category == null" ng-show="motion.hover">
|
<span ng-if="motion.category == null" ng-show="motion.hover">
|
||||||
@ -379,12 +415,12 @@
|
|||||||
<i class="fa fa-cog fa-lg spacer-left" ng-show="motion.categoryHover"></i>
|
<i class="fa fa-cog fa-lg spacer-left" ng-show="motion.categoryHover"></i>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<ul class="dropdown-menu dropdown-entries" aria-labelledby="dropdown-category{{ motion.id }}">
|
<ul class="dropdown-menu" aria-labelledby="dropdownCategory{{ motion.id }}">
|
||||||
<li ng-repeat="category in categories">
|
<li ng-repeat="category in categories">
|
||||||
<div ng-click="toggle_category(motion, category)">
|
<a href ng-click="toggleCategory(motion, category)">
|
||||||
<i class="fa fa-check" ng-if="category.id == motion.category.id"></i>
|
<i class="fa fa-check" ng-if="category.id == motion.category.id"></i>
|
||||||
{{ category.name }}
|
{{ category.name }}
|
||||||
</div>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</span>
|
</span>
|
||||||
@ -400,7 +436,7 @@
|
|||||||
ng-mouseover="motion.motionBlockHover=true"
|
ng-mouseover="motion.motionBlockHover=true"
|
||||||
ng-mouseleave="motion.motionBlockHover=false">
|
ng-mouseleave="motion.motionBlockHover=false">
|
||||||
<span uib-dropdown>
|
<span uib-dropdown>
|
||||||
<span id="dropdown-motionBlock{{ motion.id }}" class="pointer"
|
<span id="dropdownMotionBlock{{ motion.id }}" class="pointer"
|
||||||
uib-dropdown-toggle uib-tooltip="{{ 'Set a motion block' | translate }}"
|
uib-dropdown-toggle uib-tooltip="{{ 'Set a motion block' | translate }}"
|
||||||
tooltip-class="nobr">
|
tooltip-class="nobr">
|
||||||
<span ng-if="motion.motionBlock == null" ng-show="motion.hover">
|
<span ng-if="motion.motionBlock == null" ng-show="motion.hover">
|
||||||
@ -413,12 +449,12 @@
|
|||||||
<i class="fa fa-cog fa-lg spacer-left" ng-show="motion.motionBlockHover"></i>
|
<i class="fa fa-cog fa-lg spacer-left" ng-show="motion.motionBlockHover"></i>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<ul class="dropdown-menu dropdown-entries" aria-labelledby="dropdown-motionBlock{{ motion.id }}">
|
<ul class="dropdown-menu" aria-labelledby="dropdownMotionBlock{{ motion.id }}">
|
||||||
<li ng-repeat="motionBlock in motionBlocks">
|
<li ng-repeat="motionBlock in motionBlocks">
|
||||||
<div ng-click="toggle_motionBlock(motion, motionBlock)">
|
<a href ng-click="toggleMotionBlock(motion, motionBlock)">
|
||||||
<i class="fa fa-check" ng-if="motionBlock.id == motion.motionBlock.id"></i>
|
<i class="fa fa-check" ng-if="motionBlock.id == motion.motionBlock.id"></i>
|
||||||
{{ motionBlock.title }}
|
{{ motionBlock.title }}
|
||||||
</div>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</span>
|
</span>
|
||||||
@ -434,7 +470,7 @@
|
|||||||
ng-mouseover="motion.tagHover=true"
|
ng-mouseover="motion.tagHover=true"
|
||||||
ng-mouseleave="motion.tagHover=false">
|
ng-mouseleave="motion.tagHover=false">
|
||||||
<span uib-dropdown>
|
<span uib-dropdown>
|
||||||
<span id="dropdown-tags{{ motion.id }}" class="pointer"
|
<span id="dropdownTags{{ motion.id }}" class="pointer"
|
||||||
uib-dropdown-toggle uib-tooltip="{{ 'Add a tag' | translate }}"
|
uib-dropdown-toggle uib-tooltip="{{ 'Add a tag' | translate }}"
|
||||||
tooltip-class="nobr">
|
tooltip-class="nobr">
|
||||||
<span ng-if="motion.tags.length == 0" ng-show="motion.hover">
|
<span ng-if="motion.tags.length == 0" ng-show="motion.hover">
|
||||||
@ -449,12 +485,12 @@
|
|||||||
<i class="fa fa-cog fa-lg spacer-left" ng-show="motion.tagHover"></i>
|
<i class="fa fa-cog fa-lg spacer-left" ng-show="motion.tagHover"></i>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<ul class="dropdown-menu dropdown-entries" aria-labelledby="dropdown-tags{{ motion.id }}">
|
<ul class="dropdown-menu" aria-labelledby="dropdownTags{{ motion.id }}">
|
||||||
<li ng-repeat="tag in tags">
|
<li ng-repeat="tag in tags">
|
||||||
<div ng-click="toggle_tag(motion, tag)">
|
<a href ng-click="toggleTag(motion, tag)">
|
||||||
<i class="fa fa-check" ng-if="has_tag(motion, tag)"></i>
|
<i class="fa fa-check" ng-if="hasTag(motion, tag)"></i>
|
||||||
{{ tag.name }}
|
{{ tag.name }}
|
||||||
</div>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</span>
|
</span>
|
||||||
@ -475,7 +511,7 @@
|
|||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<div style="width: 10%;" class="pull-right optional">
|
<div style="width: 10%;" class="pull-right optional">
|
||||||
<div class="pull-right" ng-if="config('motions_min_supporters') != 0"
|
<div class="centered" ng-if="config('motions_min_supporters') != 0"
|
||||||
uib-tooltip="{{ motion.supporters.length }} {{ 'Supporters' | translate }}
|
uib-tooltip="{{ motion.supporters.length }} {{ 'Supporters' | translate }}
|
||||||
{{ (config('motions_min_supporters') - motion.supporters.length) > 0 ? '(' + (config('motions_min_supporters') - motion.supporters.length) + ' ' + ('needed' | translate) + ')': '' }}"
|
{{ (config('motions_min_supporters') - motion.supporters.length) > 0 ? '(' + (config('motions_min_supporters') - motion.supporters.length) + ' ' + ('needed' | translate) + ')': '' }}"
|
||||||
tooltip-class="nobr">
|
tooltip-class="nobr">
|
||||||
|
@ -491,10 +491,12 @@ angular.module('OpenSlidesApp.users.site', [
|
|||||||
'PdfMakeDocumentProvider',
|
'PdfMakeDocumentProvider',
|
||||||
'gettextCatalog',
|
'gettextCatalog',
|
||||||
'UserCsvExport',
|
'UserCsvExport',
|
||||||
'Multiselect',
|
'osTableFilter',
|
||||||
|
'osTableSort',
|
||||||
|
'gettext',
|
||||||
function($scope, $state, $http, ngDialog, UserForm, User, Group, PasswordGenerator, Projector, ProjectionDefault,
|
function($scope, $state, $http, ngDialog, UserForm, User, Group, PasswordGenerator, Projector, ProjectionDefault,
|
||||||
UserListContentProvider, Config, UserAccessDataListContentProvider, PdfMakeDocumentProvider, gettextCatalog,
|
UserListContentProvider, Config, UserAccessDataListContentProvider, PdfMakeDocumentProvider, gettextCatalog,
|
||||||
UserCsvExport, Multiselect) {
|
UserCsvExport, osTableFilter, osTableSort, gettext) {
|
||||||
User.bindAll({}, $scope, 'users');
|
User.bindAll({}, $scope, 'users');
|
||||||
Group.bindAll({where: {id: {'>': 1}}}, $scope, 'groups');
|
Group.bindAll({where: {id: {'>': 1}}}, $scope, 'groups');
|
||||||
$scope.$watch(function () {
|
$scope.$watch(function () {
|
||||||
@ -507,20 +509,46 @@ angular.module('OpenSlidesApp.users.site', [
|
|||||||
});
|
});
|
||||||
$scope.alert = {};
|
$scope.alert = {};
|
||||||
|
|
||||||
$scope.multiselect = Multiselect.instance();
|
// Filtering
|
||||||
$scope.multiselect.filters = {
|
$scope.filter = osTableFilter.createInstance();
|
||||||
|
$scope.filter.multiselectFilters = {
|
||||||
group: [],
|
group: [],
|
||||||
};
|
};
|
||||||
$scope.multiselect.propertyList = ['first_name', 'last_name', 'title', 'number', 'comment', 'structure_level'];
|
$scope.filter.propertyList = ['first_name', 'last_name', 'title', 'number', 'comment', 'structure_level'];
|
||||||
$scope.multiselect.PropertyDict = {
|
$scope.filter.propertyDict = {
|
||||||
'groups_id' : function (group_id) {
|
'groups_id' : function (group_id) {
|
||||||
return Group.get(group_id).name;
|
return Group.get(group_id).name;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
$scope.filter.booleanFilters = {
|
||||||
|
isPresent: {
|
||||||
|
value: undefined,
|
||||||
|
displayName: gettext('Present'),
|
||||||
|
choiceYes: gettext('Is present'),
|
||||||
|
choiceNo: gettext('Is not present'),
|
||||||
|
needExtraPermission: true,
|
||||||
|
},
|
||||||
|
isActive: {
|
||||||
|
value: undefined,
|
||||||
|
displayName: gettext('Active'),
|
||||||
|
choiceYes: gettext('Is active'),
|
||||||
|
choiceNo: gettext('Is not active'),
|
||||||
|
needExtraPermission: true,
|
||||||
|
},
|
||||||
|
isCommittee: {
|
||||||
|
value: undefined,
|
||||||
|
displayName: gettext('Committee'),
|
||||||
|
choiceYes: gettext('Is committee'),
|
||||||
|
choiceNo: gettext('Is not committee'),
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
$scope.getItemId = {
|
$scope.getItemId = {
|
||||||
group: function (user) {return user.groups_id;},
|
group: function (user) {return user.groups_id;},
|
||||||
};
|
};
|
||||||
// setup table sorting
|
// Sorting
|
||||||
|
$scope.sort = osTableSort.createInstance();
|
||||||
|
$scope.sort.column = $scope.config('users_sort_by');
|
||||||
$scope.sortOptions = [
|
$scope.sortOptions = [
|
||||||
{name: 'first_name',
|
{name: 'first_name',
|
||||||
display_name: 'First name'},
|
display_name: 'First name'},
|
||||||
@ -539,39 +567,6 @@ angular.module('OpenSlidesApp.users.site', [
|
|||||||
{name: 'comment',
|
{name: 'comment',
|
||||||
display_name: 'Comment'},
|
display_name: 'Comment'},
|
||||||
];
|
];
|
||||||
$scope.sortColumn = $scope.config('users_sort_by');
|
|
||||||
$scope.filterPresent = '';
|
|
||||||
$scope.reverse = false;
|
|
||||||
// function to sort by clicked column
|
|
||||||
$scope.toggleSort = function ( column ) {
|
|
||||||
if ( $scope.sortColumn === column ) {
|
|
||||||
$scope.reverse = !$scope.reverse;
|
|
||||||
}
|
|
||||||
$scope.sortColumn = column;
|
|
||||||
};
|
|
||||||
// function to operate the multiselectFilter
|
|
||||||
$scope.operateMultiselectFilter = function (filter, id) {
|
|
||||||
if (!$scope.isSelectMode) {
|
|
||||||
$scope.multiselect.operate(filter, id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// for reset-button
|
|
||||||
$scope.resetFilters = function () {
|
|
||||||
$scope.multiselect.resetFilters();
|
|
||||||
if ($scope.filter) {
|
|
||||||
$scope.filter.search = '';
|
|
||||||
}
|
|
||||||
$scope.isPresentFilter = undefined;
|
|
||||||
$scope.isActiveFilter = undefined;
|
|
||||||
$scope.isCommitteeFilter = undefined;
|
|
||||||
};
|
|
||||||
$scope.areFiltersSet = function () {
|
|
||||||
return $scope.multiselect.areFiltersSet() ||
|
|
||||||
$scope.isPresentFilter ||
|
|
||||||
$scope.isActiveFilter ||
|
|
||||||
$scope.isCommitteeFilter ||
|
|
||||||
($scope.filter ? $scope.filter.search : false);
|
|
||||||
};
|
|
||||||
|
|
||||||
// pagination
|
// pagination
|
||||||
$scope.currentPage = 1;
|
$scope.currentPage = 1;
|
||||||
|
@ -116,20 +116,20 @@
|
|||||||
<!-- filter users (for user with 'can_see_extra_data' permission) - consider present filter -->
|
<!-- filter users (for user with 'can_see_extra_data' permission) - consider present filter -->
|
||||||
<div os-perms="users.can_see_extra_data">
|
<div os-perms="users.can_see_extra_data">
|
||||||
<span ng-repeat="user in $parent.usersFiltered = (users
|
<span ng-repeat="user in $parent.usersFiltered = (users
|
||||||
| osFilter: filter.search : multiselect.getFilterString
|
| osFilter: filter.filterString : filter.getObjectQueryString
|
||||||
| filter: {is_present: isPresentFilter}
|
| filter: {is_present: filter.booleanFilters.isPresent.value}
|
||||||
| filter: {is_active: isActiveFilter}
|
| filter: {is_active: filter.booleanFilters.isActive.value}
|
||||||
| filter: {is_committee: isCommitteeFilter}
|
| filter: {is_committee: filter.booleanFilters.isCommittee.value}
|
||||||
| MultiselectFilter: multiselect.filters.group : getItemId.group
|
| MultiselectFilter: filter.multiselectFilters.group : getItemId.group
|
||||||
| orderBy: sortColumn:reverse)"></span>
|
| orderBy: sort.column: sort.reverse)"></span>
|
||||||
</div>
|
</div>
|
||||||
<!-- filter users (for user without 'can_see_extra_data' permission) -->
|
<!-- filter users (for user without 'can_see_extra_data' permission) -->
|
||||||
<div os-perms="!users.can_see_extra_data"
|
<div os-perms="!users.can_see_extra_data"
|
||||||
ng-repeat="user in $parent.usersFiltered = (users
|
ng-repeat="user in $parent.usersFiltered = (users
|
||||||
| osFilter: filter.search : multiselect.getFilterString
|
| osFilter: filter.filterString : filter.getObjectQueryString
|
||||||
| filter: {is_committee: isCommitteeFilter}
|
| filter: {is_committee: filter.booleanFilters.isCommittee.value}
|
||||||
| MultiselectFilter: multiselect.filters.group : getItemId.group
|
| MultiselectFilter: filter.multiselectFilters.group : getItemId.group
|
||||||
| orderBy: sortColumn:reverse)"></div>
|
| orderBy: sort.column: sort.reverse)"></div>
|
||||||
|
|
||||||
<div class="os-table container-fluid">
|
<div class="os-table container-fluid">
|
||||||
<div class="row header-row">
|
<div class="row header-row">
|
||||||
@ -140,100 +140,62 @@
|
|||||||
<div class="col-xs-11 main-header">
|
<div class="col-xs-11 main-header">
|
||||||
<span class="form-inline text-right pull-right">
|
<span class="form-inline text-right pull-right">
|
||||||
<!-- reset Filters -->
|
<!-- reset Filters -->
|
||||||
<span class="sort-spacer pointer" ng-click="resetFilters()"
|
<span class="sort-spacer pointer" ng-click="filter.reset()"
|
||||||
ng-if="areFiltersSet()" ng-disabled="isSelectMode"
|
ng-if="filter.areFiltersSet()" ng-disabled="isSelectMode"
|
||||||
ng-class="{'disabled': isSelectMode}">
|
ng-class="{'disabled': isSelectMode}">
|
||||||
<i class="fa fa-times-circle"></i>
|
<i class="fa fa-times-circle"></i>
|
||||||
<translate>Filter</translate>
|
<translate>Filter</translate>
|
||||||
</span>
|
</span>
|
||||||
<!-- Group filter -->
|
<!-- Group filter -->
|
||||||
<span class="dropdown" uib-dropdown>
|
<span uib-dropdown>
|
||||||
<span class="pointer" id="dropdownGroup" uib-dropdown-toggle
|
<span class="pointer" id="dropdownGroup" uib-dropdown-toggle
|
||||||
ng-class="{'bold': multiselect.filters.group.length > 0, 'disabled': isSelectMode}"
|
ng-class="{'bold': filter.multiselectFilters.group.length > 0, 'disabled': isSelectMode}"
|
||||||
ng-disabled="isSelectMode">
|
ng-disabled="isSelectMode">
|
||||||
<translate>Groups</translate>
|
<translate>Groups</translate>
|
||||||
<span class="caret"></span>
|
<span class="caret"></span>
|
||||||
</span>
|
</span>
|
||||||
<ul class="dropdown-menu dropdown-menu-right dropdown-entries" aria-labelledby="dropdownGroup">
|
<ul class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownGroup">
|
||||||
<li ng-repeat="group in groups">
|
<li ng-repeat="group in groups">
|
||||||
<div ng-click="operateMultiselectFilter('group', group.id)">
|
<a href ng-click="filter.operateMultiselectFilter('group', group.id, isSelectMode)">
|
||||||
<i class="fa fa-check" ng-if="multiselect.filters.group.indexOf(group.id) > -1"></i>
|
<i class="fa fa-check" ng-if="filter.multiselectFilters.group.indexOf(group.id) > -1"></i>
|
||||||
{{ group.name | translate }}
|
{{ group.name | translate }}
|
||||||
</div>
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="divider"></li>
|
||||||
|
<li>
|
||||||
|
<a href ng-click="filter.operateMultiselectFilter('group', -1, isSelectMode)">
|
||||||
|
<i class="fa fa-check" ng-if="filter.multiselectFilters.group.indexOf(-1) > -1"></i>
|
||||||
|
<translate>No group set</translate>
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</span>
|
</span>
|
||||||
<!-- Present filter -->
|
<!-- boolean Filters -->
|
||||||
<span class="dropdown" uib-dropdown>
|
<span ng-repeat="(name, booleanFilter) in filter.booleanFilters"
|
||||||
<span class="pointer" id="dropdownPresent" uib-dropdown-toggle
|
ng-if="!booleanFilter.needExtraPermission || operator.hasPerms('users.can_see_extra_data')" uib-dropdown>
|
||||||
ng-class="{'bold': isPresentFilter !== undefined, 'disabled': isSelectMode}"
|
<span class="pointer" id="dropdown{{ name }}" uib-dropdown-toggle
|
||||||
|
ng-class="{'bold': booleanFilter.value !== undefined, 'disabled': isSelectMode}"
|
||||||
ng-disabled="isSelectMode">
|
ng-disabled="isSelectMode">
|
||||||
<translate>Present</translate>
|
{{ booleanFilter.displayName }}
|
||||||
<span class="caret"></span>
|
<span class="caret"></span>
|
||||||
</span>
|
</span>
|
||||||
<ul class="dropdown-menu dropdown-menu-right dropdown-entries" aria-labelledby="dropdownPresent">
|
<ul class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdown{{ name }}">
|
||||||
<li>
|
<li>
|
||||||
<div ng-click="isPresentFilter = (isPresentFilter ? undefined : true)">
|
<a href ng-click="booleanFilter.value = (booleanFilter.value ? undefined : true)">
|
||||||
<i class="fa" ng-class="{'fa-check': isPresentFilter === true}"></i>
|
<i class="fa" ng-class="{'fa-check': booleanFilter.value === true}"></i>
|
||||||
<translate>Is present</translate>
|
{{ booleanFilter.choiceYes }}
|
||||||
</div>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<div ng-click="isPresentFilter = (isPresentFilter === false) ? undefined : false">
|
<a href ng-click="booleanFilter.value = (booleanFilter.value === false) ? undefined : false">
|
||||||
<i class="fa" ng-class="{'fa-check': isPresentFilter === false}"></i>
|
<i class="fa" ng-class="{'fa-check': booleanFilter.value === false}"></i>
|
||||||
<translate>Is not present</translate>
|
{{ booleanFilter.choiceNo }}
|
||||||
</div>
|
</a>
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</span>
|
|
||||||
<!-- Active filter -->
|
|
||||||
<span class="dropdown" uib-dropdown>
|
|
||||||
<span class="pointer" id="dropdownActive" uib-dropdown-toggle
|
|
||||||
ng-class="{'bold': isActiveFilter !== undefined, 'disabled': isSelectMode}"
|
|
||||||
ng-disabled="isSelecteMode">
|
|
||||||
<translate>Active</translate>
|
|
||||||
<span class="caret"></span>
|
|
||||||
</span>
|
|
||||||
<ul class="dropdown-menu dropdown-menu-right dropdown-entries" aria-labelledby="dropdownActive">
|
|
||||||
<li>
|
|
||||||
<div ng-click="isActiveFilter = (isActiveFilter ? undefined : true)">
|
|
||||||
<i class="fa" ng-class="{'fa-check': isActiveFilter === true}"></i>
|
|
||||||
<translate>Is active</translate>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div ng-click="isActiveFilter = (isActiveFilter === false ? undefined : false)">
|
|
||||||
<i class="fa" ng-class="{'fa-check': isActiveFilter === false}"></i>
|
|
||||||
<translate>Is not active</translate>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</span>
|
|
||||||
<!-- Committee filter -->
|
|
||||||
<span class="dropdown" uib-dropdown>
|
|
||||||
<span class="pointer" id="dropdownCommittee" uib-dropdown-toggle
|
|
||||||
ng-class="{'bold': isCommitteeFilter !== undefined, 'disabled': isSelectMode}"
|
|
||||||
ng-disabled="isSelecteMode">
|
|
||||||
<translate>Committee</translate>
|
|
||||||
<span class="caret"></span>
|
|
||||||
</span>
|
|
||||||
<ul class="dropdown-menu dropdown-menu-right dropdown-entries" aria-labelledby="dropdownCommittee">
|
|
||||||
<li>
|
|
||||||
<div ng-click="isCommitteeFilter = (isCommitteeFilter ? undefined : true)">
|
|
||||||
<i class="fa" ng-class="{'fa-check': isCommitteeFilter === true}"></i>
|
|
||||||
<translate>Yes</translate>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div ng-click="isCommitteeFilter = (isCommitteeFilter === false ? undefined : false)">
|
|
||||||
<i class="fa" ng-class="{'fa-check': isCommitteeFilter === false}"></i>
|
|
||||||
<translate>No</translate>
|
|
||||||
</div>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</span>
|
</span>
|
||||||
<!-- dropdown sort -->
|
<!-- dropdown sort -->
|
||||||
<span class="dropdown" uib-dropdown>
|
<span uib-dropdown>
|
||||||
<span class="pointer" id="dropdownSort" uib-dropdown-toggle
|
<span class="pointer" id="dropdownSort" uib-dropdown-toggle
|
||||||
ng-class="{'disabled': isSelectMode}"
|
ng-class="{'disabled': isSelectMode}"
|
||||||
ng-disabled="isSelectMode">
|
ng-disabled="isSelectMode">
|
||||||
@ -242,14 +204,14 @@
|
|||||||
</span>
|
</span>
|
||||||
<ul class="dropdown-menu dropdown-menu-right dropdown-entries" aria-labelledby="dropdownSort">
|
<ul class="dropdown-menu dropdown-menu-right dropdown-entries" aria-labelledby="dropdownSort">
|
||||||
<li ng-repeat="option in sortOptions">
|
<li ng-repeat="option in sortOptions">
|
||||||
<div ng-click="toggleSort(option.name)">
|
<a href ng-click="sort.toggle(option.name)">
|
||||||
{{ option.display_name | translate }}
|
{{ option.display_name | translate }}
|
||||||
<span class="spacer-right pull-right"></span>
|
<span class="spacer-right pull-right"></span>
|
||||||
<i class="pull-right fa"
|
<i class="pull-right fa"
|
||||||
ng-style="{'visibility': sortColumn === option.name ? 'visible' : 'hidden'}"
|
ng-style="{'visibility': sort.column === option.name ? 'visible' : 'hidden'}"
|
||||||
ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
|
ng-class="sort.reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
|
||||||
</i>
|
</i>
|
||||||
</div>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</span>
|
</span>
|
||||||
@ -257,7 +219,7 @@
|
|||||||
<span class="form-group">
|
<span class="form-group">
|
||||||
<span class="input-group">
|
<span class="input-group">
|
||||||
<span class="input-group-addon"><i class="fa fa-search"></i></span>
|
<span class="input-group-addon"><i class="fa fa-search"></i></span>
|
||||||
<input type="text" ng-model="filter.search" class="form-control" ng-model-options="{debounce: 500}"
|
<input type="text" ng-model="filter.filterString" class="form-control" ng-model-options="{debounce: 500}"
|
||||||
placeholder="{{ 'Search' | translate}}" ng-disabled="isSelectMode">
|
placeholder="{{ 'Search' | translate}}" ng-disabled="isSelectMode">
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
@ -265,39 +227,29 @@
|
|||||||
<!-- show all selected multiselectoptions -->
|
<!-- show all selected multiselectoptions -->
|
||||||
<span>
|
<span>
|
||||||
<span ng-repeat="group in groups" class="pointer spacer-left-lg"
|
<span ng-repeat="group in groups" class="pointer spacer-left-lg"
|
||||||
ng-if="multiselect.filters.group.indexOf(group.id) > -1"
|
ng-if="filter.multiselectFilters.group.indexOf(group.id) > -1"
|
||||||
ng-click="operateMultiselectFilter('group', group.id)"
|
ng-click="filter.operateMultiselectFilter('group', group.id, isSelectMode)"
|
||||||
ng-class="{'disabled': isSelectMode}">
|
ng-class="{'disabled': isSelectMode}">
|
||||||
<span class="nobr">
|
<span class="nobr">
|
||||||
<i class="fa fa-times-circle"></i>
|
<i class="fa fa-times-circle"></i>
|
||||||
{{ group.name | translate }}
|
{{ group.name | translate }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span ng-hide="isPresentFilter === undefined"
|
<span ng-if="filter.multiselectFilters.group.indexOf(-1) > -1" class="pointer spacer-left-lg"
|
||||||
class="pointer spacer-left-lg"
|
ng-click="filter.operateMultiselectFilter('group', -1, isSelectMode)"
|
||||||
ng-click="isPresentFilter = undefined;"
|
|
||||||
ng-class="{'disabled': isSelectMode}">
|
ng-class="{'disabled': isSelectMode}">
|
||||||
<span class="nobr">
|
<i class="fa fa-times-circle"></i>
|
||||||
<i class="fa fa-times-circle"></i>
|
<translate>No group set</translate>
|
||||||
{{ isPresentFilter ? 'Is present' : 'Is not present' | translate }}
|
|
||||||
</span>
|
|
||||||
</span>
|
</span>
|
||||||
<span ng-hide="isActiveFilter === undefined"
|
<!-- for all boolean Filters -->
|
||||||
|
<span ng-repeat="(name, booleanFilter) in filter.booleanFilters"
|
||||||
|
ng-hide="booleanFilter.value === undefined"
|
||||||
class="pointer spacer-left-lg"
|
class="pointer spacer-left-lg"
|
||||||
ng-click="isActiveFilter = undefined;"
|
ng-click="booleanFilter.value = undefined;"
|
||||||
ng-class="{'disabled': isSelectMode}">
|
ng-class="{'disabled': isSelectMode}">
|
||||||
<span class="nobr">
|
<span class="nobr">
|
||||||
<i class="fa fa-times-circle"></i>
|
<i class="fa fa-times-circle"></i>
|
||||||
{{ isActiveFilter ? 'Is active' : 'Is not active' | translate }}
|
{{ booleanFilter.value ? booleanFilter.choiceYes : booleanFilter.choiceNo | translate }}
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<span ng-hide="isCommitteeFilter === undefined"
|
|
||||||
class="pointer spacer-left-lg"
|
|
||||||
ng-click="isCommitteeFilter = undefined;"
|
|
||||||
ng-class="{'disabled': isSelectMode}">
|
|
||||||
<span class="nobr">
|
|
||||||
<i class="fa fa-times-circle"></i>
|
|
||||||
{{ isCommitteeFilter ? 'Is committee' : 'Is not committee' | translate }}
|
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
@ -350,13 +302,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- additional content column -->
|
<!-- additional content column -->
|
||||||
<style>
|
<div class="col-xs-4 content" ng-style="{'width': isSelectMode ? 'calc(50% - 120px)' : 'calc(50% - 70px)'}">
|
||||||
.os-table .row .col-xs-4 {
|
|
||||||
width: calc(50% - {{ isSelectMode ? '120' : '70' }}px);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<div class="col-xs-4 content">
|
|
||||||
<div style="width: 60%;" class="optional">
|
<div style="width: 60%;" class="optional">
|
||||||
<small>
|
<small>
|
||||||
<!-- Group dropdown for manage user -->
|
<!-- Group dropdown for manage user -->
|
||||||
@ -378,12 +326,12 @@
|
|||||||
<i class="fa fa-cog fa-lg spcaer-left" ng-show="user.groupHover"></i>
|
<i class="fa fa-cog fa-lg spcaer-left" ng-show="user.groupHover"></i>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<ul class="dropdown-menu dropdown-entries" aria-labelledby="dropdown-group{{ user.id }}">
|
<ul class="dropdown-menu" aria-labelledby="dropdown-group{{ user.id }}">
|
||||||
<li ng-repeat="group in groups">
|
<li ng-repeat="group in groups">
|
||||||
<div ng-click="toggleGroup(user, group)">
|
<a href ng-click="toggleGroup(user, group)">
|
||||||
<i class="fa fa-check" ng-if="inArray(user.groups_id, group.id)"></i>
|
<i class="fa fa-check" ng-if="inArray(user.groups_id, group.id)"></i>
|
||||||
{{ group.name | translate }}
|
{{ group.name | translate }}
|
||||||
</div>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</span>
|
</span>
|
||||||
@ -409,7 +357,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div style="width: 40%;" class="pull-right" os-perms="users.can_see_extra_data">
|
<div style="width: 40%;" class="pull-right" os-perms="users.can_see_extra_data">
|
||||||
<div os-perms="users.can_manage">
|
<div os-perms="users.can_manage">
|
||||||
<span class="pointer" ng-click="user.is_present = !user.is_present; save(user);">
|
<span class="pointer nobr" ng-click="user.is_present = !user.is_present; save(user);">
|
||||||
<i class="fa" ng-class="user.is_present ? 'fa-check-square-o' : 'fa-square-o'"></i>
|
<i class="fa" ng-class="user.is_present ? 'fa-check-square-o' : 'fa-square-o'"></i>
|
||||||
<span class="spacer-left" translate>Present</span>
|
<span class="spacer-left" translate>Present</span>
|
||||||
</span>
|
</span>
|
||||||
|
Loading…
Reference in New Issue
Block a user