commit 631a8bcf2cd8fa86556b085f1e1222a7c466d0a4
parent a155d171824195d22d805790d559c4344825179f
Author: Jan Dankert <develop@jandankert.de>
Date: Wed, 17 Feb 2021 02:34:51 +0100
Refactoring: Extract Dialog into a separate js class
Diffstat:
9 files changed, 325 insertions(+), 193 deletions(-)
diff --git a/modules/cms/ui/themes/ThemeCompiler.class.php b/modules/cms/ui/themes/ThemeCompiler.class.php
@@ -263,6 +263,7 @@ class ThemeCompiler
// OpenRat internal JS - als letztes, damit die vorigen bereits geladen sind.
$js[] = __DIR__.'/default/script/openrat/init';
$js[] = __DIR__.'/default/script/openrat/notice';
+ $js[] = __DIR__.'/default/script/openrat/dialog';
$js[] = __DIR__.'/default/script/openrat/view';
$js[] = __DIR__.'/default/script/openrat/form';
$js[] = __DIR__.'/default/script/openrat/workbench';
diff --git a/modules/cms/ui/themes/default/script/openrat.js b/modules/cms/ui/themes/default/script/openrat.js
@@ -285,7 +285,8 @@ jQuery.fn.orLinkify = function( options )
case 'edit':
case 'dialog':
- Openrat.Workbench.startDialog($link.attr('data-name'),$link.attr('data-action'),$link.attr('data-method'),$link.attr('data-id'),$link.attr('data-extra') );
+ let dialog = new Openrat.Dialog();
+ dialog.start($link.attr('data-name'),$link.attr('data-action'),$link.attr('data-method'),$link.attr('data-id'),$link.attr('data-extra') );
break;
case 'external':
@@ -1843,6 +1844,127 @@ Openrat.Notice.removeAllNotices = function( status) {
$('.or-notices').find('.or-notice').remove();
}
+/* Include script: dialog.js */
+/**
+ * A dialog is a special area in the workbench for displaying and inputting data.
+ * A dialog contains a view.
+ */
+
+Openrat.Dialog = function() {
+
+ /**
+ * The encapsulated view.
+ */
+ this.view;
+
+ /**
+ * Dirty-marker (if unsaved changes exist).
+ *
+ * @type {boolean}
+ */
+ this.isDirty = false;
+
+ /**
+ * the DOM element which contains the dialog.
+ * @type {*|jQuery|HTMLElement}
+ */
+ this.element = $('.or-dialog-content .or-view');
+
+ /**
+ * Creating a new dialog.
+ *
+ * @param name
+ * @param action Action
+ * @param method
+ * @param id Id
+ * @param params
+ *
+ * @return Promise of underlying view
+ */
+ this.start = function( name,action,method,id,params )
+ {
+ // Attribute aus dem aktuellen Editor holen, falls die Daten beim Aufrufer nicht angegeben sind.
+ if (!action)
+ action = Openrat.Workbench.state.action;
+
+ if (!id)
+ id = Openrat.Workbench.state.id;
+
+ let dialog = this;
+
+ let view = new Openrat.View( action,method,id,params );
+
+ Openrat.Notice.removeAllNotices();
+
+ //$('.or-dialog-content .or-view').html('<div class="header"><img class="or-icon" title="" src="./themes/default/images/icon/'+method+'.png" />'+name+'</div>');
+ //$('.or-dialog-content .or-view').data('id',id);
+ $('.or-dialog').removeClass('dialog--is-closed').addClass('dialog--is-open');
+ $('.or-dialog-content .or-act-dialog-name').html( name );
+
+ this.escapeKeyClosingHandler = function (e) {
+ if (e.keyCode == 27) { // ESC keycode
+ dialog.close();
+
+ $(document).off('keyup'); // de-register.
+ }
+ };
+
+ $(document).keyup(this.escapeKeyClosingHandler);
+
+ // close dialog on click onto the blurred area.
+ $('.or-dialog-filler,.or-act-dialog-close').off('click').click( function(e)
+ {
+ e.preventDefault();
+ dialog.close();
+ });
+
+
+ view.onCloseHandler.add( function() {
+ dialog.close();
+ } );
+
+ view.onChangeHandler.add( function() {
+ // data has changed
+ console.debug("Changes detected");
+ dialog.isDirty = true;
+ // Remove dirty-flag from view
+ dialog.element.addClass('view--is-dirty');
+ });
+
+ view.onSaveHandler.add( function() {
+ // data was saved
+ dialog.isDirty = false;
+ // Remove dirty-flag from view
+ dialog.element.removeClass('view--is-dirty');
+ });
+
+ this.view = view;
+
+ return this.view.start( this.element );
+ }
+
+
+ /**
+ * Closing the dialog.
+ */
+ this.close = function() {
+
+ if ( this.isDirty ) {
+ // ask the user if we should close this dialog
+ let exit = window.confirm( Openrat.Workbench.language.UNSAVED_CHANGES_CONFIRM );
+
+ if ( ! exit )
+ return;
+ }
+
+ // Remove dirty-flag from view
+ $('.or-dialog-content .or-view.or-view--is-dirty').removeClass('view--is-dirty');
+ $('.or-dialog-content .or-view').html('');
+ $('.or-dialog').removeClass('dialog--is-open').addClass('dialog--is-closed'); // Dialog schließen
+
+ $(document).unbind('keyup',this.escapeKeyClosingHandler); // Cleanup ESC-Key-Listener
+ }
+}
/* Include script: view.js */
/**
* View.
@@ -1861,6 +1983,11 @@ Openrat.View = function( action,method,id,params ) {
this.id = id;
this.params = params;
+ this.onCloseHandler = $.Callbacks();
+
+ this.onChangeHandler = $.Callbacks();
+ this.onSaveHandler = $.Callbacks();
+
this.before = function() {};
/**
@@ -1880,6 +2007,7 @@ Openrat.View = function( action,method,id,params ) {
this.close = function() {
+ this.onCloseHandler.fire();
}
@@ -1915,10 +2043,17 @@ Openrat.View = function( action,method,id,params ) {
let form = new Openrat.Form();
- form.close = function() {
+ form.onChangeHandler.add( function() {
+ view.onChangeHandler.fire();
+ });
+
+ form.onSaveHandler.add( function() {
+ view.onSaveHandler.fire();
+ });
+ form.onCloseHandler.add( function() {
view.close();
- }
+ } );
form.forwardTo = function (action, subaction, id, data) {
view.action = action;
@@ -2018,6 +2153,12 @@ Openrat.Form = function() {
closeAfterSuccess : 8,
};
+ /**
+ * Fires on input.
+ */
+ this.onChangeHandler = $.Callbacks();
+ this.onSaveHandler = $.Callbacks();
+
this.setLoadStatus = function( isLoading ) {
$(this.element).closest('div.content').toggleClass('loader',isLoading);
}
@@ -2062,7 +2203,13 @@ Openrat.Form = function() {
form.submit();
});
- // Submithandler for the whole form.
+ // Bei Änderungen in der View das Tab als 'dirty' markieren
+ $(element).find('.or-input').change( function() {
+ form.onChangeHandler.fire();
+ });
+
+
+ // Submithandler for the whole form.
$(element).submit( function( event ) {
//
@@ -2079,7 +2226,7 @@ Openrat.Form = function() {
//$(this.element).html('').parent().removeClass('is-open');
Openrat.Notice.removeAllNotices();
- this.close();
+ this.onCloseHandler.fire();
}
@@ -2087,8 +2234,7 @@ Openrat.Form = function() {
this.element.trigger('reset');
}
- this.close = function() {
- }
+ this.onCloseHandler = $.Callbacks();
this.forwardTo = function (action, subaction, id, data) {
}
@@ -2147,7 +2293,7 @@ Openrat.Form = function() {
data.output = 'json';
if ( mode == modes.closeAfterSubmit )
- this.close();
+ this.onCloseHandler();
// Async: Window is closed, but the action will be startet now.
let form = this;
@@ -2160,8 +2306,7 @@ Openrat.Form = function() {
form.doResponse(responseData,textStatus,form.element, function() {
- // Remove dirty-flag from view
- $(form.element).closest('.or-view.or-view--is-dirty').removeClass('view--is-dirty');
+ form.onSaveHandler.fire();
let afterSuccess = $(form.element).data('afterSuccess');
let forwardTo = $(form.element).data('forwardTo' );
@@ -2174,7 +2319,7 @@ Openrat.Form = function() {
// Now we can close the form.
if ( mode == modes.closeAfterSuccess )
{
- form.close();
+ form.onCloseHandler();
// clear the dirty flag.
$(form.element).closest('div.panel').find('div.header ul.views li.action.active').removeClass('dirty');
@@ -2361,7 +2506,8 @@ Openrat.Workbench = new function()
this.openModalDialog = function () {
if ( $('#dialog').data('action') ) {
- this.startDialog('',$('#dialog').data('action'),$('#dialog').data('action'),0,{})
+ let dialog = new Openrat.Dialog();
+ dialog.start('',$('#dialog').data('action'),$('#dialog').data('action'),0,{} )
}
}
@@ -2662,83 +2808,7 @@ Openrat.Workbench = new function()
- /**
- * Creating a new modal dialog.
- *
- * @param name
- * @param action Action
- * @param method
- * @param id Id
- * @param params
- */
- this.startDialog = function( name,action,method,id,params )
- {
- // Attribute aus dem aktuellen Editor holen, falls die Daten beim Aufrufer nicht angegeben sind.
- if (!action)
- action = Openrat.Workbench.state.action;
-
- if (!id)
- id = Openrat.Workbench.state.id;
-
- let view = new Openrat.View( action,method,id,params );
-
- view.before = function() {
-
- Openrat.Notice.removeAllNotices();
-
- $('.or-dialog-content .or-view').html('<div class="header"><img class="or-icon" title="" src="./themes/default/images/icon/'+method+'.png" />'+name+'</div>');
- $('.or-dialog-content .or-view').data('id',id);
- $('.or-dialog').removeClass('dialog--is-closed').addClass('dialog--is-open');
- $('.or-dialog-content .or-act-dialog-name').html( name );
-
- let view = this;
-
- this.escapeKeyClosingHandler = function (e) {
- if (e.keyCode == 27) { // ESC keycode
- view.close();
-
- $(document).off('keyup'); // de-register.
- }
- };
-
- $(document).keyup(this.escapeKeyClosingHandler);
-
- // Nicht-Modale Dialoge durch Klick auf freie Fläche schließen.
- $('.or-dialog-filler,.or-act-dialog-close').click( function(e)
- {
- e.preventDefault();
- view.close();
- });
-
- }
-
- view.close = function() {
-
- let isDirty = $('.or-view--is-dirty').length; // has this view unsaved changes?
-
- if ( isDirty ) {
- // ask the user if we should close this dialog
- let exit = window.confirm( Openrat.Workbench.language.UNSAVED_CHANGES_CONFIRM );
-
- if ( ! exit )
- return;
- }
-
- // Strong modal dialogs are unable to close.
- // Really?
- if ( $('.or-dialog').hasClass('or-dialog--modal') )
- return;
-
- // Remove dirty-flag from view
- $('.or-dialog-content .or-view.or-view--is-dirty').removeClass('view--is-dirty');
- $('.or-dialog-content .or-view').html('');
- $('.or-dialog').removeClass('dialog--is-open').addClass('dialog--is-closed'); // Dialog schließen
-
- $(document).unbind('keyup',this.escapeKeyClosingHandler); // Cleanup ESC-Key-Listener
- }
- return view.start( $('.or-dialog-content .or-view') );
- }
@@ -3205,11 +3275,6 @@ Openrat.Workbench.afterViewLoadedHandler.add( function(viewEl ) {
registerDragAndDrop(viewEl);
- // Bei Änderungen in der View das Tab als 'dirty' markieren
- $(viewEl).find('.or-input').change( function() {
- $(this).closest('.or-view').addClass('view--is-dirty');
- });
-
// Theme-Auswahl mit Preview
$(viewEl).find('.or-theme-chooser').change( function() {
Openrat.Workbench.setUserStyle( this.value );
diff --git a/modules/cms/ui/themes/default/script/openrat.min.js b/modules/cms/ui/themes/default/script/openrat.min.js
@@ -117,7 +117,7 @@ else{this.currentItem.show()};if(this.fromOutside&&!e){s.push(function(t){this._
;jQuery.fn.orSearch=function(t){var e=$.extend({'dropdown':$(),'select':function(e){},'afterSelect':function(){},'onSearchActive':function(){},'onSearchInactive':function(){},'openDropdown':!0,'action':'search','method':'quicksearch','resultEntryClass':'or-dropdown-entry',},t);return $(this).on('input change',function(){let searchInput=$(this);let searchArgument=searchInput.val();let dropdownEl=$(e.dropdown);if(searchArgument.length){e.onSearchActive();$('.or-search').addClass('search--is-active');dropdownEl.addClass('search-result--is-active');$.ajax({'type':'GET',url:'./api/?action='+e.action+'&subaction='+e.method+'&output=json&search='+searchArgument,data:null,success:function(t,n,r){$(dropdownEl).empty();for(id in t.output.result){let result=t.output.result[id];let div=$('<div class="'+e.resultEntryClass+' '+e.resultEntryClass+'--active" title="'+result.desc+'"></div>');div.data('object',{'name':result.name,'action':result.type,'id':result.id});let link=$('<a class="or-link"/>').attr('href',Openrat.Navigator.createShortUrl(result.type,result.id));link.click(function(e){e.preventDefault()});$(link).append('<i class="or-image-icon or-image-icon--action-'+result.type+'" />');$(link).append('<span class="or-dropdown-text">'+result.name+'</span>');$(div).append(link);$(dropdownEl).append(div)};if(t.output.result&&e.openDropdown){$(dropdownEl).addClass('dropdown--is-open')}
else{$(dropdownEl).removeClass('dropdown--is-open')};$(dropdownEl).find('.or-search-result-entry').click(function(t){e.select($(this).data('object'));e.afterSelect();searchInput.val('')})}})}
else{e.onSearchInactive();$(dropdownEl).empty();dropdownEl.removeClass('search-result--is-active')}})};
-;jQuery.fn.orLinkify=function(t){var a=$.extend({'openAction':function(t,a,e){Openrat.Workbench.openNewAction(t,a,e)}},t);$(this).addClass('linkified');if($(this).is('a'))$(this).click(function(t){t.preventDefault()});else $(this).find('a').click(function(t){t.preventDefault()});return $(this).click(function(t){$el=$(this);if($el.is('a'))$link=$el;else $link=$el.find('a').first();let type=$link.attr('data-type');if($link.parent().hasClass('dropdown-entry--inactive'))return;switch(type){case'post':$form=$('<form />').attr('method','POST').addClass('invisible');$form.data('afterSuccess',$link.data('afterSuccess'));let params=jQuery.parseJSON($link.attr('data-data'));params.output='json';$.each(params,function(t,a){let $input=$('<input />').attr('type','hidden').attr('name',t).attr('value',a);$form.append($input)});let form=new Openrat.Form();form.initOnElement($form);form.submit();break;case'edit':case'dialog':Openrat.Workbench.startDialog($link.attr('data-name'),$link.attr('data-action'),$link.attr('data-method'),$link.attr('data-id'),$link.attr('data-extra'));break;case'external':window.open($link.attr('data-url'),' _blank');break;case'window':window.location.href=Openrat.View.createUrl($link.attr('data-action'),$link.attr('data-method'),$link.attr('data-id'));break;case'popup':Openrat.Workbench.popupWindow=window.open($link.attr('data-url'),'Popup','location=no,menubar=no,scrollbars=yes,toolbar=no,resizable=yes');break;case'help':help($link,$link.attr('data-url'),$link.attr('data-suffix'));break;case'fullscreen':fullscreen($link);break;case'open':a.openAction($link.text().trim(),$link.attr('data-action'),$link.attr('data-id'));break;default:throw'UI error: Unknown link type: '+type+' in link '+$link.html()}})};
+;jQuery.fn.orLinkify=function(t){var a=$.extend({'openAction':function(t,a,e){Openrat.Workbench.openNewAction(t,a,e)}},t);$(this).addClass('linkified');if($(this).is('a'))$(this).click(function(t){t.preventDefault()});else $(this).find('a').click(function(t){t.preventDefault()});return $(this).click(function(t){$el=$(this);if($el.is('a'))$link=$el;else $link=$el.find('a').first();let type=$link.attr('data-type');if($link.parent().hasClass('dropdown-entry--inactive'))return;switch(type){case'post':$form=$('<form />').attr('method','POST').addClass('invisible');$form.data('afterSuccess',$link.data('afterSuccess'));let params=jQuery.parseJSON($link.attr('data-data'));params.output='json';$.each(params,function(t,a){let $input=$('<input />').attr('type','hidden').attr('name',t).attr('value',a);$form.append($input)});let form=new Openrat.Form();form.initOnElement($form);form.submit();break;case'edit':case'dialog':let dialog=new Openrat.Dialog();dialog.start($link.attr('data-name'),$link.attr('data-action'),$link.attr('data-method'),$link.attr('data-id'),$link.attr('data-extra'));break;case'external':window.open($link.attr('data-url'),' _blank');break;case'window':window.location.href=Openrat.View.createUrl($link.attr('data-action'),$link.attr('data-method'),$link.attr('data-id'));break;case'popup':Openrat.Workbench.popupWindow=window.open($link.attr('data-url'),'Popup','location=no,menubar=no,scrollbars=yes,toolbar=no,resizable=yes');break;case'help':help($link,$link.attr('data-url'),$link.attr('data-suffix'));break;case'fullscreen':fullscreen($link);break;case'open':a.openAction($link.text().trim(),$link.attr('data-action'),$link.attr('data-id'));break;default:throw'UI error: Unknown link type: '+type+' in link '+$link.html()}})};
;jQuery.fn.orTree=function(e){var n=$.extend({'openAction':function(e,n,o){}},e);let registerTreeBranchEvents=function(e){Openrat.Workbench.registerDraggable(e)};$(this).each(function(o,e){$(e).children('.or-navtree-node-control').click(function(){let $node=$(this).parent('.or-navtree-node');if($node.is('.or-navtree-node--is-open')){$node.children('ul').slideUp('fast').remove();$node.removeClass('navtree-node--is-open').addClass('navtree-node--is-closed').find('.or-navtree-tree-icon').removeClass('image-icon--node-open').addClass('image-icon--node-closed')}
else{$(e).closest('div.view').addClass('loader');let $link=$node.find('a');let id=$link.data('id');let extraId=$link.data('extra');let loadBranchUrl='./?action=tree&subaction=branch&id='+id+'';if(typeof extraId==='string'){jQuery.each(jQuery.parseJSON(extraId.replace(/'/g,'"')),function(e,n){loadBranchUrl=loadBranchUrl+'&'+e+'='+n})}
else if(typeof extraId==='object'){jQuery.each(extraId,function(e,n){loadBranchUrl=loadBranchUrl+'&'+e+'='+n})}
@@ -1174,20 +1174,21 @@ jQuery.trumbowyg={langs:{en:{viewHTML:"View HTML",undo:"Undo",redo:"Redo",format
;Openrat.Notice=function(){'use strict';this.typ='';this.id=0;this.name='';this.status='inactive';this.msg='';this.log='';let element=$('<div class="or-notice or-notice--is-inactive"></div>');const type=Object.freeze({warning:0,validation:1,info:2,success:3,error:3,loading:3,inactive:4});this.before=function(){};this.close=function(){element.fadeOut('fast',function(){element.remove()})};this.setStatus=function(t){element.removeClass('notice--'+this.status);this.status=t;element.addClass('notice--'+this.status)};this.inProgress=function(){element.addClass('loader')};this.stopProgress=function(){element.removeClass('loader')};this.show=function(){console.debug('user notice: '+this.msg);let notice=this;element.removeClass('notice--is-inactive');element.appendTo('.or-notices');let toolbar=$('<div class="or-notice-toolbar"></div>');toolbar.appendTo(element);toolbar.append('<i class="or-image-icon or-image-icon--menu-close or-act-notice-close"></i>');if(this.log)toolbar.append('<i class="or-act-notice-full or-image-icon or-image-icon--menu-fullscreen"></i>');if(this.name)element.append('<div class="or-notice-name"><a class="or-act-clickable" href="'+Openrat.Navigator.createShortUrl(this.typ,this.id)+'" data-type="open" data-action="'+this.typ+'" data-id="'+this.id+'"><i class="or-notice-action-full or-image-icon or-image-icon--action-'+this.typ+'"></i> '+this.name+'</a></div>');element.append('<div class="or-notice-text">'+htmlEntities(this.msg)+'</div>');if(this.log)element.append('<div class="or-notice-log"><pre>'+htmlEntities(this.log)+'</pre></div>');element.orLinkify();element.find('.or-act-notice-full').click(function(){element.toggleClass('notice--is-full')});element.find('.or-act-notice-close').click(function(){notice.close()});let timeout=1;if(this.status=='ok')timeout=3;if(this.status=='info')timeout=30;if(this.status=='warning')timeout=40;if(this.status=='error')timeout=50;if(timeout>0)setTimeout(function(){element.fadeOut('slow',function(){element.remove()})},timeout*1000)};this.setContext=function(t,e,i){this.typ=t;this.id=e;this.name=i};this.start=function(t,e,i,n,o,log=null,notifyTheBrowser=!1){this.setContext(t,e,i);this.msg=o;this.log=log;if(notifyTheBrowser)this.notifyBrowser(o);this.setStatus(n)};this.notifyBrowser=function(t){if(!('Notification' in window)){return}
else if(Notification.permission==='granted'){let notification=new Notification(t)}
else if(Notification.permission!=='denied'){Notification.requestPermission(function(e){if(e==='granted'){let notification=new Notification(t)}})}};let htmlEntities=function(t){return String(t).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"')}};Openrat.Notice.removeNoticesWithStatus=function(t){$('.or-notices').find('.or-notice--'+t).remove()};Openrat.Notice.removeAllNotices=function(t){$('.or-notices').find('.or-notice').remove()};
-;Openrat.View=function(e,t,i,r){this.action=e;this.method=t;this.id=i;this.params=r;this.before=function(){};this.start=function(e){this.before();this.element=e;return this.loadView()};this.afterLoad=function(){};this.close=function(){};function n(e){Openrat.Workbench.afterViewLoadedHandler.fire(e)};this.loadView=function(){let url=Openrat.View.createUrl(this.action,this.method,this.id,this.params,!1);let element=this.element;let view=this;let loadViewHtmlPromise=$.ajax(url);$(this.element).addClass('loader');console.debug(view);loadViewHtmlPromise.done(function(e,t){if(!e)e='';$(element).html(e).removeClass('loader');$(element).find('form').each(function(){let form=new Openrat.Form();form.close=function(){view.close()};form.forwardTo=function(e,t,i,r){view.action=e;view.method=t;view.id=i;view.params=r;view.loadView()};form.initOnElement(this)});n(element)});loadViewHtmlPromise.fail(function(e,t,i){$(element).html('');console.error({view:view,url:url,status:t,cause:i});let notice=new Openrat.Notice();notice.setStatus('error');notice.msg=Openrat.Workbench.language.ERROR;notice.show()});let apiUrl=Openrat.View.createUrl(this.action,this.method,this.id,this.params,!0);return loadViewHtmlPromise};Openrat.View.createUrl=function(e,subaction,i,extraid={},api=!1){let url='./';if(api)url+='api/';url+='?';if(e)url+='&action='+e;if(subaction)url+='&subaction='+subaction;if(i)url+='&id='+i;if(typeof extraid==='string'){extraid=extraid.replace(/'/g,'"');let extraObject=jQuery.parseJSON(extraid);jQuery.each(extraObject,function(e,t){url=url+'&'+e+'='+t})}
+;Openrat.Dialog=function(){this.view;this.isDirty=!1;this.element=$('.or-dialog-content .or-view');this.start=function(e,i,t,o,n){if(!i)i=Openrat.Workbench.state.action;if(!o)o=Openrat.Workbench.state.id;let dialog=this;let view=new Openrat.View(i,t,o,n);Openrat.Notice.removeAllNotices();$('.or-dialog').removeClass('dialog--is-closed').addClass('dialog--is-open');$('.or-dialog-content .or-act-dialog-name').html(e);this.escapeKeyClosingHandler=function(e){if(e.keyCode==27){dialog.close();$(document).off('keyup')}};$(document).keyup(this.escapeKeyClosingHandler);$('.or-dialog-filler,.or-act-dialog-close').off('click').click(function(e){e.preventDefault();dialog.close()});view.onCloseHandler.add(function(){dialog.close()});view.onChangeHandler.add(function(){console.debug('Changes detected');dialog.isDirty=!0;dialog.element.addClass('view--is-dirty')});view.onSaveHandler.add(function(){dialog.isDirty=!1;dialog.element.removeClass('view--is-dirty')});this.view=view;return this.view.start(this.element)};this.close=function(){if(this.isDirty){let exit=window.confirm(Openrat.Workbench.language.UNSAVED_CHANGES_CONFIRM);if(!exit)return};$('.or-dialog-content .or-view.or-view--is-dirty').removeClass('view--is-dirty');$('.or-dialog-content .or-view').html('');$('.or-dialog').removeClass('dialog--is-open').addClass('dialog--is-closed');$(document).unbind('keyup',this.escapeKeyClosingHandler)}};
+;Openrat.View=function(e,t,i,n){this.action=e;this.method=t;this.id=i;this.params=n;this.onCloseHandler=$.Callbacks();this.onChangeHandler=$.Callbacks();this.onSaveHandler=$.Callbacks();this.before=function(){};this.start=function(e){this.before();this.element=e;return this.loadView()};this.afterLoad=function(){};this.close=function(){this.onCloseHandler.fire()};function r(e){Openrat.Workbench.afterViewLoadedHandler.fire(e)};this.loadView=function(){let url=Openrat.View.createUrl(this.action,this.method,this.id,this.params,!1);let element=this.element;let view=this;let loadViewHtmlPromise=$.ajax(url);$(this.element).addClass('loader');console.debug(view);loadViewHtmlPromise.done(function(e,t){if(!e)e='';$(element).html(e).removeClass('loader');$(element).find('form').each(function(){let form=new Openrat.Form();form.onChangeHandler.add(function(){view.onChangeHandler.fire()});form.onSaveHandler.add(function(){view.onSaveHandler.fire()});form.onCloseHandler.add(function(){view.close()});form.forwardTo=function(e,t,i,n){view.action=e;view.method=t;view.id=i;view.params=n;view.loadView()};form.initOnElement(this)});r(element)});loadViewHtmlPromise.fail(function(e,t,i){$(element).html('');console.error({view:view,url:url,status:t,cause:i});let notice=new Openrat.Notice();notice.setStatus('error');notice.msg=Openrat.Workbench.language.ERROR;notice.show()});let apiUrl=Openrat.View.createUrl(this.action,this.method,this.id,this.params,!0);return loadViewHtmlPromise};Openrat.View.createUrl=function(e,subaction,i,extraid={},api=!1){let url='./';if(api)url+='api/';url+='?';if(e)url+='&action='+e;if(subaction)url+='&subaction='+subaction;if(i)url+='&id='+i;if(typeof extraid==='string'){extraid=extraid.replace(/'/g,'"');let extraObject=jQuery.parseJSON(extraid);jQuery.each(extraObject,function(e,t){url=url+'&'+e+'='+t})}
else if(typeof extraid==='object'){jQuery.each(extraid,function(e,t){url=url+'&'+e+'='+t})}
else{};return url}};
-;Openrat.Form=function(){const modes={showBrowserNotice:1,keepOpen:2,closeAfterSubmit:4,closeAfterSuccess:8,};this.setLoadStatus=function(e){$(this.element).closest('div.content').toggleClass('loader',e)};this.initOnElement=function(e){this.element=e;let form=this;if($(this.element).data('autosave')){$(this.element).find('input[type="checkbox"]').click(function(){form.submit(modes.keepOpen)});$(this.element).find('select').change(function(){form.submit(modes.keepOpen)})};$(e).find('.or-act-form-cancel').click(function(){form.cancel()});$(e).find('.or-act-form-reset').click(function(){form.rollback()});$(e).find('.or-act-form-apply').click(function(){form.submit(modes.keepOpen)});$(e).find('.or-act-form-save').click(function(){form.submit()});$(e).submit(function(e){if($(this).data('target')=='view'){form.submit();e.preventDefault()}})};this.cancel=function(){Openrat.Notice.removeAllNotices();this.close()};this.rollback=function(){this.element.trigger('reset')};this.close=function(){};this.forwardTo=function(e,t,o,s){};this.submit=function(e){if(e===undefined)if($(this.element).data('async'))e=modes.closeAfterSubmit;else e=modes.closeAfterSuccess;Openrat.Notice.removeAllNotices();let status=new Openrat.Notice();status.setStatus('info');status.inProgress();status.msg=Openrat.Workbench.language.PROGRESS;status.show();$(this.element).find('.or-input--error').removeClass('input--error');let params=$(this.element).serializeArray();let data={};$(params).each(function(e,t){data[t.name]=t.value});if(!data.id)data.id=Openrat.Workbench.state.id;if(!data.action)data.action=Openrat.Workbench.state.action;let formMethod=$(this.element).attr('method').toUpperCase();if(formMethod=='GET'){this.forwardTo(data.action,data.subaction,data.id,data);$(status).remove()}
-else{let url='./api/';this.setLoadStatus(!0);url+='';data.output='json';if(e==modes.closeAfterSubmit)this.close();let form=this;console.debug(form);$.ajax({'type':'POST',url:url,data:data,success:function(t,o,s){form.setLoadStatus(!1);status.close();form.doResponse(t,o,form.element,function(){$(form.element).closest('.or-view.or-view--is-dirty').removeClass('view--is-dirty');let afterSuccess=$(form.element).data('afterSuccess');let forwardTo=$(form.element).data('forwardTo');let async=$(form.element).data('async');if(afterSuccess=='forward')e=modes.keepOpen;if(e==modes.closeAfterSuccess){form.close();$(form.element).closest('div.panel').find('div.header ul.views li.action.active').removeClass('dirty')};if(afterSuccess){if(afterSuccess=='reloadAll'){Openrat.Workbench.reloadAll()}
+;Openrat.Form=function(){const modes={showBrowserNotice:1,keepOpen:2,closeAfterSubmit:4,closeAfterSuccess:8,};this.onChangeHandler=$.Callbacks();this.onSaveHandler=$.Callbacks();this.setLoadStatus=function(e){$(this.element).closest('div.content').toggleClass('loader',e)};this.initOnElement=function(e){this.element=e;let form=this;if($(this.element).data('autosave')){$(this.element).find('input[type="checkbox"]').click(function(){form.submit(modes.keepOpen)});$(this.element).find('select').change(function(){form.submit(modes.keepOpen)})};$(e).find('.or-act-form-cancel').click(function(){form.cancel()});$(e).find('.or-act-form-reset').click(function(){form.rollback()});$(e).find('.or-act-form-apply').click(function(){form.submit(modes.keepOpen)});$(e).find('.or-act-form-save').click(function(){form.submit()});$(e).find('.or-input').change(function(){form.onChangeHandler.fire()});$(e).submit(function(e){if($(this).data('target')=='view'){form.submit();e.preventDefault()}})};this.cancel=function(){Openrat.Notice.removeAllNotices();this.onCloseHandler.fire()};this.rollback=function(){this.element.trigger('reset')};this.onCloseHandler=$.Callbacks();this.forwardTo=function(e,t,o,s){};this.submit=function(e){if(e===undefined)if($(this.element).data('async'))e=modes.closeAfterSubmit;else e=modes.closeAfterSuccess;Openrat.Notice.removeAllNotices();let status=new Openrat.Notice();status.setStatus('info');status.inProgress();status.msg=Openrat.Workbench.language.PROGRESS;status.show();$(this.element).find('.or-input--error').removeClass('input--error');let params=$(this.element).serializeArray();let data={};$(params).each(function(e,t){data[t.name]=t.value});if(!data.id)data.id=Openrat.Workbench.state.id;if(!data.action)data.action=Openrat.Workbench.state.action;let formMethod=$(this.element).attr('method').toUpperCase();if(formMethod=='GET'){this.forwardTo(data.action,data.subaction,data.id,data);$(status).remove()}
+else{let url='./api/';this.setLoadStatus(!0);url+='';data.output='json';if(e==modes.closeAfterSubmit)this.onCloseHandler();let form=this;console.debug(form);$.ajax({'type':'POST',url:url,data:data,success:function(t,o,s){form.setLoadStatus(!1);status.close();form.doResponse(t,o,form.element,function(){form.onSaveHandler.fire();let afterSuccess=$(form.element).data('afterSuccess');let forwardTo=$(form.element).data('forwardTo');let async=$(form.element).data('async');if(afterSuccess=='forward')e=modes.keepOpen;if(e==modes.closeAfterSuccess){form.onCloseHandler();$(form.element).closest('div.panel').find('div.header ul.views li.action.active').removeClass('dirty')};if(afterSuccess){if(afterSuccess=='reloadAll'){Openrat.Workbench.reloadAll()}
else if(afterSuccess=='forward'){if(forwardTo)form.forwardTo(data.action,forwardTo,data.id,[])}}
else{if(async);else Openrat.Workbench.reloadViews()}})},error:function(e,t,o){console.warn({message:'could not post form',jqXHR:e,form:form,status:t,error:o});form.setLoadStatus(!1);status.close();let msg='';try{msg=jQuery.parseJSON(e.responseText).error}catch(s){msg=e.responseText};let notice=new Openrat.Notice();notice.setStatus('error');notice.msg=msg;notice.show()}});$(form.element).fadeIn()}};this.doResponse=function(e,t,o,onSuccess=$.noop){if(t!='success'){console.error('Server error: '+t);let notice=new Openrat.Notice();notice.setStatus('error');notice.msg=Openrat.Workbench.language.ERROR;notice.show();return};let form=this;$.each(e['notices'],function(t,e){let notifyBrowser=$(o).data('async');let notice=new Openrat.Notice();notice.setContext(e.type,e.id,e.name);notice.log=e.log;notice.setStatus(e.status);notice.msg=e.text;notice.show();if(notifyBrowser)notice.notifyBrowser();if(e.status=='ok'){onSuccess();Openrat.Workbench.dataChangedHandler.fire()}
else{}});$.each(e['errors'],function(e,t){$('.or-input[name='+t+']').addClass('input--error').parent().addClass('input--error').parents('.or-group').removeClass('closed').addClass('show').addClass('open')})}};
;Openrat.Workbench=new function(){'use strict';this.state={action:'',id:0,extra:{}};this.popupWindow=null;this.initialize=function(){this.initializePingTimer();this.initializeDirtyWarning();this.initializeState();this.openModalDialog();Openrat.Workbench.registerOpenClose($('.or-collapsible'));console.info('Application started')};this.initializeDirtyWarning=function(){window.addEventListener('beforeunload',function(e){if($('.or-view--is-dirty').length>0){e.preventDefault();return'Unsaved content will be lost.'}
-else{return undefined}})};this.openModalDialog=function(){if($('#dialog').data('action')){this.startDialog('',$('#dialog').data('action'),$('#dialog').data('action'),0,{})}};this.initializeState=function(){let parts=window.location.hash.split('/');let state={action:'index',id:0};if(parts.length>=2)state.action=parts[1].toLowerCase();if(parts.length>=3)state.id=parts[2].replace(/[^0-9_]/gim,'');Openrat.Workbench.state=state;Openrat.Navigator.toActualHistory(state)};this.initializePingTimer=function(){let ping=function(){let pingPromise=$.getJSON(Openrat.View.createUrl('profile','ping',0,{},!0));console.debug('ping');pingPromise.fail(function(e,t,i){console.warn({message:'The server ping has failed.',jqXHR:e,status:t,error:i});if($('.view.dirty').length>0){window.alert('The server session is lost, please save your data.')}
-else{}})};let timeoutMinutes=5;window.setInterval(ping,timeoutMinutes*60*1000)};this.loadNewActionState=function(e){Openrat.Workbench.state=e;Openrat.Workbench.loadNewAction(e.action,e.id,e.data);this.afterNewActionHandler.fire()};this.afterNewActionHandler=$.Callbacks();this.afterAllViewsLoaded=$.Callbacks();this.loadNewAction=function(e,t,i){this.reloadViews()};this.reloadViews=function(){$('.or-workbench-section--is-closed .or-act-view-loader').empty();let promise=Openrat.Workbench.loadViews($('.or-workbench .or-act-view-loader'));promise.done(function(){Openrat.Workbench.afterAllViewsLoaded.fire()});return promise};this.reloadAll=function(){let promise=Openrat.Workbench.loadViews($('.or-act-view-loader,.or-act-view-static').empty());console.debug('reloading all views');promise.done(function(){Openrat.Workbench.afterAllViewsLoaded.fire()});this.loadUserStyle();this.loadLanguage();this.loadUISettings();return promise};this.loadUserStyle=function(){let url=Openrat.View.createUrl('profile','userinfo',0,{},!0);$.getJSON(url,function(e){let style=e.output['style'];Openrat.Workbench.setUserStyle(style);let color=e.output['theme-color'];Openrat.Workbench.setThemeColor(color)})};this.settings={};this.language={};this.loadLanguage=function(){let url=Openrat.View.createUrl('profile','language',0,{},!0);$.getJSON(url,function(e){Openrat.Workbench.language=e.output.language})};this.loadUISettings=function(){let url=Openrat.View.createUrl('profile','uisettings',0,{},!0);$.getJSON(url,function(e){Openrat.Workbench.settings=e.output.settings.settings})};this.loadViews=function(e){let promises=[];e.each(function(e){let $targetDOMElement=$(this);promises.push(Openrat.Workbench.loadNewActionIntoElement($targetDOMElement))});return $.when.apply($,promises)};this.loadNewActionIntoElement=function(e){let action;if(e.is('.or-act-view-static'))action=e.attr('data-action');else action=Openrat.Workbench.state.action;let id=Openrat.Workbench.state.id;let params=Openrat.Workbench.state.extra;let method=e.data('method');let view=new Openrat.View(action,method,id,params);return view.start(e)};this.setUserStyle=function(e){var t=$('html'),i=t.attr('class').split(/\s+/);$.each(i,function(e,i){if(i.startsWith('or-theme-')){t.removeClass(i.substring(3))}});t.addClass('theme-'+e.toLowerCase())};this.setThemeColor=function(e){$('#theme-color').attr('content',e)};this.dataChangedHandler=$.Callbacks();this.dataChangedHandler.add(function(){if(Openrat.Workbench.popupWindow)Openrat.Workbench.popupWindow.location.reload()});this.afterViewLoadedHandler=$.Callbacks();this.setApplicationTitle=function(e){if(e)$('head > title').text(e+' - '+$('head > title').data('default'));else $('head > title').text($('head > title').data('default'))};this.registerOpenClose=function(e){$(e).children('.or-collapsible-act-switch').click(function(){$(this).closest('.or-collapsible').toggleClass('collapsible--is-open').toggleClass('collapsible--is-closed')})};this.openNewAction=function(e,t,i){$('.or-workbench-navigation').removeClass('workbench-navigation--is-open');Openrat.Workbench.setApplicationTitle(e);Openrat.Navigator.navigateToNew({'action':t,'id':i})};this.startDialog=function(e,t,i,o,a){if(!t)t=Openrat.Workbench.state.action;if(!o)o=Openrat.Workbench.state.id;let view=new Openrat.View(t,i,o,a);view.before=function(){Openrat.Notice.removeAllNotices();$('.or-dialog-content .or-view').html('<div class="header"><img class="or-icon" title="" src="./themes/default/images/icon/'+i+'.png" />'+e+'</div>');$('.or-dialog-content .or-view').data('id',o);$('.or-dialog').removeClass('dialog--is-closed').addClass('dialog--is-open');$('.or-dialog-content .or-act-dialog-name').html(e);let view=this;this.escapeKeyClosingHandler=function(e){if(e.keyCode==27){view.close();$(document).off('keyup')}};$(document).keyup(this.escapeKeyClosingHandler);$('.or-dialog-filler,.or-act-dialog-close').click(function(e){e.preventDefault();view.close()})};view.close=function(){let isDirty=$('.or-view--is-dirty').length;if(isDirty){let exit=window.confirm(Openrat.Workbench.language.UNSAVED_CHANGES_CONFIRM);if(!exit)return};if($('.or-dialog').hasClass('or-dialog--modal'))return;$('.or-dialog-content .or-view.or-view--is-dirty').removeClass('view--is-dirty');$('.or-dialog-content .or-view').html('');$('.or-dialog').removeClass('dialog--is-open').addClass('dialog--is-closed');$(document).unbind('keyup',this.escapeKeyClosingHandler)};return view.start($('.or-dialog-content .or-view'))};this.registerDraggable=function(e){$(e).find('.or-draggable').draggable({helper:'clone',opacity:0.7,zIndex:3,distance:10,cursor:'move',revert:'false'})};this.registerDroppable=function(e){$(e).find('.or-droppable-selector').droppable({accept:'.or-draggable',hoverClass:'droppable--hover',activeClass:'droppable--active',drop:function(e,t){let dropped=t.draggable;console.info('dropped:');console.info(dropped);let id=$(dropped).find('.or-link').data('id');let name=$(dropped).find('.or-navtree-text').text();if(!name)name=id;$(this).find('.or-selector-link-value').val(id);$(this).find('.or-selector-link-name').val(name).attr('placeholder',name)}})}};
+else{return undefined}})};this.openModalDialog=function(){if($('#dialog').data('action')){let dialog=new Openrat.Dialog();dialog.start('',$('#dialog').data('action'),$('#dialog').data('action'),0,{})}};this.initializeState=function(){let parts=window.location.hash.split('/');let state={action:'index',id:0};if(parts.length>=2)state.action=parts[1].toLowerCase();if(parts.length>=3)state.id=parts[2].replace(/[^0-9_]/gim,'');Openrat.Workbench.state=state;Openrat.Navigator.toActualHistory(state)};this.initializePingTimer=function(){let ping=function(){let pingPromise=$.getJSON(Openrat.View.createUrl('profile','ping',0,{},!0));console.debug('ping');pingPromise.fail(function(e,t,i){console.warn({message:'The server ping has failed.',jqXHR:e,status:t,error:i});if($('.view.dirty').length>0){window.alert('The server session is lost, please save your data.')}
+else{}})};let timeoutMinutes=5;window.setInterval(ping,timeoutMinutes*60*1000)};this.loadNewActionState=function(e){Openrat.Workbench.state=e;Openrat.Workbench.loadNewAction(e.action,e.id,e.data);this.afterNewActionHandler.fire()};this.afterNewActionHandler=$.Callbacks();this.afterAllViewsLoaded=$.Callbacks();this.loadNewAction=function(e,t,i){this.reloadViews()};this.reloadViews=function(){$('.or-workbench-section--is-closed .or-act-view-loader').empty();let promise=Openrat.Workbench.loadViews($('.or-workbench .or-act-view-loader'));promise.done(function(){Openrat.Workbench.afterAllViewsLoaded.fire()});return promise};this.reloadAll=function(){let promise=Openrat.Workbench.loadViews($('.or-act-view-loader,.or-act-view-static').empty());console.debug('reloading all views');promise.done(function(){Openrat.Workbench.afterAllViewsLoaded.fire()});this.loadUserStyle();this.loadLanguage();this.loadUISettings();return promise};this.loadUserStyle=function(){let url=Openrat.View.createUrl('profile','userinfo',0,{},!0);$.getJSON(url,function(e){let style=e.output['style'];Openrat.Workbench.setUserStyle(style);let color=e.output['theme-color'];Openrat.Workbench.setThemeColor(color)})};this.settings={};this.language={};this.loadLanguage=function(){let url=Openrat.View.createUrl('profile','language',0,{},!0);$.getJSON(url,function(e){Openrat.Workbench.language=e.output.language})};this.loadUISettings=function(){let url=Openrat.View.createUrl('profile','uisettings',0,{},!0);$.getJSON(url,function(e){Openrat.Workbench.settings=e.output.settings.settings})};this.loadViews=function(e){let promises=[];e.each(function(e){let $targetDOMElement=$(this);promises.push(Openrat.Workbench.loadNewActionIntoElement($targetDOMElement))});return $.when.apply($,promises)};this.loadNewActionIntoElement=function(e){let action;if(e.is('.or-act-view-static'))action=e.attr('data-action');else action=Openrat.Workbench.state.action;let id=Openrat.Workbench.state.id;let params=Openrat.Workbench.state.extra;let method=e.data('method');let view=new Openrat.View(action,method,id,params);return view.start(e)};this.setUserStyle=function(e){var t=$('html'),i=t.attr('class').split(/\s+/);$.each(i,function(e,i){if(i.startsWith('or-theme-')){t.removeClass(i.substring(3))}});t.addClass('theme-'+e.toLowerCase())};this.setThemeColor=function(e){$('#theme-color').attr('content',e)};this.dataChangedHandler=$.Callbacks();this.dataChangedHandler.add(function(){if(Openrat.Workbench.popupWindow)Openrat.Workbench.popupWindow.location.reload()});this.afterViewLoadedHandler=$.Callbacks();this.setApplicationTitle=function(e){if(e)$('head > title').text(e+' - '+$('head > title').data('default'));else $('head > title').text($('head > title').data('default'))};this.registerOpenClose=function(e){$(e).children('.or-collapsible-act-switch').click(function(){$(this).closest('.or-collapsible').toggleClass('collapsible--is-open').toggleClass('collapsible--is-closed')})};this.openNewAction=function(e,t,i){$('.or-workbench-navigation').removeClass('workbench-navigation--is-open');Openrat.Workbench.setApplicationTitle(e);Openrat.Navigator.navigateToNew({'action':t,'id':i})};this.registerDraggable=function(e){$(e).find('.or-draggable').draggable({helper:'clone',opacity:0.7,zIndex:3,distance:10,cursor:'move',revert:'false'})};this.registerDroppable=function(e){$(e).find('.or-droppable-selector').droppable({accept:'.or-draggable',hoverClass:'droppable--hover',activeClass:'droppable--active',drop:function(e,t){let dropped=t.draggable;console.info('dropped:');console.info(dropped);let id=$(dropped).find('.or-link').data('id');let name=$(dropped).find('.or-navtree-text').text();if(!name)name=id;$(this).find('.or-selector-link-value').val(id);$(this).find('.or-selector-link-name').val(name).attr('placeholder',name)}})}};
;Openrat.Navigator=new function(){'use strict';this.navigateTo=function(t){Openrat.Workbench.loadNewActionState(t)};this.navigateToNew=function(t){this.navigateTo(t);window.history.pushState(t,t.name,this.createShortUrl(t.action,t.id))};this.toActualHistory=function(t){window.history.replaceState(t,t.name,this.createShortUrl(t.action,t.id))};this.createShortUrl=function(t,i){return'./#/'+t+(i?'/'+i:'')}};
;$(function(){$('html').removeClass('nojs');$('.or--initial-hidden').removeClass('-initial-hidden');function t(){};t();window.onpopstate=function(e){Openrat.Navigator.navigateTo(e.state)};Openrat.Workbench.initialize();Openrat.Workbench.reloadAll();let registerWorkbenchGlobalEvents=function(){$('.keystroke').each(function(){let keystrokeElement=$(this);let keystroke=keystrokeElement.text();if(keystroke.length==0)return;let keyaction=function(){keystrokeElement.click()};$(document).bind('keydown',keystroke,keyaction)})};$('.or-act-initial-notice').each(function(){let notice=new Openrat.Notice();notice.setStatus('info');notice.msg=$(this).text();notice.show();$(this).remove()});registerWorkbenchGlobalEvents();let closeMenu=function(){$('body').click(function(){$('.or-menu').removeClass('menu--is-open')})};closeMenu();let closeMobileNavigation=function(){$('.or-act-navigation-close').click(function(){$('.or-workbench-navigation').removeClass('workbench-navigation--is-open');$('.or-workbench').removeClass('workbench--navigation-is-open')})};closeMobileNavigation();let closeDesktopNavigation=function(){$('.or-workbench-title .or-act-nav-small').click(function(){$('.or-workbench').addClass('workbench--navigation-is-small');$('.or-workbench-navigation').addClass('workbench-navigation--is-small')})};closeDesktopNavigation();let registerGlobalSearch=function(){$('.or-search-input .or-input').orSearch({onSearchActive:function(){$('.or-search').addClass('search--is-active')},onSearchInactive:function(){$('.or-search').removeClass('search--is-active')},dropdown:'.or-act-search-result',resultEntryClass:'or-search-result-entry',select:function(e){Openrat.Workbench.openNewAction(e.name,e.action,e.id)},afterSelect:function(){}});$('.or-search .or-act-search-delete').click(function(){$('.or-search .or-title-input').val('').change()})};registerGlobalSearch();Openrat.Workbench.afterNewActionHandler.add(function(){$('.or-sidebar').find('.or-sidebar-button').orLinkify()});Openrat.Workbench.afterNewActionHandler.add(function(){let url=Openrat.View.createUrl('tree','path',Openrat.Workbench.state.id,{'type':Openrat.Workbench.state.action});let loadPromise=$.get(url);loadPromise.done(function(e){$('.or-breadcrumb').empty().append(e).find('.or-act-clickable').orLinkify();$('nav .or-navtree-node').removeClass('or-navtree-node--selected');$('.or-breadcrumb a').each(function(){let action=$(this).data('action');let id=$(this).data('id');let $navControl=$('nav .or-navtree-node[data-type='+action+'][data-id='+id+'].or-navtree-node--is-closed .or-navtree-node-control');$navControl.click()})}).fail(function(t,n,o){console.warn({message:'Failed to load path',url:url,error:e,status:n,o})}).always(function(){})});Openrat.Workbench.afterNewActionHandler.fire()});let filterMenus=function(){let action=Openrat.Workbench.state.action;let id=Openrat.Workbench.state.id;$('.or-workbench-title .or-dropdown-entry.or-act-clickable').addClass('dropdown-entry--active');$('.or-workbench-title .or-dropdown-entry.or-act-clickable.or-filtered').removeClass('dropdown-entry--active').addClass('dropdown-entry--inactive');$('.or-workbench-title .or-dropdown-entry.or-act-clickable.or-filtered .or-link').attr('data-id',id);let url=Openrat.View.createUrl('profile','available',id,{'queryaction':action},!0);let promise=$.getJSON(url);promise.done(function(e){jQuery.each(e.output.views,function(e,t){$('.or-workbench-title .or-dropdown-entry.or-act-clickable.or-filtered > .or-link[data-method=\''+t+'\']').parent().addClass('dropdown-entry--active').removeClass('dropdown-entry--inactive')})})};Openrat.Workbench.afterAllViewsLoaded.add(function(){filterMenus()});Openrat.Workbench.afterViewLoadedHandler.add(function(e){if(Openrat.Workbench.popupWindow)$(e).find('a[data-type=\'popup\']').each(function(){Openrat.Workbench.popupWindow.location.href=$(this).attr('data-url')})});Openrat.Workbench.afterViewLoadedHandler.add(function(e){$(e).find('.or-input--password').dblclick(function(){$(this).toggleAttr('type','text','password')});$(e).find('.or-act-make-visible').click(function(){$(this).toggleClass('btn--is-active');$(this).parent().children('input').toggleAttr('type','text','password')})});Openrat.Workbench.afterViewLoadedHandler.add(function(e){e.find('.or-act-load-nav-tree').each(function(){let type=$(this).data('type')||'root';let loadBranchUrl='./?action=tree&subaction=branch&id=0&type='+type;let $targetElement=$(this);$.get(loadBranchUrl).done(function(e){let $ul=$('<ul class="or-navtree-list" />');$ul.appendTo($targetElement.empty()).append(e);$ul.find('li').orTree({'openAction':function(e,t,n){Openrat.Workbench.openNewAction(e,t,n)}});$ul.find('.or-act-clickable').orLinkify();$ul.find('.or-navtree-node-control').first().click()})})});Openrat.Workbench.afterViewLoadedHandler.add(function(e){var t=$(e).closest('section');t.toggleClass('is-empty',$(e).is(':empty'));if(!$(e).is(':empty'))t.slideDown('fast');else t.slideUp('fast');$(e).find('.or-act-nav-open-close').click(function(){$('.or-workbench').toggleClass('workbench--navigation-is-open');$('.or-workbench-navigation').toggleClass('workbench-navigation--is-open')});$(e).find('.or-act-nav-small').click(function(){$('.or-workbench').addClass('workbench--navigation-is-small');$('.or-workbench-navigation').addClass('workbench-navigation--is-small')});$(e).find('.or-act-nav-wide').click(function(){$('.or-workbench').removeClass('workbench--navigation-is-small');$('.or-workbench-navigation').removeClass('workbench-navigation--is-small')});$(e).find('.or-act-selector-tree-button').click(function(){let $selector=$(this).parent('.or-selector');let $targetElement=$selector.find('.or-act-load-selector-tree');if($selector.hasClass('selector--is-tree-active')){$selector.removeClass('selector--is-tree-active');$targetElement.empty()}
-else{$selector.addClass('selector--is-tree-active');var e=this;let id=$(this).data('init-folder-id');let type=id?'folder':'projects';let loadBranchUrl='./?action=tree&subaction=branch&id='+id+'&type='+type;$.get(loadBranchUrl).done(function(e){let $ul=$('<ul class="or-navtree-list" />');$ul.appendTo($targetElement).append(e);$ul.find('li').orTree({'openAction':function(e,t,n){$selector.find('.or-selector-link-value').val(n);$selector.find('.or-selector-link-name').val('').attr('placeholder',e);$selector.removeClass('selector--is-tree-active');$targetElement.empty()}});$ul.find('.or-act-clickable').orLinkify();$ul.find('.or-navtree-node-control').first().click()})}});n(e);$(e).find('.or-input').change(function(){$(this).closest('.or-view').addClass('view--is-dirty')});$(e).find('.or-theme-chooser').change(function(){Openrat.Workbench.setUserStyle(this.value)});function o(e){$(e).find('.or-menu-category').click(function(e){e.stopPropagation();$(this).parents('.or-menu').toggleClass('menu--is-open')});$(e).find('.or-menu-category').mouseover(function(){$(this).parents('.or-menu').find('.or-menu-category').removeClass('menu-category--is-open');$(this).addClass('menu-category--is-open')})};function r(e){$(e).find('.or-act-selector-search').orSearch({onSearchActive:function(){$(this).parent('or-selector').addClass('selector-search--is-active')},onSearchInactive:function(){$(this).parent('or-selector').removeClass('selector-search--is-active')},dropdown:'.or-act-selector-search-results',resultEntryClass:'or-search-result-entry',select:function(t){$(e).find('.or-selector-link-value').val(t.id);$(e).find('.or-selector-link-name').val(t.name).attr('placeholder',t.name)},afterSelect:function(){$('.or-dropdown.or-act-selector-search-results').empty()}})};function a(e){};o(e);r(e);a(e);function n(e){Openrat.Workbench.registerDraggable(e);Openrat.Workbench.registerDroppable(e)};n(e)});
+else{$selector.addClass('selector--is-tree-active');var e=this;let id=$(this).data('init-folder-id');let type=id?'folder':'projects';let loadBranchUrl='./?action=tree&subaction=branch&id='+id+'&type='+type;$.get(loadBranchUrl).done(function(e){let $ul=$('<ul class="or-navtree-list" />');$ul.appendTo($targetElement).append(e);$ul.find('li').orTree({'openAction':function(e,t,n){$selector.find('.or-selector-link-value').val(n);$selector.find('.or-selector-link-name').val('').attr('placeholder',e);$selector.removeClass('selector--is-tree-active');$targetElement.empty()}});$ul.find('.or-act-clickable').orLinkify();$ul.find('.or-navtree-node-control').first().click()})}});n(e);$(e).find('.or-theme-chooser').change(function(){Openrat.Workbench.setUserStyle(this.value)});function o(e){$(e).find('.or-menu-category').click(function(e){e.stopPropagation();$(this).parents('.or-menu').toggleClass('menu--is-open')});$(e).find('.or-menu-category').mouseover(function(){$(this).parents('.or-menu').find('.or-menu-category').removeClass('menu-category--is-open');$(this).addClass('menu-category--is-open')})};function r(e){$(e).find('.or-act-selector-search').orSearch({onSearchActive:function(){$(this).parent('or-selector').addClass('selector-search--is-active')},onSearchInactive:function(){$(this).parent('or-selector').removeClass('selector-search--is-active')},dropdown:'.or-act-selector-search-results',resultEntryClass:'or-search-result-entry',select:function(t){$(e).find('.or-selector-link-value').val(t.id);$(e).find('.or-selector-link-name').val(t.name).attr('placeholder',t.name)},afterSelect:function(){$('.or-dropdown.or-act-selector-search-results').empty()}})};function a(e){};o(e);r(e);a(e);function n(e){Openrat.Workbench.registerDraggable(e);Openrat.Workbench.registerDroppable(e)};n(e)});
;Openrat.Workbench.afterViewLoadedHandler.add(function(e){});
;Openrat.Workbench.afterViewLoadedHandler.add(function(e){$(e).find('textarea').orAutoheight();$(e).find('textarea.or-editor.or-code-editor').each(function(){let mode=$(this).data('mode');let mimetype=$(this).data('mimetype');if(mimetype.length>0)mode=mimetype;let textareaEl=this;let editor=CodeMirror.fromTextArea(textareaEl,{lineNumbers:!0,viewportMargin:Infinity,mode:mode});editor.on('change',function(){let newValue=editor.getValue();$(textareaEl).val(newValue)});$(editor.getWrapperElement()).droppable({accept:'.or-draggable',hoverClass:'or-droppable--hover',activeClass:'or-droppable--active',drop:function(e,t){let dropped=t.draggable;let pos=editor.getCursor();editor.setSelection(pos,pos);let insertText=dropped.data('id');let toInsert=''+insertText;editor.replaceSelection(toInsert)}})});$(e).find('textarea.or-editor.or-markdown-editor').each(function(){let textarea=this;let toolbar=[{name:'bold',action:SimpleMDE.toggleBold,className:'image-icon image-icon--editor-bold',title:'Bold',},{name:'italic',action:SimpleMDE.toggleItalic,className:'image-icon image-icon--editor-italic',title:'Italic',},{name:'heading',action:SimpleMDE.toggleHeadingBigger,className:'image-icon image-icon--editor-headline',title:'Headline',},'|',{name:'quote',action:SimpleMDE.toggleBlockquote,className:'image-icon image-icon--editor-quote',title:'Quote',},{name:'code',action:SimpleMDE.toggleCodeBlock,className:'image-icon image-icon--editor-code',title:'Code',},'|',{name:'generic list',action:SimpleMDE.toggleUnorderedList,className:'image-icon image-icon--editor-unnumberedlist',title:'Unnumbered list',},{name:'numbered list',action:SimpleMDE.toggleOrderedList,className:'image-icon image-icon--editor-numberedlist',title:'Numbered list',},'|',{name:'table',action:SimpleMDE.drawTable,className:'image-icon image-icon--editor-table',title:'Table',},{name:'horizontalrule',action:SimpleMDE.drawHorizontalRule,className:'image-icon image-icon--editor-horizontalrule',title:'Horizontal rule',},'|',{name:'undo',action:SimpleMDE.undo,className:'image-icon image-icon--editor-undo',title:'Undo',},{name:'redo',action:SimpleMDE.redo,className:'image-icon image-icon--editor-redo',title:'Redo',},'|',{name:'link',action:SimpleMDE.drawLink,className:'image-icon image-icon--editor-link',title:'Link',},{name:'image',action:SimpleMDE.drawImage,className:'image-icon image-icon--editor-image',title:'Image',},'|',{name:'guide',action:'https://simplemde.com/markdown-guide',className:'image-icon image-icon--editor-help',title:'Howto markdown',},];let mde=new SimpleMDE({element:$(this)[0],toolbar:toolbar,autoDownloadFontAwesome:!1});let codemirror=mde.codemirror;$(codemirror.getWrapperElement()).droppable({accept:'.or-draggable',hoverClass:'or-droppable--hover',activeClass:'or-droppable--active',drop:function(e,t){let dropped=t.draggable;let insertText='';let id=dropped.data('id');let url='__OID__'+id+'__';if(dropped.data('type')=='image')insertText='';else insertText='['+id+']('+url+')';let pos=codemirror.getCursor();codemirror.setSelection(pos,pos);codemirror.replaceSelection(insertText)}});codemirror.on('change',function(){let newValue=codemirror.getValue();$(textarea).val(newValue)})});$(e).find('textarea.or-editor.or-html-editor').each(function(){let textarea=this;$.trumbowyg.svgPath='./modules/editor/trumbowyg/ui/icons.svg';$(textarea).trumbowyg();$(textarea).closest('form').find('.trumbowyg-editor').droppable({accept:'.or-draggable',hoverClass:'or-droppable--hover',activeClass:'or-droppable--active',drop:function(e,t){let dropped=t.draggable;let id=dropped.data('id');let url='./?_='+dropped.data('type')+'-'+id+'&subaction=show&embed=1&__OID__'+id+'__='+id;let insertText='';if(dropped.data('type')=='image')insertText='<img src="'+url+'" alt="" />';else insertText='<a href="'+url+'" />'+id+'</a>';$(textarea).trumbowyg('execCmd',{cmd:'insertHTML',param:insertText,forceCss:!1,})}})})});
;Openrat.Workbench.afterViewLoadedHandler.add(function(e){Openrat.Workbench.registerOpenClose($(e).find('.or-collapsible.or-group'))});
diff --git a/modules/cms/ui/themes/default/script/openrat/common.js b/modules/cms/ui/themes/default/script/openrat/common.js
@@ -350,11 +350,6 @@ Openrat.Workbench.afterViewLoadedHandler.add( function(viewEl ) {
registerDragAndDrop(viewEl);
- // Bei Änderungen in der View das Tab als 'dirty' markieren
- $(viewEl).find('.or-input').change( function() {
- $(this).closest('.or-view').addClass('view--is-dirty');
- });
-
// Theme-Auswahl mit Preview
$(viewEl).find('.or-theme-chooser').change( function() {
Openrat.Workbench.setUserStyle( this.value );
diff --git a/modules/cms/ui/themes/default/script/openrat/dialog.js b/modules/cms/ui/themes/default/script/openrat/dialog.js
@@ -0,0 +1,120 @@
+/**
+ * A dialog is a special area in the workbench for displaying and inputting data.
+ * A dialog contains a view.
+ */
+
+Openrat.Dialog = function() {
+
+ /**
+ * The encapsulated view.
+ */
+ this.view;
+
+ /**
+ * Dirty-marker (if unsaved changes exist).
+ *
+ * @type {boolean}
+ */
+ this.isDirty = false;
+
+ /**
+ * the DOM element which contains the dialog.
+ * @type {*|jQuery|HTMLElement}
+ */
+ this.element = $('.or-dialog-content .or-view');
+
+ /**
+ * Creating a new dialog.
+ *
+ * @param name
+ * @param action Action
+ * @param method
+ * @param id Id
+ * @param params
+ *
+ * @return Promise of underlying view
+ */
+ this.start = function( name,action,method,id,params )
+ {
+ // Attribute aus dem aktuellen Editor holen, falls die Daten beim Aufrufer nicht angegeben sind.
+ if (!action)
+ action = Openrat.Workbench.state.action;
+
+ if (!id)
+ id = Openrat.Workbench.state.id;
+
+ let dialog = this;
+
+ let view = new Openrat.View( action,method,id,params );
+
+ Openrat.Notice.removeAllNotices();
+
+ //$('.or-dialog-content .or-view').html('<div class="header"><img class="or-icon" title="" src="./themes/default/images/icon/'+method+'.png" />'+name+'</div>');
+ //$('.or-dialog-content .or-view').data('id',id);
+ $('.or-dialog').removeClass('dialog--is-closed').addClass('dialog--is-open');
+ $('.or-dialog-content .or-act-dialog-name').html( name );
+
+ this.escapeKeyClosingHandler = function (e) {
+ if (e.keyCode == 27) { // ESC keycode
+ dialog.close();
+
+ $(document).off('keyup'); // de-register.
+ }
+ };
+
+ $(document).keyup(this.escapeKeyClosingHandler);
+
+ // close dialog on click onto the blurred area.
+ $('.or-dialog-filler,.or-act-dialog-close').off('click').click( function(e)
+ {
+ e.preventDefault();
+ dialog.close();
+ });
+
+
+ view.onCloseHandler.add( function() {
+ dialog.close();
+ } );
+
+ view.onChangeHandler.add( function() {
+ // data has changed
+ console.debug("Changes detected");
+ dialog.isDirty = true;
+ // Remove dirty-flag from view
+ dialog.element.addClass('view--is-dirty');
+ });
+
+ view.onSaveHandler.add( function() {
+ // data was saved
+ dialog.isDirty = false;
+ // Remove dirty-flag from view
+ dialog.element.removeClass('view--is-dirty');
+ });
+
+ this.view = view;
+
+ return this.view.start( this.element );
+ }
+
+
+ /**
+ * Closing the dialog.
+ */
+ this.close = function() {
+
+ if ( this.isDirty ) {
+ // ask the user if we should close this dialog
+ let exit = window.confirm( Openrat.Workbench.language.UNSAVED_CHANGES_CONFIRM );
+
+ if ( ! exit )
+ return;
+ }
+
+ // Remove dirty-flag from view
+ $('.or-dialog-content .or-view.or-view--is-dirty').removeClass('view--is-dirty');
+ $('.or-dialog-content .or-view').html('');
+ $('.or-dialog').removeClass('dialog--is-open').addClass('dialog--is-closed'); // Dialog schließen
+
+ $(document).unbind('keyup',this.escapeKeyClosingHandler); // Cleanup ESC-Key-Listener
+ }
+}+
\ No newline at end of file
diff --git a/modules/cms/ui/themes/default/script/openrat/form.js b/modules/cms/ui/themes/default/script/openrat/form.js
@@ -13,6 +13,12 @@ Openrat.Form = function() {
closeAfterSuccess : 8,
};
+ /**
+ * Fires on input.
+ */
+ this.onChangeHandler = $.Callbacks();
+ this.onSaveHandler = $.Callbacks();
+
this.setLoadStatus = function( isLoading ) {
$(this.element).closest('div.content').toggleClass('loader',isLoading);
}
@@ -57,7 +63,13 @@ Openrat.Form = function() {
form.submit();
});
- // Submithandler for the whole form.
+ // Bei Änderungen in der View das Tab als 'dirty' markieren
+ $(element).find('.or-input').change( function() {
+ form.onChangeHandler.fire();
+ });
+
+
+ // Submithandler for the whole form.
$(element).submit( function( event ) {
//
@@ -74,7 +86,7 @@ Openrat.Form = function() {
//$(this.element).html('').parent().removeClass('is-open');
Openrat.Notice.removeAllNotices();
- this.close();
+ this.onCloseHandler.fire();
}
@@ -82,8 +94,7 @@ Openrat.Form = function() {
this.element.trigger('reset');
}
- this.close = function() {
- }
+ this.onCloseHandler = $.Callbacks();
this.forwardTo = function (action, subaction, id, data) {
}
@@ -142,7 +153,7 @@ Openrat.Form = function() {
data.output = 'json';
if ( mode == modes.closeAfterSubmit )
- this.close();
+ this.onCloseHandler();
// Async: Window is closed, but the action will be startet now.
let form = this;
@@ -155,8 +166,7 @@ Openrat.Form = function() {
form.doResponse(responseData,textStatus,form.element, function() {
- // Remove dirty-flag from view
- $(form.element).closest('.or-view.or-view--is-dirty').removeClass('view--is-dirty');
+ form.onSaveHandler.fire();
let afterSuccess = $(form.element).data('afterSuccess');
let forwardTo = $(form.element).data('forwardTo' );
@@ -169,7 +179,7 @@ Openrat.Form = function() {
// Now we can close the form.
if ( mode == modes.closeAfterSuccess )
{
- form.close();
+ form.onCloseHandler();
// clear the dirty flag.
$(form.element).closest('div.panel').find('div.header ul.views li.action.active').removeClass('dirty');
diff --git a/modules/cms/ui/themes/default/script/openrat/view.js b/modules/cms/ui/themes/default/script/openrat/view.js
@@ -15,6 +15,11 @@ Openrat.View = function( action,method,id,params ) {
this.id = id;
this.params = params;
+ this.onCloseHandler = $.Callbacks();
+
+ this.onChangeHandler = $.Callbacks();
+ this.onSaveHandler = $.Callbacks();
+
this.before = function() {};
/**
@@ -34,6 +39,7 @@ Openrat.View = function( action,method,id,params ) {
this.close = function() {
+ this.onCloseHandler.fire();
}
@@ -69,10 +75,17 @@ Openrat.View = function( action,method,id,params ) {
let form = new Openrat.Form();
- form.close = function() {
+ form.onChangeHandler.add( function() {
+ view.onChangeHandler.fire();
+ });
+ form.onSaveHandler.add( function() {
+ view.onSaveHandler.fire();
+ });
+
+ form.onCloseHandler.add( function() {
view.close();
- }
+ } );
form.forwardTo = function (action, subaction, id, data) {
view.action = action;
diff --git a/modules/cms/ui/themes/default/script/openrat/workbench.js b/modules/cms/ui/themes/default/script/openrat/workbench.js
@@ -56,7 +56,8 @@ Openrat.Workbench = new function()
this.openModalDialog = function () {
if ( $('#dialog').data('action') ) {
- this.startDialog('',$('#dialog').data('action'),$('#dialog').data('action'),0,{})
+ let dialog = new Openrat.Dialog();
+ dialog.start('',$('#dialog').data('action'),$('#dialog').data('action'),0,{} )
}
}
@@ -357,83 +358,7 @@ Openrat.Workbench = new function()
- /**
- * Creating a new modal dialog.
- *
- * @param name
- * @param action Action
- * @param method
- * @param id Id
- * @param params
- */
- this.startDialog = function( name,action,method,id,params )
- {
- // Attribute aus dem aktuellen Editor holen, falls die Daten beim Aufrufer nicht angegeben sind.
- if (!action)
- action = Openrat.Workbench.state.action;
-
- if (!id)
- id = Openrat.Workbench.state.id;
-
- let view = new Openrat.View( action,method,id,params );
-
- view.before = function() {
-
- Openrat.Notice.removeAllNotices();
-
- $('.or-dialog-content .or-view').html('<div class="header"><img class="or-icon" title="" src="./themes/default/images/icon/'+method+'.png" />'+name+'</div>');
- $('.or-dialog-content .or-view').data('id',id);
- $('.or-dialog').removeClass('dialog--is-closed').addClass('dialog--is-open');
- $('.or-dialog-content .or-act-dialog-name').html( name );
-
- let view = this;
-
- this.escapeKeyClosingHandler = function (e) {
- if (e.keyCode == 27) { // ESC keycode
- view.close();
-
- $(document).off('keyup'); // de-register.
- }
- };
-
- $(document).keyup(this.escapeKeyClosingHandler);
-
- // Nicht-Modale Dialoge durch Klick auf freie Fläche schließen.
- $('.or-dialog-filler,.or-act-dialog-close').click( function(e)
- {
- e.preventDefault();
- view.close();
- });
-
- }
-
- view.close = function() {
-
- let isDirty = $('.or-view--is-dirty').length; // has this view unsaved changes?
- if ( isDirty ) {
- // ask the user if we should close this dialog
- let exit = window.confirm( Openrat.Workbench.language.UNSAVED_CHANGES_CONFIRM );
-
- if ( ! exit )
- return;
- }
-
- // Strong modal dialogs are unable to close.
- // Really?
- if ( $('.or-dialog').hasClass('or-dialog--modal') )
- return;
-
- // Remove dirty-flag from view
- $('.or-dialog-content .or-view.or-view--is-dirty').removeClass('view--is-dirty');
- $('.or-dialog-content .or-view').html('');
- $('.or-dialog').removeClass('dialog--is-open').addClass('dialog--is-closed'); // Dialog schließen
-
- $(document).unbind('keyup',this.escapeKeyClosingHandler); // Cleanup ESC-Key-Listener
- }
-
- return view.start( $('.or-dialog-content .or-view') );
- }
diff --git a/modules/cms/ui/themes/default/script/plugin/jquery-plugin-orLinkify.js b/modules/cms/ui/themes/default/script/plugin/jquery-plugin-orLinkify.js
@@ -68,7 +68,8 @@ jQuery.fn.orLinkify = function( options )
case 'edit':
case 'dialog':
- Openrat.Workbench.startDialog($link.attr('data-name'),$link.attr('data-action'),$link.attr('data-method'),$link.attr('data-id'),$link.attr('data-extra') );
+ let dialog = new Openrat.Dialog();
+ dialog.start($link.attr('data-name'),$link.attr('data-action'),$link.attr('data-method'),$link.attr('data-id'),$link.attr('data-extra') );
break;
case 'external':