diff options
author | Simon Rettberg | 2016-05-03 19:03:09 +0200 |
---|---|---|
committer | Simon Rettberg | 2016-05-03 19:03:09 +0200 |
commit | 50404f3b23b7fd6aeae4c9d2f6df0ea25e984e66 (patch) | |
tree | 05e99fdffa696434960d7c77966c0bc36d6339e8 /modules-available/sysconfignew | |
parent | Second half of merge.... (diff) | |
download | slx-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.json | 3 | ||||
-rw-r--r-- | modules-available/sysconfignew/lang/en/module.json | 23 | ||||
-rw-r--r-- | modules-available/sysconfignew/lang/pt/module.json | 23 | ||||
-rw-r--r-- | modules-available/sysconfignew/page.inc.php | 113 | ||||
-rw-r--r-- | modules-available/sysconfignew/templates/_pagenew.html | 190 | ||||
-rw-r--r-- | modules-available/sysconfignew/templates/module-editor.html | 269 |
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">×</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">×</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">×</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">×</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">×</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 |