summaryrefslogtreecommitdiffstats
path: root/modules-available/sysconfignew
diff options
context:
space:
mode:
authorSimon Rettberg2016-05-03 19:03:09 +0200
committerSimon Rettberg2016-05-03 19:03:09 +0200
commit50404f3b23b7fd6aeae4c9d2f6df0ea25e984e66 (patch)
tree05e99fdffa696434960d7c77966c0bc36d6339e8 /modules-available/sysconfignew
parentSecond half of merge.... (diff)
downloadslx-admin-50404f3b23b7fd6aeae4c9d2f6df0ea25e984e66.tar.gz
slx-admin-50404f3b23b7fd6aeae4c9d2f6df0ea25e984e66.tar.xz
slx-admin-50404f3b23b7fd6aeae4c9d2f6df0ea25e984e66.zip
WIP
Diffstat (limited to 'modules-available/sysconfignew')
-rw-r--r--modules-available/sysconfignew/config.json3
-rw-r--r--modules-available/sysconfignew/lang/en/module.json23
-rw-r--r--modules-available/sysconfignew/lang/pt/module.json23
-rw-r--r--modules-available/sysconfignew/page.inc.php113
-rw-r--r--modules-available/sysconfignew/templates/_pagenew.html190
-rw-r--r--modules-available/sysconfignew/templates/module-editor.html269
6 files changed, 621 insertions, 0 deletions
diff --git a/modules-available/sysconfignew/config.json b/modules-available/sysconfignew/config.json
new file mode 100644
index 00000000..4da67ef8
--- /dev/null
+++ b/modules-available/sysconfignew/config.json
@@ -0,0 +1,3 @@
+{
+ "enabled":"true"
+}
diff --git a/modules-available/sysconfignew/lang/en/module.json b/modules-available/sysconfignew/lang/en/module.json
new file mode 100644
index 00000000..3ec89616
--- /dev/null
+++ b/modules-available/sysconfignew/lang/en/module.json
@@ -0,0 +1,23 @@
+{
+ "lang_back": "Back",
+ "lang_cancel": "Cancel",
+ "lang_cannotOpen": "could no be opened",
+ "lang_changeLink": "Change link",
+ "lang_compilingIpxe": "Compiling iPXE",
+ "lang_configName": "Name",
+ "lang_configsDescription": "Here it is possible to create a system configuration by choosing the desired modules.",
+ "lang_configurations": "Configurations",
+ "lang_create": "Create",
+ "lang_edit": "Edit",
+ "lang_file": "File",
+ "lang_leavingMessage": "You have unsaved changes on your module.",
+ "lang_loading": "Loading",
+ "lang_modules": "Modules",
+ "lang_modulesDescription": "Here it is possible to create a system module through an editor.",
+ "lang_name": "Name",
+ "lang_new": "New",
+ "lang_newConfig": "New Config",
+ "lang_newModule": "New Module",
+ "lang_remove": "Remove",
+ "lang_save": "Save"
+} \ No newline at end of file
diff --git a/modules-available/sysconfignew/lang/pt/module.json b/modules-available/sysconfignew/lang/pt/module.json
new file mode 100644
index 00000000..af0d7ad7
--- /dev/null
+++ b/modules-available/sysconfignew/lang/pt/module.json
@@ -0,0 +1,23 @@
+{
+ "lang_back": "Voltar",
+ "lang_cancel": "Cancelar",
+ "lang_cannotOpen": "n\u00e3o p\u00f4de ser aberto",
+ "lang_changeLink": "Mudar link",
+ "lang_compilingIpxe": "Compilando iPXE",
+ "lang_configName": "Nome",
+ "lang_configsDescription": "Aqui \u00e9 poss\u00edvel criar uma configura\u00e7\u00e3o do sistema escolhendo os m\u00f3dulos desejados.",
+ "lang_configurations": "Configura\u00e7\u00f5es",
+ "lang_create": "Criar",
+ "lang_edit": "Editar",
+ "lang_file": "Arquivo",
+ "lang_leavingMessage": "Voc\u00ea possui mudan\u00e7as n\u00e3o salvas no seu m\u00f3dulo.",
+ "lang_loading": "Carregando",
+ "lang_modules": "M\u00f3dulos",
+ "lang_modulesDescription": "Aqui \u00e9 poss\u00edvel criar um m\u00f3dulo do sistema atrav\u00e9s de um editor.",
+ "lang_name": "Nome",
+ "lang_new": "Novo",
+ "lang_newConfig": "Nova Configura\u00e7\u00e3o",
+ "lang_newModule": "Novo M\u00f3dulo",
+ "lang_remove": "Remover",
+ "lang_save": "Salvar"
+} \ No newline at end of file
diff --git a/modules-available/sysconfignew/page.inc.php b/modules-available/sysconfignew/page.inc.php
new file mode 100644
index 00000000..105ad6c7
--- /dev/null
+++ b/modules-available/sysconfignew/page.inc.php
@@ -0,0 +1,113 @@
+<?php
+
+class Page_SysConfigNew extends Page
+{
+ // private $tmpath = '/srv/openslx/www/';
+ private $tmpath = '/home/raul/tm-scripts/server';
+ private $tmconfigs;
+ private $tmmodules;
+
+ protected function doPreprocess(){
+ User::load();
+ if (!User::hasPermission('baseconfig_local')) {
+ Message::addError('no-permission');
+ Util::redirect('?do=Main');
+ }
+
+ $this->tmconfigs = $this->tmpath . '/configs';
+ $this->tmmodules = $this->tmpath . '/modules';
+ }
+
+
+ protected function doRender(){
+ $module = $_GET['module'];
+ if(isset($module)){
+ Render::addTemplate('module-editor',array(
+ "module" => $module
+ ));
+ }else{
+ if(is_dir($this->tmpath)){
+ $configs = array();
+ $modules = array();
+
+ foreach($this->listDirectory($this->tmconfigs) as $key => $value)
+ $configs[] = array(
+ "name" => $value
+ );
+
+ foreach($this->listDirectory($this->tmmodules) as $key => $value)
+ $modules[] = array(
+ "name" => $value
+ );
+
+ $data = array(
+ "configs" => $configs,
+ "modules" => $modules
+ );
+ Render::addTemplate('_pagenew',$data);
+ }else{
+ Message::addError('no-tm-scripts');
+ }
+ }
+ }
+
+ protected function doAjax(){
+ $request = $_GET['request'];
+ switch($request){
+ case "module-contents":
+ $path = $this->tmpath . '/modules/' . Request::get('module');
+ $data = $this->getDirContents($path);
+ $json = json_encode($data);
+ print_r($json);
+ break;
+ case "configs":
+ $this->tmconfigs = $this->tmpath . '/configs';
+ $this->tmmodules = $this->tmpath . '/modules';
+ $userModules = $this->listDirectory($this->tmconfigs . '/' . Request::get('config'));
+ $modules = array();
+ foreach($this->listDirectory($this->tmmodules) as $key => $value){
+ $chosen = (in_array($value, $userModules)) ? true : false;
+ $modules[] = array(
+ "name" => $value,
+ "chosen" => $chosen
+ );
+ }
+
+ foreach ($modules as $module) {
+ $class = ($module['chosen']) ? "select-item select-item-selected" : "select-item";
+ $ret .= "<button type='button' class='" . $class . "' onclick='select(this)' >";
+ $ret .= $module['name'];
+ $ret .= "</button>";
+ }
+
+ echo $ret;
+ break;
+ }
+
+ }
+
+ private function getDirContents($path){
+ $ret = array();
+ foreach ($this->listDirectory($path) as $key => $value) {
+ if(is_dir($path . "/" . $value)){
+ $ret["dir_" . $value] = $this->getDirContents($path . "/" . $value);
+ }else{
+ if(is_link($path . "/" . $value)){
+ $ret["link_" . $value] = readlink($path . "/" . $value);
+ }else{
+ if(mime_content_type($path . "/" . $value) == "text/plain"){
+ $ret["file_" . $value] = file_get_contents($path . "/" . $value);
+ }else{
+ $ret["lock_" . $value] = " oops";
+ }
+ }
+ }
+ }
+ return $ret;
+ }
+
+ private function listDirectory($path){
+ return array_diff(scandir($path), array('..', '.'));
+ }
+
+}
diff --git a/modules-available/sysconfignew/templates/_pagenew.html b/modules-available/sysconfignew/templates/_pagenew.html
new file mode 100644
index 00000000..98881ae3
--- /dev/null
+++ b/modules-available/sysconfignew/templates/_pagenew.html
@@ -0,0 +1,190 @@
+<div class="row">
+ <div class="col-md-6">
+ <div class="panel panel-default">
+ <div class="panel-heading" >
+ <div class="panel-title">{{lang_configurations}}</div>
+ </div>
+ <div class="panel-body">
+ {{lang_configsDescription}}
+ </div>
+ <table class="table table-striped">
+ <thead>
+ <th style="width: 70%">{{lang_configName}}</th>
+ <th></th>
+ <th></th>
+ </thead>
+ <tbody>
+ {{#configs}}
+ <tr>
+ <td>{{name}}</td>
+ <td>
+ <button type="button" class="btn btn-xs btn-primary" onclick="loadConfig('{{name}}')" data-toggle="modal" data-target="#edit-modal" >
+ <span class="glyphicon glyphicon-edit" aria-hidden="true"></span>
+ {{lang_edit}}
+ </button>
+ </td>
+ <td>
+ <button type="button" class="btn btn-xs btn-danger">
+ <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
+ {{lang_remove}}
+ </button>
+ </td>
+ </tr>
+ {{/configs}}
+ </tbody>
+ </table>
+ <div class="panel-footer">
+ <button id="new-config-button" type="button" class="btn btn-primary" data-toggle="modal" data-target="#new-config-modal" >
+ <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
+ {{lang_newConfig}}
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class="col-md-6">
+ <div class="panel panel-default">
+ <div class="panel-heading" >
+ <div class="panel-title">{{lang_modules}}</div>
+ </div>
+ <div class="panel-body">
+ {{lang_modulesDescription}}
+ </div>
+ <table class="table table-striped">
+ <thead>
+ <th style="width: 70%">{{lang_configName}}</th>
+ <th></th>
+ <th></th>
+ </thead>
+ <tbody>
+ {{#modules}}
+ <tr>
+ <td>{{name}}</td>
+ <td>
+ <button type="button" class="btn btn-xs btn-primary" onclick="loadModule('{{name}}')" >
+ <span class="glyphicon glyphicon-edit" aria-hidden="true"></span>
+ {{lang_edit}}
+ </button>
+ </td>
+ <td>
+ <button type="button" class="btn btn-xs btn-danger">
+ <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
+ {{lang_remove}}
+ </button>
+ </td>
+ </tr>
+ {{/modules}}
+ </tbody>
+ </table>
+ <div class="panel-footer">
+ <button id="new-module-button" type="button" class="btn btn-primary" data-toggle="modal" data-target="#new-module-modal" >
+ <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
+ {{lang_newModule}}
+ </button>
+ </div>
+ </div>
+ </div>
+</div>
+
+<!-- Generic modal, will have its content changed dynamically -->
+<div class="modal fade" id="edit-modal" tabindex="-1" role="dialog" aria-labelledby="edit-modal-label" aria-hidden="true">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <!-- Header -->
+ <div class="modal-header" id="edit-modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+ <h4 class="modal-title" id="edit-modal-label">{{lang_compilingIpxe}}</h4>
+ </div>
+ <!-- Body -->
+ <div class="modal-body" id="edit-modal-body" style="overflow: auto;">
+ {{lang_loading}} <img src='fonts/loader.gif'/>
+
+ </div>
+ <!-- Footer -->
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">{{lang_cancel}}</button>
+ <button type="button" class="btn btn-primary" disabled="disabled">{{lang_save}}</button>
+ </div>
+ </div>
+ </div>
+</div>
+
+<!-- New config modal -->
+<form action="" method="POST">
+ <div class="modal fade" id="new-config-modal" tabindex="-1" role="dialog" aria-labelledby="new-config-modal-label" aria-hidden="true">
+ <form action="#" method="post">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <!-- Header -->
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+ <h4 class="modal-title" id="new-config-modal-label">{{lang_compilingIpxe}}</h4>
+ </div>
+ <!-- Body -->
+ <div class="modal-body" id="new-config-modal-body" style="overflow: auto;">
+ <div>
+ <label for="new-config-name">{{lang_name}}</label>
+ <input type="text" name="new-config-name" class="form-control">
+ </div>
+ <hr>
+ <div>
+ <label>{{lang_modules}}</label>
+ </div>
+ {{#modules}}
+ <button name="{{name}}" type='button' class='select-item' onclick='select(this)' >{{name}}</button>
+ {{/modules}}
+ </div>
+ <!-- Footer -->
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">{{lang_cancel}}</button>
+ <input type="submit" class="btn btn-primary" value="{{lang_create}}">
+ </div>
+ </div>
+ </div>
+ </form>
+ </div>
+</form>
+<!-- New module modal -->
+<div class="modal fade" id="new-module-modal" tabindex="-1" role="dialog" aria-labelledby="new-module-modal-label" aria-hidden="true">
+ <form action="#" method="post">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <!-- Header -->
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+ <h4 class="modal-title" id="new-module-modal-label">{{lang_compilingIpxe}}</h4>
+ </div>
+ <!-- Body -->
+ <div class="modal-body" id="new-module-modal-body">
+ <textarea class="form-control" style="resize:none"></textarea>
+ </div>
+ <!-- Footer -->
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">{{lang_cancel}}</button>
+ <button type="button" class="btn btn-primary" disabled="disabled">{{lang_save}}</button>
+ </div>
+ </div>
+ </div>
+ </form>
+</div>
+
+
+<script>
+ function loadConfig(config){
+ $.ajax({
+ method: "GET",
+ url: "?do=SysConfig",
+ data: { request:"configs", async: "True", config: config }
+ }).done(function( msg ) {
+ $("#edit-modal-body").html( msg );
+ $("#edit-modal-header").html( '<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> <h4 class="modal-title" id="edit-modal-label">' + config + '</h4>' );
+ });
+ }
+
+ function loadModule(module){
+ window.location = "?do=SysConfig&module=" + module;
+ }
+
+ function select(element){0
+ element.className = (element.className == 'select-item') ? 'select-item select-item-selected' : 'select-item';
+ }
+</script> \ No newline at end of file
diff --git a/modules-available/sysconfignew/templates/module-editor.html b/modules-available/sysconfignew/templates/module-editor.html
new file mode 100644
index 00000000..3ea28bf8
--- /dev/null
+++ b/modules-available/sysconfignew/templates/module-editor.html
@@ -0,0 +1,269 @@
+
+<div class="container">
+ <div class="row">
+ <a href="?do=Sysconfig" style="display:inline-block;margin-bottom: 10px;">{{lang_back}}</a>
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ {{module}}
+ </div>
+ <div class="panel-body">
+ <div class="mod-nav" id="mod-nav">
+
+ </div>
+ <input class="form-control" disabled="disabled" id="editor-header">
+ <textarea class="editor-box" id="mod-editor" onkeyup="changeContent(this);"></textarea>
+ </div>
+ <div class="panel-footer">
+ <button id="new-item-button" type="button" class="btn btn-default" data-toggle="modal" data-target="#item-modal" onclick="cleanModal()" >
+ <span class="glyphicon glyphicon-file" aria-hidden="true"></span>
+ {{lang_new}}
+ </button>
+ <button type="button" class="btn btn-default" onclick="save();">
+ <span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span>
+ {{lang_save}}
+ </button>
+ </div>
+ </div>
+ </div>
+</div>
+
+<!-- New item modal -->
+<div class="modal fade" id="item-modal" tabindex="-1" role="dialog" aria-labelledby="item-modal-label" aria-hidden="true">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <!-- Header -->
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+ <h4 class="modal-title" id="new-config-modal-label">{{lang_new}}</h4>
+ </div>
+ <!-- Body -->
+ <div class="modal-body" id="new-module-modal-body" style="overflow: auto;">
+ <div class="mod-nav" style="height: 250px">
+ <div class="item dir" onclick="clickDir(this)" data-target="#root" data-path="/"><div class="glyphicon glyphicon-folder-close dir-icon" aria-hidden="true" id="root-icon"></div> /</div>
+ <div class="folder" id="root">
+ <div id="dir-nav">
+ </div>
+ </div>
+ </div>
+ <div style="float:left">
+ <input class="form-control" disabled="disabled" id="dir-path" style="width: 250px;margin-left: 20px;" value="/">
+ <br>
+ <div class="btn-group-vertical" role="group" aria-label="..." style="width: 250px;margin-left: 20px;">
+ <button type="button" class="btn btn-default" onclick="switchFileInput('file')">Arquivo de Texto</button>
+ <button type="button" class="btn btn-default" onclick="switchFileInput('upload')">Upload de Arquivo</button>
+ <button type="button" class="btn btn-default" onclick="switchFileInput('folder')">Pasta</button>
+ <button type="button" class="btn btn-default" onclick="switchFileInput('link')">Link</button>
+ </div>
+ <br>
+ <br>
+ <div id="new-file-input" style="width: 250px;margin-left: 20px;">
+ <div class="form-group">
+ <label for="name">Nome do Arquivo</label>
+ <input type="name" class="form-control" id="new-file-data">
+ </div>
+ </div>
+ </div>
+ </div>
+ <!-- Footer -->
+ <div class="modal-footer" >
+ <button type="button" class="btn btn-primary" data-dismiss="modal">{{lang_cancel}}</button>
+ <button type="button" class="btn btn-default" data-dismiss="modal">{{lang_cancel}}</button>
+ </div>
+ </div>
+ </div>
+</div>
+
+<script type="text/javascript">
+
+// Global variables
+var original;
+var module;
+var current;
+var path;
+
+function cleanModal(){
+ $('#dir-path').val("/");
+}
+
+function clickDir(element){
+ var target = element.getAttribute("data-target");
+ target = target.replace(/\./g,"\\.");
+ $(target + "-icon").attr('class',(($(target).css('display') == 'none') ? 'glyphicon glyphicon-folder-open dir-icon' : 'glyphicon glyphicon-folder-close dir-icon' ));
+ $(target).css('display', ($(target).css('display') == 'none') ? 'block' : 'none' );
+ $('#dir-path').val(element.getAttribute("data-path"));
+}
+
+function getFile(obj,file){
+ var folder = file.split("/")[1];
+ for (var property in obj) {
+ if (obj.hasOwnProperty(property)) {
+ if(property.substring(0, 4) == "dir_"){
+ var pname = property.slice(4);
+ if(pname == folder){
+ var ret = getFile(obj[property],file.replace("/" + folder,""));
+ if(ret != "Invalid file")
+ return ret;
+ }
+ }
+ if(property.substring(0, 5) == "file_"){
+ if(property.slice(5) == file.replace("/",""))
+ return obj[property];
+ }
+ }
+ }
+ return 'Invalid file';
+}
+
+function changeFile(obj,file,data){
+ var folder = file.split("/")[1];
+ for (var property in obj) {
+ if (obj.hasOwnProperty(property)) {
+ if(property.substring(0, 4) == "dir_"){
+ var pname = property.slice(4);
+ if(pname == folder){
+ var ret = changeFile(obj[property],file.replace("/" + folder,""),data);
+ if(ret != "")
+ return ret;
+ }
+ }
+ if(property.substring(0, 5) == "file_"){
+ if(property.slice(5) == file.replace("/","")){
+ obj[property] = data;
+ }
+ }
+ }
+ }
+ return "";
+}
+
+function clickItem(element){
+ var id = element.getAttribute("id");
+ var target = id.split("/").pop();
+ document.getElementById('mod-editor').value = getFile(module,id);
+ document.getElementById('editor-header').value = id;
+ current = id;
+}
+
+function clickLock(element){
+ var id = element.getAttribute("id");
+ alert("{{lang_file}}: " + id + " {{lang_cannotOpen}}");
+}
+
+function clickLink(element){
+ var data = element.getAttribute("data-value");
+ var newLink = prompt("{{lang_changeLink}}:",data);
+ if(newLink){
+ element.setAttribute("data-value",newLink);
+ }
+}
+
+function changeContent(element){
+ changeFile(module,current,element.value);
+}
+
+function switchFileInput(type){
+ var html = "";
+ switch(type){
+ case "file":
+ html = "<div class='form-group'><label for='name'>Nome do Arquivo</label><input type='name' class='form-control' id='new-file-data'></div>";
+ break;
+ case 'upload':
+ html = "<div class='form-group'><label for='name'>Arquivo</label><input type='file' class='form-control' id='new-file-data'></div>";
+ break;
+ case 'folder':
+ html = "<div class='form-group'><label for='name'>Nome da Pasta</label><input type='name' class='form-control' id='new-file-data'></div>";
+ break;
+ case 'link':
+ html = "<div class='form-group'><label for='name'>Nome do Link</label><input type='name' class='form-control' id='new-file-data'></div>";
+ break;
+ }
+ document.getElementById('new-file-input').innerHTML = html;
+}
+
+function getContent(obj,path,dirOnly){
+ var folders = "";
+ var files = "";
+ for (var property in obj) {
+ if (obj.hasOwnProperty(property)) {
+ if(property.substring(0, 4) == "dir_"){
+ var pname = property.slice(4);
+ // Create file navigation tree
+ if(!dirOnly){
+ folders += '<div class="item dir" onclick="clickDir(this)" data-target="#' + pname + '" data-path="' + path + pname + '/' + '"><div class="glyphicon glyphicon-folder-close dir-icon" aria-hidden="true" id="' + pname + '-icon"></div> ' + pname + '</div>';
+ folders += '<div class="folder" id="' + pname + '">';
+ folders += getContent(obj[property],path + pname + "/",dirOnly);
+ folders += '</div>';
+ }
+ // Create directory chooser
+ else{
+ folders += '<div class="item dir" onclick="clickDir(this)" data-target="#' + pname + '-dc" data-path="' + path + pname + '/' + '"><div class="glyphicon glyphicon-folder-close dir-icon" aria-hidden="true" id="' + pname + '-dc' + '-icon"></div> ' + pname + '</div>';
+ folders += '<div class="folder" id="' + pname + '-dc' + '">';
+ folders += getContent(obj[property],path + pname + "/",dirOnly);
+ folders += '</div>';
+ }
+ }
+ if(!dirOnly){
+ if(property.substring(0, 5) == "file_"){
+ var pname = property.slice(5);
+ files += '<div class="item" id="' + path + pname + '" onclick="clickItem(this)">' + pname + '</div>';
+ }
+ if(property.substring(0, 5) == "link_"){
+ var pname = property.slice(5);
+ files += '<div class="item item-link" data-value="' + obj[property] + '" onclick="clickLink(this)">'
+ + '<span class="glyphicon glyphicon-link" aria-hidden="true"></span> ' + pname + '</div>';
+ }
+ if(property.substring(0, 5) == "lock_"){
+ var pname = property.slice(5);
+ files += '<div class="item item-lock" id="' + path + pname + '" onclick="clickLock(this)">'
+ + pname + '</div>';
+ }
+ }
+ }
+ }
+ return folders+ files;
+}
+
+function mountNav(dirOnly){
+ document.getElementById((dirOnly) ? 'dir-nav' : 'mod-nav').innerHTML = getContent(module,"/",dirOnly);
+}
+
+function init(){
+ $.ajax({
+ method: "GET",
+ url: "?do=SysConfig&async=true",
+ data: { request:"module-contents", module: "{{module}}" }
+ }).done(function( data ) {
+ if(data != ""){
+ module = JSON.parse(data);
+ original = JSON.parse(data);
+ mountNav(false);
+ mountNav(true);
+ }
+ });
+}
+
+function save(){
+ //send JSON to PHP
+ if(JSON.stringify(original) != JSON.stringify(module)){
+
+ }
+}
+
+window.onbeforeunload = function (e) {
+ if(JSON.stringify(original) != JSON.stringify(module)){
+ var message = "{{lang_leavingMessage}}",
+ e = e || window.event;
+
+ // For IE and Firefox
+ if (e) {
+ e.returnValue = message;
+ }
+
+ // For Safari
+ return message;
+ }
+ return;
+};
+
+init();
+</script> \ No newline at end of file