--- /dev/null
- margin-left: 0.1em;
+body {
+ margin: 0;
+
+ font: 12px Helvetica, Verdana, sans-serif;
+ overflow: hidden;
+ background: #AAA;
+}
+
+/* fix icon buttons */
+
+button img {
+ vertical-align: middle;
+ margin: 0px;
+}
+
+/* default form style hacks */
+select {
+ border: none;
- padding: 0px;
++ margin-left: 0.1em;f
+}
+
+#body-wrap {
+ margin: 0px;
- /* ========== */
- /* = Panels = */
- /* ========== */
-
- /* #panels {
- height: 100%;
- width: 100%;
- }
-
- .panel-wrap {
- overflow: hidden;
- position: absolute;
- top: 0px;
- bottom: 0px;
- }
-
- #left-panel-wrap {
- left: 0px;
- width: 8px;
- }
-
- #right-panel-wrap {
- right: 0px;
- width: auto;
- left: 8px;
- }
-
- .panel-content {
- position: absolute;
- overflow: auto;
- overflow-x: hidden;
- top: 25px; left: 0px; bottom:0px; right: 0px;
- }
-
- .panel-overlay {
- position: absolute;
- top: 0px; bottom: 0px; left: 0px; right: 0px;
- z-index: 100;
- background: gray;
- opacity: 0.8;
- text-align: center;
- overflow: hidden;
- display: none;
- cursor: col-resize;
- }
-
- .panel-content-overlay {
- }
-
- .panel-wrap.last-panel .panel-content {
- right: 0px;
- }
-
- .panel-wrap.last-panel .panel-slider {
- display: none;
- }
-
- .panel-wrap .panel-toolbar {
- position: absolute;
- top: 0px; left:0px; right: 0px; height: 26px;
- padding: 0px;
-
- border-bottom: 1px solid #AAA;
- z-index: 80;
- }
- .panel-wrap .panel-slider {
- position: absolute;
- background-color: #DDD;
-
- top: 0px; bottom: 0px; right: 0px; width: 4px;
-
- border-left: 1px solid #999;
- border-right: 1px solid #999;
- border-top: none;
- border-bottom: none;
-
- z-index: 90;
- cursor: col-resize;
- }
-
- .panel-wrap .panel-slider:hover {
- background-color: #999;
- }
-
- .panel-content-overlay.panel-wrap .panel-slider {
- background-color: #DDD;
- }
-
- */
-
- /* OLD STUFF AGAIN */
-
++ padding: 0px;
++ position: fixed;
++ left: 0px;
++ right: 0px;
++ bottom: 0px;
++ top: 0px;
+}
+
+#header {
+ position: absolute;
+ padding: 2px 0.5em;
+ background-color: #CDCDCD; /* !unused */
+ border-bottom: 2px solid black;
+
+ font-size: 14px;
+
+ line-height: 26px;
+ vertical-align: middle;
+
+ /* height: 30px; */
+ top: 0px; left: 0px; right: 0px;
+ z-index: 300;
+}
+
+#content {
+ position: absolute;
+ top: 32px; left: 0px; right: 0px; bottom: 0px;
+ overflow: auto;
+ background-color: white;
+}
+
+#header #breadcrumbs {
+}
+
+#header-right-toolbar {
+ position: absolute;
+ right: 1em;
+}
+
+#header button {
+ vertical-align: middle;
+}
+
- text-valign: center;
+/* Commit dialog */
+#commit-dialog-error-empty-message {
+ color: red;
+ display: none;
+ font-weight: bold;
+}
+
+text#commit-dialog-message {
+ width: 80%;
+ margin: auto;
+}
+
+#split-dialog .container-box form {
+ margin: 0.2em 1em;
+}
+
+#split-dialog .container-box fieldset {
+ margin: 0.5em;
+}
+
+
+
+
+/* ======= */
+/* = New = */
+/* ======= */
+#splitview {
+ width: 100%;
+ height: 100%;
+ padding: 0;
+ margin: 0;
+}
+
+.splitview-splitbar {
+ width: 5px;
+ border-left: 1px solid #999;
+ border-right: 1px solid #999;
+ height: 100%;
+ background-color: #CCC;
+ z-index: 100;
+}
+
+.splitview-overlay {
+ z-index: 90;
+ background: #FFF;
+ opacity: 0.5;
+}
+
+.panel-container {
+ height: 100%;
+ position: relative;
+}
+
+.content-view {
+ position: absolute;
+ top: 25px;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ overflow: hidden;
+}
+
+.panel-main-toolbar {
+ z-index: 1100;
+ position: absolute;
+
+ top: 0px;
+ right: 0px;
+ left: 0px;
+ height: 24px;
+
+ border-bottom: 1px solid black;
+ background: gray;
+
+ padding: 0px;
+}
+
+.panel-main-toolbar p {
+ margin: 0px;
+ padding: 2px;
+ line-height: 20px;
+ font-size: 13px;
+}
+
+.xmlview {
+ height: 100%;
+}
+
+.view-overlay {
+ z-index: 1000;
+ background: #FFF;
+ opacity: 0.8;
+ text-align: center;
- .view-overlay p {
- display: block;
- position: relative;
- top: auto;
- bottom: auto;
- height: 40px;
++ vertical-align: middle;
++
++ position: absolute;
++ left: 0;
++ right: 0;
++ top: 0;
++ bottom: 0;
++
++ user-select: 'none';
++ -webkit-user-select: 'none';
++ -khtml-user-select: 'none';
++ -moz-user-select: 'none';
++ overflow: 'hidden';
+}
+
++.view-overlay div {
++ position: absolute;
+}
+
+/* .buttontoolbarview {
+ display: block;
+ background-color: #CCC;
+}
+
+.buttontoolbarview a {
+ color: #000;
+ text-decoration: none;
+} */ /* Similar classes already exist in toolbar.css */
+
+
+/* ================= */
+/* = Gallery panel = */
+/* ================= */
+.image-gallery-view-template {
+ position: absolute;
+ top: 0px; left: 0px; right: 0px; bottom: 0px;
+ overflow: hidden;
+}
+
+.image-gallery-header {
+ position: absolute;
+ bottom: 0px;
+ left: 0px;
+ right: 0px;
+ height: 30px;
+
+ background: gray;
+ border-top: 1px solid #780000;
+ z-index: 100;
+}
+
+input.image-gallery-current-page {
+ text-align: center;
+}
+
+.image-gallery-header p {
+ margin: 0px;
+ padding: 3px 1em;
+ height: 30px;
+ line-height: 24px;
+ text-align: center;
+ white-space: nowrap;
+}
+
+.image-gallery-page-list {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ right: 0px;
+ bottom: 31px;
+ background: black;
+ z-index: 0;
+
+ overflow: hidden;
+}
+
+.image-gallery-page-container {
+ display: none;
+ border: none;
+
+ position: absolute;
+ top: 0px; left: 0px;
+
+ text-align: center;
+ padding: 0px;
+}
+
+.htmlview {
+ position: absolute;
+ top: 25px;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ overflow: auto;
+ margin: 0;
+}
+
+.image-gallery-page-container img {
+ /* border: 2px solid green; */
+ margin: 0px;
+}
+
+body#base button {
+ background-color: #DDD;
+ border-width: 1px;
+ padding: 0px 0.5em;
+ font-family: Sans-Serif;
+ /* color: #000; */
+ margin: 2px 4px;
+}
+
+body#base button:hover {
+ background-color: #EEE;
+}
+
+/* HTML editor interactive elements */
+
+.html-editarea {
+ border: 2px solid black;
+ background-color: gray;
+ padding: 1px;
+
+ z-index: 2000;
+}
+
+.html-editarea textarea
+{
+
+ border: 0px;
+ margin: 0px;
+ padding: 0px;
+
+ width: 100%;
+ height: 100%;
+
+ z-index: 0;
+ font-size: 10pt;
+ background-color: ivory;
+}
+
+.html-editarea p.html-editarea-toolbar {
+ position: absolute;
+ background: gray;
+
+ bottom: -26px;
+ height: 24px;
+
+ left: 0px;
+ right: 0px;
+
+ border: 2px solid black;
+
+ margin: 0px;
+ padding: 0px;
+
+ z-index: 100;
+}
+
+/* ================= */
+/* = Message boxes = */
+/* ================= */
+.info {
+ background-color: gray;
+}
+
+.success {
+ background-color: green;
+}
+
+.error {
+ background-color: yellow;
+}
+
+.critical {
+ background-color: red;
+}
+
--- /dev/null
- var panels = [];
+/*global Class*/
+var editor;
+var panel_hooks;
+
+
+// prevent a console.log from blowing things up if we are on a browser that
+// does not support it
+if (typeof console === 'undefined') {
+ window.console = {} ;
+ console.log = console.info = console.warn = console.error = function(){};
+}
+
+
+(function(){
+ // Classes
+ var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
+ this.Class = function(){};
+ Class.extend = function(prop) {
+ var _super = this.prototype;
+ initializing = true;
+ var prototype = new this();
+ initializing = false;
+ for (var name in prop) {
+ prototype[name] = typeof prop[name] == "function" &&
+ typeof _super[name] == "function" && fnTest.test(prop[name]) ?
+ (function(name, fn){
+ return function() {
+ var tmp = this._super;
+ this._super = _super[name];
+ var ret = fn.apply(this, arguments);
+ this._super = tmp;
+ return ret;
+ };
+ })(name, prop[name]) :
+ prop[name];
+ }
+ function Class() {
+ if ( !initializing && this.init )
+ this.init.apply(this, arguments);
+ }
+ Class.prototype = prototype;
+ Class.constructor = Class;
+ Class.extend = arguments.callee;
+ return Class;
+ };
+
+ // Templates
+ var cache = {};
+
+ this.render_template = function render_template(str, data){
+ // Figure out if we're getting a template, or if we need to
+ // load the template - and be sure to cache the result.
+ var fn = !/^[\d\s-_]/.test(str) ?
+ cache[str] = cache[str] ||
+ render_template(document.getElementById(str).innerHTML) :
+
+ // Generate a reusable function that will serve as a template
+ // generator (and which will be cached).
+
+ new Function("obj",
+ "var p=[],print=function(){p.push.apply(p,arguments);};" +
+
+ // Introduce the data as local variables using with(){}
+ "with(obj){p.push('" +
+
+ // Convert the template into pure JavaScript
+ str
+ .replace(/[\r\t\n]/g, " ")
+ .split("<%").join("\t")
+ .replace(/((^|%>)[^\t]*)'/g, "$1\r")
+ .replace(/\t=(.*?)%>/g, "',$1,'")
+ .split("\t").join("');")
+ .split("%>").join("p.push('")
+ .split("\r").join("\\'")
+ + "');}return p.join('');");
+
+ // Provide some basic currying to the user
+ return data ? fn( data ) : fn;
+ };
+})();
+
+
+(function() {
+ var slice = Array.prototype.slice;
+
+ function update(array, args) {
+ var arrayLength = array.length, length = args.length;
+ while (length--) array[arrayLength + length] = args[length];
+ return array;
+ };
+
+ function merge(array, args) {
+ array = slice.call(array, 0);
+ return update(array, args);
+ };
+
+ Function.prototype.bind = function(context) {
+ if (arguments.length < 2 && typeof arguments[0] === 'undefined') {
+ return this;
+ }
+ var __method = this;
+ var args = slice.call(arguments, 1);
+ return function() {
+ var a = merge(args, arguments);
+ return __method.apply(context, a);
+ }
+ }
+
+})();
+
+
+var Editor = Editor || {};
+
+// Obiekt implementujący wzorzec KVC/KVO
+Editor.Object = Class.extend({
+ _className: 'Editor.Object',
+ _observers: {},
+ _guid: null,
+
+ init: function() {
+ this._observers = {};
+ },
+
+ description: function() {
+ return this._className + '(guid = ' + this.guid() + ')';
+ },
+
+ addObserver: function(observer, property, callback) {
+ // console.log('Add observer', observer.description(), 'to', this.description(), '[', property, ']');
+ if (!this._observers[property]) {
+ this._observers[property] = {}
+ }
+ this._observers[property][observer.guid()] = callback;
+ return this;
+ },
+
+ removeObserver: function(observer, property) {
+ if (!property) {
+ for (var property in this._observers) {
+ this.removeObserver(observer, property)
+ }
+ } else {
+ // console.log('Remove observer', observer.description(), 'from', this.description(), '[', property, ']');
+ delete this._observers[property][observer.guid()];
+ }
+ return this;
+ },
+
+ notifyObservers: function(property) {
+ var currentValue = this[property];
+ for (var guid in this._observers[property]) {
+ // console.log(this._observers[property][guid]);
+ // console.log('Notifying', guid, 'of', this.description(), '[', property, ']');
+ this._observers[property][guid](property, currentValue, this);
+ }
+ return this;
+ },
+
+ guid: function() {
+ if (!this._guid) {
+ this._guid = ('editor-' + Editor.Object._lastGuid++);
+ }
+ return this._guid;
+ },
+
+ get: function(property) {
+ return this[property];
+ },
+
+ set: function(property, value) {
+ if (this[property] != value) {
+ this[property] = value;
+ this.notifyObservers(property);
+ }
+ return this;
+ },
+
+ dispose: function() {
+ delete this._observers;
+ }
+});
+
++// Handle JSON error responses in uniform way
++function parseXHRError(response)
++{
++ var message = ""
++ try {
++ var json = $.evalJSON(response.responseText);
++
++ if(json.reason == 'xml-parse-error') {
++ message = json_response.message.replace(/(line\s+)(\d+)(\s+)/i,
++ "<a class='xml-editor-ref' href='#xml-$2-1'>$1$2$3</a>");
++
++ message = message.replace(/(line\s+)(\d+)(\,\s*column\s+)(\d+)/i,
++ "<a class='xml-editor-ref' href='#xml-$2-$4'>$1$2$3$4</a>");
++ }
++ message = json_response.message || json_response.reason || "Nieznany błąd :((";
++ } catch(e) {
++ // not a valid JSON response
++ message = response.statusText;
++ }
++ return message;
++}
++
+Editor.Object._lastGuid = 0;
+
++var panels = [];
--- /dev/null
- init: function() {
- this.messages = [];
- this.flashMessages = [];
- this.firstFlashMessage = null;
- },
+/*global Editor*/
+Editor.MessageCenter = Editor.Object.extend({
- addMessage: function(type, text, flash) {
- if (!flash) {
- flash = text;
- }
- this.messages.push({type: type, text: text});
- this.flashMessages.push({type: type, text: flash});
- if (this.flashMessages.length == 1) {
- this.set('firstFlashMessage', this.flashMessages[0]);
- setTimeout(this.changeFlashMessage.bind(this), 1000 * 10);
- }
- },
++ init: function() {
++ this.messages = [];
++ this.flashMessages = [];
++ this.firstFlashMessage = null;
++ this.timeout = null;
++ console.log("MSC-init:", Date(), this);
++ },
+
- changeFlashMessage: function() {
- this.flashMessages.splice(0, 1);
- if (this.flashMessages.length > 0) {
- this.set('firstFlashMessage', this.flashMessages[0]);
- setTimeout(this.changeFlashMessage.bind(this), 1000 * 3); // 3 seconds
- } else {
- this.set('firstFlashMessage', null);
++ addMessage: function(type, tag, text, flash)
++ {
++ if (!tag) tag = '#default'
++
++ if (!flash) {
++ flash = text;
++ }
++
++ this.messages.push({
++ type: type,
++ text: text
++ });
++
++ this.flashMessages.push({
++ type: type,
++ text: flash,
++ tag: tag
++ });
++
++ if(this.timeout) {
++ if(this.flashMessages[0] && (this.flashMessages[0].tag == tag))
++ {
++ clearTimeout(this.timeout);
++ this.timeout = null;
++ this.changeFlashMessage();
++ }
++ }
++
++ else {
++ /* queue was empty at the start */
++ if (this.flashMessages.length == 1) {
++ console.log("MSC-added-fisrt", Date(), this);
++ this.set('firstFlashMessage', this.flashMessages[0]);
++ this.timeout = setTimeout(this.changeFlashMessage.bind(this), 3000);
++ }
++
++ }
++
++ },
+
- }
++ changeFlashMessage: function()
++ {
++ console.log("MSC-change", Date(), this);
++ var previous = this.flashMessages.splice(0, 1);
++
++ if (this.flashMessages.length > 0)
++ {
++ console.log("MSC-chaning-first", Date(), this);
++ this.set('firstFlashMessage', this.flashMessages[0]);
++ this.timeout = setTimeout(this.changeFlashMessage.bind(this), 3000);
++ } else {
++ console.log("MSC-emptying", Date(), this);
++ this.set('firstFlashMessage', null);
++ }
+ }
+
+});
+
+
+var messageCenter = new Editor.MessageCenter();
+
--- /dev/null
-
+/*globals Editor fileId SplitView PanelContainerView EditorView FlashView messageCenter*/
+Editor.Model = Editor.Object.extend({
+ synced: false,
+ data: null
+});
+
- url: toolbarUrl,
+Editor.ToolbarButtonsModel = Editor.Model.extend({
+ className: 'Editor.ToolbarButtonsModel',
+ buttons: {},
+
+ init: function() {
+ this._super();
+ },
+
+ load: function() {
+ if (!this.get('buttons').length) {
+ $.ajax({
- init: function(serverURL, revision) {
++ url: documentInfo.toolbarURL,
+ dataType: 'json',
+ success: this.loadSucceeded.bind(this)
+ });
+ }
+ },
+
+ loadSucceeded: function(data)
+ {
+ // do some escaping
+ $.each(data, function() {
+ $.each(this.buttons, function() {
+ //do some lame escapes
+ this.tooltip = this.tooltip.replace(/"/g, """);
+ });
+ });
+ this.set('buttons', data);
+ }
+});
+
+
+// Stany modelu:
+//
+// -> error -> loading
+// /
+// empty -> loading -> synced -> unsynced -> loading
+// \
+// -> dirty -> updating -> updated -> synced
+//
+Editor.XMLModel = Editor.Model.extend({
+ _className: 'Editor.XMLModel',
+ serverURL: null,
+ data: '',
+ state: 'empty',
+
- this.set('revision', revision);
++ init: function(document, serverURL) {
+ this._super();
+ this.set('state', 'empty');
- messageCenter.addMessage('info', 'Wczytuję XML...');
++ this.set('revision', document.get('revision'));
++ this.document = document;
+ this.serverURL = serverURL;
+ this.toolbarButtonsModel = new Editor.ToolbarButtonsModel();
+ this.addObserver(this, 'data', this.dataChanged.bind(this));
+ },
+
+ load: function(force) {
+ if (force || this.get('state') == 'empty') {
+ this.set('state', 'loading');
- revision: this.get('revision')
++ messageCenter.addMessage('info', 'xmlload', 'Wczytuję XML...');
+ $.ajax({
+ url: this.serverURL,
+ dataType: 'text',
+ data: {
- messageCenter.addMessage('success', 'Wczytałem XML :-)');
++ revision: this.get('revision'),
++ user: this.document.get('user')
+ },
+ success: this.loadingSucceeded.bind(this),
+ error: this.loadingFailed.bind(this)
+ });
+ return true;
+ }
+ return false;
+ },
+
+ loadingSucceeded: function(data) {
+ if (this.get('state') != 'loading') {
+ alert('erroneous state:', this.get('state'));
+ }
+ this.set('data', data);
+ this.set('state', 'synced');
- this.set('error', 'Nie udało się załadować panelu');
++ messageCenter.addMessage('success', 'xmlload', 'Wczytałem XML :-)');
+ },
+
+ loadingFailed: function() {
+ if (this.get('state') != 'loading') {
+ alert('erroneous state:', this.get('state'));
+ }
- messageCenter.addMessage('error', 'Nie udało mi się wczytać XML. Spróbuj ponownie :-(');
++ var message = parseXHRError(response);
++
++ this.set('error', '<h2>Błąd przy ładowaniu XML</h2><p>'+message+'</p>');
+ this.set('state', 'error');
- update: function(message) {
++ messageCenter.addMessage('error', 'xmlload', 'Nie udało mi się wczytać XML. Spróbuj ponownie :-(');
+ },
+
- messageCenter.addMessage('info', 'Zapisuję XML...');
++ save: function(message) {
+ if (this.get('state') == 'dirty') {
+ this.set('state', 'updating');
- revision: this.get('revision')
++ messageCenter.addMessage('info', 'xmlsave', 'Zapisuję XML...');
+
+ var payload = {
+ contents: this.get('data'),
- success: this.updatingSucceeded.bind(this),
- error: this.updatingFailed.bind(this)
++ revision: this.get('revision'),
++ user: this.document.get('user')
+ };
+ if (message) {
+ payload.message = message;
+ }
+
+ $.ajax({
+ url: this.serverURL,
+ type: 'post',
+ dataType: 'json',
+ data: payload,
- updatingSucceeded: function(data) {
++ success: this.saveSucceeded.bind(this),
++ error: this.saveFailed.bind(this)
+ });
+ return true;
+ }
+ return false;
+ },
+
- messageCenter.addMessage('success', 'Zapisałem XML :-)');
++ saveSucceeded: function(data) {
+ if (this.get('state') != 'updating') {
+ alert('erroneous state:', this.get('state'));
+ }
+ this.set('revision', data.revision);
+ this.set('state', 'updated');
- updatingFailed: function() {
++ messageCenter.addMessage('success', 'xmlsave', 'Zapisałem XML :-)');
+ },
+
- messageCenter.addMessage('error', 'Nie udało mi się zapisać XML. Spróbuj ponownie :-(');
++ saveFailed: function() {
+ if (this.get('state') != 'updating') {
+ alert('erroneous state:', this.get('state'));
+ }
- init: function(htmlURL, revision, dataURL) {
++ messageCenter.addMessage('error', 'xmlsave', 'Nie udało mi się zapisać XML. Spróbuj ponownie :-(');
+ this.set('state', 'dirty');
+ },
+
+ // For debbuging
+ set: function(property, value) {
+ if (property == 'state') {
+ console.log(this.description(), ':', property, '=', value);
+ }
+ return this._super(property, value);
+ },
+
+ dataChanged: function(property, value) {
+ if (this.get('state') == 'synced') {
+ this.set('state', 'dirty');
+ }
+ },
+
+ dispose: function() {
+ this.removeObserver(this);
+ this._super();
+ }
+});
+
+
+Editor.HTMLModel = Editor.Model.extend({
+ _className: 'Editor.HTMLModel',
+ dataURL: null,
+ htmlURL: null,
+ renderURL: null,
+ displaData: '',
+ xmlParts: {},
+ state: 'empty',
+
- this.set('revision', revision);
++ init: function(document, dataURL, htmlURL) {
+ this._super();
+ this.set('state', 'empty');
- this.renderURL = "http://localhost:8000/api/render";
++ this.set('revision', document.get('revision'));
++
++ this.document = document;
+ this.htmlURL = htmlURL;
+ this.dataURL = dataURL;
- revision: this.get('revision')
++ this.renderURL = documentInfo.renderURL;
+ this.xmlParts = {};
+ },
+
+ load: function(force) {
+ if (force || this.get('state') == 'empty') {
+ this.set('state', 'loading');
+
+ // load the transformed data
+ // messageCenter.addMessage('info', 'Wczytuję HTML...');
+
+ $.ajax({
+ url: this.htmlURL,
+ dataType: 'text',
+ data: {
- },
++ revision: this.get('revision'),
++ user: this.document.get('user')
+ },
+ success: this.loadingSucceeded.bind(this),
+ error: this.loadingFailed.bind(this)
+ });
+ }
- // messageCenter.addMessage('success', 'Wczytałem HTML :-)');
++ },
+
+ loadingSucceeded: function(data) {
+ if (this.get('state') != 'loading') {
+ alert('erroneous state:', this.get('state'));
+ }
+ this.set('data', data);
+ this.set('state', 'synced');
-
- var json_response = null;
- var message = "";
-
- try {
- json_response = $.evalJSON(response.responseText);
-
- if(json_response.reason == 'xml-parse-error') {
-
- message = json_response.message.replace(/(line\s+)(\d+)(\s+)/i,
- "<a class='xml-editor-ref' href='#xml-$2-1'>$1$2$3</a>");
-
- message = message.replace(/(line\s+)(\d+)(\,\s*column\s+)(\d+)/i,
- "<a class='xml-editor-ref' href='#xml-$2-$4'>$1$2$3$4</a>");
-
-
- }
- else {
- message = json_response.message || json_response.reason || "nieznany błąd.";
- }
- }
- catch (e) {
- message = response.statusText;
- }
-
+ },
+
+ loadingFailed: function(response) {
+ if (this.get('state') != 'loading') {
+ alert('erroneous state:', this.get('state'));
+ }
-
- this.set('state', 'error');
- // messageCenter.addMessage('error', 'Nie udało mi się wczytać HTML. Spróbuj ponownie :-(');
++
++ var message = parseXHRError(response);
++
+ this.set('error', '<p>Nie udało się wczytać widoku HTML: </p>' + message);
- update: function(message) {
++ this.set('state', 'error');
+ },
+
+ getXMLPart: function(elem, callback)
+ {
+ var path = elem.attr('wl2o:path');
+ if(!this.xmlParts[path])
+ this.loadXMLPart(elem, callback);
+ else
+ callback(path, this.xmlParts[path]);
+ },
+
+ loadXMLPart: function(elem, callback)
+ {
+ var path = elem.attr('wl2o:path');
+ var self = this;
+
+ $.ajax({
+ url: this.dataURL,
+ dataType: 'text',
+ data: {
+ revision: this.get('revision'),
++ user: this.document.get('user'),
+ part: path
+ },
+ success: function(data) {
+ self.xmlParts[path] = data;
+ callback(path, data);
+ },
+ // TODO: error handling
+ error: function(data) {
+ console.log('Failed to load fragment');
+ callback(undefined, undefined);
+ }
+ });
+ },
+
+ putXMLPart: function(elem, data) {
+ var self = this;
+
+ var path = elem.attr('wl2o:path');
+ this.xmlParts[path] = data;
+
+ this.set('state', 'unsynced');
+
+ /* re-render the changed fragment */
+ $.ajax({
+ url: this.renderURL,
+ type: "POST",
+ dataType: 'text; charset=utf-8',
+ data: {
+ fragment: data,
+ part: path
+ },
+ success: function(htmldata) {
+ elem.replaceWith(htmldata);
+ self.set('state', 'dirty');
+ }
+ });
+ },
+
- revision: this.get('revision')
++ save: function(message) {
+ if (this.get('state') == 'dirty') {
+ this.set('state', 'updating');
+
+ var payload = {
+ chunks: $.toJSON(this.xmlParts),
- success: this.updatingSucceeded.bind(this),
- error: this.updatingFailed.bind(this)
++ revision: this.get('revision'),
++ user: this.document.get('user')
+ };
+
+ if (message) {
+ payload.message = message;
+ }
+
+ console.log(payload)
+
+ $.ajax({
+ url: this.dataURL,
+ type: 'post',
+ dataType: 'json',
+ data: payload,
- updatingSucceeded: function(data) {
++ success: this.saveSucceeded.bind(this),
++ error: this.saveFailed.bind(this)
+ });
+ return true;
+ }
+ return false;
+
+ },
+
- updatingFailed: function() {
++ saveSucceeded: function(data) {
+ if (this.get('state') != 'updating') {
+ alert('erroneous state:', this.get('state'));
+ }
+
+ // flush the cache
+ this.xmlParts = {};
+
+ this.set('revision', data.revision);
+ this.set('state', 'updated');
+ },
+
- }
- messageCenter.addMessage('error', 'Uaktualnienie nie powiodło się', 'Uaktualnienie nie powiodło się');
++ saveFailed: function() {
+ if (this.get('state') != 'updating') {
+ alert('erroneous state:', this.get('state'));
- } else {
- console.log('dupa');
++ }
+ this.set('state', 'dirty');
+ },
+
+ // For debbuging
+ set: function(property, value) {
+ if (property == 'state') {
+ console.log(this.description(), ':', property, '=', value);
+ }
+ return this._super(property, value);
+ }
+});
+
+
+Editor.ImageGalleryModel = Editor.Model.extend({
+ _className: 'Editor.ImageGalleryModel',
+ serverURL: null,
+ data: [],
+ state: 'empty',
+
+ init: function(serverURL) {
+ this._super();
+ this.set('state', 'empty');
+ this.serverURL = serverURL;
+ // olewać data
+ this.pages = [];
+ },
+
+ load: function(force) {
+ if (force || this.get('state') == 'empty') {
+ this.set('state', 'loading');
+ $.ajax({
+ url: this.serverURL,
+ dataType: 'json',
+ success: this.loadingSucceeded.bind(this)
+ });
+ }
+ },
+
+ loadingSucceeded: function(data) {
+ if (this.get('state') != 'loading') {
+ alert('erroneous state:', this.get('state'));
+ }
+
+ console.log('galleries:', data);
+
+ if (data.length === 0) {
+ this.set('data', []);
- this.set('state', 'empty');
- this.load();
++ } else {
+ this.set('data', data[0].pages);
+ }
+
+ this.set('state', 'synced');
+ },
+
+ set: function(property, value) {
+ if (property == 'state') {
+ console.log(this.description(), ':', property, '=', value);
+ }
+ return this._super(property, value);
+ }
+});
+
+
+Editor.DocumentModel = Editor.Model.extend({
+ _className: 'Editor.DocumentModel',
+ data: null, // name, text_url, user_revision, latest_shared_rev, parts_url, dc_url, size, merge_url
+ contentModels: {},
+ state: 'empty',
++ errors: '',
++ revision: '',
++ user: '',
+
+ init: function() {
+ this._super();
- messageCenter.addMessage('info', 'Ładuję dane dokumentu...');
++ this.set('state', 'empty');
+ },
+
+ load: function() {
+ if (this.get('state') == 'empty') {
+ this.set('state', 'loading');
- url: documentsUrl + fileId,
++ messageCenter.addMessage('info', 'docload', 'Ładuję dane dokumentu...');
+ $.ajax({
+ cache: false,
- success: this.successfulLoad.bind(this)
++ url: documentInfo.docURL,
+ dataType: 'json',
- 'xml': new Editor.XMLModel(data.text_url, data.user_revision),
- 'html': new Editor.HTMLModel(data.html_url, data.user_revision, data.text_url),
- 'gallery': new Editor.ImageGalleryModel(data.gallery_url)
- };
++ success: this.successfulLoad.bind(this),
++ error: this.failedLoad.bind(this)
+ });
+ }
+ },
+
+ successfulLoad: function(data) {
+ this.set('data', data);
+ this.set('state', 'synced');
++
++ this.set('revision', data.user_revision);
++ this.set('user', data.user);
++
+ this.contentModels = {
- messageCenter.addMessage('success', 'Dane dokumentu zostały załadowane :-)');
++ 'xml': new Editor.XMLModel(this, data.text_url),
++ 'html': new Editor.HTMLModel(this, data.text_url, data.html_url),
++ 'gallery': new Editor.ImageGalleryModel(this, data.gallery_url)
++ };
++
+ for (var key in this.contentModels) {
+ this.contentModels[key].addObserver(this, 'state', this.contentModelStateChanged.bind(this));
+ }
- this.contentModels[key].update(message);
++
++ this.error = '';
++
++ messageCenter.addMessage('success', 'docload', 'Dokument załadowany poprawnie :-)');
++ },
++
++ failedLoad: function(response) {
++ if (this.get('state') != 'loading') {
++ alert('erroneous state:', this.get('state'));
++ }
++
++ var message = parseXHRError(response);
++ this.set('error', '<h2>Nie udało się wczytać dokumentu</h2><p>'+message+"</p>");
++ this.set('state', 'error');
+ },
+
+ contentModelStateChanged: function(property, value, contentModel) {
+ if (value == 'dirty') {
+ this.set('state', 'dirty');
+ for (var key in this.contentModels) {
+ if (this.contentModels[key].guid() != contentModel.guid()) {
+ this.contentModels[key].set('state', 'unsynced');
+ }
+ }
+ } else if (value == 'updated') {
+ this.set('state', 'synced');
+ for (key in this.contentModels) {
+ if (this.contentModels[key].guid() == contentModel.guid()) {
+ this.contentModels[key].set('state', 'synced');
+ this.data.user_revision = this.contentModels[key].get('revision');
+ }
+ }
+ for (key in this.contentModels) {
+ if (this.contentModels[key].guid() != contentModel.guid()) {
+ this.contentModels[key].set('revision', this.data.user_revision);
+ this.contentModels[key].set('state', 'empty');
+ }
+ }
+ }
+ },
+
+ saveDirtyContentModel: function(message) {
+ for (var key in this.contentModels) {
+ if (this.contentModels[key].get('state') == 'dirty') {
- target_revision: this.data.user_revision
++ this.contentModels[key].save(message);
+ break;
+ }
+ }
+ },
+
+ update: function() {
+ this.set('state', 'loading');
+ messageCenter.addMessage('info', 'Uaktualniam dokument...');
+ $.ajax({
+ url: this.data.merge_url,
+ dataType: 'json',
+ type: 'post',
+ data: {
+ type: 'update',
- this.data.user_revision = this.get('updateData').revision;
- messageCenter.addMessage('info', 'Uaktualnienie dokumentu do wersji ' + this.get('updateData').revision,
++ revision: this.revision,
++ user: this.user
+ },
+ complete: this.updateCompleted.bind(this),
+ success: function(data) {
+ this.set('updateData', data);
+ }.bind(this)
+ });
+ },
+
+ updateCompleted: function(xhr, textStatus) {
+ console.log(xhr.status, textStatus);
+ if (xhr.status == 200) { // Sukces
- messageCenter.addMessage('success', 'Uaktualniłem dokument do najnowszej wersji :-)');
++ this.data = this.get('updateData');
++ this.revision = this.data.user_revision;
++ this.user = this.data.user;
++
++ messageCenter.addMessage('info', null, 'Uaktualnienie dokumentu do wersji ' + this.get('updateData').revision,
+ 'Uaktualnienie dokumentu do wersji ' + this.get('updateData').revision);
+ for (var key in this.contentModels) {
+ this.contentModels[key].set('revision', this.data.user_revision);
+ this.contentModels[key].set('state', 'empty');
+ }
- messageCenter.addMessage('info', 'Nic się nie zmieniło od ostatniej aktualizacji. Po co mam uaktualniać?');
++ messageCenter.addMessage('success', null, 'Uaktualniłem dokument do najnowszej wersji :-)');
+ } else if (xhr.status == 202) { // Wygenerowano PullRequest (tutaj?)
+ } else if (xhr.status == 204) { // Nic nie zmieniono
- messageCenter.addMessage('error', 'Wystąpił konflikt podczas aktualizacji. Pędź po programistów! :-(');
++ messageCenter.addMessage('info', null, 'Nic się nie zmieniło od ostatniej aktualizacji. Po co mam uaktualniać?');
+ } else if (xhr.status == 409) { // Konflikt podczas operacji
- messageCenter.addMessage('critical', 'Błąd serwera. Pędź po programistów! :-(');
++ messageCenter.addMessage('error', null, 'Wystąpił konflikt podczas aktualizacji. Pędź po programistów! :-(');
+ } else if (xhr.status == 500) {
- messageCenter.addMessage('info', 'Scalam dokument z głównym repozytorium...');
++ messageCenter.addMessage('critical', null, 'Błąd serwera. Pędź po programistów! :-(');
+ }
+ this.set('state', 'synced');
+ this.set('updateData', null);
+ },
+
+ merge: function(message) {
+ this.set('state', 'loading');
- target_revision: this.data.user_revision,
++ messageCenter.addMessage('info', null, 'Scalam dokument z głównym repozytorium...');
+ $.ajax({
+ url: this.data.merge_url,
+ type: 'post',
+ dataType: 'json',
+ data: {
+ type: 'share',
- this.data.user_revision = this.get('mergeData').revision;
++ revision: this.revision,
++ user: this.user,
+ message: message
+ },
+ complete: this.mergeCompleted.bind(this),
+ success: function(data) {
+ this.set('mergeData', data);
+ }.bind(this)
+ });
+ },
+
+ mergeCompleted: function(xhr, textStatus) {
+ console.log(xhr.status, textStatus);
+ if (xhr.status == 200) { // Sukces
- this.contentModels[key].set('revision', this.data.user_revision);
++ this.data = this.get('updateData');
++ this.revision = this.data.user_revision;
++ this.user = this.data.user;
++
+ for (var key in this.contentModels) {
- messageCenter.addMessage('success', 'Scaliłem dokument z głównym repozytorium :-)');
++ this.contentModels[key].set('revision', this.revision);
+ this.contentModels[key].set('state', 'empty');
+ }
- messageCenter.addMessage('success', 'Wysłałem prośbę o scalenie dokumentu z głównym repozytorium.');
++
++ messageCenter.addMessage('success', null, 'Scaliłem dokument z głównym repozytorium :-)');
+ } else if (xhr.status == 202) { // Wygenerowano PullRequest
- messageCenter.addMessage('info', 'Nic się nie zmieniło od ostatniego scalenia. Po co mam scalać?');
++ messageCenter.addMessage('success', null, 'Wysłałem prośbę o scalenie dokumentu z głównym repozytorium.');
+ } else if (xhr.status == 204) { // Nic nie zmieniono
- messageCenter.addMessage('error', 'Wystąpił konflikt podczas scalania. Pędź po programistów! :-(');
++ messageCenter.addMessage('info', null, 'Nic się nie zmieniło od ostatniego scalenia. Po co mam scalać?');
+ } else if (xhr.status == 409) { // Konflikt podczas operacji
- messageCenter.addMessage('critical', 'Błąd serwera. Pędź po programistów! :-(');
++ messageCenter.addMessage('error', null, 'Wystąpił konflikt podczas scalania. Pędź po programistów! :-(');
+ } else if (xhr.status == 500) {
- documentsUrl = $('#api-base-url').text() + '/';
- toolbarUrl = $('#api-toolbar-url').text();
-
++ messageCenter.addMessage('critical', null, 'Błąd serwera. Pędź po programistów! :-(');
+ }
+ this.set('state', 'synced');
+ this.set('mergeData', null);
+ },
+
+ // For debbuging
+ set: function(property, value) {
+ if (property == 'state') {
+ console.log(this.description(), ':', property, '=', value);
+ }
+ return this._super(property, value);
+ }
+});
+
+
+var leftPanelView, rightPanelContainer, doc;
+
+$(function()
+{
- EditorView.freeze();
++ var flashView = new FlashView('#flashview', messageCenter);
++
+ doc = new Editor.DocumentModel();
+
+ EditorView = new EditorView('#body-wrap', doc);
- var flashView = new FlashView('#flashview', messageCenter);
++ EditorView.freeze("<h1>Wczytuję dokument...</h1>");
+
+ leftPanelView = new PanelContainerView('#left-panel-container', doc);
+ rightPanelContainer = new PanelContainerView('#right-panel-container', doc);
+
++
+});
--- /dev/null
- } else if (value == 'synced') {
+/*global View render_template panels */
+var EditorView = View.extend({
+ _className: 'EditorView',
+ element: null,
+ model: null,
+ template: null,
+
+ init: function(element, model, template) {
+ this._super(element, model, template);
+
+ this.quickSaveButton = $('#action-quick-save', this.element).bind('click.editorview', this.quickSave.bind(this));
+ this.commitButton = $('#action-commit', this.element).bind('click.editorview', this.commit.bind(this));
+ this.updateButton = $('#action-update', this.element).bind('click.editorview', this.update.bind(this));
+ this.mergeButton = $('#action-merge', this.element).bind('click.editorview', this.merge.bind(this));
+
+ this.model.addObserver(this, 'state', this.modelStateChanged.bind(this));
+ this.modelStateChanged('state', this.model.get('state'));
+
+ this.splitView = new SplitView('#splitview', doc);
+
+ // Inicjalizacja okien jQuery Modal
+ $('#commit-dialog', this.element).
+ jqm({
+ modal: true,
+ onShow: this.loadRelatedIssues.bind(this)
+ });
+
+ $('#commit-dialog-cancel-button', this.element).click(function() {
+ $('#commit-dialog-error-empty-message').hide();
+ $('#commit-dialog').jqmHide();
+ });
++
+
+ // $('#split-dialog').jqm({
+ // modal: true,
+ // onShow: $.fbind(self, self.loadSplitDialog)
+ // }).
+ // jqmAddClose('button.dialog-close-button');
+
+ this.model.load();
+ },
+
+ quickSave: function(event) {
+ this.model.saveDirtyContentModel();
+ },
+
+ commit: function(event) {
+ $('#commit-dialog', this.element).jqmShow({
+ callback: this.doCommit.bind(this)
+ });
+ },
+
+ doCommit: function(message) {
+ this.model.saveDirtyContentModel(message);
+ },
+
+ update: function(event) {
+ this.model.update();
+ },
+
+ merge: function(event) {
+ $('#commit-dialog', this.element).jqmShow({
+ callback: this.doMerge.bind(this)
+ });
+ },
+
+ doMerge: function(message) {
+ this.model.merge(message);
+ },
+
+ loadRelatedIssues: function(hash) {
+ var self = this;
+ var c = $('#commit-dialog-related-issues');
+
+ $('#commit-dialog-save-button').click(function(event, data)
+ {
+ if ($('#commit-dialog-message').val().match(/^\s*$/)) {
+ $('#commit-dialog-error-empty-message').fadeIn();
+ } else {
+ $('#commit-dialog-error-empty-message').hide();
+ $('#commit-dialog').jqmHide();
+
+ var message = $('#commit-dialog-message').val();
+ $('#commit-dialog-related-issues input:checked')
+ .each(function() {
+ message += ' refs #' + $(this).val();
+ });
+ console.log("COMMIT APROVED", hash.t);
+ hash.t.callback(message);
+ }
+ return false;
+ });
+
+ $("div.loading-box", c).show();
+ $("div.fatal-error-box", c).hide();
+ $("div.container-box", c).hide();
+
+ $.getJSON(c.attr('ui:ajax-src') + '?callback=?',
+ function(data, status)
+ {
+ var fmt = '';
+ $(data).each( function() {
+ fmt += '<label><input type="checkbox" checked="checked"';
+ fmt += ' value="' + this.id + '" />' + this.subject +'</label>\n';
+ });
+ $("div.container-box", c).html(fmt);
+ $("div.loading-box", c).hide();
+ $("div.container-box", c).show();
+ });
+
+ hash.w.show();
+ },
+
+ modelStateChanged: function(property, value) {
+ // Uaktualnia stan przycisków
+ if (value == 'dirty') {
+ this.quickSaveButton.attr('disabled', null);
+ this.commitButton.attr('disabled', null);
+ this.updateButton.attr('disabled', 'disabled');
+ this.mergeButton.attr('disabled', 'disabled');
++ } else if (value == 'synced') {
+ this.quickSaveButton.attr('disabled', 'disabled');
+ this.commitButton.attr('disabled', 'disabled');
+ this.updateButton.attr('disabled', null);
+ this.mergeButton.attr('disabled', null);
++ this.unfreeze();
+ } else if (value == 'empty') {
+ this.quickSaveButton.attr('disabled', 'disabled');
+ this.commitButton.attr('disabled', 'disabled');
+ this.updateButton.attr('disabled', 'disabled');
+ this.mergeButton.attr('disabled', 'disabled');
++ } else if (value == 'error') {
++ this.freeze(this.model.get('error'));
++ this.quickSaveButton.attr('disabled', 'disabled');
++ this.commitButton.attr('disabled', 'disabled');
++ this.updateButton.attr('disabled', 'disabled');
++ this.mergeButton.attr('disabled', 'disabled');
++
+ }
+ },
+
+ dispose: function() {
+ $('#action-quick-save', this.element).unbind('click.editorview');
+ $('#action-commit', this.element).unbind('click.editorview');
+ $('#action-update', this.element).unbind('click.editorview');
+ $('#action-merge', this.element).unbind('click.editorview');
+
+ this.model.removeObserver(this);
+ this._super();
+ }
+});
--- /dev/null
- modelFirstFlashMessageChanged: function(property, value) {
- this.element.fadeOut('slow', function() {
- this.element.css({'z-index': 0});
- this.shownMessage = value;
- this.render();
+/*globals View render_template*/
+var FlashView = View.extend({
+ template: 'flash-view-template',
+
+ init: function(element, model, template) {
+ this.shownMessage = null;
+ this._super(element, model, template);
+ this.setModel(model);
+ },
+
+ setModel: function(model) {
+ if (this.model) {
+ this.model.removeObserver(this);
+ }
+ this.model = model;
+ this.shownMessage = null;
+ if (this.model) {
+ this.shownMessage = this.model.get('firstFlashMessage');
+ this.model.addObserver(this, 'firstFlashMessage', this.modelFirstFlashMessageChanged.bind(this));
+ }
+ this.render();
+ },
+
+ render: function() {
+ this.element.html(render_template(this.template, this));
++ setTimeout(function() {}, 0);
+ },
+
- if(this.shownMessage) {
++ modelFirstFlashMessageChanged: function(property, value) {
++ this.element.fadeOut(200, (function() {
++
++ this.element.css({'z-index': 0});
++ this.shownMessage = value;
++ this.render();
+
- this.element.fadeIn('slow');
- }
- }.bind(this));
++ if(this.shownMessage) {
+ this.element.css({'z-index': 1000});
++ this.element.fadeIn();
++ };
++ }).bind(this));
+ }
+});
--- /dev/null
- this.$printLink.attr('href', base + "?revision=" + this.model.get('revision'));
+/*global View render_template panels */
+var HTMLView = View.extend({
+ _className: 'HTMLView',
+ element: null,
+ model: null,
+ template: 'html-view-template',
+
+ init: function(element, model, parent, template) {
+ this._super(element, model, template);
+ this.parent = parent;
+
+ this.model
+ .addObserver(this, 'data', this.modelDataChanged.bind(this))
+ .addObserver(this, 'state', this.modelStateChanged.bind(this));
+
+ $('.htmlview', this.element).html(this.model.get('data'));
+ this.modelStateChanged('state', this.model.get('state'));
+ this.model.load();
+ },
+
+ modelDataChanged: function(property, value) {
+ $('.htmlview', this.element).html(value);
++ this.updatePrintLink();
++ },
+
++ updatePrintLink: function() {
+ var base = this.$printLink.attr('ui:baseref');
-
- var base = this.$printLink.attr('ui:baseref');
- this.$printLink.attr('href', base + "?revision=" + this.model.get('revision'));
++ this.$printLink.attr('href', base + "?user="+this.model.document.get('user')+"&revision=" + this.model.get('revision'));
+ },
+
+ modelStateChanged: function(property, value)
+ {
+ var self = $(this);
+
+ if (value == 'synced' || value == 'dirty') {
+ this.unfreeze();
+ } else if (value == 'unsynced') {
+ this.freeze('Niezsynchronizowany...');
+ } else if (value == 'loading') {
+ this.freeze('Ładowanie...');
+ } else if (value == 'saving') {
+ this.freeze('Zapisywanie...');
+ } else if (value == 'error') {
+ this.freeze(this.model.get('error'));
+ $('.xml-editor-ref', this.overlay).click(
+ function(event) {
+ console.log("Sending scroll rq.", this);
+ try {
+ var href = $(this).attr('href').split('-');
+ var line = parseInt(href[1]);
+ var column = parseInt(href[2]);
+
+ $(document).trigger('xml-scroll-request', {line:line, column:column});
+ } catch(e) {
+ console.log(e);
+ }
+
+ return false;
+ });
+ }
+ },
+
+ render: function() {
+ this.element.unbind('click');
+
+ if(this.$printLink) this.$printLink.unbind();
+ this._super();
+ this.$printLink = $('.html-print-link', this.element);
++ this.updatePrintLink();
+
+ this.element.bind('click', this.itemClicked.bind(this));
+ },
+
+ reload: function() {
+ this.model.load(true);
+ },
+
+ dispose: function() {
+ this.model.removeObserver(this);
+ this._super();
+ },
+
+ itemClicked: function(event)
+ {
+ var self = this;
+
+ console.log('click:', event, event.ctrlKey, event.target);
+ var editableContent = null;
+ var $e = $(event.target);
+
+ var n = 0;
+
+ while( ($e[0] != this.element[0]) && !($e.attr('wl2o:editable'))
+ && n < 50)
+ {
+ // console.log($e, $e.parent(), this.element);
+ $e = $e.parent();
+ n += 1;
+ }
+
+ if(!$e.attr('wl2o:editable'))
+ return true;
+
+ // start edition on this node
+
+
+ var $overlay = $(
+ '<div class="html-editarea">\n\
+ <p class="html-editarea-toolbar">\n\
+ <button class="html-editarea-save-button" type="button">Zapisz</button>\n\
+ <button class="html-editarea-cancel-button" type="button">Anuluj</button>\n\
+ </p>\n\
+ <textarea></textarea>\n\
+ </div>');
+
+ var x = $e[0].offsetLeft;
+ var y = $e[0].offsetTop;
+ var w = $e.outerWidth();
+ var h = $e.innerHeight();
+ $overlay.css({position: 'absolute', height: h, left: "5%", top: y, width: "90%"});
+ $e.offsetParent().append($overlay);
+
+ // load the original XML content
+ console.log($e, $e.offsetParent(), $overlay);
+
+ $('.html-editarea-cancel-button', $overlay).click(function() {
+ $overlay.remove();
+ });
+
+ $('.html-editarea-save-button', $overlay).click(function() {
+ $overlay.remove();
+
+ // put the part back to the model
+ self.model.putXMLPart($e, $('textarea', $overlay).val());
+ });
+
+ $('textarea', $overlay).focus(function() {
+ $overlay.css('z-index', 3000);
+ }).blur(function() {
+ $overlay.css('z-index', 2000);
+ });
+
+ this.model.getXMLPart($e, function(path, data) {
+ $('textarea', $overlay).val(data);
+ });
+
+ return false;
+ }
+
+});
+
+// Register view
+panels['html'] = HTMLView;
--- /dev/null
- this.overlay = this.overlay
- || $('<div><div>' + message + '</div></div>')
- .addClass(this.overlayClass)
+/*globals Editor render_template*/
+var View = Editor.Object.extend({
+ _className: 'View',
+ element: null,
+ model: null,
+ template: null,
+ overlayClass: 'view-overlay',
+ overlay: null,
+
+ init: function(element, model, template)
+ {
+ console.log("init for view");
+ this.element = $(element);
+ this.model = model;
+ this.template = template || this.template;
+
+ if (this.template) this.render();
+
+ this._resizeHandler = this.resized.bind(this);
+ $(window).bind('resize', this._resizeHandler);
+ $(this.element).bind('resize', this._resizeHandler);
+ },
+
+ render: function() {
+ console.log('rendering:', this._className);
+ this.element.html(render_template(this.template, this));
+ },
+
+ frozen: function() {
+ return !!this.overlay;
+ },
+
+ freeze: function(message) {
+ if (this.frozen()) {
+ this.unfreeze();
+ }
- position: 'absolute',
- width: this.element.width(),
- height: this.element.height(),
- top: this.element.position().top,
- left: this.element.position().left,
- 'user-select': 'none',
- '-webkit-user-select': 'none',
- '-khtml-user-select': 'none',
- '-moz-user-select': 'none',
- overflow: 'hidden'
- })
- .attr('unselectable', 'on')
- .appendTo(this.element.parent());
++ this.overlay = this.overlay || $('<div><div>' + message + '</div></div>');
++
++ this.overlay.addClass(this.overlayClass)
+ .css({
- position: 'relative',
- top: this.overlay.height() / 2 - 20
- });
+
++ }).attr('unselectable', 'on')
++
++ this.overlay.appendTo(this.element);
++
++ var ovc = this.overlay.children('div');
++ var padV = (this.overlay.height() - ovc.outerHeight())/2;
++ var padH = (this.overlay.width() - ovc.outerWidth())/2;
++
+ this.overlay.children('div').css({
- if (this.frozen()) {
- this.overlay.css({
- position: 'absolute',
- width: this.element.width(),
- height: this.element.height(),
- top: this.element.position().top,
- left: this.element.position().left
- }).children('div').css({
- position: 'relative',
- top: this.overlay.height() / 2 - 20
++ top: padV, left: padH
++ });
+ },
+
+ unfreeze: function() {
+ if (this.frozen()) {
+ this.overlay.remove();
+ this.overlay = null;
+ }
+ },
+
+ resized: function(event) {
- });
++ if(this.overlay) {
++ var ovc = this.overlay.children('div');
++ var padV = (this.overlay.height() - ovc.outerHeight())/2;
++ var padH = (this.overlay.width() - ovc.outerWidth())/2;
++
++ this.overlay.children('div').css({
++ top: padV,
++ left: padH
+ });
+ }
+ },
+
+ dispose: function() {
+ console.log('disposing:', this._className);
+ $(window).unbind('resize', this._resizeHandler);
+ $(this.element).unbind('resize', this._resizeHandler);
+ this.unfreeze();
+ this.element.html('');
+ }
++});
--- /dev/null
- .load();
-
- this.parent.unfreeze();
+/*global View CodeMirror ToolbarView render_template panels */
+var XMLView = View.extend({
+ _className: 'XMLView',
+ element: null,
+ model: null,
+ template: 'xml-view-template',
+ editor: null,
+ buttonToolbar: null,
+
+ init: function(element, model, parent, template) {
+ this._super(element, model, template);
+ this.parent = parent;
+ this.buttonToolbar = new ButtonToolbarView(
+ $('.xmlview-toolbar', this.element),
+ this.model.toolbarButtonsModel, parent);
+
+ this.hotkeys = [];
+ var self = this;
+
+ $('.xmlview-toolbar', this.element).bind('resize.xmlview', this.resized.bind(this));
+
+ // scroll to the given position (if availble)
+ this.scrollCallback = this.scrollOnRequest.bind(this);
+ $(document).bind('xml-scroll-request', this.scrollCallback);
+
+ this.parent.freeze('Ładowanie edytora...');
++
++ setTimeout((function(){
++
+ this.editor = new CodeMirror($('.xmlview', this.element).get(0), {
+ parserfile: 'parsexml.js',
+ path: "/static/js/lib/codemirror/",
+ stylesheet: "/static/css/xmlcolors.css",
+ parserConfig: {
+ useHTMLKludges: false
+ },
+ textWrapping: true,
+ tabMode: 'spaces',
+ indentUnit: 0,
+ onChange: this.editorDataChanged.bind(this),
+ initCallback: this.editorDidLoad.bind(this)
+ });
++
++ }).bind(this), 0);
+ },
+
+ resized: function(event) {
+ var height = this.element.height() - $('.xmlview-toolbar', this.element).outerHeight();
+ $('.xmlview', this.element).height(height);
+ },
+
+ reload: function() {
+ this.model.load(true);
+ },
+
+ editorDidLoad: function(editor) {
+ $(editor.frame).css({
+ width: '100%',
+ height: '100%'
+ });
+ this.model
+ .addObserver(this, 'data', this.modelDataChanged.bind(this))
+ .addObserver(this, 'state', this.modelStateChanged.bind(this))
- );
++ .load();
+
+ this.editor.setCode(this.model.get('data'));
+ this.modelStateChanged('state', this.model.get('state'));
+
+ editor.grabKeys(
+ this.hotkeyPressed.bind(this),
+ this.isHotkey.bind(this)
- this.freeze('Ładowanie...');
++ );
++
++ this.parent.unfreeze();
+ },
+
+ editorDataChanged: function() {
+ this.model.set('data', this.editor.getCode());
+ },
+
+ modelDataChanged: function(property, value) {
+ if (this.editor.getCode() != value) {
+ this.editor.setCode(value);
+ }
+ },
+
+ modelStateChanged: function(property, value) {
+ if (value == 'synced' || value == 'dirty') {
+ this.unfreeze();
+ } else if (value == 'unsynced') {
+ this.freeze('Niezsynchronizowany...');
+ } else if (value == 'loading') {
++ this.freeze('Ładowanie danych...');
+ } else if (value == 'saving') {
+ this.freeze('Zapisywanie...');
+ } else if (value == 'error') {
+ this.freeze(this.model.get('error'));
+ }
+ },
+
+ dispose: function() {
+ $(document).unbind('xml-scroll-request', this.scrollCallback);
+
+ this.model.removeObserver(this);
+ $(this.editor.frame).remove();
+ this._super();
+ },
+
+ getHotkey: function(event) {
+ var code = event.keyCode;
+ if(!((code >= 97 && code <= 122)
+ || (code >= 65 && code <= 90)) ) return null;
+
+ var ch = String.fromCharCode(code & 0xff).toLowerCase();
+ /* # console.log(ch.charCodeAt(0), '#', buttons); */
+
+ var buttons = $('.buttontoolbarview-button[hotkey='+ch+']', this.element);
+ var mod = 0;
+
+ if(event.altKey) mod |= 0x01;
+ if(event.ctrlKey) mod |= 0x02;
+ if(event.shiftKey) mod |= 0x04;
+
+ if(buttons.length) {
+ var match = null;
+
+ buttons.each(function() {
+ if( parseInt($(this).attr('ui:hotkey_mod')) == mod ) {
+ match = this;
+ return;
+ }
+ })
+
+ return match;
+ }
+ else {
+ return null;
+ }
+ },
+
+ isHotkey: function() {
+ /* console.log(arguments); */
+ if(this.getHotkey.apply(this, arguments))
+ return true;
+ else
+ return false;
+ },
+
+ hotkeyPressed: function() {
+ var button = this.getHotkey.apply(this, arguments);
+ this.buttonToolbar.buttonPressed({
+ target: button
+ });
+ },
+
+ scrollOnRequest: function(event, data)
+ {
+ try {
+ var line = this.editor.nthLine(data.line);
+ this.editor.selectLines(line, (data.column-1));
+ } catch(e) {
+ console.log('Exception in scrollOnRequest:', e);
+ }
+ }
+
+});
+
+function Hotkey(code) {
+ this.code = code;
+ this.has_alt = ((code & 0x01 << 8) !== 0);
+ this.has_ctrl = ((code & 0x01 << 9) !== 0);
+ this.has_shift = ((code & 0x01 << 10) !== 0);
+ this.character = String.fromCharCode(code & 0xff);
+}
+
+Hotkey.prototype.toString = function() {
+ var mods = [];
+ if(this.has_alt) mods.push('Alt');
+ if(this.has_ctrl) mods.push('Ctrl');
+ if(this.has_shift) mods.push('Shift');
+ mods.push('"'+this.character+'"');
+ return mods.join('+');
+};
+
+// Register view
+panels['xml'] = XMLView;
--- /dev/null
- var fileId = '{{ fileid }}';
+{% extends "base.html" %}
+
+{% block extrahead %}
+ <link rel="stylesheet" href="{{STATIC_URL}}css/jquery.modal.css" type="text/css" media="screen" charset="utf-8">
+ <link rel="stylesheet" href="{{STATIC_URL}}css/html.css" type="text/css" charset="utf-8">
+ <link rel="stylesheet" href="{{STATIC_URL}}css/toolbar.css" type="text/css" charset="utf-8">
+ <link rel="stylesheet" href="{{STATIC_URL}}css/autumn.css" type="text/css" media="screen" title="Autumn colors" charset="utf-8">
+
+ <script type="text/javascript" charset="utf-8">
- <script src="{{STATIC_URL}}js/lib/codemirror/codemirror.js" type="text/javascript" charset="utf-8"></script>
++ var documentInfo = {
++ docID: '{{ fileid }}',
++ userID: '{{ euser }}',
++ docURL: '{% url document_view fileid %}{% if euser %}?user={{ euser|urlencode }}{% endif %}',
++ toolbarURL: '{% url toolbar_buttons %}',
++ renderURL: '{% url api.views.render %}'
++ }
++
+ </script>
+
+ {# Libraries #}
- {% block breadcrumbs %}<a href="{% url file_list %}">Platforma Redakcyjna</a> > {{ fileid }}{% endblock breadcrumbs %}
++ <script src="{{STATIC_URL}}js/lib/codemirror/codemirror.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{STATIC_URL}}js/lib/jquery.modal.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{STATIC_URL}}js/lib/jquery.json.js" type="text/javascript" charset="utf-8"></script>
++
+ {# Scriptlets #}
+ <script src="{{STATIC_URL}}js/button_scripts.js" type="text/javascript" charset="utf-8"></script>
+
+ {# App and views #}
+ <script src="{{STATIC_URL}}js/app.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{STATIC_URL}}js/messages.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{STATIC_URL}}js/views/view.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{STATIC_URL}}js/views/flash.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{STATIC_URL}}js/views/editor.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{STATIC_URL}}js/views/button_toolbar.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{STATIC_URL}}js/views/split.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{STATIC_URL}}js/views/xml.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{STATIC_URL}}js/views/html.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{STATIC_URL}}js/views/gallery.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{STATIC_URL}}js/views/panel_container.js" type="text/javascript" charset="utf-8"></script>
+
+ <script src="{{STATIC_URL}}js/models.js" type="text/javascript" charset="utf-8"></script>
+
+ {# JavaScript templates #}
+ <script type="text/html" charset="utf-8" id="panel-container-view-template">
+ <div class="panel-main-toolbar">
+ <p><select>
+ <option value="empty" selected="selected"> ---- </option>
+ <% for (panel in panels) { %>
+ <option value="<%= panel %>"><%= panel %></option>
+ <% }; %>
+ </select> <button class="refresh">Odśwież panel</button></p>
+ </div>
+ <div class="content-view"></div>
+ </script>
+
+ <script type="text/html" charset="utf-8" id="xml-view-template">
+ <div class="xmlview-toolbar"></div>
+ <div class="xmlview">
+
+ </div>
+ </script>
+
+ <script type="text/html" charset="utf-8" id="html-view-template">
+ <div class="htmlview-toolbar">
+ <a class="html-print-link" href="print" ui:baseref="{% url file_print fileid %}" target="_new">Wersja do druku</a>
+ </div>
+
+ <div class="htmlview">
+ </div>
+ </script>
+
+ <script type="text/html" charset="utf-8" id="flash-view-template">
+ <div class="flashview">
+ <% if (shownMessage) { %>
+ <p style="margin: 0; padding: 0.2em 0.5em; line-height: 1.8em" class="<%= shownMessage.type %>"><%= shownMessage.text %></p>
+ <% } %>
+ </div>
+ </script>
+
+ <script type="text/html" charset="utf-8" id="image-gallery-view-template">
+ <div class="image-gallery-view-template">
+
+ <div class="image-gallery-header">
+ <p>
+ <button type="button" class="image-gallery-prev-button">
+ <img alt="PPrevious" src="{{STATIC_URL}}/icons/go-previous.png" width="16" height="16" />
+ </button>
+
+ <input type="input" class="image-gallery-current-page"
+ size="5" value="<%= (currentPage + 1) %>" />
+
+
+ <button type="button" class="image-gallery-next-button">
+ <img alt="Next" src="{{STATIC_URL}}/icons/go-next.png" width="16" height="16" />
+ </button>
+
+ <button type="button" class="image-gallery-zoom-in">
+ <img alt="Zoom in" src="{{STATIC_URL}}/icons/zoom_in.png" width="16" height="16" />
+ </button>
+ <button type="button" class="image-gallery-zoom-out">
+ <img alt="Zoom out" src="{{STATIC_URL}}/icons/zoom_out.png" width="16" height="16" />
+ </button>
+ <button type="button" class="image-gallery-zoom-reset">
+ <img alt="Zoom reset" src="{{STATIC_URL}}/icons/zoom.png" width="16" height="16" />
+ </button>
+ </p>
+ </div>
+
+ <div class="image-gallery-page-list">
+ <% for(var i=0; i < model.data.length; i++) { %>
+ <div class="image-gallery-page-container"
+ ui:model="<%= model.data[i] %>"
+ ui:width="480"
+ ui:height="752"
+ ></div>
+ <% }; %>
+ </div>
+
+ </div>
+ </script>
+
+ <script type="text/html" charset="utf-8" id="button-toolbar-view-template">
+ <div class="buttontoolbarview panel-toolbar">
+ <div class="buttontoolbarview-tabs toolbar-tabs-container toolbar-buttons-container">
+ <% for (var i=0; i < buttons.length; i++) { %>
+ <button type="button" class="buttontoolbarview-tab" ui:groupindex="<%= i %>"><%= buttons[i].name %></button>
+ <% }; %>
+ </div>
+ <div class="buttontoolbarview-groups ">
+ <% for (var i=0; i < buttons.length; i++) { %>
+ <div class="buttontoolbarview-group toolbar-buttons-container" ui:groupIndex="<%= i %>" style="display: none">
+ <% for (var j=0; j < buttons[i].buttons.length; j++) { %>
+ <% if (buttons[i].buttons[j].scriptlet_id) { %>
+ <button type="button" class="buttontoolbarview-button"
+ title="<%= buttons[i].buttons[j].tooltip %>"
+ hotkey="<%= buttons[i].buttons[j].key %>"
+ ui:hotkey_mod="<%= buttons[i].buttons[j].key_mod %>"
+ ui:groupindex="<%= i %>" ui:buttonindex="<%= j %>">
+ <%= buttons[i].buttons[j].label %>
+ </button>
+ <% } %>
+ <% } %>
+ </div>
+ <% }; %>
+ </div>
+ </div>
+ </script>
+{% endblock extrahead %}
+
- {% block maincontent %}
- <p style="display: none;" id="api-base-url">{% url document_list_view %}</p>
- <p style="display: none;" id="api-toolbar-url">{% url toolbar_buttons %}</p>
++{% block breadcrumbs %}<a href="{% url file_list %}">Platforma</a> > {{euser}} > {{ fileid }}{% endblock breadcrumbs %}
+
+{% block header-toolbar %}
+ <a href="http://stigma.nowoczesnapolska.org.pl/platforma-hg/ksiazki/log/tip/{{ fileid }}.xml" target="_new" >Historia</a>
+ <button id="action-merge">Merge</button>
+ <button id="action-update">Update</button>
+ <button id="action-commit">Commit</button>
+ <button id="action-quick-save">Quick Save</button>
+{% endblock %}
+
++{% block maincontent %}
++
+
+ <div id="splitview">
+ <div id="left-panel-container" class='panel-container'></div>
+ <div id="right-panel-container" class='panel-container'></div>
+ </div>
+
+ <div id="commit-dialog" class="jqmWindow" style="display:none">
+ <form action="" method="POST">
+ <label for="message">Commit message:</label>
+ <textarea cols="60" rows="10" name="message" id="commit-dialog-message"></textarea>
+ <p id="commit-dialog-error-empty-message">Wiadomość nie może być pusta.</p>
+ <fieldset id="commit-dialog-related-issues" ui:ajax-src="{{REDMINE_URL}}/publications/issues/{{fileid}}">
+ <legend>Related issues</legend>
+ <div class="loading-box" style="display: none;">
+ <p>Loading related issues...</p>
+ </div>
+ <div class="container-box">No related issues.</div>
+ </fieldset>
+ <p>
+ <input type="button" value="Save" id="commit-dialog-save-button" />
+ <input type="reset" value="Cancel" id="commit-dialog-cancel-button" />
+ </p>
+ </form>
+ </div>
+
+ <div id="split-dialog" class="jqmWindow" style="display:none">
+ <div class="container-box"> </div>
+ <div class="loading-box" style="display: none;">
+ <p>Loading dialog contents...</p>
+ <!-- <p><button type="button" class="dialog-close-button">Close</button></p> -->
+ </div>
+ <div class="fatal-error-box" style="display: none;">
+ <p>Server error, while loading dialog :(</p>
+ <p><button type="button" class="dialog-close-button">Close</button></p>
+ </div>
+ </div>
+{% endblock maincontent %}
+
+{% block extrabody %}
+ <div style="position: absolute; left: 35%; right: 35%; top: 0; height: 20px; z-index: 0" id="flashview"></div>
+{% endblock %}
--- /dev/null
- <th>Akcje</th>
+{% extends 'base.html' %}
+
+{% block extrahead %}
+<link rel="stylesheet" href="{{ STATIC_URL }}css/managment.css" type="text/css" />
+<script type="text/javascript">
+
+
+ $(function() {
+
+ function refreshRow(id) {
+ var row = $('#request-' +id);
+
+ $.ajax({
+ url: '{% url pullrequest_list %}/'+id,
+ dataType: 'json',
+ type: 'GET',
+ success: function(data) {
+ row.removeClass('status-N');
+ row.removeClass('status-R');
+ row.removeClass('status-A');
+ row.addClass('status-'+ data.status);
+
+ $('.column-doc', row).html(data.document);
+ $('.column-status', row).html(data.status);
+
+ alert('Merge accepted.');
+ }
+ });
+
+ }
+
+ $('.accept-button').click(function()
+ {
+ var id = parseInt($(this).attr('title'));
+
+
+ $.ajax({
+ url: '{% url pullrequest_list %}/'+id,
+ data: {action: 'accept'},
+ dataType: 'json',
+ type: 'PUT',
+ success: function(data) {
+ refreshRow(id);
+ }
+ });
+
+ });
+
+ });
+</script>
+{% endblock %}
+
+{% block maincontent %}
+<table class="request-report" cellspacing="0">
+ <tr>
+ <th>Utwór</th><th>Użytkownik</th><th>Komentarz</th><th>Stan</th>
- <td><button type="button" class="accept-button" title="{{pullreq.id}}">Akceptuj</button></td>
++ <th>Zgłoszono</th><th>Akcje</th>
+ </tr>
+{% if objects %}
+ {% for pullreq in objects %}
+ <tr class="status-{{pullreq.status}}" id="request-{{pullreq.id}}">
+ <td class="column-doc">{{ pullreq.document }}</td>
+ <td class="column-user">{{ pullreq.comitter }}</td>
+ <td class="column-comment">{{ pullreq.comment }}</td>
+ <td class="column-status"> {{ pullreq.status }}</td>
- <tr><td colspan="*">Brak żądań</td></tr>
++ <td class="column-data">{{ pullreq.timestamp }}</td>
++ <td>
++ <button type="button" class="accept-button" title="{{pullreq.id}}">Akceptuj</button>
++ <a href="{% url editor_view pullreq.document %}?user=$prq-{{pullreq.id}}">Zobacz</a>
++ </td>
+ </tr>
+
+ {% endfor %}
+{% else %}
++ <tr><td colspan="6">Brak żądań</td></tr>
+{% endif %}
+</table>
+
+{% endblock %}