diff --git a/bower.json b/bower.json
index 1c33da2da..839d98d77 100644
--- a/bower.json
+++ b/bower.json
@@ -8,8 +8,7 @@
"bootstrap": "~3.3.1",
"datatables-bootstrap3-plugin": "~0.2.0",
"angular": "~1.3.11",
- "angular-cookies": "~1.3.11",
- "angular-route": "~1.3.11",
+ "angular-ui-router": "~0.2.13",
"angular-data": "~1.5.3",
"sockjs": "~0.3.4",
"jed": "~1.1.0"
diff --git a/openslides/agenda/static/js/agenda/agenda.js b/openslides/agenda/static/js/agenda/agenda.js
index 4827224e6..b720052fd 100644
--- a/openslides/agenda/static/js/agenda/agenda.js
+++ b/openslides/agenda/static/js/agenda/agenda.js
@@ -1,39 +1,37 @@
angular.module('OpenSlidesApp.agenda', [])
-.config(['$routeProvider', function($routeProvider) {
- $routeProvider
- .when('/agenda', {
- templateUrl: 'static/templates/agenda/item-list.html',
- controller: 'ItemListCtrl',
+.config(function($stateProvider) {
+ $stateProvider
+ .state('agenda', {
+ url: '/agenda',
+ abstract: true,
+ template: "",
+ })
+ .state('agenda.item', {
+ abstract: true,
+ template: "",
+ })
+ .state('agenda.item.list', {
resolve: {
items: function(Agenda) {
return Agenda.findAll();
}
}
})
- .when('/agenda/new', {
- templateUrl: 'static/templates/agenda/item-form.html',
- controller: 'ItemCreateCtrl'
- })
- .when('/agenda/:id', {
- templateUrl: 'static/templates/agenda/item-detail.html',
- controller: 'ItemDetailCtrl',
+ .state('agenda.item.create', {})
+ .state('agenda.item.detail', {
resolve: {
- item: function(Agenda, $route) {
- return Agenda.find($route.current.params.id);
+ item: function(Agenda, $stateParams) {
+ return Agenda.find($stateParams.id);
}
}
})
- .when('/agenda/:id/edit', {
- templateUrl: 'static/templates/agenda/item-form.html',
- controller: 'ItemUpdateCtrl',
- resolve: {
- item: function(Agenda, $route) {
- return Agenda.find($route.current.params.id);
- }
+ .state('agenda.item.detail.update', {
+ views: {
+ '@agenda.item': {}
}
});
-}])
+})
.factory('Agenda', function(DS) {
return DS.defineResource({
@@ -48,20 +46,21 @@ angular.module('OpenSlidesApp.agenda', [])
$scope.test_singular = i18n.ngettext('test', 'tests', 1);
})
-.controller('ItemDetailCtrl', function($scope, $routeParams, Agenda) {
- Agenda.bindOne($scope, 'item', $routeParams.id);
+.controller('ItemDetailCtrl', function($scope, Agenda, item) {
+ Agenda.bindOne($scope, 'item', item.id);
})
.controller('ItemCreateCtrl', function($scope, Agenda) {
$scope.item = {};
$scope.save = function (item) {
item.weight = 0; // TODO: the rest_api should do this
+ item.tags = []; // TODO: the rest_api should do this
Agenda.create(item);
// TODO: redirect to list-view
};
})
-.controller('ItemUpdateCtrl', function($scope, $routeParams, Agenda, item) {
+.controller('ItemUpdateCtrl', function($scope, Agenda, item) {
$scope.item = item; // do not use Agenda.binOne(...) so autoupdate is not activated
$scope.save = function (item) {
Agenda.save(item);
diff --git a/openslides/agenda/static/templates/agenda/item-list.html b/openslides/agenda/static/templates/agenda/item-list.html
index bb2485b15..b98d3da53 100644
--- a/openslides/agenda/static/templates/agenda/item-list.html
+++ b/openslides/agenda/static/templates/agenda/item-list.html
@@ -1,9 +1,9 @@
-{{ gettext('New') }}
-{{ test_singular }}
-{{ test_plural }}
+{{ gettext('New') }}
+
{{ test_singular }}
+
{{ test_plural }}
diff --git a/openslides/assignment/static/js/assignment/assignment.js b/openslides/assignment/static/js/assignment/assignment.js
deleted file mode 100644
index 9e4f2a219..000000000
--- a/openslides/assignment/static/js/assignment/assignment.js
+++ /dev/null
@@ -1,68 +0,0 @@
-angular.module('OpenSlidesApp.assignment', [])
-
-.config(['$routeProvider', function($routeProvider) {
- $routeProvider
- .when('/assignment', {
- templateUrl: 'static/templates/assignment/assignment-list.html',
- controller: 'AssignmentListCtrl',
- resolve: {
- assignments: function(Assignment) {
- return Assignment.findAll();
- }
- }
- })
- .when('/assignment/new', {
- templateUrl: 'static/templates/assignment/assignment-form.html',
- controller: 'AssignmentCreateCtrl'
- })
- .when('/assignment/:id', {
- templateUrl: 'static/templates/assignment/assignment-detail.html',
- controller: 'AssignmentDetailCtrl',
- resolve: {
- assignment: function(Assignment, $route) {
- return Assignment.find($route.current.params.id);
- }
- }
- })
- .when('/assignment/:id/edit', {
- templateUrl: 'static/templates/assignment/assignment-form.html',
- controller: 'AssignmentUpdateCtrl',
- resolve: {
- assignment: function(Assignment, $route) {
- return Assignment.find($route.current.params.id);
- }
- }
- });
-}])
-
-.factory('Assignment', function(DS) {
- return DS.defineResource({
- name: 'assignment/assignment',
- endpoint: '/rest/assignment/assignment/'
- });
-})
-
-.controller('AssignmentListCtrl', function($scope, Assignment) {
- Assignment.bindAll($scope, 'assignments');
-})
-
-.controller('AssignmentDetailCtrl', function($scope, $routeParams, Assignment) {
- Assignment.bindOne($scope, 'assignment', $routeParams.id)
-})
-
-.controller('AssignmentCreateCtrl', function($scope, Assignment) {
- $scope.assignment = {};
- $scope.save = function(assignment) {
- Assignment.create(assignment);
- // TODO: redirect to list-view
- };
-})
-
-.controller('AssignmentUpdateCtrl', function($scope, $routeParams, Assignment, assignment) {
- $scope.assignment = assignment; // do not use .binOne(...) so autoupdate is not activated
- $scope.save = function (assignment) {
- Assignment.save(assignment);
- // TODO: redirect to list-view
- };
-});
-
diff --git a/openslides/assignment/static/js/assignments/assignments.js b/openslides/assignment/static/js/assignments/assignments.js
new file mode 100644
index 000000000..071a2976a
--- /dev/null
+++ b/openslides/assignment/static/js/assignments/assignments.js
@@ -0,0 +1,69 @@
+angular.module('OpenSlidesApp.assignments', [])
+
+.config(function($stateProvider) {
+ $stateProvider
+ .state('assignments', {
+ url: '/assignment',
+ abstract: true,
+ template: "",
+ })
+ .state('assignments.assignment', {
+ abstract: true,
+ template: "",
+ })
+ .state('assignments.assignment.list', {
+ resolve: {
+ assignments: function(Assignment) {
+ return Assignment.findAll();
+ }
+ }
+ })
+ .state('assignments.assignment.create', {})
+ .state('assignments.assignment.detail', {
+ controller: 'AssignmentDetailCtrl',
+ resolve: {
+ assignment: function(Assignment, $stateParams) {
+ return Assignment.find($stateParams.id);
+ }
+ }
+ })
+ .state('assignments.assignment.detail.update', {
+ views: {
+ '@assignments.assignment': {}
+ }
+ });
+})
+
+.factory('Assignment', function(DS) {
+ return DS.defineResource({
+ name: 'assignment/assignment',
+ endpoint: '/rest/assignment/assignment/'
+ });
+})
+
+.controller('AssignmentListCtrl', function($scope, Assignment) {
+ Assignment.bindAll($scope, 'assignments');
+})
+
+.controller('AssignmentDetailCtrl', function($scope, Assignment, assignment) {
+ Assignment.bindOne($scope, 'assignment', assignment.id)
+})
+
+.controller('AssignmentCreateCtrl', function($scope, Assignment) {
+ $scope.assignment = {};
+ $scope.save = function(assignment) {
+ assignment.posts = 1;
+ assignment.tags = []; // TODO: the rest_api should do this
+ Assignment.create(assignment);
+ // TODO: redirect to list-view
+ };
+})
+
+.controller('AssignmentUpdateCtrl', function($scope, Assignment, assignment) {
+ $scope.assignment = assignment; // do not use .binOne(...) so autoupdate is not activated
+ $scope.save = function (assignment) {
+ Assignment.save(assignment);
+ // TODO: redirect to list-view
+ };
+});
+
diff --git a/openslides/assignment/static/templates/assignment/assignment-list.html b/openslides/assignment/static/templates/assignment/assignment-list.html
deleted file mode 100644
index 404e8344a..000000000
--- a/openslides/assignment/static/templates/assignment/assignment-list.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-Neu
diff --git a/openslides/assignment/static/templates/assignment/assignment-detail.html b/openslides/assignment/static/templates/assignments/assignment-detail.html
similarity index 100%
rename from openslides/assignment/static/templates/assignment/assignment-detail.html
rename to openslides/assignment/static/templates/assignments/assignment-detail.html
diff --git a/openslides/assignment/static/templates/assignment/assignment-form.html b/openslides/assignment/static/templates/assignments/assignment-form.html
similarity index 100%
rename from openslides/assignment/static/templates/assignment/assignment-form.html
rename to openslides/assignment/static/templates/assignments/assignment-form.html
diff --git a/openslides/assignment/static/templates/assignments/assignment-list.html b/openslides/assignment/static/templates/assignments/assignment-list.html
new file mode 100644
index 000000000..b9594dccd
--- /dev/null
+++ b/openslides/assignment/static/templates/assignments/assignment-list.html
@@ -0,0 +1,7 @@
+
+Neu
diff --git a/openslides/core/static/js/app.js b/openslides/core/static/js/app.js
index ad815ab02..9d1259697 100644
--- a/openslides/core/static/js/app.js
+++ b/openslides/core/static/js/app.js
@@ -1,105 +1,20 @@
angular.module('OpenSlidesApp', [
- 'ngRoute',
+ 'ui.router',
'angular-data.DS',
- 'ngCookies',
+ 'OpenSlidesApp.core',
'OpenSlidesApp.agenda',
- 'OpenSlidesApp.assignment',
- 'OpenSlidesApp.user',
+ 'OpenSlidesApp.assignments',
+ 'OpenSlidesApp.users',
])
-.config(function($routeProvider, $locationProvider) {
- $routeProvider
- .when('/', {
- templateUrl: 'static/templates/dashboard.html'
- })
- .otherwise({redirectTo: '/'});
+.config(function($urlRouterProvider, $locationProvider) {
+ // define fallback url and html5Mode
+ $urlRouterProvider.otherwise('/');
$locationProvider.html5Mode(true);
})
-.run(function($http, $cookies) {
- $http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
- $http.defaults.headers.put['X-CSRFToken'] = $cookies.csrftoken;
-})
-
-.run(function(DS, autoupdate) {
- autoupdate.on_message(function(data) {
- // TODO: when MODEL.find() is called after this
- // a new request is fired. This could be a bug in DS
- if (data.status_code == 200) {
- DS.inject(data.collection, data.data)
- }
- // TODO: handle other statuscodes
- });
-})
-
-.run(function($rootScope, i18n) {
- // Puts the gettext methods into each scope.
- // Uses the methods that are known by xgettext by default.
- methods = ['gettext', 'dgettext', 'dcgettext', 'ngettext', 'dngettext',
- 'pgettext', 'dpgettext'];
- _.forEach(methods, function(method) {
- $rootScope[method] = _.bind(i18n[method], i18n);
- });
-})
-
-.run(function($rootScope, Config) {
- // Puts the config object into each scope.
- // TODO: maybe rootscope.config has to set before findAll() is finished
- Config.findAll().then(function() {;
- $rootScope.config = function(key) {
- return Config.get(key).value;
- }
- });
-})
-
-.factory('autoupdate', function() {
- //TODO: use config here
- var url = "http://" + location.host + "/sockjs";
-
- var Autoupdate = {
- socket: null,
- message_receivers: [],
- connect: function() {
- var autoupdate = this;
- this.socket = new SockJS(url);
-
- this.socket.onmessage = function(event) {
- _.forEach(autoupdate.message_receivers, function(receiver) {
- receiver(event.data);
- });
- }
-
- this.socket.onclose = function() {
- setTimeout(autoupdate.connect, 5000);
- }
- },
- on_message: function(receiver) {
- this.message_receivers.push(receiver);
- }
- };
- Autoupdate.connect();
- return Autoupdate;
-})
-
-.factory('i18n', function($http) {
- // TODO: there is a bug(?) in jed. I had to call val_idx++; in line 285
- // TODO: make the language variable and changeable at runtime
- var i18n = new Jed({
- 'domain': 'de',
- 'locale_data': {'de': {"": {}}},
- }); // TODO: use promise here
- $http.get('/static/i18n/de.json')
- .success(function(data) {
- // TODO: check data.
- i18n.options.locale_data['de'] = data;
- });
- return i18n;
-})
-
-.factory('Config', function(DS) {
- return DS.defineResource({
- name: 'config/config',
- idAttribute: 'key',
- endpoint: '/rest/config/config/'
- });
+.config(function($httpProvider) {
+ // Combine the django csrf system with the angular csrf system
+ $httpProvider.defaults.xsrfCookieName = 'csrftoken';
+ $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
});
diff --git a/openslides/core/static/js/core.js b/openslides/core/static/js/core.js
new file mode 100644
index 000000000..1c24d545f
--- /dev/null
+++ b/openslides/core/static/js/core.js
@@ -0,0 +1,176 @@
+angular.module('OpenSlidesApp.core', [])
+
+.config(function($stateProvider) {
+ // Use stateProvider.decorator to give default values to our states
+ $stateProvider.decorator('views', function(state, parent) {
+
+
+ var result = {},
+ views = parent(state);
+
+ if (state.abstract) {
+ return views;
+ }
+
+ angular.forEach(views, function(config, name) {
+ // Sets default values for templateUrl
+ var patterns = state.name.split('.'),
+ templateUrl,
+ controller,
+ defaultControllers = {
+ create: 'CreateCtrl',
+ update: 'UpdateCtrl',
+ list: 'ListCtrl',
+ detail: 'DetailCtrl',
+ };
+
+ // templateUrl
+ if (_.last(patterns).match(/(create|update)/)) {
+ // When state_patterns is in the form "app.module.create" or
+ // "app.module.update", use the form template.
+ templateUrl = 'static/templates/' + patterns[0] + '/' + patterns[1] + '-form.html'
+ } else {
+ // Replaces the first point through a slash (the app name)
+ var appName = state.name.replace('.', '/');
+ // Replaces any folowing points though a -
+ templateUrl = 'static/templates/' + appName.replace(/\./g, '-') + '.html';
+ }
+ config.templateUrl = config.templateUrl || templateUrl;
+
+ // controller
+ if (patterns.length >= 3) {
+ controller = _.capitalize(patterns[1]) + defaultControllers[_.last(patterns)];
+ config.controller = config.controller || controller;
+ }
+ result[name] = config;
+ });
+ return result;
+ })
+
+ .decorator('url', function(state, parent) {
+ var defaultUrl;
+
+ if (state.abstract) {
+ defaultUrl = '';
+ } else {
+ var patterns = state.name.split('.'),
+ defaultUrls = {
+ create: '/new',
+ update: '/edit',
+ list: '',
+ detail: '/:id',
+ };
+
+ defaultUrl = defaultUrls[_.last(patterns)];
+ }
+
+ state.url = state.url || defaultUrl;
+ return parent(state)
+ });
+})
+
+.config(function($stateProvider, $urlRouterProvider, $locationProvider) {
+ // Core urls
+ $urlRouterProvider.otherwise('/');
+
+ $stateProvider
+ .state('dashboard', {
+ url: '/',
+ templateUrl: 'static/templates/dashboard.html'
+ });
+
+ $locationProvider.html5Mode(true);
+})
+
+.run(function(DS, autoupdate) {
+ autoupdate.on_message(function(data) {
+ // TODO: when MODEL.find() is called after this
+ // a new request is fired. This could be a bug in DS
+ if (data.status_code == 200) {
+ DS.inject(data.collection, data.data)
+ }
+ // TODO: handle other statuscodes
+ });
+})
+
+.run(function($rootScope, i18n) {
+ // Puts the gettext methods into each scope.
+ // Uses the methods that are known by xgettext by default.
+ methods = ['gettext', 'dgettext', 'dcgettext', 'ngettext', 'dngettext',
+ 'pgettext', 'dpgettext'];
+ _.forEach(methods, function(method) {
+ $rootScope[method] = _.bind(i18n[method], i18n);
+ });
+})
+
+.run(function($rootScope, i18n) {
+ // Puts the gettext methods into each scope.
+ // Uses the methods that are known by xgettext by default.
+ methods = ['gettext', 'dgettext', 'dcgettext', 'ngettext', 'dngettext',
+ 'pgettext', 'dpgettext'];
+ _.forEach(methods, function(method) {
+ $rootScope[method] = _.bind(i18n[method], i18n);
+ });
+})
+
+.run(function($rootScope, Config) {
+ // Puts the config object into each scope.
+ // TODO: maybe rootscope.config has to set before findAll() is finished
+ Config.findAll().then(function() {;
+ $rootScope.config = function(key) {
+ return Config.get(key).value;
+ }
+ });
+})
+
+.factory('autoupdate', function() {
+ //TODO: use config here
+ var url = "http://" + location.host + "/sockjs";
+
+ var Autoupdate = {
+ socket: null,
+ message_receivers: [],
+ connect: function() {
+ var autoupdate = this;
+ this.socket = new SockJS(url);
+
+ this.socket.onmessage = function(event) {
+ _.forEach(autoupdate.message_receivers, function(receiver) {
+ receiver(event.data);
+ });
+ }
+
+ this.socket.onclose = function() {
+ setTimeout(autoupdate.connect, 5000);
+ }
+ },
+ on_message: function(receiver) {
+ this.message_receivers.push(receiver);
+ }
+ };
+ Autoupdate.connect();
+ return Autoupdate;
+})
+
+.factory('i18n', function($http) {
+ // TODO: there is a bug(?) in jed. I had to call val_idx++; in line 285
+ // TODO: make the language variable and changeable at runtime
+ var i18n = new Jed({
+ 'domain': 'de',
+ 'locale_data': {'de': {"": {}}},
+ }); // TODO: use promise here
+ $http.get('/static/i18n/de.json')
+ .success(function(data) {
+ // TODO: check data.
+ i18n.options.locale_data['de'] = data;
+ });
+ return i18n;
+})
+
+.factory('Config', function(DS) {
+ return DS.defineResource({
+ name: 'config/config',
+ idAttribute: 'key',
+ endpoint: '/rest/config/config/'
+ });
+});
diff --git a/openslides/core/static/templates/dashboard.html b/openslides/core/static/templates/dashboard.html
index 8ea14ece0..24c08a0ea 100644
--- a/openslides/core/static/templates/dashboard.html
+++ b/openslides/core/static/templates/dashboard.html
@@ -1,4 +1,4 @@
Dashboard
-Assignments
-Agenda
-User
+Assignments
+Agenda
+User
diff --git a/openslides/core/static/templates/index.html b/openslides/core/static/templates/index.html
index e1872c894..02e161343 100644
--- a/openslides/core/static/templates/index.html
+++ b/openslides/core/static/templates/index.html
@@ -78,7 +78,7 @@
@@ -94,8 +94,9 @@
+
-
-
+
+