Improved related agenda items
- Added QuickEdit mode for related agenda items - show/hide hidden agenda items - Added ng-dialog for modal create/update dialogs of customslides - use generic links for list of speakers, edit, delete, project - Moved projector elements to sidebar of index template (In progress! It will be improved with new base template design). - Fixed error if chat messages is empty. - Moved ngSanitize to base.js to use ng-bind-html in projector slides.
This commit is contained in:
parent
78c7b2497f
commit
968083e9e5
@ -23,6 +23,7 @@
|
||||
"angular-xeditable": "~0.1.9",
|
||||
"angular-scroll-glue": "~2.0.6",
|
||||
"ngBootbox": "~0.1.2",
|
||||
"ng-dialog": "~0.5.6",
|
||||
"sockjs": "~0.3.4",
|
||||
"font-awesome-bower": "~4.4.0",
|
||||
"js-data": "~2.8.1",
|
||||
|
@ -92,26 +92,82 @@ angular.module('OpenSlidesApp.agenda.site', ['OpenSlidesApp.agenda'])
|
||||
'$scope',
|
||||
'$http',
|
||||
'$state',
|
||||
'ngDialog',
|
||||
'Agenda',
|
||||
'AgendaTree',
|
||||
'Customslide',
|
||||
'Projector',
|
||||
function($scope, $http, $state, Agenda, AgendaTree, Projector) {
|
||||
function($scope, $http, $state, ngDialog, Agenda, AgendaTree, Customslide, Projector) {
|
||||
// Bind agenda tree to the scope
|
||||
$scope.$watch(function () {
|
||||
return Agenda.lastModified();
|
||||
|
||||
}, function () {
|
||||
$scope.items = AgendaTree.getFlatTree(Agenda.getAll());
|
||||
});
|
||||
$scope.alert = {};
|
||||
|
||||
// open detail view link
|
||||
$scope.openDetail = function (id) {
|
||||
$state.go('agenda.item.detail', {id: id});
|
||||
// project related item (content object)
|
||||
$scope.project = function (item) {
|
||||
item.getContentResource().find(item.content_object.id).then(
|
||||
function(object) {
|
||||
object.project();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
// save changed item
|
||||
$scope.save = function (item) {
|
||||
Agenda.save(item);
|
||||
// open new customslide dialog
|
||||
$scope.newDialog = function () {
|
||||
ngDialog.open({
|
||||
template: 'static/templates/core/customslide-form.html',
|
||||
controller: 'CustomslideCreateCtrl',
|
||||
className: 'ngdialog-theme-default wide-form'
|
||||
});
|
||||
};
|
||||
// detail view of related item (content object)
|
||||
$scope.open = function (item) {
|
||||
$state.go(item.content_object.collection.replace('/','.')+'.detail',
|
||||
{id: item.content_object.id});
|
||||
};
|
||||
// edit view of related item (content object)
|
||||
$scope.edit = function (item) {
|
||||
if (item.content_object.collection == "core/customslide") {
|
||||
ngDialog.open({
|
||||
template: 'static/templates/core/customslide-form.html',
|
||||
controller: 'CustomslideUpdateCtrl',
|
||||
className: 'ngdialog-theme-default wide-form',
|
||||
resolve: {
|
||||
customslide: function(Customslide) {
|
||||
return Customslide.find(item.content_object.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
$state.go(item.content_object.collection.replace('/','.')+'.detail.update',
|
||||
{id: item.content_object.id});
|
||||
}
|
||||
};
|
||||
// update changed item
|
||||
$scope.update = function (item) {
|
||||
Agenda.save(item).then(
|
||||
function(success) {
|
||||
item.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 related item
|
||||
$scope.deleteRelatedItem = function (item) {
|
||||
if (item.content_object.collection == 'core/customslide') {
|
||||
Customslide.destroy(item.content_object.id);
|
||||
}
|
||||
};
|
||||
|
||||
// *** delete mode functions ***
|
||||
@ -131,11 +187,14 @@ angular.module('OpenSlidesApp.agenda.site', ['OpenSlidesApp.agenda'])
|
||||
});
|
||||
}
|
||||
};
|
||||
// delete selected item
|
||||
// delete selected items only if items are customslides
|
||||
$scope.delete = function () {
|
||||
angular.forEach($scope.items, function (item) {
|
||||
if (item.selected)
|
||||
Agenda.destroy(item.id);
|
||||
if (item.selected) {
|
||||
if (item.content_object.collection == 'core/customslide') {
|
||||
Customslide.destroy(item.content_object.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
$scope.isDeleteMode = false;
|
||||
$scope.uncheckAll();
|
||||
@ -292,7 +351,8 @@ angular.module('OpenSlidesApp.agenda.site', ['OpenSlidesApp.agenda'])
|
||||
'$scope',
|
||||
'$state',
|
||||
'Agenda',
|
||||
function($scope, $state, Agenda) {
|
||||
'Customslide',
|
||||
function($scope, $state, Agenda, Customslide) {
|
||||
// import from textarea
|
||||
$scope.importByLine = function () {
|
||||
$scope.items = $scope.itemlist[0].split("\n");
|
||||
@ -300,7 +360,7 @@ angular.module('OpenSlidesApp.agenda.site', ['OpenSlidesApp.agenda'])
|
||||
$scope.items.forEach(function(title) {
|
||||
var item = {title: title};
|
||||
// TODO: create all items in bulk mode
|
||||
Agenda.create(item).then(
|
||||
Customslide.create(item).then(
|
||||
function(success) {
|
||||
$scope.importcounter++;
|
||||
}
|
||||
@ -324,8 +384,8 @@ angular.module('OpenSlidesApp.agenda.site', ['OpenSlidesApp.agenda'])
|
||||
var item = {};
|
||||
item.title = obj[i].title;
|
||||
item.text = obj[i].text;
|
||||
item.duration = obj[i].duration;
|
||||
Agenda.create(item).then(
|
||||
// TODO: save also 'duration' in related agenda item
|
||||
Customslide.create(item).then(
|
||||
function(success) {
|
||||
$scope.csvimportcounter++;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
<h1>{{ item.get_title }}</h1>
|
||||
<h1>{{ item.title }}</h1>
|
||||
|
||||
<div id="submenu">
|
||||
<a ui-sref="agenda.item.list" class="btn btn-sm btn-default">
|
||||
<i class="fa fa-angle-double-left fa-lg"></i>
|
||||
<translate>Back to overview</translate>
|
||||
<translate>Back to agenda</translate>
|
||||
</a>
|
||||
<!-- project -->
|
||||
<a os-perms="core.can_manage_projector" class="btn btn-default btn-sm"
|
||||
@ -12,28 +12,11 @@
|
||||
title="{{ 'Project item' | translate }}">
|
||||
<i class="fa fa-video-camera"></i>
|
||||
</a>
|
||||
<!-- edit -->
|
||||
<a ui-sref="agenda.item.detail.update({id: item.id })" os-perms="agenda.can_manage"
|
||||
class="btn btn-default btn-sm"
|
||||
title="{{ 'Edit' | translate}}">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="white-space-pre-line">{{ item.text }}</div>
|
||||
|
||||
<div os-perm="agenda.can_manage">
|
||||
<h2 os-perm="agenda.can_manage" translate>Duration</h2>
|
||||
{{ item.duration }}
|
||||
</div>
|
||||
|
||||
<div os-perm="agenda.can_manage">
|
||||
<h2 os-perm="agenda.can_manage" translate>Comment</h2>
|
||||
<div class="white-space-pre-line">{{ item.comment }}</div>
|
||||
</div>
|
||||
|
||||
|
||||
<h2 translate>List of speakers</h2>
|
||||
<h2>
|
||||
<translate>List of speakers</translate>
|
||||
<span os-perms="agenda.can_manage">
|
||||
<button ng-if="item.speaker_list_closed" ng-click="closeList(false)"
|
||||
class="btn btn-sm btn-danger" translate>
|
||||
@ -44,18 +27,18 @@
|
||||
Opened
|
||||
</button>
|
||||
</span>
|
||||
<!-- project list -->
|
||||
<!-- TODO: project list
|
||||
ng-class="{ 'btn-primary': item.isListOfSpeakersProjected() }"-->
|
||||
<a os-perms="core.can_manage_projector" class="btn btn-default btn-sm"
|
||||
ng-class="{ 'btn-primary': item.isProjected() }"
|
||||
ng-click="projectListOfSpeakers()">
|
||||
<i class="fa fa-video-camera"></i> Project list
|
||||
<i class="fa fa-video-camera"></i>
|
||||
<translate>List of speakers</translate>
|
||||
</a>
|
||||
</h2>
|
||||
|
||||
<!-- TODO:
|
||||
* show only 'add me' OR 'remove me' button
|
||||
-->
|
||||
<div class="well">
|
||||
<button class="btn btn-default btn-xs" type="button"
|
||||
data-toggle="collapse" data-target="#old_speakers"
|
||||
aria-expanded="false" aria-controls="collapseExample">
|
||||
@ -133,4 +116,3 @@
|
||||
<translate>Stop current speaker</translate>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -34,7 +34,7 @@ Keep each item in a single line.</p>
|
||||
<p translate>Please note:</p>
|
||||
<ul><!--TODO: utf-8 encoding still required with angular-csv? -->
|
||||
<li><translate>Required comma separated values</translate>:<br>
|
||||
<code translate>'title, text, duration'</code>
|
||||
<code translate>'title, text'</code>
|
||||
<li translate>Text and duration are optional and may be empty.
|
||||
<li translate>The header in first line is required.
|
||||
<li translate>Required CSV file encoding is UTF-8.
|
||||
|
@ -1,7 +1,7 @@
|
||||
<h1 translate>Agenda</h1>
|
||||
|
||||
<div id="submenu">
|
||||
<a ui-sref="agenda.item.create" os-perms="agenda.can_manage" class="btn btn-primary btn-sm">
|
||||
<a ng-click="newDialog()" ng-dialog-class="ngdialog-theme-plain"os-perms="agenda.can_manage" class="btn btn-primary btn-sm">
|
||||
<i class="fa fa-plus fa-lg"></i>
|
||||
<translate>New</translate>
|
||||
</a>
|
||||
@ -51,6 +51,16 @@
|
||||
<i class="fa fa-trash fa-lg"></i>
|
||||
<translate>Delete selected items</translate>
|
||||
</a>
|
||||
<!-- hidden item filter -->
|
||||
<label>
|
||||
<input type="checkbox" ng-model="filter.noHiddenItems" ng-true-value="1" ng-false-value="">
|
||||
<translate> Hide internal agenda items</translate>
|
||||
</label>
|
||||
<!-- closed filter -->
|
||||
<label>
|
||||
<input type="checkbox" ng-model="filter.noClosedItems" ng-true-value="false" ng-false-value="">
|
||||
<translate> Hide closed items</translate>
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -84,32 +94,95 @@
|
||||
<th class="minimum">
|
||||
<translate>Done</translate>
|
||||
<tbody>
|
||||
<tr ng-repeat="item in items | filter: filter.search"
|
||||
ng-click="openDetail(item.id)"
|
||||
ng-class="{ 'activeline': item.isProjected() }"
|
||||
class="pointer">
|
||||
<tr ng-repeat="item in items | filter: filter.search | filter: {type: filter.noHiddenItems}
|
||||
| filter: {closed: filter.noClosedItems}"
|
||||
class="animate-item"
|
||||
ng-class="{ 'activeline': item.isProjected(), 'selected': item.selected, 'hiddenrow': item.type == 2}">
|
||||
<!-- projector column -->
|
||||
<td ng-show="!isDeleteMode" os-perms="core.can_manage_projector">
|
||||
<a class="btn btn-default btn-sm"
|
||||
ng-class="{ 'btn-primary': item.isProjected() }"
|
||||
ng-click="item.project(); $event.stopPropagation();"
|
||||
ng-click="project(item)"
|
||||
title="{{ 'Project item' | translate }}">
|
||||
<i class="fa fa-video-camera"></i>
|
||||
</a>
|
||||
<!-- delete selection column -->
|
||||
<td ng-show="isDeleteMode" os-perms="agenda.can_manage" class="deleteColumn"
|
||||
ng-click="$event.stopPropagation();">
|
||||
<td ng-show="isDeleteMode" os-perms="agenda.can_manage" class="deleteColumn">
|
||||
<input type="checkbox" ng-model="item.selected">
|
||||
<!-- agenda data columns -->
|
||||
<td>
|
||||
<span ng-repeat="n in [].constructor(item.parentCount) track by $index">–</span>
|
||||
{{ item.item_number }} {{ item.getTitle() }}
|
||||
<td ng-if="!item.quickEdit" ng-mouseover="item.hover=true" ng-mouseleave="item.hover=false">
|
||||
<span ng-if="item.type == 2" title="'Hidden agenda item'|translate"><i class="fa fa-ban"></i></span>
|
||||
<strong>
|
||||
<a href="" ng-click="open(item)">
|
||||
<span ng-repeat="n in [].constructor(item.parentCount) track by $index">–</span>
|
||||
{{ item.getTitle() }}
|
||||
</a>
|
||||
</strong>
|
||||
<div ng-if="item.comment">
|
||||
<small><i class="fa fa-info-circle"></i> {{ item.comment }}</small>
|
||||
</div>
|
||||
<td os-perms="agenda.can_manage" class="optional">
|
||||
<div os-perms="agenda.can_manage" class="hoverActions" ng-class="{'hiddenDiv': !item.hover}">
|
||||
<a ui-sref="agenda.item.detail({id: item.id})" translate>List of speakers</a> |
|
||||
<a href="" ng-click="item.quickEdit=true" translate>QuickEdit</a> |
|
||||
<a href="" ng-click="edit(item)" translate>Edit</a>
|
||||
<!-- TODO: translate confirm message -->
|
||||
<span ng-if="item.content_object.collection == 'core/customslide'"> |
|
||||
<a href="" class="text-danger"
|
||||
ng-bootbox-confirm="Are you sure you want to delete <b>{{ item.getTitle() }}</b>?"
|
||||
ng-bootbox-confirm-action="deleteRelatedItem(item)" translate>Delete</a>
|
||||
</span>
|
||||
</div>
|
||||
<td ng-if="!item.quickEdit" class="optional">
|
||||
{{ item.duration }}
|
||||
<span ng-if="item.duration" translate>h</span>
|
||||
<td ng-click="$event.stopPropagation();">
|
||||
<input type="checkbox" ng-model="item.closed" ng-change="save(item.id);">
|
||||
<td ng-if="!item.quickEdit">
|
||||
<input type="checkbox" ng-model="item.closed" ng-change="update(item.id);">
|
||||
<!-- quickEdit columns -->
|
||||
<td ng-if="item.quickEdit" os-perms-lite="agenda.can_manage" colspan="3">
|
||||
<form ng-submit="update(item)">
|
||||
<h4>{{ item.getTitle() }} <span class="text-muted">– QuickEdit</span></h4>
|
||||
<alert ng-show="alert.show" type="{{ alert.type }}" ng-click="alert={}" close="alert={}">
|
||||
{{alert.msg}}
|
||||
</alert>
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<label for="inputTitle" translate>Title</label>
|
||||
<input type="text" ng-model="item.title" class="form-control input-sm" id="inputTitle">
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<label for="inputComment" translate>Comment</label>
|
||||
<input type="text" ng-model="item.comment" class="form-control input-sm" id="inputComment">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<label for="inputItemNumber" translate>Item number</label>
|
||||
<input type="text" ng-model="item.item_number" class="form-control input-sm" id="inputItemNumber">
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<label for="inputDuration" translate>Duration</label>
|
||||
<input type="text" ng-model="item.duration" class="form-control input-sm" id="inputDuration">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<label>
|
||||
<!-- item type: AGENDA_ITEM = 1, HIDDEN_ITEM = 2 -->
|
||||
<input type="checkbox" ng-model="item.type" ng-true-value="2" ng-false-value="1">
|
||||
<translate> Hidden agenda item</translate>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
</div>
|
||||
</div>
|
||||
<div class="spacer">
|
||||
<button ng-click="item.quickEdit=false" class="btn btn-default pull-left" translate>
|
||||
Cancel
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary" translate>
|
||||
Update
|
||||
</button>
|
||||
<a href="" ng-click="edit(item)" class="pull-right"><translate>Edit</translate>...</a>
|
||||
</div>
|
||||
</form>
|
||||
</table>
|
||||
|
@ -61,8 +61,8 @@ body {
|
||||
.hiddenDiv {
|
||||
visibility: hidden;
|
||||
}
|
||||
/* override bootstraps's progress bar for poll results*/
|
||||
.progress {
|
||||
/* override bootstraps's progress bar for poll results */
|
||||
.pollresults .progress {
|
||||
height: 12px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
@ -70,6 +70,31 @@ body {
|
||||
.result_label {
|
||||
margin-top: 5px;
|
||||
}
|
||||
/* background colors for table rows */
|
||||
tr.offline td, li.offline {
|
||||
background-color: #EAEAEA !important;
|
||||
}
|
||||
tr.hiddenrow td {
|
||||
background-color: #e5e5e5;
|
||||
}
|
||||
tr.activeline td, li.activeline, .projected {
|
||||
background-color: #bed4de;
|
||||
}
|
||||
tr.selected td {
|
||||
background-color: #ff9999;
|
||||
}
|
||||
|
||||
/* override ngdialog-theme-default */
|
||||
.ngdialog.ngdialog-theme-default {
|
||||
padding-top: 50px;
|
||||
}
|
||||
.ngdialog.ngdialog-theme-default.wide-form .ngdialog-content {
|
||||
width: 650px;
|
||||
}
|
||||
.ngdialog h2 {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.inline {
|
||||
display: inline;
|
||||
@ -253,15 +278,7 @@ div.import > div > input[type="text"] {
|
||||
}
|
||||
|
||||
|
||||
tr.offline td, li.offline {
|
||||
background-color: #EAEAEA !important;
|
||||
}
|
||||
tr.activeline td, li.activeline, .projected {
|
||||
background-color: #bed4de;
|
||||
}
|
||||
tr.selected td {
|
||||
background-color: #ff9999;
|
||||
}
|
||||
|
||||
.nopadding {
|
||||
padding: 0;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ angular.module('OpenSlidesApp.core', [
|
||||
'js-data',
|
||||
'gettext',
|
||||
'ngAnimate',
|
||||
'ngSanitize', // TODO: only use this in functions that need it.
|
||||
'ui.bootstrap',
|
||||
'ui.tree',
|
||||
'uiSwitch',
|
||||
|
@ -9,9 +9,9 @@ angular.module('OpenSlidesApp.core.site', [
|
||||
'formly',
|
||||
'formlyBootstrap',
|
||||
'ngBootbox',
|
||||
'ngDialog',
|
||||
'ngMessages',
|
||||
'ngCsvImport',
|
||||
'ngSanitize', // TODO: only use this in functions that need it.
|
||||
'ui.select',
|
||||
'luegg.directives',
|
||||
'xeditable',
|
||||
@ -220,14 +220,6 @@ angular.module('OpenSlidesApp.core.site', [
|
||||
abstract: true,
|
||||
template: "<ui-view/>",
|
||||
})
|
||||
.state('core.customslide.list', {
|
||||
resolve: {
|
||||
customslides: function(Customslide) {
|
||||
return Customslide.findAll();
|
||||
}
|
||||
}
|
||||
})
|
||||
.state('core.customslide.create', {})
|
||||
.state('core.customslide.detail', {
|
||||
resolve: {
|
||||
customslide: function(Customslide, $stateParams) {
|
||||
@ -235,11 +227,6 @@ angular.module('OpenSlidesApp.core.site', [
|
||||
}
|
||||
}
|
||||
})
|
||||
.state('core.customslide.detail.update', {
|
||||
views: {
|
||||
'@core.customslide': {}
|
||||
}
|
||||
})
|
||||
// tag
|
||||
.state('core.tag', {
|
||||
url: '/tag',
|
||||
@ -369,46 +356,6 @@ angular.module('OpenSlidesApp.core.site', [
|
||||
};
|
||||
})
|
||||
|
||||
.controller("LoginFormCtrl", function ($scope, $modal) {
|
||||
$scope.open = function () {
|
||||
var modalInstance = $modal.open({
|
||||
animation: true,
|
||||
templateUrl: 'LoginForm.html',
|
||||
controller: 'LoginFormModalCtrl',
|
||||
size: 'sm',
|
||||
});
|
||||
};
|
||||
})
|
||||
|
||||
.controller('LoginFormModalCtrl', [
|
||||
'$scope',
|
||||
'$modalInstance',
|
||||
'$http',
|
||||
'operator',
|
||||
function ($scope, $modalInstance, $http, operator) {
|
||||
$scope.login = function () {
|
||||
$http.post(
|
||||
'/users/login/',
|
||||
{'username': $scope.username, 'password': $scope.password}
|
||||
).success(function(data) {
|
||||
if (data.success) {
|
||||
operator.setUser(data.user_id);
|
||||
$scope.loginFailed = false;
|
||||
$modalInstance.close();
|
||||
} else {
|
||||
$scope.loginFailed = true;
|
||||
}
|
||||
});
|
||||
};
|
||||
$scope.guest = function () {
|
||||
$modalInstance.dismiss('cancel');
|
||||
};
|
||||
$scope.cancel = function () {
|
||||
$modalInstance.dismiss('cancel');
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
// Version Controller
|
||||
.controller('VersionCtrl', [
|
||||
'$scope',
|
||||
@ -433,37 +380,33 @@ angular.module('OpenSlidesApp.core.site', [
|
||||
};
|
||||
})
|
||||
|
||||
// Customslide Controller
|
||||
.controller('CustomslideListCtrl', [
|
||||
'$scope',
|
||||
'$http',
|
||||
'Customslide',
|
||||
function($scope, $http, Customslide) {
|
||||
Customslide.bindAll({}, $scope, 'customslides');
|
||||
|
||||
// setup table sorting
|
||||
$scope.sortColumn = 'title';
|
||||
$scope.reverse = false;
|
||||
// function to sort by clicked column
|
||||
$scope.toggleSort = function ( column ) {
|
||||
if ( $scope.sortColumn === column ) {
|
||||
$scope.reverse = !$scope.reverse;
|
||||
// Provide generic motion form fields for create and update view
|
||||
.factory('CustomslideFormFieldFactory', [
|
||||
'gettext',
|
||||
'CKEditorOptions',
|
||||
function (gettext, CKEditorOptions) {
|
||||
return {
|
||||
getFormFields: function () {
|
||||
return [
|
||||
{
|
||||
key: 'title',
|
||||
type: 'input',
|
||||
templateOptions: {
|
||||
label: gettext('Title'),
|
||||
required: true
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'text',
|
||||
type: 'textarea',
|
||||
templateOptions: {
|
||||
label: gettext('Text')
|
||||
},
|
||||
ngModelElAttrs: {'ckeditor': 'CKEditorOptions'}
|
||||
}];
|
||||
}
|
||||
$scope.sortColumn = column;
|
||||
};
|
||||
|
||||
// save changed customslide
|
||||
$scope.save = function (customslide) {
|
||||
Customslide.save(customslide);
|
||||
};
|
||||
$scope.delete = function (customslide) {
|
||||
//TODO: add confirm message
|
||||
Customslide.destroy(customslide.id).then(
|
||||
function(success) {
|
||||
//TODO: success message
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
@ -660,6 +603,7 @@ angular.module('OpenSlidesApp.core.site', [
|
||||
}
|
||||
])
|
||||
|
||||
// Customslide Controllers
|
||||
.controller('CustomslideDetailCtrl', function($scope, Customslide, customslide) {
|
||||
Customslide.bindOne(customslide.id, $scope, 'customslide');
|
||||
Customslide.loadRelations(customslide, 'agenda_item');
|
||||
@ -668,15 +612,18 @@ angular.module('OpenSlidesApp.core.site', [
|
||||
.controller('CustomslideCreateCtrl', [
|
||||
'$scope',
|
||||
'$state',
|
||||
'CKEditorOptions',
|
||||
'Customslide',
|
||||
function($scope, $state, CKEditorOptions, Customslide) {
|
||||
'CustomslideFormFieldFactory',
|
||||
function($scope, $state, Customslide, CustomslideFormFieldFactory) {
|
||||
$scope.customslide = {};
|
||||
$scope.CKEditorOptions = CKEditorOptions;
|
||||
// get all form fields
|
||||
$scope.formFields = CustomslideFormFieldFactory.getFormFields();
|
||||
|
||||
// save form
|
||||
$scope.save = function (customslide) {
|
||||
Customslide.create(customslide).then(
|
||||
function(success) {
|
||||
$state.go('core.customslide.list');
|
||||
$scope.closeThisDialog();
|
||||
}
|
||||
);
|
||||
};
|
||||
@ -686,16 +633,20 @@ angular.module('OpenSlidesApp.core.site', [
|
||||
.controller('CustomslideUpdateCtrl', [
|
||||
'$scope',
|
||||
'$state',
|
||||
'CKEditorOptions',
|
||||
'Customslide',
|
||||
'CustomslideFormFieldFactory',
|
||||
'customslide',
|
||||
function($scope, $state, CKEditorOptions, Customslide, customslide) {
|
||||
$scope.customslide = customslide;
|
||||
$scope.CKEditorOptions = CKEditorOptions;
|
||||
function($scope, $state, Customslide, CustomslideFormFieldFactory, customslide) {
|
||||
// set initial values for form model
|
||||
$scope.model = customslide;
|
||||
// get all form fields
|
||||
$scope.formFields = CustomslideFormFieldFactory.getFormFields();
|
||||
|
||||
// save form
|
||||
$scope.save = function (customslide) {
|
||||
Customslide.save(customslide).then(
|
||||
function(success) {
|
||||
$state.go('core.customslide.list');
|
||||
$scope.closeThisDialog();
|
||||
}
|
||||
);
|
||||
};
|
||||
@ -791,10 +742,12 @@ angular.module('OpenSlidesApp.core.site', [
|
||||
// increment unread messages counter for each new message
|
||||
$scope.$watch('chatmessages', function (newVal, oldVal) {
|
||||
// add new message id if there is really a new message which is not yet tracked
|
||||
if ((oldVal[oldVal.length-1].id != newVal[newVal.length-1].id) &&
|
||||
($.inArray(newVal[newVal.length-1].id, NewChatMessages) == -1)) {
|
||||
NewChatMessages.push(newVal[newVal.length-1].id);
|
||||
$scope.unreadMessages = NewChatMessages.length;
|
||||
if (oldVal.length > 0) {
|
||||
if ((oldVal[oldVal.length-1].id != newVal[newVal.length-1].id) &&
|
||||
($.inArray(newVal[newVal.length-1].id, NewChatMessages) == -1)) {
|
||||
NewChatMessages.push(newVal[newVal.length-1].id);
|
||||
$scope.unreadMessages = NewChatMessages.length;
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -1,24 +1,23 @@
|
||||
<h1>{{ customslide.title }}</h1>
|
||||
|
||||
<div id="submenu">
|
||||
<a ui-sref="core.customslide.list" class="btn btn-sm btn-default">
|
||||
<a ui-sref="agenda.item.list" class="btn btn-sm btn-default">
|
||||
<i class="fa fa-angle-double-left fa-lg"></i>
|
||||
<translate>Back to overview</translate>
|
||||
</a>
|
||||
<!-- projector, TODO: add link to activate slide-->
|
||||
<a href="#TODO" os-perms="core.can_manage_projector" class="btn btn-default btn-sm"
|
||||
title="{{ 'Show' | translate }}">
|
||||
<i class="fa fa-video-camera"></i>
|
||||
<!-- List of speakers -->
|
||||
<a ui-sref="agenda.item.detail({id: customslide.agenda_item_id})" class="btn btn-sm btn-default">
|
||||
<i class="fa fa-microphone fa-lg"></i>
|
||||
<translate>List of speakers</translate>
|
||||
</a>
|
||||
<!-- edit -->
|
||||
<a ui-sref="core.customslide.detail.update({id: customslide.id })" os-perms="core.can_mange_projector"
|
||||
class="btn btn-default btn-sm"
|
||||
title="{{ 'Edit' | translate}}">
|
||||
<i class="fa fa-pencil"></i>
|
||||
<!-- project -->
|
||||
<a os-perms="core.can_manage_projector" class="btn btn-default btn-sm"
|
||||
ng-class="{ 'btn-primary': customslide.isProjected() }"
|
||||
ng-click="customslide.project()"
|
||||
title="{{ 'Project agenda item' | translate }}">
|
||||
<i class="fa fa-video-camera"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{{ customslide.agenda_item }}
|
||||
|
||||
<div class="white-space-pre-line">{{ customslide.text }}</div>
|
||||
<div ng-bind-html="customslide.text"></div>
|
||||
|
||||
|
@ -1,27 +1,13 @@
|
||||
<h1 ng-if="customslide.id" translate>Edit custom slide</h1>
|
||||
<h1 ng-if="!customslide.id" translate>New custom slide</h1>
|
||||
<h1 ng-if="customslide.id" translate>Edit agenda item</h1>
|
||||
<h2 ng-if="!customslide.id" translate>New agenda item</h2>
|
||||
|
||||
<div id="submenu">
|
||||
<a ui-sref="core.customslide.list" class="btn btn-sm btn-default">
|
||||
<i class="fa fa-angle-double-left fa-lg"></i>
|
||||
<translate>Back to overview</translate>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<form name="customslideForm">
|
||||
<div class="form-group" >
|
||||
<label for="inputTitle" translate>Title</label>
|
||||
<input type="text" ng-model="customslide.title" class="form-control" name="inputTitle" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="customSlideTextCKEditor" translate>Text</label>
|
||||
<div id="customSlideTextCKEditor" ckeditor="CKEditorOptions" ng-model="customslide.text"></div>
|
||||
</div>
|
||||
|
||||
<button type="submit" ng-click="save(customslide)" class="btn btn-primary" translate>
|
||||
Save
|
||||
</button>
|
||||
<button ui-sref="core.customslide.list" class="btn btn-default" translate>
|
||||
Cancel
|
||||
</button>
|
||||
<form name="customslideForm" ng-submit="save(model)">
|
||||
<formly-form model="model" fields="formFields">
|
||||
<button type="submit" ng-disabled="customslideForm.$invalid" class="btn btn-primary" translate>
|
||||
Submit
|
||||
</button>
|
||||
<button ng-click="closeThisDialog()" class="btn btn-default" translate>
|
||||
Cancel
|
||||
</button>
|
||||
</formly-form>
|
||||
</form>
|
||||
|
28
openslides/core/static/templates/core/login-form.html
Normal file
28
openslides/core/static/templates/core/login-form.html
Normal file
@ -0,0 +1,28 @@
|
||||
<form ng-submit="login(username, password)">
|
||||
<div class="modal-header">
|
||||
<img src="/static/img/logo-login.png" alt="OpenSlides" class="center-block">
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<uib-alert ng-repeat="alert in alerts" type="{{ alert.type }}" close="closeAlert($index)">
|
||||
<span ng-bind-html="alert.msg"><span>
|
||||
</uib-alert>
|
||||
<div class="input-group form-group">
|
||||
<div class="input-group-addon"><i class="fa fa-user"></i></div>
|
||||
<input os-focus-me type="text" ng-model="username" class="form-control input-lg"
|
||||
placeholder="{{ 'Username' | translate }}">
|
||||
</div>
|
||||
<div class="input-group form-group">
|
||||
<div class="input-group-addon"><i class="fa fa-key"></i></div>
|
||||
<input type="password" ng-model="password" class="form-control input-lg"
|
||||
placeholder="{{ 'Password' | translate }}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary pull-right" translate>
|
||||
Login
|
||||
</button>
|
||||
<button ng-if="guestAllowed" ng-click="guestLogin()" class="btn btn-default" translate>
|
||||
Continue as guest
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
@ -1,4 +1,4 @@
|
||||
<div ng-controller="SlideCustomSlideCtrl" class="content scrollcontent">
|
||||
<h1>{{ customslide.title }}</h1>
|
||||
<div class="white-space-pre-line">{{ customslide.text }}</div>
|
||||
<div ng-bind-html="customslide.text"></div>
|
||||
</div>
|
||||
|
@ -22,6 +22,7 @@
|
||||
</div>
|
||||
<div class="navbar-right" ng-controller="userMenu">
|
||||
<div class="btn-group">
|
||||
<!-- Logout / user setttings button -->
|
||||
<div ng-if="operator.isAuthenticated()">
|
||||
|
||||
<!-- chatbox -->
|
||||
@ -84,47 +85,9 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Login dialog (modal) -->
|
||||
<div ng-controller="LoginFormCtrl" ng-if="!operator.isAuthenticated()">
|
||||
<script type="text/ng-template" id="LoginForm.html">
|
||||
<form ng-submit="login(username, password)">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title" translate>Please sign in!</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p ng-if='loginFailed' class="text-danger">
|
||||
<strong translate>Username or password is not correct.</strong>
|
||||
<div class="input-group form-group">
|
||||
<div class="input-group-addon"><i class="fa fa-user"></i></div>
|
||||
<input os-focus-me type="text" ng-model="username" class="form-control input-lg"
|
||||
placeholder="{{ 'Username' | translate }}">
|
||||
</div>
|
||||
<div class="input-group form-group">
|
||||
<div class="input-group-addon"><i class="fa fa-key"></i></div>
|
||||
<input type="password" ng-model="password" class="form-control input-lg"
|
||||
placeholder="{{ 'Password' | translate }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary btn-lg btn-block" translate>
|
||||
Login
|
||||
</button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<!-- TODO: show only if anonymous user is activate -->
|
||||
<button ng-click="guest()" class="btn btn-default" translate>
|
||||
Continue as guest
|
||||
</button>
|
||||
<button ng-click="cancel()" class="btn btn-default" translate>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</script>
|
||||
<button class="btn btn-default" ng-click="open()">
|
||||
<!-- Login button -->
|
||||
<div ng-if="!operator.isAuthenticated()">
|
||||
<button class="btn btn-default" ng-click="openLoginForm()">
|
||||
<i class="fa fa-sign-in"></i>
|
||||
<translate>Login</translate>
|
||||
</button>
|
||||
@ -173,13 +136,18 @@
|
||||
</ul>
|
||||
</div><!--/#main-menu-->
|
||||
<!-- Content -->
|
||||
<div id="content" class="col-md-10">
|
||||
<div id="content" class="col-md-7">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div ui-view></div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/#content-->
|
||||
<div class="col-sm-3" os-perms="core.can_see_projector">
|
||||
<div class="well">
|
||||
<div ng-include src="'static/templates/core/projector-controls.html'"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/.row-->
|
||||
|
||||
<hr>
|
||||
|
@ -180,14 +180,6 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions'])
|
||||
});
|
||||
});
|
||||
|
||||
// hover edit actions
|
||||
$scope.hoverIn = function () {
|
||||
$scope.showEditActions = true;
|
||||
};
|
||||
$scope.hoverOut = function () {
|
||||
$scope.showEditActions = false;
|
||||
};
|
||||
|
||||
// save changed motion
|
||||
$scope.update = function (motion) {
|
||||
// get (unchanged) values from latest version for update method
|
||||
|
@ -17,6 +17,11 @@
|
||||
<i class="fa fa-file-pdf-o fa-lg"></i>
|
||||
<translate>PDF</translate>
|
||||
</a>
|
||||
<!-- List of speakers -->
|
||||
<a ui-sref="agenda.item.detail({id: motion.agenda_item_id})" class="btn btn-sm btn-default">
|
||||
<i class="fa fa-microphone fa-lg"></i>
|
||||
<translate>List of speakers</translate>
|
||||
</a>
|
||||
<!-- project -->
|
||||
<a os-perms="core.can_manage_projector" class="btn btn-default btn-sm"
|
||||
ng-class="{ 'btn-primary': motion.isProjected() }"
|
||||
@ -171,7 +176,7 @@
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div ng-show="!poll.isEditMode && poll.yes >= -2">
|
||||
<div ng-show="!poll.isEditMode && poll.yes >= -2" class="pollresults">
|
||||
<!-- yes -->
|
||||
<div class="result_label">
|
||||
<i class="fa fa-thumbs-up"></i>
|
||||
|
@ -563,7 +563,8 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users'])
|
||||
'DS',
|
||||
'User',
|
||||
'operator',
|
||||
function($scope, $http, DS, User, operator) {
|
||||
'ngDialog',
|
||||
function($scope, $http, DS, User, operator, ngDialog) {
|
||||
$scope.logout = function() {
|
||||
$http.post('/users/logout/').success(function(data) {
|
||||
operator.setUser(null);
|
||||
@ -571,6 +572,59 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users'])
|
||||
// DS.flush();
|
||||
});
|
||||
};
|
||||
$scope.openLoginForm = function () {
|
||||
ngDialog.open({
|
||||
template: 'static/templates/core/login-form.html',
|
||||
controller: 'LoginFormCtrl',
|
||||
});
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
.controller('LoginFormCtrl', [
|
||||
'$scope',
|
||||
'$http',
|
||||
'operator',
|
||||
'gettext',
|
||||
'Config',
|
||||
function ($scope, $http, operator, gettext, Config) {
|
||||
$scope.alerts = [];
|
||||
|
||||
// TODO: add welcome message only on first time (or if admin password not changed)
|
||||
$scope.alerts.push({
|
||||
type: 'success',
|
||||
msg: gettext("Installation was successfully.") + "<br>" +
|
||||
gettext("Use <strong>admin</strong> and <strong>admin</strong> for first login.") + "<p>" +
|
||||
gettext("Important: Please change your password!")
|
||||
});
|
||||
// close alert function
|
||||
$scope.closeAlert = function(index) {
|
||||
$scope.alerts.splice(index, 1);
|
||||
};
|
||||
// check if guest login is allowed
|
||||
$scope.guestAllowed = true; //TODO Config.get('general_system_enable_anonymous').value;
|
||||
// login
|
||||
$scope.login = function () {
|
||||
$http.post(
|
||||
'/users/login/',
|
||||
{'username': $scope.username, 'password': $scope.password}
|
||||
).success(function(data) {
|
||||
if (data.success) {
|
||||
operator.setUser(data.user_id);
|
||||
$scope.closeThisDialog();
|
||||
} else {
|
||||
$scope.alerts.push({
|
||||
type: 'danger',
|
||||
msg: gettext('Username or password was not correct.')
|
||||
});
|
||||
//Username or password is not correct.
|
||||
}
|
||||
});
|
||||
};
|
||||
// guest login
|
||||
$scope.guestLogin = function () {
|
||||
$scope.closeThisDialog();
|
||||
};
|
||||
}
|
||||
]);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user