Merge pull request #2973 from FinnStutzenstein/Dialogs
Dialogs for some views
This commit is contained in:
commit
6bad8e8cc6
@ -48,6 +48,8 @@ Core:
|
|||||||
- Added success/error symbol to config to show if saving was successful.
|
- Added success/error symbol to config to show if saving was successful.
|
||||||
- Added UTF-8 byte order mark for every CSV export.
|
- Added UTF-8 byte order mark for every CSV export.
|
||||||
- Moved full-text search to client-side (removed the server-side search engine Whoosh).
|
- Moved full-text search to client-side (removed the server-side search engine Whoosh).
|
||||||
|
- Better dialog handling. Show dialog just in forground without changing the state url.
|
||||||
|
Added new dialog for profile, change password, tag and category update view.
|
||||||
|
|
||||||
Motions:
|
Motions:
|
||||||
- Added adjustable line numbering mode (outside, inside, none) for each
|
- Added adjustable line numbering mode (outside, inside, none) for each
|
||||||
|
@ -81,6 +81,7 @@ angular.module('OpenSlidesApp.agenda.site', [
|
|||||||
'$filter',
|
'$filter',
|
||||||
'$http',
|
'$http',
|
||||||
'$state',
|
'$state',
|
||||||
|
'$injector',
|
||||||
'DS',
|
'DS',
|
||||||
'operator',
|
'operator',
|
||||||
'ngDialog',
|
'ngDialog',
|
||||||
@ -96,9 +97,9 @@ angular.module('OpenSlidesApp.agenda.site', [
|
|||||||
'osTableFilter',
|
'osTableFilter',
|
||||||
'AgendaCsvExport',
|
'AgendaCsvExport',
|
||||||
'PdfCreate',
|
'PdfCreate',
|
||||||
function($scope, $filter, $http, $state, DS, operator, ngDialog, Agenda, TopicForm, AgendaTree, Projector,
|
function($scope, $filter, $http, $state, $injector, DS, operator, ngDialog, Agenda, TopicForm,
|
||||||
ProjectionDefault, AgendaContentProvider, PdfMakeDocumentProvider, gettextCatalog, gettext, osTableFilter,
|
AgendaTree, Projector, ProjectionDefault, AgendaContentProvider, PdfMakeDocumentProvider,
|
||||||
AgendaCsvExport, PdfCreate) {
|
gettextCatalog, gettext, osTableFilter, AgendaCsvExport, PdfCreate) {
|
||||||
// Bind agenda tree to the scope
|
// Bind agenda tree to the scope
|
||||||
$scope.$watch(function () {
|
$scope.$watch(function () {
|
||||||
return Agenda.lastModified();
|
return Agenda.lastModified();
|
||||||
@ -268,13 +269,22 @@ angular.module('OpenSlidesApp.agenda.site', [
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
$scope.getUpdateStatePrefix = function (item) {
|
$scope.getDetailStatePrefix = function (item) {
|
||||||
var prefix = item.content_object.collection.replace('/','.');
|
var prefix = item.content_object.collection.replace('/','.');
|
||||||
// Hotfix for Issue 2566.
|
// Hotfix for Issue 2566.
|
||||||
// The changes could be reverted if Issue 2480 is closed.
|
// The changes could be reverted if Issue 2480 is closed.
|
||||||
prefix = prefix.replace('motion-block', 'motionBlock');
|
prefix = prefix.replace('motion-block', 'motionBlock');
|
||||||
return prefix;
|
return prefix;
|
||||||
};
|
};
|
||||||
|
$scope.edit = function (item) {
|
||||||
|
var formName = item.content_object.collection.split('/')[1];
|
||||||
|
// Hotfix for Issue 2566.
|
||||||
|
// The changes could be reverted if Issue 2480 is closed.
|
||||||
|
formName = formName.replace('motion-block', 'motionBlock');
|
||||||
|
formName = formName.charAt(0).toUpperCase() + formName.slice(1) + 'Form';
|
||||||
|
var form = $injector.get(formName);
|
||||||
|
ngDialog.open(form.getDialog({id: item.content_object.id}));
|
||||||
|
};
|
||||||
// export
|
// export
|
||||||
$scope.pdfExport = function () {
|
$scope.pdfExport = function () {
|
||||||
var filename = gettextCatalog.getString('Agenda') + '.pdf';
|
var filename = gettextCatalog.getString('Agenda') + '.pdf';
|
||||||
|
@ -271,7 +271,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<!-- ID and title -->
|
<!-- ID and title -->
|
||||||
<div>
|
<div>
|
||||||
<a class="title" ui-sref="{{ getUpdateStatePrefix(item) }}.detail({id: item.content_object.id})" ng-show="isAllowedToSeeOpenLink(item)">
|
<a class="title" ui-sref="{{ getDetailStatePrefix(item) }}.detail({id: item.content_object.id})" ng-show="isAllowedToSeeOpenLink(item)">
|
||||||
{{ item.getListViewTitle() }}
|
{{ item.getListViewTitle() }}
|
||||||
</a>
|
</a>
|
||||||
<span class="title" ng-hide="isAllowedToSeeOpenLink(item)">
|
<span class="title" ng-hide="isAllowedToSeeOpenLink(item)">
|
||||||
@ -283,8 +283,7 @@
|
|||||||
<small>
|
<small>
|
||||||
<a ui-sref="agenda.item.detail({id: item.id})" translate>List of speakers</a>
|
<a ui-sref="agenda.item.detail({id: item.id})" translate>List of speakers</a>
|
||||||
<span os-perms="agenda.can_manage"> ·
|
<span os-perms="agenda.can_manage"> ·
|
||||||
<a ui-sref="{{ getUpdateStatePrefix(item) }}.detail.update({id: item.content_object.id})"
|
<a href="" ng-click="edit(item)" translate>Edit</a> ·
|
||||||
translate>Edit</a> ·
|
|
||||||
<a href="" class="text-danger"
|
<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>{{ item.getTitle() }}</b>"
|
<b>{{ item.getTitle() }}</b>"
|
||||||
|
@ -682,8 +682,9 @@ angular.module('OpenSlidesApp.core', [
|
|||||||
.factory('Projector', [
|
.factory('Projector', [
|
||||||
'DS',
|
'DS',
|
||||||
'$http',
|
'$http',
|
||||||
|
'$injector',
|
||||||
'Config',
|
'Config',
|
||||||
function(DS, $http, Config) {
|
function(DS, $http, $injector, Config) {
|
||||||
return DS.defineResource({
|
return DS.defineResource({
|
||||||
name: 'core/projector',
|
name: 'core/projector',
|
||||||
onConflict: 'replace',
|
onConflict: 'replace',
|
||||||
@ -701,13 +702,13 @@ angular.module('OpenSlidesApp.core', [
|
|||||||
{"action": action, "direction": direction}
|
{"action": action, "direction": direction}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
getStateForCurrentSlide: function () {
|
getFormOrStateForCurrentSlide: function () {
|
||||||
var return_dict;
|
var return_dict;
|
||||||
angular.forEach(this.elements, function(value, key) {
|
angular.forEach(this.elements, function(value, key) {
|
||||||
if (value.name == 'agenda/list-of-speakers') {
|
if (value.name == 'agenda/list-of-speakers') {
|
||||||
return_dict = {
|
return_dict = {
|
||||||
'state': 'agenda.item.detail',
|
state: 'agenda.item.detail',
|
||||||
'param': {id: value.id}
|
id: value.id,
|
||||||
};
|
};
|
||||||
} else if (
|
} else if (
|
||||||
value.name != 'agenda/item-list' &&
|
value.name != 'agenda/item-list' &&
|
||||||
@ -715,10 +716,15 @@ angular.module('OpenSlidesApp.core', [
|
|||||||
value.name != 'core/countdown' &&
|
value.name != 'core/countdown' &&
|
||||||
value.name != 'core/projector-message' &&
|
value.name != 'core/projector-message' &&
|
||||||
value.name != 'agenda/current-list-of-speakers' ) {
|
value.name != 'agenda/current-list-of-speakers' ) {
|
||||||
return_dict = {
|
var formName = value.name.split('/')[1];
|
||||||
'state': value.name.replace('/', '.')+'.detail.update',
|
// Hotfix for Issue 2566.
|
||||||
'param': {id: value.id}
|
// The changes could be reverted if Issue 2480 is closed.
|
||||||
};
|
formName = formName.replace('motion-block', 'motionBlock');
|
||||||
|
formName = formName.charAt(0).toUpperCase() + formName.slice(1) + 'Form';
|
||||||
|
return_dict = {
|
||||||
|
form: $injector.get(formName),
|
||||||
|
id: value.id
|
||||||
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return return_dict;
|
return return_dict;
|
||||||
|
@ -370,25 +370,7 @@ angular.module('OpenSlidesApp.core.site', [
|
|||||||
basePerm: 'core.can_manage_tags',
|
basePerm: 'core.can_manage_tags',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.state('core.tag.list', {})
|
.state('core.tag.list', {});
|
||||||
.state('core.tag.create', {})
|
|
||||||
.state('core.tag.detail', {
|
|
||||||
resolve: {
|
|
||||||
tagId: ['$stateParams', function($stateParams) {
|
|
||||||
return $stateParams.id;
|
|
||||||
}],
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.state('core.tag.detail.update', {
|
|
||||||
resolve: {
|
|
||||||
tagId: ['$stateParams', function($stateParams) {
|
|
||||||
return $stateParams.id;
|
|
||||||
}],
|
|
||||||
},
|
|
||||||
views: {
|
|
||||||
'@core.tag': {}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$locationProvider.html5Mode(true);
|
$locationProvider.html5Mode(true);
|
||||||
}
|
}
|
||||||
@ -438,6 +420,38 @@ angular.module('OpenSlidesApp.core.site', [
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
.factory('TagForm', [
|
||||||
|
'gettextCatalog',
|
||||||
|
function (gettextCatalog) {
|
||||||
|
return {
|
||||||
|
getDialog: function (tag) {
|
||||||
|
return {
|
||||||
|
template: 'static/templates/core/tag-form.html',
|
||||||
|
controller: (tag) ? 'TagUpdateCtrl' : 'TagCreateCtrl',
|
||||||
|
className: 'ngdialog-theme-default wide-form',
|
||||||
|
closeByEscape: false,
|
||||||
|
closeByDocument: false,
|
||||||
|
resolve: {
|
||||||
|
tagId: function () {return tag ? tag.id : void 0;},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getFormFields: function() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
type: 'input',
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('Name'),
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
/* This factory handles the filtering of the OS-data-tables. It contains
|
/* This factory handles the filtering of the OS-data-tables. It contains
|
||||||
* all logic needed for the table header filtering. Things to configure:
|
* 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.
|
* - multiselectFilters: A dict associating the filter name to a list (empty per default). E.g.
|
||||||
@ -615,6 +629,11 @@ angular.module('OpenSlidesApp.core.site', [
|
|||||||
extends: 'textarea',
|
extends: 'textarea',
|
||||||
templateUrl: 'static/templates/core/editor.html',
|
templateUrl: 'static/templates/core/editor.html',
|
||||||
});
|
});
|
||||||
|
formlyConfig.setType({
|
||||||
|
name: 'password',
|
||||||
|
extends: 'input',
|
||||||
|
templateUrl: 'static/templates/core/password.html',
|
||||||
|
});
|
||||||
formlyConfig.setType({
|
formlyConfig.setType({
|
||||||
name: 'select-single',
|
name: 'select-single',
|
||||||
extends: 'select',
|
extends: 'select',
|
||||||
@ -1122,9 +1141,13 @@ angular.module('OpenSlidesApp.core.site', [
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.editCurrentSlide = function (projector) {
|
$scope.editCurrentSlide = function (projector) {
|
||||||
var state = projector.getStateForCurrentSlide();
|
var data = projector.getFormOrStateForCurrentSlide();
|
||||||
if (state) {
|
if (data) {
|
||||||
$state.go(state.state, state.param);
|
if (data.form) {
|
||||||
|
ngDialog.open(data.form.getDialog({id: data.id}));
|
||||||
|
} else {
|
||||||
|
$state.go(data.state, {id: data.id});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1227,13 +1250,14 @@ angular.module('OpenSlidesApp.core.site', [
|
|||||||
.controller('ManageProjectorsCtrl', [
|
.controller('ManageProjectorsCtrl', [
|
||||||
'$scope',
|
'$scope',
|
||||||
'$http',
|
'$http',
|
||||||
'$state',
|
|
||||||
'$timeout',
|
'$timeout',
|
||||||
'Projector',
|
'Projector',
|
||||||
'ProjectionDefault',
|
'ProjectionDefault',
|
||||||
'Config',
|
'Config',
|
||||||
'ProjectorMessage',
|
'ProjectorMessage',
|
||||||
function ($scope, $http, $state, $timeout, Projector, ProjectionDefault, Config, ProjectorMessage) {
|
'ngDialog',
|
||||||
|
function ($scope, $http, $timeout, Projector, ProjectionDefault, Config,
|
||||||
|
ProjectorMessage, ngDialog) {
|
||||||
ProjectionDefault.bindAll({}, $scope, 'projectiondefaults');
|
ProjectionDefault.bindAll({}, $scope, 'projectiondefaults');
|
||||||
|
|
||||||
// watch for changes in projector_broadcast
|
// watch for changes in projector_broadcast
|
||||||
@ -1316,9 +1340,13 @@ angular.module('OpenSlidesApp.core.site', [
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
$scope.editCurrentSlide = function (projector) {
|
$scope.editCurrentSlide = function (projector) {
|
||||||
var state = projector.getStateForCurrentSlide();
|
var data = projector.getFormOrStateForCurrentSlide();
|
||||||
if (state) {
|
if (data) {
|
||||||
$state.go(state.state, state.param);
|
if (data.form) {
|
||||||
|
ngDialog.open(data.form.getDialog({id: data.id}));
|
||||||
|
} else {
|
||||||
|
$state.go(data.state, {id: data.id});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
$scope.editName = function (projector) {
|
$scope.editName = function (projector) {
|
||||||
@ -1378,8 +1406,12 @@ angular.module('OpenSlidesApp.core.site', [
|
|||||||
.controller('TagListCtrl', [
|
.controller('TagListCtrl', [
|
||||||
'$scope',
|
'$scope',
|
||||||
'Tag',
|
'Tag',
|
||||||
function($scope, Tag) {
|
'ngDialog',
|
||||||
|
'TagForm',
|
||||||
|
'gettext',
|
||||||
|
function($scope, Tag, ngDialog, TagForm, gettext) {
|
||||||
Tag.bindAll({}, $scope, 'tags');
|
Tag.bindAll({}, $scope, 'tags');
|
||||||
|
$scope.alert = {};
|
||||||
|
|
||||||
// setup table sorting
|
// setup table sorting
|
||||||
$scope.sortColumn = 'name';
|
$scope.sortColumn = 'name';
|
||||||
@ -1391,40 +1423,48 @@ angular.module('OpenSlidesApp.core.site', [
|
|||||||
}
|
}
|
||||||
$scope.sortColumn = column;
|
$scope.sortColumn = column;
|
||||||
};
|
};
|
||||||
|
|
||||||
// save changed tag
|
|
||||||
$scope.save = function (tag) {
|
|
||||||
Tag.save(tag);
|
|
||||||
};
|
|
||||||
$scope.delete = function (tag) {
|
$scope.delete = function (tag) {
|
||||||
Tag.destroy(tag.id).then(
|
Tag.destroy(tag.id).then(
|
||||||
function(success) {
|
function(success) {
|
||||||
//TODO: success message
|
$scope.alert = {
|
||||||
|
type: 'success',
|
||||||
|
msg: gettext('The delete was successful.'),
|
||||||
|
show: true,
|
||||||
|
};
|
||||||
|
}, function (error) {
|
||||||
|
var message = '';
|
||||||
|
for (var e in error.data) {
|
||||||
|
message += e + ': ' + error.data[e] + ' ';
|
||||||
|
}
|
||||||
|
$scope.alert = {type: 'danger', msg: message, show: true};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
$scope.editOrCreate = function (tag) {
|
||||||
])
|
ngDialog.open(TagForm.getDialog(tag));
|
||||||
|
};
|
||||||
.controller('TagDetailCtrl', [
|
|
||||||
'$scope',
|
|
||||||
'Tag',
|
|
||||||
'tagId',
|
|
||||||
function($scope, Tag, tagId) {
|
|
||||||
Tag.bindOne(tagId, $scope, 'tag');
|
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
.controller('TagCreateCtrl', [
|
.controller('TagCreateCtrl', [
|
||||||
'$scope',
|
'$scope',
|
||||||
'$state',
|
|
||||||
'Tag',
|
'Tag',
|
||||||
function($scope, $state, Tag) {
|
'TagForm',
|
||||||
$scope.tag = {};
|
function($scope, Tag, TagForm) {
|
||||||
|
$scope.model = {};
|
||||||
|
$scope.alert = {};
|
||||||
|
$scope.formFields = TagForm.getFormFields();
|
||||||
$scope.save = function (tag) {
|
$scope.save = function (tag) {
|
||||||
Tag.create(tag).then(
|
Tag.create(tag).then(
|
||||||
function(success) {
|
function (success) {
|
||||||
$state.go('core.tag.list');
|
$scope.closeThisDialog();
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
var message = '';
|
||||||
|
for (var e in error.data) {
|
||||||
|
message += e + ': ' + error.data[e] + ' ';
|
||||||
|
}
|
||||||
|
$scope.alert = {type: 'danger', msg: message, show: true};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -1433,17 +1473,27 @@ angular.module('OpenSlidesApp.core.site', [
|
|||||||
|
|
||||||
.controller('TagUpdateCtrl', [
|
.controller('TagUpdateCtrl', [
|
||||||
'$scope',
|
'$scope',
|
||||||
'$state',
|
|
||||||
'Tag',
|
'Tag',
|
||||||
'tagId',
|
'tagId',
|
||||||
function($scope, $state, Tag, tagId) {
|
'TagForm',
|
||||||
$scope.tag = Tag.get(tagId);
|
function($scope, Tag, tagId, TagForm) {
|
||||||
|
$scope.model = angular.copy(Tag.get(tagId));
|
||||||
|
$scope.alert = {};
|
||||||
|
$scope.formFields = TagForm.getFormFields();
|
||||||
$scope.save = function (tag) {
|
$scope.save = function (tag) {
|
||||||
Tag.save(tag).then(
|
Tag.inject(tag);
|
||||||
function(success) {
|
Tag.save(tag).then(function(success) {
|
||||||
$state.go('core.tag.list');
|
$scope.closeThisDialog();
|
||||||
|
}, function (error) {
|
||||||
|
// save error: revert all changes by restore
|
||||||
|
// the original object
|
||||||
|
Tag.refresh(tag);
|
||||||
|
var message = '';
|
||||||
|
for (var e in error.data) {
|
||||||
|
message += e + ': ' + error.data[e] + ' ';
|
||||||
}
|
}
|
||||||
);
|
$scope.alert = {type: 'danger', msg: message, show: true};
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
@ -1493,12 +1543,15 @@ angular.module('OpenSlidesApp.core.site', [
|
|||||||
// increment unread messages counter for each new message
|
// increment unread messages counter for each new message
|
||||||
$scope.$watch('chatmessages', function (newVal, oldVal) {
|
$scope.$watch('chatmessages', function (newVal, oldVal) {
|
||||||
// add new message id if there is really a new message which is not yet tracked
|
// add new message id if there is really a new message which is not yet tracked
|
||||||
if (oldVal.length > 0) {
|
if (oldVal.length > 0 && newVal.length > 0) {
|
||||||
if ((oldVal[oldVal.length-1].id != newVal[newVal.length-1].id) &&
|
if ((oldVal[oldVal.length-1].id != newVal[newVal.length-1].id) &&
|
||||||
($.inArray(newVal[newVal.length-1].id, NewChatMessages) == -1)) {
|
($.inArray(newVal[newVal.length-1].id, NewChatMessages) == -1)) {
|
||||||
NewChatMessages.push(newVal[newVal.length-1].id);
|
NewChatMessages.push(newVal[newVal.length-1].id);
|
||||||
$scope.unreadMessages = NewChatMessages.length;
|
$scope.unreadMessages = NewChatMessages.length;
|
||||||
}
|
}
|
||||||
|
} else if (newVal.length === 0) {
|
||||||
|
NewChatMessages = [];
|
||||||
|
$scope.unreadMessages = 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@
|
|||||||
<div class="nobr">
|
<div class="nobr">
|
||||||
<!-- edit -->
|
<!-- edit -->
|
||||||
<a ng-click="editCurrentSlide(projector)"
|
<a ng-click="editCurrentSlide(projector)"
|
||||||
ng-disabled="!projector.getStateForCurrentSlide()"
|
ng-disabled="!projector.getFormOrStateForCurrentSlide()"
|
||||||
class="btn btn-default btn-sm"
|
class="btn btn-default btn-sm"
|
||||||
title="{{ 'Edit current slide' | translate}}">
|
title="{{ 'Edit current slide' | translate}}">
|
||||||
<i class="fa fa-pencil"></i>
|
<i class="fa fa-pencil"></i>
|
||||||
|
1
openslides/core/static/templates/core/password.html
Normal file
1
openslides/core/static/templates/core/password.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
<input type="password" ng-model="model[options.key]" class="form-control">
|
@ -86,7 +86,7 @@
|
|||||||
<div os-perms="core.can_manage_projector" class="nobr">
|
<div os-perms="core.can_manage_projector" class="nobr">
|
||||||
<!-- edit -->
|
<!-- edit -->
|
||||||
<a ng-click="editCurrentSlide(active_projector)"
|
<a ng-click="editCurrentSlide(active_projector)"
|
||||||
ng-disabled="!active_projector.getStateForCurrentSlide()"
|
ng-disabled="!active_projector.getFormOrStateForCurrentSlide()"
|
||||||
class="btn btn-default btn-sm"
|
class="btn btn-default btn-sm"
|
||||||
title="{{ 'Edit current slide' | translate}}">
|
title="{{ 'Edit current slide' | translate}}">
|
||||||
<i class="fa fa-pencil"></i>
|
<i class="fa fa-pencil"></i>
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
<div class="header">
|
|
||||||
<div class="title">
|
|
||||||
<div class="submenu">
|
|
||||||
<a ui-sref="core.tag.list" class="btn btn-sm btn-default">
|
|
||||||
<i class="fa fa-angle-double-left fa-lg"></i>
|
|
||||||
<translate>Back to overview</translate>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<h1>{{ tag.name }}</h1>
|
|
||||||
<h2 translate>Tag</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="details"></div>
|
|
@ -1,28 +1,17 @@
|
|||||||
<div class="header">
|
<h1 ng-if="model.id" translate>Edit tag</h1>
|
||||||
<div class="title">
|
<h1 ng-if="!model.id" translate>New tag</h1>
|
||||||
<div class="submenu">
|
|
||||||
<a ui-sref="core.tag.list" class="btn btn-sm btn-default">
|
<div uib-alert ng-show="alert.show" ng-class="'alert-' + (alert.type || 'warning')" close="alert={}">
|
||||||
<i class="fa fa-angle-double-left fa-lg"></i>
|
{{ alert.msg }}
|
||||||
<translate>Back to overview</translate>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<h1 ng-if="tag.id" translate>Edit tag</h1>
|
|
||||||
<h1 ng-if="!tag.id" translate>New tag</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="details">
|
<form name="userForm" ng-submit="save(model)">
|
||||||
<form name="tagForm">
|
<formly-form model="model" fields="formFields">
|
||||||
<div class="form-group">
|
<button type="submit" ng-disabled="userForm.$invalid" class="btn btn-primary" translate>
|
||||||
<label for="inputName" translate>Name</label>
|
Save
|
||||||
<input type="text" ng-model="tag.name" class="form-control" name="inputName" required>
|
</button>
|
||||||
</div>
|
<button ng-click="closeThisDialog()" class="btn btn-default" translate>
|
||||||
|
Cancel
|
||||||
<button type="submit" ng-click="save(tag)" class="btn btn-primary" translate>
|
</button>
|
||||||
Save
|
</formly-form>
|
||||||
</button>
|
|
||||||
<button ui-sref="core.tag.list" class="btn btn-default" translate>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<i class="fa fa-angle-double-left fa-lg"></i>
|
<i class="fa fa-angle-double-left fa-lg"></i>
|
||||||
<translate>Back to overview</translate>
|
<translate>Back to overview</translate>
|
||||||
</a>
|
</a>
|
||||||
<a ui-sref="core.tag.create" os-perms="core.can_manage_tags" class="btn btn-primary btn-sm">
|
<a href="" ng-click="editOrCreate()" os-perms="core.can_manage_tags" class="btn btn-primary btn-sm">
|
||||||
<i class="fa fa-plus fa-lg"></i>
|
<i class="fa fa-plus fa-lg"></i>
|
||||||
<translate>New</translate>
|
<translate>New</translate>
|
||||||
</a>
|
</a>
|
||||||
@ -16,7 +16,11 @@
|
|||||||
|
|
||||||
<div class="details">
|
<div class="details">
|
||||||
<div class="row form-group">
|
<div class="row form-group">
|
||||||
<div class="col-sm-8"></div>
|
<div class="col-sm-8">
|
||||||
|
<div uib-alert ng-show="alert.show" ng-class="'alert-' + (alert.type || 'warning')" close="alert={}">
|
||||||
|
{{ alert.msg }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-4">
|
||||||
<input type="text" ng-model="filter.search" class="form-control"
|
<input type="text" ng-model="filter.search" class="form-control"
|
||||||
placeholder="{{ 'Filter' | translate}}">
|
placeholder="{{ 'Filter' | translate}}">
|
||||||
@ -37,7 +41,7 @@
|
|||||||
<td ng-mouseover="tag.hover=true" ng-mouseleave="tag.hover=false">
|
<td ng-mouseover="tag.hover=true" ng-mouseleave="tag.hover=false">
|
||||||
<strong>{{ tag.name }}</strong>
|
<strong>{{ tag.name }}</strong>
|
||||||
<div class="hoverActions" ng-class="{'hiddenDiv': !tag.hover}">
|
<div class="hoverActions" ng-class="{'hiddenDiv': !tag.hover}">
|
||||||
<a ui-sref="core.tag.detail.update({id: tag.id })" translate>Edit</a> ·
|
<a href="" ng-click="editOrCreate(tag)" translate>Edit</a> ·
|
||||||
<a href="" class="text-danger"
|
<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>{{ tag.name }}</b>"
|
<b>{{ tag.name }}</b>"
|
||||||
|
@ -91,12 +91,13 @@
|
|||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu pull-right" uib-dropdown-menu aria-labelledby="user-settings-dropdown">
|
<ul class="dropdown-menu pull-right" uib-dropdown-menu aria-labelledby="user-settings-dropdown">
|
||||||
<li>
|
<li>
|
||||||
<a ui-sref="users.user.detail.profile({ id: operator.user.id })">
|
<!--<a ui-sref="users.user.detail.profile({ id: operator.user.id })">-->
|
||||||
|
<a href="" ng-click="editProfile()">
|
||||||
<i class="fa fa-cog"></i>
|
<i class="fa fa-cog"></i>
|
||||||
<translate>Edit profile</translate>
|
<translate>Edit profile</translate>
|
||||||
</a>
|
</a>
|
||||||
<li>
|
<li>
|
||||||
<a ui-sref="users.user.detail.password({ id: operator.user.id })">
|
<a href="" ng-click="changePassword()">
|
||||||
<i class="fa fa-key"></i>
|
<i class="fa fa-key"></i>
|
||||||
<translate>Change password</translate>
|
<translate>Change password</translate>
|
||||||
</a>
|
</a>
|
||||||
|
@ -153,7 +153,7 @@ angular.module('OpenSlidesApp.motions.motionBlock', [])
|
|||||||
$scope.defaultProjectorId = projectiondefault.projector_id;
|
$scope.defaultProjectorId = projectiondefault.projector_id;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$scope.openDialog = function (topic) {
|
$scope.openDialog = function (motionBlock) {
|
||||||
ngDialog.open(MotionBlockForm.getDialog(motionBlock));
|
ngDialog.open(MotionBlockForm.getDialog(motionBlock));
|
||||||
};
|
};
|
||||||
$scope.followRecommendations = function () {
|
$scope.followRecommendations = function () {
|
||||||
|
@ -103,19 +103,6 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
.state('motions.category.list', {})
|
.state('motions.category.list', {})
|
||||||
.state('motions.category.create', {})
|
|
||||||
.state('motions.category.detail', {
|
|
||||||
resolve: {
|
|
||||||
categoryId: ['$stateParams', function($stateParams) {
|
|
||||||
return $stateParams.id;
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.state('motions.category.detail.update', {
|
|
||||||
views: {
|
|
||||||
'@motions.category': {}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.state('motions.category.sort', {
|
.state('motions.category.sort', {
|
||||||
url: '/sort/{id}',
|
url: '/sort/{id}',
|
||||||
controller: 'CategorySortCtrl',
|
controller: 'CategorySortCtrl',
|
||||||
@ -524,6 +511,45 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
.factory('CategoryForm', [
|
||||||
|
'gettextCatalog',
|
||||||
|
function (gettextCatalog) {
|
||||||
|
return {
|
||||||
|
getDialog: function (category) {
|
||||||
|
return {
|
||||||
|
template: 'static/templates/motions/category-form.html',
|
||||||
|
controller: category ? 'CategoryUpdateCtrl' : 'CategoryCreateCtrl',
|
||||||
|
className: 'ngdialog-theme-default wide-form',
|
||||||
|
closeByEscape: false,
|
||||||
|
closeByDocument: false,
|
||||||
|
resolve: {
|
||||||
|
categoryId: function () {return category ? category.id : void 0;},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
},
|
||||||
|
getFormFields: function () {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
key: 'prefix',
|
||||||
|
type: 'input',
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('Prefix')
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
type: 'input',
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('Name')
|
||||||
|
},
|
||||||
|
}
|
||||||
|
];
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
// Provide generic motionpoll form fields for poll update view
|
// Provide generic motionpoll form fields for poll update view
|
||||||
.factory('MotionPollForm', [
|
.factory('MotionPollForm', [
|
||||||
'gettextCatalog',
|
'gettextCatalog',
|
||||||
@ -1780,7 +1806,9 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
.controller('CategoryListCtrl', [
|
.controller('CategoryListCtrl', [
|
||||||
'$scope',
|
'$scope',
|
||||||
'Category',
|
'Category',
|
||||||
function($scope, Category) {
|
'ngDialog',
|
||||||
|
'CategoryForm',
|
||||||
|
function($scope, Category, ngDialog, CategoryForm) {
|
||||||
Category.bindAll({}, $scope, 'categories');
|
Category.bindAll({}, $scope, 'categories');
|
||||||
|
|
||||||
// setup table sorting
|
// setup table sorting
|
||||||
@ -1798,28 +1826,31 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
$scope.delete = function (category) {
|
$scope.delete = function (category) {
|
||||||
Category.destroy(category.id);
|
Category.destroy(category.id);
|
||||||
};
|
};
|
||||||
}
|
$scope.editOrCreate = function (category) {
|
||||||
])
|
ngDialog.open(CategoryForm.getDialog(category));
|
||||||
|
};
|
||||||
.controller('CategoryDetailCtrl', [
|
|
||||||
'$scope',
|
|
||||||
'Category',
|
|
||||||
'categoryId',
|
|
||||||
function($scope, Category, categoryId) {
|
|
||||||
Category.bindOne(categoryId, $scope, 'category');
|
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
.controller('CategoryCreateCtrl', [
|
.controller('CategoryCreateCtrl', [
|
||||||
'$scope',
|
'$scope',
|
||||||
'$state',
|
|
||||||
'Category',
|
'Category',
|
||||||
function($scope, $state, Category) {
|
'CategoryForm',
|
||||||
$scope.category = {};
|
function($scope, Category, CategoryForm) {
|
||||||
|
$scope.model = {};
|
||||||
|
$scope.alert = {};
|
||||||
|
$scope.formFields = CategoryForm.getFormFields();
|
||||||
$scope.save = function (category) {
|
$scope.save = function (category) {
|
||||||
Category.create(category).then(
|
Category.create(category).then(
|
||||||
function(success) {
|
function(success) {
|
||||||
$state.go('motions.category.list');
|
$scope.closeThisDialog();
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
var message = '';
|
||||||
|
for (var e in error.data) {
|
||||||
|
message += e + ': ' + error.data[e] + ' ';
|
||||||
|
}
|
||||||
|
$scope.alert = {type: 'danger', msg: message, show: true};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -1828,15 +1859,28 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
|
|
||||||
.controller('CategoryUpdateCtrl', [
|
.controller('CategoryUpdateCtrl', [
|
||||||
'$scope',
|
'$scope',
|
||||||
'$state',
|
|
||||||
'Category',
|
'Category',
|
||||||
'categoryId',
|
'categoryId',
|
||||||
function($scope, $state, Category, categoryId) {
|
'CategoryForm',
|
||||||
$scope.category = Category.get(categoryId);
|
function($scope, Category, categoryId, CategoryForm) {
|
||||||
|
$scope.alert = {};
|
||||||
|
$scope.model = angular.copy(Category.get(categoryId));
|
||||||
|
$scope.formFields = CategoryForm.getFormFields();
|
||||||
$scope.save = function (category) {
|
$scope.save = function (category) {
|
||||||
|
Category.inject(category);
|
||||||
Category.save(category).then(
|
Category.save(category).then(
|
||||||
function(success) {
|
function(success) {
|
||||||
$state.go('motions.category.list');
|
$scope.closeThisDialog();
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
// save error: revert all changes by restore
|
||||||
|
// (refresh) original category object from server
|
||||||
|
Category.refresh(category);
|
||||||
|
var message = '';
|
||||||
|
for (var e in error.data) {
|
||||||
|
message += e + ': ' + error.data[e] + ' ';
|
||||||
|
}
|
||||||
|
$scope.alert = {type: 'danger', msg: message, show: true};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
<div class="header">
|
|
||||||
<div class="title">
|
|
||||||
<div class="submenu">
|
|
||||||
<a ui-sref="motions.category.list" class="btn btn-sm btn-default">
|
|
||||||
<i class="fa fa-angle-double-left fa-lg"></i>
|
|
||||||
<translate>Back to overview</translate>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<h1>{{ category.name }}</h1>
|
|
||||||
<h2 translate>Category</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="details">
|
|
||||||
<strong translate>Prefix:</strong>
|
|
||||||
{{ category.prefix }}
|
|
||||||
</div>
|
|
@ -1,32 +1,17 @@
|
|||||||
<div class="header">
|
<h1 ng-if="model.id" translate>Edit category</h1>
|
||||||
<div class="title">
|
<h1 ng-if="!model.id" translate>New category</h1>
|
||||||
<div class="submenu">
|
|
||||||
<a ui-sref="motions.category.list" class="btn btn-sm btn-default">
|
<div uib-alert ng-show="alert.show" ng-class="'alert-' + (alert.type || 'warning')" close="alert={}">
|
||||||
<i class="fa fa-angle-double-left fa-lg"></i>
|
{{ alert.msg }}
|
||||||
<translate>Back to overview</translate>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<h1 ng-if="category.id" translate>Edit category</h1>
|
|
||||||
<h1 ng-if="!category.id" translate>New category</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="details">
|
<form name="categoryForm" ng-submit="save(model)">
|
||||||
<form name="groupForm">
|
<formly-form model="model" fields="formFields">
|
||||||
<div class="form-group">
|
<button type="submit" ng-disabled="categoryForm.$invalid" class="btn btn-primary" translate>
|
||||||
<label for="inputPrefix" translate>Prefix</label>
|
|
||||||
<input type="text" ng-model="category.prefix" class="form-control" name="inputPrefix">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="inputName" translate>Name</label>
|
|
||||||
<input type="text" ng-model="category.name" class="form-control" name="inputName" ng-required="true">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" ng-click="save(category)" class="btn btn-primary" translate>
|
|
||||||
Save
|
Save
|
||||||
</button>
|
</button>
|
||||||
<button ui-sref="motions.category.list" class="btn btn-default" translate>
|
<button ng-click="closeThisDialog()" class="btn btn-default" translate>
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</formly-form>
|
||||||
</div>
|
</form>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<i class="fa fa-angle-double-left fa-lg"></i>
|
<i class="fa fa-angle-double-left fa-lg"></i>
|
||||||
<translate>Back to overview</translate>
|
<translate>Back to overview</translate>
|
||||||
</a>
|
</a>
|
||||||
<a ui-sref="motions.category.create" os-perms="motions.can_manage" class="btn btn-primary btn-sm">
|
<a href="" os-perms="motions.can_manage" class="btn btn-primary btn-sm" ng-click="editOrCreate()">
|
||||||
<i class="fa fa-plus fa-lg"></i>
|
<i class="fa fa-plus fa-lg"></i>
|
||||||
<translate>New</translate>
|
<translate>New</translate>
|
||||||
</a>
|
</a>
|
||||||
@ -43,7 +43,7 @@
|
|||||||
<!-- sort -->
|
<!-- sort -->
|
||||||
<a ui-sref="motions.category.sort({ id: category.id })" translate>Sort</a> |
|
<a ui-sref="motions.category.sort({ id: category.id })" translate>Sort</a> |
|
||||||
<!-- edit -->
|
<!-- edit -->
|
||||||
<a ui-sref="motions.category.detail.update({id: category.id })" translate>Edit</a> |
|
<a href="" ng-click="editOrCreate(category)" translate>Edit</a> |
|
||||||
<!-- delete -->
|
<!-- delete -->
|
||||||
<a href="" class="text-danger"
|
<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>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<h1 ng-if="model.id" translate>Edit change recommendation</h1>
|
<h1 ng-if="model.id" translate>Edit change recommendation</h1>
|
||||||
<h1 ng-if="!model.id" translate>New change recommendation</h1>
|
<h1 ng-if="!model.id" translate>New change recommendation</h1>
|
||||||
|
|
||||||
<uib-alert ng-show="alert.show" type="{{ alert.type }}" ng-click="alert={}" close="alert={}">
|
<div uib-alert ng-show="alert.show" ng-class="'alert-' + (alert.type || 'warning')" close="alert={}">
|
||||||
{{ alert.msg }}
|
{{ alert.msg }}
|
||||||
</uib-alert>
|
</div>
|
||||||
|
|
||||||
<form name="changeRecommendationForm" ng-submit="save(model)">
|
<form name="changeRecommendationForm" ng-submit="save(model)">
|
||||||
<formly-form model="model" fields="formFields">
|
<formly-form model="model" fields="formFields">
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<h1 ng-if="model.id" translate>Edit motion block</h1>
|
<h1 ng-if="model.id" translate>Edit motion block</h1>
|
||||||
<h1 ng-if="!model.id" translate>New motion block</h1>
|
<h1 ng-if="!model.id" translate>New motion block</h1>
|
||||||
|
|
||||||
<div uib-alert ng-show="alert.show" ng-class="'alert-' + (alert.type || 'warning')" ng-click="alert={}" close="alert={}">
|
<div uib-alert ng-show="alert.show" ng-class="'alert-' + (alert.type || 'warning')" close="alert={}">
|
||||||
{{ alert.msg }}
|
{{ alert.msg }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<h1 ng-if="!model.id && !parent" translate>New motion</h1>
|
<h1 ng-if="!model.id && !parent" translate>New motion</h1>
|
||||||
<h1 ng-if="parent"><translate>New amendment of motion</translate> {{ parent.identifier || parent.getTitle() }}</h1>
|
<h1 ng-if="parent"><translate>New amendment of motion</translate> {{ parent.identifier || parent.getTitle() }}</h1>
|
||||||
|
|
||||||
<div uib-alert ng-show="alert.show" ng-class="'alert-' + (alert.type || 'warning')" ng-click="alert={}" close="alert={}">
|
<div uib-alert ng-show="alert.show" ng-class="'alert-' + (alert.type || 'warning')" close="alert={}">
|
||||||
{{ alert.msg }}
|
{{ alert.msg }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -10,9 +10,9 @@ class UserAccessPermissions(BaseAccessPermissions):
|
|||||||
"""
|
"""
|
||||||
def check_permissions(self, user):
|
def check_permissions(self, user):
|
||||||
"""
|
"""
|
||||||
Returns True if the user has read access model instances.
|
Every user has read access for their model instnces.
|
||||||
"""
|
"""
|
||||||
return has_perm(user, 'users.can_see_name')
|
return True
|
||||||
|
|
||||||
def get_serializer_class(self, user=None):
|
def get_serializer_class(self, user=None):
|
||||||
"""
|
"""
|
||||||
|
@ -62,40 +62,6 @@ angular.module('OpenSlidesApp.users.site', [
|
|||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// Redirects to user detail view and opens user edit form dialog, uses edit url.
|
|
||||||
// Used by $state.go(..) from core/site.js only (for edit current slide button).
|
|
||||||
// (from users list controller use UserForm factory instead to open dialog in front of
|
|
||||||
// current view without redirect)
|
|
||||||
.state('users.user.detail.update', {
|
|
||||||
onEnter: ['$stateParams', '$state', 'ngDialog',
|
|
||||||
function($stateParams, $state, ngDialog) {
|
|
||||||
ngDialog.open({
|
|
||||||
template: 'static/templates/users/user-form.html',
|
|
||||||
controller: 'UserUpdateCtrl',
|
|
||||||
className: 'ngdialog-theme-default wide-form',
|
|
||||||
closeByEscape: false,
|
|
||||||
closeByDocument: false,
|
|
||||||
resolve: {
|
|
||||||
userId: function() {return $stateParams.id;}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
.state('users.user.detail.profile', {
|
|
||||||
views: {
|
|
||||||
'@users.user': {},
|
|
||||||
},
|
|
||||||
url: '/profile',
|
|
||||||
controller: 'UserProfileCtrl',
|
|
||||||
})
|
|
||||||
.state('users.user.detail.password', {
|
|
||||||
views: {
|
|
||||||
'@users.user': {},
|
|
||||||
},
|
|
||||||
url: '/password',
|
|
||||||
controller: 'UserPasswordCtrl',
|
|
||||||
})
|
|
||||||
.state('users.user.change-password', {
|
.state('users.user.change-password', {
|
||||||
url: '/change-password/{id}',
|
url: '/change-password/{id}',
|
||||||
controller: 'UserChangePasswordCtrl',
|
controller: 'UserChangePasswordCtrl',
|
||||||
@ -417,6 +383,146 @@ angular.module('OpenSlidesApp.users.site', [
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
.factory('UserProfileForm', [
|
||||||
|
'gettextCatalog',
|
||||||
|
'Editor',
|
||||||
|
'Mediafile',
|
||||||
|
function (gettextCatalog, Editor, Mediafile) {
|
||||||
|
return {
|
||||||
|
// ngDialog for user form
|
||||||
|
getDialog: function (user) {
|
||||||
|
return {
|
||||||
|
template: 'static/templates/users/profile-password-form.html',
|
||||||
|
controller: 'UserProfileCtrl',
|
||||||
|
className: 'ngdialog-theme-default wide-form',
|
||||||
|
closeByEscape: false,
|
||||||
|
closeByDocument: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
// angular-formly fields for user form
|
||||||
|
getFormFields: function (hideOnCreateForm) {
|
||||||
|
var images = Mediafile.getAllImages();
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
key: 'username',
|
||||||
|
type: 'input',
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('Username'),
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
className: "row",
|
||||||
|
fieldGroup: [
|
||||||
|
{
|
||||||
|
key: 'title',
|
||||||
|
type: 'input',
|
||||||
|
className: "col-xs-2 no-padding-left",
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('Title')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'first_name',
|
||||||
|
type: 'input',
|
||||||
|
className: "col-xs-5 no-padding",
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('Given name')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'last_name',
|
||||||
|
type: 'input',
|
||||||
|
className: "col-xs-5 no-padding-right",
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('Surname')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
className: "row",
|
||||||
|
fieldGroup: [
|
||||||
|
{
|
||||||
|
key: 'structure_level',
|
||||||
|
type: 'input',
|
||||||
|
className: "col-xs-9 no-padding-left",
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('Structure level'),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ key: 'number',
|
||||||
|
type: 'input',
|
||||||
|
className: "col-xs-3 no-padding-left no-padding-right",
|
||||||
|
templateOptions: {
|
||||||
|
label:gettextCatalog.getString('Participant number')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'about_me',
|
||||||
|
type: 'editor',
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('About me'),
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
ckeditorOptions: Editor.getOptions(images)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
.factory('UserPasswordForm', [
|
||||||
|
'gettextCatalog',
|
||||||
|
function (gettextCatalog) {
|
||||||
|
return {
|
||||||
|
// ngDialog for user form
|
||||||
|
getDialog: function (user) {
|
||||||
|
return {
|
||||||
|
template: 'static/templates/users/profile-password-form.html',
|
||||||
|
controller: 'UserPasswordCtrl',
|
||||||
|
className: 'ngdialog-theme-default wide-form',
|
||||||
|
closeByEscape: false,
|
||||||
|
closeByDocument: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
// angular-formly fields for user form
|
||||||
|
getFormFields: function (hideOnCreateForm) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
key: 'oldPassword',
|
||||||
|
type: 'password',
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('Old password'),
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'newPassword',
|
||||||
|
type: 'password',
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('New password'),
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'newPassword2',
|
||||||
|
type: 'password',
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('Confirm new password'),
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
.controller('UserListCtrl', [
|
.controller('UserListCtrl', [
|
||||||
'$scope',
|
'$scope',
|
||||||
'$state',
|
'$state',
|
||||||
@ -761,20 +867,30 @@ angular.module('OpenSlidesApp.users.site', [
|
|||||||
|
|
||||||
.controller('UserProfileCtrl', [
|
.controller('UserProfileCtrl', [
|
||||||
'$scope',
|
'$scope',
|
||||||
'$state',
|
|
||||||
'Editor',
|
'Editor',
|
||||||
'User',
|
'User',
|
||||||
'userId',
|
'operator',
|
||||||
function($scope, $state, Editor, User, userId) {
|
'UserProfileForm',
|
||||||
$scope.user = angular.copy(User.get(userId));
|
'gettext',
|
||||||
$scope.ckeditorOptions = Editor.getOptions();
|
function($scope, Editor, User, operator, UserProfileForm, gettext) {
|
||||||
|
$scope.model = angular.copy(operator.user);
|
||||||
|
$scope.title = gettext('Edit profile');
|
||||||
|
$scope.formFields = UserProfileForm.getFormFields();
|
||||||
$scope.save = function (user) {
|
$scope.save = function (user) {
|
||||||
|
User.inject(user);
|
||||||
User.save(user).then(
|
User.save(user).then(
|
||||||
function(success) {
|
function(success) {
|
||||||
$state.go('users.user.list');
|
$scope.closeThisDialog();
|
||||||
},
|
},
|
||||||
function(error) {
|
function(error) {
|
||||||
$scope.formError = error;
|
// save error: revert all changes by restore
|
||||||
|
// (refresh) original user object from server
|
||||||
|
User.refresh(user);
|
||||||
|
var message = '';
|
||||||
|
for (var e in error.data) {
|
||||||
|
message += e + ': ' + error.data[e] + ' ';
|
||||||
|
}
|
||||||
|
$scope.alert = {type: 'danger', msg: message, show: true};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -791,7 +907,7 @@ angular.module('OpenSlidesApp.users.site', [
|
|||||||
'PasswordGenerator',
|
'PasswordGenerator',
|
||||||
function($scope, $state, $http, User, userId, gettextCatalog, PasswordGenerator) {
|
function($scope, $state, $http, User, userId, gettextCatalog, PasswordGenerator) {
|
||||||
User.bindOne(userId, $scope, 'user');
|
User.bindOne(userId, $scope, 'user');
|
||||||
$scope.alert={};
|
$scope.alert = {};
|
||||||
$scope.generatePassword = function () {
|
$scope.generatePassword = function () {
|
||||||
$scope.new_password = PasswordGenerator.generate();
|
$scope.new_password = PasswordGenerator.generate();
|
||||||
};
|
};
|
||||||
@ -818,24 +934,38 @@ angular.module('OpenSlidesApp.users.site', [
|
|||||||
'$scope',
|
'$scope',
|
||||||
'$state',
|
'$state',
|
||||||
'$http',
|
'$http',
|
||||||
function($scope, $state, $http) {
|
'gettext',
|
||||||
$scope.save = function () {
|
'UserPasswordForm',
|
||||||
if ($scope.newPassword != $scope.newPassword2) {
|
function($scope, $state, $http, gettext, UserPasswordForm) {
|
||||||
$scope.newPassword = $scope.newPassword2 = '';
|
$scope.title = 'Change password';
|
||||||
$scope.formError = 'Password confirmation does not match.';
|
$scope.alert = {};
|
||||||
|
$scope.model = {};
|
||||||
|
$scope.formFields = UserPasswordForm.getFormFields();
|
||||||
|
$scope.save = function (data) {
|
||||||
|
if (data.newPassword != data.newPassword2) {
|
||||||
|
data.newPassword = data.newPassword2 = '';
|
||||||
|
$scope.alert = {
|
||||||
|
type: 'danger',
|
||||||
|
msg: gettext('Password confirmation does not match.'),
|
||||||
|
show: true,
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
$http.post(
|
$http.post(
|
||||||
'/users/setpassword/',
|
'/users/setpassword/',
|
||||||
{'old_password': $scope.oldPassword, 'new_password': $scope.newPassword}
|
{'old_password': data.oldPassword, 'new_password': data.newPassword}
|
||||||
).then(
|
).then(
|
||||||
function (response) {
|
function (success) {
|
||||||
// Success.
|
$scope.closeThisDialog();
|
||||||
$state.go('users.user.list');
|
|
||||||
},
|
},
|
||||||
function (response) {
|
function (error) {
|
||||||
// Error, e. g. wrong old password.
|
// Error, e. g. wrong old password.
|
||||||
$scope.oldPassword = $scope.newPassword = $scope.newPassword2 = '';
|
$scope.model = {};
|
||||||
$scope.formError = response.data.detail;
|
|
||||||
|
var message = '';
|
||||||
|
for (var e in error.data) {
|
||||||
|
message += e + ': ' + error.data[e] + ' ';
|
||||||
|
}
|
||||||
|
$scope.alert = {type: 'danger', msg: message, show: true};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1342,13 +1472,21 @@ angular.module('OpenSlidesApp.users.site', [
|
|||||||
'User',
|
'User',
|
||||||
'operator',
|
'operator',
|
||||||
'ngDialog',
|
'ngDialog',
|
||||||
function($scope, $http, DS, User, operator, ngDialog) {
|
'UserProfileForm',
|
||||||
|
'UserPasswordForm',
|
||||||
|
function($scope, $http, DS, User, operator, ngDialog, UserProfileForm, UserPasswordForm) {
|
||||||
$scope.logout = function () {
|
$scope.logout = function () {
|
||||||
$http.post('/users/logout/').then(function (response) {
|
$http.post('/users/logout/').then(function (response) {
|
||||||
operator.setUser(null);
|
operator.setUser(null);
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
$scope.editProfile = function () {
|
||||||
|
ngDialog.open(UserProfileForm.getDialog());
|
||||||
|
};
|
||||||
|
$scope.changePassword = function () {
|
||||||
|
ngDialog.open(UserPasswordForm.getDialog());
|
||||||
|
};
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
<h1>{{ title | translate }}</h1>
|
||||||
|
|
||||||
|
<div uib-alert ng-show="alert.show" ng-class="'alert-' + (alert.type || 'warning')" close="alert={}">
|
||||||
|
{{ alert.msg }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form name="profileForm" ng-submit="save(model)">
|
||||||
|
<formly-form model="model" fields="formFields">
|
||||||
|
<button type="submit" ng-disabled="profileForm.$invalid" class="btn btn-primary" translate>
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
|
<button ng-click="closeThisDialog()" class="btn btn-default" translate>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</formly-form>
|
||||||
|
</form>
|
@ -1,43 +0,0 @@
|
|||||||
<div class="header">
|
|
||||||
<div class="title">
|
|
||||||
<h1 translate>Change password</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="details">
|
|
||||||
<p ng-if='formError' class="text-danger">
|
|
||||||
<strong>{{ formError }}</strong>
|
|
||||||
</p>
|
|
||||||
<form name="userForm" >
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="inputOldPassword" translate>Old password</label>
|
|
||||||
<input type="password"
|
|
||||||
ng-model="oldPassword"
|
|
||||||
class="form-control"
|
|
||||||
name="inputOldPassword"
|
|
||||||
required>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="inputNewPassword" translate>New password</label>
|
|
||||||
<input type="password"
|
|
||||||
ng-model="newPassword"
|
|
||||||
class="form-control"
|
|
||||||
name="inputNewPassword"
|
|
||||||
required>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="inputNewPassword2" translate>Confirm new password</label>
|
|
||||||
<input type="password"
|
|
||||||
ng-model="newPassword2"
|
|
||||||
class="form-control"
|
|
||||||
name="inputNewPassword2"
|
|
||||||
required>
|
|
||||||
</div>
|
|
||||||
<button type="submit" ng-click="save()" class="btn btn-primary" translate>
|
|
||||||
Save
|
|
||||||
</button>
|
|
||||||
<button ui-sref="users.user.list" class="btn btn-default" translate>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
@ -1,50 +0,0 @@
|
|||||||
<div class="header">
|
|
||||||
<div class="title">
|
|
||||||
<h1 translate>Edit profile</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="details">
|
|
||||||
<p ng-if='formError' class="text-danger">
|
|
||||||
<strong>{{ formError }}</strong>
|
|
||||||
</p>
|
|
||||||
<form name="userForm" >
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="inputUsername" translate>Username</label>
|
|
||||||
<input type="text"
|
|
||||||
ng-model="user.username"
|
|
||||||
class="form-control"
|
|
||||||
name="inputUsername"
|
|
||||||
required>
|
|
||||||
</div>
|
|
||||||
<div class="form-group row">
|
|
||||||
<div class="col-xs-2">
|
|
||||||
<label for="inputTitle" translate-comment="academic degree" translate>Title</label>
|
|
||||||
<input type="text" ng-model="user.title" class="form-control" name="inputTitle">
|
|
||||||
</div>
|
|
||||||
<div class="col-xs-5">
|
|
||||||
<label for="inputFirstName" translate>Given name</label>
|
|
||||||
<input type="text" ng-model="user.first_name" class="form-control" name="inputFirstName">
|
|
||||||
</div>
|
|
||||||
<div class="col-xs-5">
|
|
||||||
<label for="inputLastName" translate>Surname</label>
|
|
||||||
<input type="text" ng-model="user.last_name" class="form-control" name="inputLastName">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="inputStructureLevel" translate>Structure level</label>
|
|
||||||
<input type="text" ng-model="user.structure_level" class="form-control" name="inputStructureLevel">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="textAbout" translate>About me</label>
|
|
||||||
<textarea ng-model="user.about_me" class="form-control" name="textAbout" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" ng-click="save(user)" class="btn btn-primary" translate>
|
|
||||||
Save
|
|
||||||
</button>
|
|
||||||
<button ui-sref="users.user.list" class="btn btn-default" translate>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
@ -1,7 +1,7 @@
|
|||||||
<h1 ng-if="model.id" translate>Edit participant</h1>
|
<h1 ng-if="model.id" translate>Edit participant</h1>
|
||||||
<h1 ng-if="!model.id" translate>New participant</h1>
|
<h1 ng-if="!model.id" translate>New participant</h1>
|
||||||
|
|
||||||
<div uib-alert ng-show="alert.show" ng-class="'alert-' + (alert.type || 'warning')" ng-click="alert={}" close="alert={}">
|
<div uib-alert ng-show="alert.show" ng-class="'alert-' + (alert.type || 'warning')" close="alert={}">
|
||||||
{{ alert.msg }}
|
{{ alert.msg }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
from django.contrib.auth import login as auth_login
|
from django.contrib.auth import login as auth_login
|
||||||
from django.contrib.auth import logout as auth_logout
|
from django.contrib.auth import logout as auth_logout
|
||||||
|
from django.contrib.auth import update_session_auth_hash
|
||||||
from django.contrib.auth.forms import AuthenticationForm
|
from django.contrib.auth.forms import AuthenticationForm
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
@ -39,8 +40,10 @@ class UserViewSet(ModelViewSet):
|
|||||||
"""
|
"""
|
||||||
if self.action in ('list', 'retrieve'):
|
if self.action in ('list', 'retrieve'):
|
||||||
result = self.get_access_permissions().check_permissions(self.request.user)
|
result = self.get_access_permissions().check_permissions(self.request.user)
|
||||||
elif self.action in ('metadata', 'update', 'partial_update'):
|
elif self.action == 'metadata':
|
||||||
result = has_perm(self.request.user, 'users.can_see_name')
|
result = has_perm(self.request.user, 'users.can_see_name')
|
||||||
|
elif self.action in ('update', 'partial_update'):
|
||||||
|
result = self.request.user.is_authenticated()
|
||||||
elif self.action in ('create', 'destroy', 'reset_password'):
|
elif self.action in ('create', 'destroy', 'reset_password'):
|
||||||
result = (has_perm(self.request.user, 'users.can_see_name') and
|
result = (has_perm(self.request.user, 'users.can_see_name') and
|
||||||
has_perm(self.request.user, 'users.can_see_extra_data') and
|
has_perm(self.request.user, 'users.can_see_extra_data') and
|
||||||
@ -264,6 +267,7 @@ class SetPasswordView(APIView):
|
|||||||
if user.check_password(request.data['old_password']):
|
if user.check_password(request.data['old_password']):
|
||||||
user.set_password(request.data['new_password'])
|
user.set_password(request.data['new_password'])
|
||||||
user.save()
|
user.save()
|
||||||
|
update_session_auth_hash(request, user)
|
||||||
else:
|
else:
|
||||||
raise ValidationError({'detail': _('Old password does not match.')})
|
raise ValidationError({'detail': _('Old password does not match.')})
|
||||||
return super().post(request, *args, **kwargs)
|
return super().post(request, *args, **kwargs)
|
||||||
|
Loading…
Reference in New Issue
Block a user