Merge pull request #2364 from CatoTH/motion-detail-behaviour-services
Move inline editing methods into a separate service
This commit is contained in:
commit
27223c35d9
@ -8,7 +8,7 @@ class MotionsAppConfig(AppConfig):
|
|||||||
angular_site_module = True
|
angular_site_module = True
|
||||||
angular_projector_module = True
|
angular_projector_module = True
|
||||||
js_files = ['js/motions/base.js', 'js/motions/site.js', 'js/motions/projector.js',
|
js_files = ['js/motions/base.js', 'js/motions/site.js', 'js/motions/projector.js',
|
||||||
'js/motions/linenumbering.js', 'js/motions/diff.js']
|
'js/motions/linenumbering.js', 'js/motions/diff.js', 'js/motions/motion-services.js']
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
# Load projector elements.
|
# Load projector elements.
|
||||||
|
121
openslides/motions/static/js/motions/motion-services.js
Normal file
121
openslides/motions/static/js/motions/motion-services.js
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
(function () {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
angular.module('OpenSlidesApp.motions.motionservices', ['OpenSlidesApp.motions', 'OpenSlidesApp.motions.lineNumbering'])
|
||||||
|
|
||||||
|
.factory('MotionInlineEditing', [
|
||||||
|
'Editor',
|
||||||
|
'Motion',
|
||||||
|
'Config',
|
||||||
|
'$timeout',
|
||||||
|
function (Editor, Motion, Config, $timeout) {
|
||||||
|
var obj = {
|
||||||
|
active: false,
|
||||||
|
changed: false,
|
||||||
|
trivialChange: false,
|
||||||
|
editor: null,
|
||||||
|
lineBrokenText: null,
|
||||||
|
originalHtml: null
|
||||||
|
};
|
||||||
|
|
||||||
|
var $scope, motion;
|
||||||
|
|
||||||
|
obj.init = function (_scope, _motion) {
|
||||||
|
$scope = _scope;
|
||||||
|
motion = _motion;
|
||||||
|
obj.lineBrokenText = motion.getTextWithLineBreaks($scope.version);
|
||||||
|
obj.originalHtml = obj.lineBrokenText;
|
||||||
|
|
||||||
|
if (motion.state.versioning && Config.get('motions_allow_disable_versioning').value) {
|
||||||
|
obj.trivialChange = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
obj.tinymceOptions = Editor.getOptions(null, true);
|
||||||
|
obj.tinymceOptions.readonly = 1;
|
||||||
|
obj.tinymceOptions.setup = function (editor) {
|
||||||
|
obj.editor = editor;
|
||||||
|
editor.on("init", function () {
|
||||||
|
obj.lineBrokenText = motion.getTextWithLineBreaks($scope.version);
|
||||||
|
obj.editor.setContent(obj.lineBrokenText);
|
||||||
|
obj.originalHtml = obj.editor.getContent();
|
||||||
|
obj.changed = false;
|
||||||
|
});
|
||||||
|
editor.on("change", function () {
|
||||||
|
obj.changed = (editor.getContent() != obj.originalHtml);
|
||||||
|
});
|
||||||
|
editor.on("undo", function () {
|
||||||
|
obj.changed = (editor.getContent() != obj.originalHtml);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.setVersion = function (_motion, versionId) {
|
||||||
|
motion = _motion; // If this is not updated,
|
||||||
|
console.log(versionId, motion.getTextWithLineBreaks(versionId));
|
||||||
|
obj.lineBrokenText = motion.getTextWithLineBreaks(versionId);
|
||||||
|
obj.changed = false;
|
||||||
|
obj.active = false;
|
||||||
|
if (obj.editor) {
|
||||||
|
obj.editor.setContent(obj.lineBrokenText);
|
||||||
|
obj.editor.setMode("readonly");
|
||||||
|
obj.originalHtml = obj.editor.getContent();
|
||||||
|
} else {
|
||||||
|
obj.originalHtml = obj.lineBrokenText;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.enable = function () {
|
||||||
|
obj.editor.setMode("design");
|
||||||
|
obj.active = true;
|
||||||
|
obj.changed = false;
|
||||||
|
|
||||||
|
obj.lineBrokenText = motion.getTextWithLineBreaks($scope.version);
|
||||||
|
obj.editor.setContent(obj.lineBrokenText);
|
||||||
|
obj.originalHtml = obj.editor.getContent();
|
||||||
|
$timeout(function () {
|
||||||
|
obj.editor.focus();
|
||||||
|
}, 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.disable = function () {
|
||||||
|
obj.editor.setMode("readonly");
|
||||||
|
obj.active = false;
|
||||||
|
obj.changed = false;
|
||||||
|
obj.lineBrokenText = obj.originalHtml;
|
||||||
|
obj.editor.setContent(obj.originalHtml);
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.save = function () {
|
||||||
|
if (!motion.isAllowed('update')) {
|
||||||
|
throw "No permission to update motion";
|
||||||
|
}
|
||||||
|
|
||||||
|
motion.setTextStrippingLineBreaks(motion.active_version, obj.editor.getContent());
|
||||||
|
motion.disable_versioning = (obj.trivialChange && Config.get('motions_allow_disable_versioning').value);
|
||||||
|
|
||||||
|
Motion.inject(motion);
|
||||||
|
// save change motion object on server
|
||||||
|
Motion.save(motion, {method: 'PATCH'}).then(
|
||||||
|
function (success) {
|
||||||
|
$scope.showVersion(motion.getVersion(-1));
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
// save error: revert all changes by restore
|
||||||
|
// (refresh) original motion object from server
|
||||||
|
Motion.refresh(motion);
|
||||||
|
var message = '';
|
||||||
|
for (var e in error.data) {
|
||||||
|
message += e + ': ' + error.data[e] + ' ';
|
||||||
|
}
|
||||||
|
$scope.alert = {type: 'danger', msg: message, show: true};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
}());
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlidesApp.motions.diff'])
|
angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlidesApp.motions.diff', 'OpenSlidesApp.motions.motionservices'])
|
||||||
|
|
||||||
.factory('MotionContentProvider', ['gettextCatalog', function(gettextCatalog) {
|
.factory('MotionContentProvider', ['gettextCatalog', function(gettextCatalog) {
|
||||||
/**
|
/**
|
||||||
@ -1023,7 +1023,6 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid
|
|||||||
.controller('MotionDetailCtrl', [
|
.controller('MotionDetailCtrl', [
|
||||||
'$scope',
|
'$scope',
|
||||||
'$http',
|
'$http',
|
||||||
'$timeout',
|
|
||||||
'ngDialog',
|
'ngDialog',
|
||||||
'MotionComment',
|
'MotionComment',
|
||||||
'MotionForm',
|
'MotionForm',
|
||||||
@ -1033,7 +1032,6 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid
|
|||||||
'Tag',
|
'Tag',
|
||||||
'User',
|
'User',
|
||||||
'Workflow',
|
'Workflow',
|
||||||
'Editor',
|
|
||||||
'Config',
|
'Config',
|
||||||
'motion',
|
'motion',
|
||||||
'SingleMotionContentProvider',
|
'SingleMotionContentProvider',
|
||||||
@ -1041,11 +1039,11 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid
|
|||||||
'PollContentProvider',
|
'PollContentProvider',
|
||||||
'PdfMakeConverter',
|
'PdfMakeConverter',
|
||||||
'PdfMakeDocumentProvider',
|
'PdfMakeDocumentProvider',
|
||||||
|
'MotionInlineEditing',
|
||||||
'gettextCatalog',
|
'gettextCatalog',
|
||||||
'diffService',
|
function($scope, $http, ngDialog, MotionComment, MotionForm, Motion, Category, Mediafile, Tag,
|
||||||
function($scope, $http, $timeout, ngDialog, MotionComment, MotionForm, Motion, Category, Mediafile, Tag,
|
User, Workflow, Config, motion, SingleMotionContentProvider, MotionContentProvider,
|
||||||
User, Workflow, Editor, Config, motion, SingleMotionContentProvider, MotionContentProvider,
|
PollContentProvider, PdfMakeConverter, PdfMakeDocumentProvider, MotionInlineEditing, gettextCatalog) {
|
||||||
PollContentProvider, PdfMakeConverter, PdfMakeDocumentProvider, gettextCatalog, diffService) {
|
|
||||||
Motion.bindOne(motion.id, $scope, 'motion');
|
Motion.bindOne(motion.id, $scope, 'motion');
|
||||||
Category.bindAll({}, $scope, 'categories');
|
Category.bindAll({}, $scope, 'categories');
|
||||||
Mediafile.bindAll({}, $scope, 'mediafiles');
|
Mediafile.bindAll({}, $scope, 'mediafiles');
|
||||||
@ -1057,7 +1055,6 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid
|
|||||||
$scope.isCollapsed = true;
|
$scope.isCollapsed = true;
|
||||||
$scope.commentsFields = MotionComment.getFields();
|
$scope.commentsFields = MotionComment.getFields();
|
||||||
$scope.lineNumberMode = Config.get('motions_default_line_numbering').value;
|
$scope.lineNumberMode = Config.get('motions_default_line_numbering').value;
|
||||||
$scope.lineBrokenText = motion.getTextWithLineBreaks($scope.version);
|
|
||||||
if (motion.parent_id) {
|
if (motion.parent_id) {
|
||||||
Motion.bindOne(motion.parent_id, $scope, 'parent');
|
Motion.bindOne(motion.parent_id, $scope, 'parent');
|
||||||
}
|
}
|
||||||
@ -1168,17 +1165,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid
|
|||||||
// show specific version
|
// show specific version
|
||||||
$scope.showVersion = function (version) {
|
$scope.showVersion = function (version) {
|
||||||
$scope.version = version.id;
|
$scope.version = version.id;
|
||||||
$scope.lineBrokenText = motion.getTextWithLineBreaks($scope.version);
|
$scope.inlineEditing.setVersion(motion, version.id);
|
||||||
$scope.inlineEditing.allowed = (motion.isAllowed('update') && $scope.version == motion.getVersion(-1).id);
|
|
||||||
$scope.inlineEditing.changed = false;
|
|
||||||
$scope.inlineEditing.active = false;
|
|
||||||
if ($scope.inlineEditing.editor) {
|
|
||||||
$scope.inlineEditing.editor.setContent($scope.lineBrokenText);
|
|
||||||
$scope.inlineEditing.editor.setMode("readonly");
|
|
||||||
$scope.inlineEditing.originalHtml = $scope.inlineEditing.editor.getContent();
|
|
||||||
} else {
|
|
||||||
$scope.inlineEditing.originalHtml = $scope.lineBrokenText;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
// permit specific version
|
// permit specific version
|
||||||
$scope.permitVersion = function (version) {
|
$scope.permitVersion = function (version) {
|
||||||
@ -1199,96 +1186,8 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Inline editing functions
|
// Inline editing functions
|
||||||
$scope.inlineEditing = {
|
$scope.inlineEditing = MotionInlineEditing;
|
||||||
allowed: (motion.isAllowed('update') && $scope.version == motion.getVersion(-1).id),
|
$scope.inlineEditing.init($scope, motion);
|
||||||
active: false,
|
|
||||||
changed: false,
|
|
||||||
trivialChange: false,
|
|
||||||
trivialChangeAllowed: false,
|
|
||||||
editor: null,
|
|
||||||
originalHtml: $scope.lineBrokenText,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (motion.state.versioning && Config.get('motions_allow_disable_versioning').value) {
|
|
||||||
$scope.inlineEditing.trivialChange = true;
|
|
||||||
$scope.inlineEditing.trivialChangeAllowed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.$watch(
|
|
||||||
function () {
|
|
||||||
return Motion.lastModified();
|
|
||||||
},
|
|
||||||
function () {
|
|
||||||
$scope.inlineEditing.trivialChangeAllowed =
|
|
||||||
(motion.state.versioning && Config.get('motions_allow_disable_versioning').value);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
$scope.tinymceOptions = Editor.getOptions(null, true);
|
|
||||||
$scope.tinymceOptions.readonly = 1;
|
|
||||||
$scope.tinymceOptions.setup = function (editor) {
|
|
||||||
$scope.inlineEditing.editor = editor;
|
|
||||||
editor.on("init", function () {
|
|
||||||
$scope.lineBrokenText = motion.getTextWithLineBreaks($scope.version);
|
|
||||||
$scope.inlineEditing.editor.setContent($scope.lineBrokenText);
|
|
||||||
$scope.inlineEditing.originalHtml = $scope.inlineEditing.editor.getContent();
|
|
||||||
$scope.inlineEditing.changed = false;
|
|
||||||
});
|
|
||||||
editor.on("change", function () {
|
|
||||||
$scope.inlineEditing.changed = (editor.getContent() != $scope.inlineEditing.originalHtml);
|
|
||||||
});
|
|
||||||
editor.on("undo", function() {
|
|
||||||
$scope.inlineEditing.changed = (editor.getContent() != $scope.inlineEditing.originalHtml);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.enableInlineEditing = function() {
|
|
||||||
$scope.inlineEditing.editor.setMode("design");
|
|
||||||
$scope.inlineEditing.active = true;
|
|
||||||
$scope.inlineEditing.changed = false;
|
|
||||||
|
|
||||||
$scope.lineBrokenText = motion.getTextWithLineBreaks($scope.version);
|
|
||||||
$scope.inlineEditing.editor.setContent($scope.lineBrokenText);
|
|
||||||
$scope.inlineEditing.originalHtml = $scope.inlineEditing.editor.getContent();
|
|
||||||
$timeout(function() {
|
|
||||||
$scope.inlineEditing.editor.focus();
|
|
||||||
}, 100);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.disableInlineEditing = function() {
|
|
||||||
$scope.inlineEditing.editor.setMode("readonly");
|
|
||||||
$scope.inlineEditing.active = false;
|
|
||||||
$scope.inlineEditing.changed = false;
|
|
||||||
$scope.lineBrokenText = $scope.inlineEditing.originalHtml;
|
|
||||||
$scope.inlineEditing.editor.setContent($scope.inlineEditing.originalHtml);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.motionInlineSave = function () {
|
|
||||||
if (!$scope.inlineEditing.allowed) {
|
|
||||||
throw "No permission to update motion";
|
|
||||||
}
|
|
||||||
|
|
||||||
motion.setTextStrippingLineBreaks(motion.active_version, $scope.inlineEditing.editor.getContent());
|
|
||||||
motion.disable_versioning = $scope.inlineEditing.trivialChange;
|
|
||||||
|
|
||||||
Motion.inject(motion);
|
|
||||||
// save change motion object on server
|
|
||||||
Motion.save(motion, { method: 'PATCH' }).then(
|
|
||||||
function(success) {
|
|
||||||
$scope.showVersion(motion.getVersion(-1));
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
// save error: revert all changes by restore
|
|
||||||
// (refresh) original motion object from server
|
|
||||||
Motion.refresh(motion);
|
|
||||||
var message = '';
|
|
||||||
for (var e in error.data) {
|
|
||||||
message += e + ': ' + error.data[e] + ' ';
|
|
||||||
}
|
|
||||||
$scope.alert = {type: 'danger', msg: message, show: true};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -274,12 +274,13 @@
|
|||||||
|
|
||||||
<div class="details">
|
<div class="details">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="pull-right inline-editing-activator" ng-if="inlineEditing.allowed">
|
<div class="pull-right inline-editing-activator"
|
||||||
<button ng-if="!inlineEditing.active" ng-click="enableInlineEditing()" class="btn btn-sm btn-default">
|
ng-if="motion.isAllowed('update') && version == motion.getVersion(-1).id">
|
||||||
|
<button ng-if="!inlineEditing.active" ng-click="inlineEditing.enable()" class="btn btn-sm btn-default">
|
||||||
<i class="fa fa-toggle-off"></i>
|
<i class="fa fa-toggle-off"></i>
|
||||||
<translate>Inline editing inactive</translate>
|
<translate>Inline editing inactive</translate>
|
||||||
</button>
|
</button>
|
||||||
<button ng-if="inlineEditing.active" ng-click="disableInlineEditing()" class="btn btn-sm btn-default">
|
<button ng-if="inlineEditing.active" ng-click="inlineEditing.disable()" class="btn btn-sm btn-default">
|
||||||
<i class="fa fa-toggle-on"></i>
|
<i class="fa fa-toggle-on"></i>
|
||||||
<translate>Inline editing active</translate>
|
<translate>Inline editing active</translate>
|
||||||
</button>
|
</button>
|
||||||
@ -313,9 +314,9 @@
|
|||||||
|
|
||||||
<div ng-class="{'col-sm-8': (lineNumberMode != 'outside'), 'col-sm-12': (lineNumberMode == 'outside')}">
|
<div ng-class="{'col-sm-8': (lineNumberMode != 'outside'), 'col-sm-12': (lineNumberMode == 'outside')}">
|
||||||
|
|
||||||
<div ng-if="inlineEditing.allowed">
|
<div ng-if="motion.isAllowed('update') && version == motion.getVersion(-1).id">
|
||||||
<div ng-show="inlineEditing.active">
|
<div ng-show="inlineEditing.active">
|
||||||
<div ui-tinymce="tinymceOptions" ng-model="lineBrokenText"
|
<div ui-tinymce="inlineEditing.tinymceOptions" ng-model="inlineEditing.lineBrokenText"
|
||||||
class="motion-text line-numbers-{{ lineNumberMode }}"></div>
|
class="motion-text line-numbers-{{ lineNumberMode }}"></div>
|
||||||
</div>
|
</div>
|
||||||
<div ng-show="!inlineEditing.active" ng-bind-html="motion.getTextWithLineBreaks(version) | trusted"
|
<div ng-show="!inlineEditing.active" ng-bind-html="motion.getTextWithLineBreaks(version) | trusted"
|
||||||
@ -323,14 +324,14 @@
|
|||||||
|
|
||||||
<div class="motion-save-toolbar" ng-class="{ 'visible': (inlineEditing.changed && inlineEditing.active) }">
|
<div class="motion-save-toolbar" ng-class="{ 'visible': (inlineEditing.changed && inlineEditing.active) }">
|
||||||
<div class="changed-hint" translate>The text has been changed.</div>
|
<div class="changed-hint" translate>The text has been changed.</div>
|
||||||
<button type="button" ng-click="motionInlineSave()" class="btn btn-primary">Save</button>
|
<button type="button" ng-click="inlineEditing.save()" class="btn btn-primary">Save</button>
|
||||||
<label ng-if="inlineEditing.trivialChangeAllowed">
|
<label ng-if="motion.state.versioning && config('motions_allow_disable_versioning')">
|
||||||
<input type="checkbox" ng-model="inlineEditing.trivialChange" value="1">
|
<input type="checkbox" ng-model="inlineEditing.trivialChange" value="1">
|
||||||
<span translate>Trivial change</span>
|
<span translate>Trivial change</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div ng-if="!inlineEditing.allowed">
|
<div ng-if="!(motion.isAllowed('update') && version == motion.getVersion(-1).id)">
|
||||||
<div ng-bind-html="motion.getTextWithLineBreaks(version) | trusted"
|
<div ng-bind-html="motion.getTextWithLineBreaks(version) | trusted"
|
||||||
class="motion-text line-numbers-{{ lineNumberMode }}"></div>
|
class="motion-text line-numbers-{{ lineNumberMode }}"></div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user