1
0
Fork 0

Merge pull request #1443 from pixelfed/frontend-ui-refactor

Add Admin Configuration Editor
This commit is contained in:
daniel 2019-06-20 21:06:19 -06:00 committed by GitHub
commit 5896a5103c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 22360 additions and 90 deletions

View File

@ -11,41 +11,79 @@ use App\Util\Lexer\PrettyNumber;
trait AdminSettingsController
{
public function settings(Request $request)
{
return view('admin.settings.home');
}
public function settings(Request $request)
{
return view('admin.settings.home');
}
public function settingsBackups(Request $request)
{
$path = storage_path('app/'.config('app.name'));
$files = is_dir($path) ? new \DirectoryIterator($path) : [];
return view('admin.settings.backups', compact('files'));
}
public function settingsBackups(Request $request)
{
$path = storage_path('app/'.config('app.name'));
$files = is_dir($path) ? new \DirectoryIterator($path) : [];
return view('admin.settings.backups', compact('files'));
}
public function settingsConfig(Request $request)
{
$editor = [];
$config = file_get_contents(base_path('.env'));
return view('admin.settings.config', compact('editor', 'config'));
}
public function settingsConfig(Request $request)
{
$editor = config('pixelfed.admin.env_editor');
$config = !$editor ? false : file_get_contents(base_path('.env'));
$backup = !$editor ? false : (is_file(base_path('.env.backup')) ? file_get_contents(base_path('.env.backup')) : false);
return view('admin.settings.config', compact('editor', 'config', 'backup'));
}
public function settingsMaintenance(Request $request)
{
return view('admin.settings.maintenance');
}
public function settingsConfigStore(Request $request)
{
if(config('pixelfed.admin.env_editor') !== true) {
abort(400);
}
$res = $request->input('res');
public function settingsStorage(Request $request)
{
$storage = [];
return view('admin.settings.storage', compact('storage'));
}
$old = file_get_contents(app()->environmentFilePath());
if(empty($old) || $old != $res) {
$oldFile = fopen(app()->environmentFilePath().'.backup', 'w');
fwrite($oldFile, $old);
fclose($oldFile);
}
$file = fopen(app()->environmentFilePath(), 'w');
fwrite($file, $res);
fclose($file);
Artisan::call('config:cache');
return ['msg' => 200];
}
public function settingsConfigRestore(Request $request)
{
if(config('pixelfed.admin.env_editor') !== true) {
abort(400);
}
$res = file_get_contents(app()->environmentFilePath().'.backup');
if(empty($res)) {
abort(400, 'No backup exists.');
}
$file = fopen(app()->environmentFilePath(), 'w');
fwrite($file, $res);
fclose($file);
Artisan::call('config:cache');
return ['msg' => 200];
}
public function settingsMaintenance(Request $request)
{
return view('admin.settings.maintenance');
}
public function settingsStorage(Request $request)
{
$storage = [];
return view('admin.settings.storage', compact('storage'));
}
public function settingsFeatures(Request $request)
{
return view('admin.settings.features');
}
public function settingsFeatures(Request $request)
{
return view('admin.settings.features');
}
public function settingsHomeStore(Request $request)
{
$this->validate($request, [
@ -57,7 +95,7 @@ trait AdminSettingsController
public function settingsPages(Request $request)
{
$pages = Page::orderByDesc('updated_at')->paginate(10);
$pages = Page::orderByDesc('updated_at')->paginate(10);
return view('admin.pages.home', compact('pages'));
}
@ -66,35 +104,35 @@ trait AdminSettingsController
return view('admin.pages.edit');
}
public function settingsSystem(Request $request)
{
$sys = [
'pixelfed' => config('pixelfed.version'),
'php' => phpversion(),
'laravel' => app()->version(),
];
switch (config('database.default')) {
case 'pgsql':
$sys['database'] = [
'name' => 'Postgres',
'version' => explode(' ', DB::select(DB::raw('select version();'))[0]->version)[1]
];
break;
public function settingsSystem(Request $request)
{
$sys = [
'pixelfed' => config('pixelfed.version'),
'php' => phpversion(),
'laravel' => app()->version(),
];
switch (config('database.default')) {
case 'pgsql':
$sys['database'] = [
'name' => 'Postgres',
'version' => explode(' ', DB::select(DB::raw('select version();'))[0]->version)[1]
];
break;
case 'mysql':
$sys['database'] = [
'name' => 'MySQL',
'version' => DB::select( DB::raw("select version()") )[0]->{'version()'}
];
break;
default:
$sys['database'] = [
'name' => 'Unknown',
'version' => '?'
];
break;
}
return view('admin.settings.system', compact('sys'));
}
case 'mysql':
$sys['database'] = [
'name' => 'MySQL',
'version' => DB::select( DB::raw("select version()") )[0]->{'version()'}
];
break;
default:
$sys['database'] = [
'name' => 'Unknown',
'version' => '?'
];
break;
}
return view('admin.settings.system', compact('sys'));
}
}

View File

@ -274,4 +274,8 @@ return [
'sanitizer' => [
'restrict_html_types' => env('RESTRICT_HTML_TYPES', true)
],
'admin' => [
'env_editor' => env('ADMIN_ENV_EDITOR', false)
],
];

1
public/js/ace.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
public/js/app.js vendored
View File

@ -1 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[3],{"+lRy":function(e,n){},0:function(e,n,t){t("JO1w"),t("+lRy"),t("xWuY"),t("YfGV"),e.exports=t("RvBz")},"8oxB":function(e,n){var t,r,o=e.exports={};function i(){throw new Error("setTimeout has not been defined")}function u(){throw new Error("clearTimeout has not been defined")}function c(e){if(t===setTimeout)return setTimeout(e,0);if((t===i||!t)&&setTimeout)return t=setTimeout,setTimeout(e,0);try{return t(e,0)}catch(n){try{return t.call(null,e,0)}catch(n){return t.call(this,e,0)}}}!function(){try{t="function"==typeof setTimeout?setTimeout:i}catch(e){t=i}try{r="function"==typeof clearTimeout?clearTimeout:u}catch(e){r=u}}();var f,s=[],a=!1,l=-1;function d(){a&&f&&(a=!1,f.length?s=f.concat(s):l=-1,s.length&&w())}function w(){if(!a){var e=c(d);a=!0;for(var n=s.length;n;){for(f=s,s=[];++l<n;)f&&f[l].run();l=-1,n=s.length}f=null,a=!1,function(e){if(r===clearTimeout)return clearTimeout(e);if((r===u||!r)&&clearTimeout)return r=clearTimeout,clearTimeout(e);try{r(e)}catch(n){try{return r.call(null,e)}catch(n){return r.call(this,e)}}}(e)}}function h(e,n){this.fun=e,this.array=n}function p(){}o.nextTick=function(e){var n=new Array(arguments.length-1);if(arguments.length>1)for(var t=1;t<arguments.length;t++)n[t-1]=arguments[t];s.push(new h(e,n)),1!==s.length||a||c(w)},h.prototype.run=function(){this.fun.apply(null,this.array)},o.title="browser",o.browser=!0,o.env={},o.argv=[],o.version="",o.versions={},o.on=p,o.addListener=p,o.once=p,o.off=p,o.removeListener=p,o.removeAllListeners=p,o.emit=p,o.prependListener=p,o.prependOnceListener=p,o.listeners=function(e){return[]},o.binding=function(e){throw new Error("process.binding is not supported")},o.cwd=function(){return"/"},o.chdir=function(e){throw new Error("process.chdir is not supported")},o.umask=function(){return 0}},HijD:function(e,n,t){window._=t("LvDl"),window.Popper=t("8L3F").default,window.pixelfed=window.pixelfed||{},window.$=window.jQuery=t("EVdn"),t("SYky"),window.axios=t("vDqi"),window.axios.defaults.headers.common["X-Requested-With"]="XMLHttpRequest",t("KGuw");var r=document.head.querySelector('meta[name="csrf-token"]');r?window.axios.defaults.headers.common["X-CSRF-TOKEN"]=r.content:console.error("CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token")},JO1w:function(e,n,t){t("HijD")},RvBz:function(e,n){},YfGV:function(e,n){},YuTi:function(e,n){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}},xWuY:function(e,n){},yLpj:function(e,n){var t;t=function(){return this}();try{t=t||new Function("return this")()}catch(e){"object"==typeof window&&(t=window)}e.exports=t}},[[0,0,1]]]);
(window.webpackJsonp=window.webpackJsonp||[]).push([[4],{"+lRy":function(e,n){},0:function(e,n,t){t("JO1w"),t("+lRy"),t("xWuY"),t("YfGV"),e.exports=t("RvBz")},"8oxB":function(e,n){var t,r,o=e.exports={};function i(){throw new Error("setTimeout has not been defined")}function u(){throw new Error("clearTimeout has not been defined")}function c(e){if(t===setTimeout)return setTimeout(e,0);if((t===i||!t)&&setTimeout)return t=setTimeout,setTimeout(e,0);try{return t(e,0)}catch(n){try{return t.call(null,e,0)}catch(n){return t.call(this,e,0)}}}!function(){try{t="function"==typeof setTimeout?setTimeout:i}catch(e){t=i}try{r="function"==typeof clearTimeout?clearTimeout:u}catch(e){r=u}}();var f,s=[],a=!1,l=-1;function d(){a&&f&&(a=!1,f.length?s=f.concat(s):l=-1,s.length&&w())}function w(){if(!a){var e=c(d);a=!0;for(var n=s.length;n;){for(f=s,s=[];++l<n;)f&&f[l].run();l=-1,n=s.length}f=null,a=!1,function(e){if(r===clearTimeout)return clearTimeout(e);if((r===u||!r)&&clearTimeout)return r=clearTimeout,clearTimeout(e);try{r(e)}catch(n){try{return r.call(null,e)}catch(n){return r.call(this,e)}}}(e)}}function h(e,n){this.fun=e,this.array=n}function p(){}o.nextTick=function(e){var n=new Array(arguments.length-1);if(arguments.length>1)for(var t=1;t<arguments.length;t++)n[t-1]=arguments[t];s.push(new h(e,n)),1!==s.length||a||c(w)},h.prototype.run=function(){this.fun.apply(null,this.array)},o.title="browser",o.browser=!0,o.env={},o.argv=[],o.version="",o.versions={},o.on=p,o.addListener=p,o.once=p,o.off=p,o.removeListener=p,o.removeAllListeners=p,o.emit=p,o.prependListener=p,o.prependOnceListener=p,o.listeners=function(e){return[]},o.binding=function(e){throw new Error("process.binding is not supported")},o.cwd=function(){return"/"},o.chdir=function(e){throw new Error("process.chdir is not supported")},o.umask=function(){return 0}},HijD:function(e,n,t){window._=t("LvDl"),window.Popper=t("8L3F").default,window.pixelfed=window.pixelfed||{},window.$=window.jQuery=t("EVdn"),t("SYky"),window.axios=t("vDqi"),window.axios.defaults.headers.common["X-Requested-With"]="XMLHttpRequest",t("KGuw");var r=document.head.querySelector('meta[name="csrf-token"]');r?window.axios.defaults.headers.common["X-CSRF-TOKEN"]=r.content:console.error("CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token")},JO1w:function(e,n,t){t("HijD")},RvBz:function(e,n){},YfGV:function(e,n){},YuTi:function(e,n){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}},xWuY:function(e,n){},yLpj:function(e,n){var t;t=function(){return this}();try{t=t||new Function("return this")()}catch(e){"object"==typeof window&&(t=window)}e.exports=t}},[[0,0,1]]]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
public/js/loops.js vendored

File diff suppressed because one or more lines are too long

1
public/js/mode-dot.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
public/js/quill.js vendored

File diff suppressed because one or more lines are too long

2
public/js/search.js vendored

File diff suppressed because one or more lines are too long

2
public/js/status.js vendored

File diff suppressed because one or more lines are too long

1
public/js/theme-monokai.js vendored Normal file
View File

@ -0,0 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[15],{14:function(e,a,o){e.exports=o("YMO/")},"YMO/":function(e,a,o){(function(e){function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}ace.define("ace/theme/monokai",["require","exports","module","ace/lib/dom"],function(e,a,o){a.isDark=!0,a.cssClass="ace-monokai",a.cssText=".ace-monokai .ace_gutter {background: #2F3129;color: #8F908A}.ace-monokai .ace_print-margin {width: 1px;background: #555651}.ace-monokai {background-color: #272822;color: #F8F8F2}.ace-monokai .ace_cursor {color: #F8F8F0}.ace-monokai .ace_marker-layer .ace_selection {background: #49483E}.ace-monokai.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #272822;}.ace-monokai .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-monokai .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #49483E}.ace-monokai .ace_marker-layer .ace_active-line {background: #202020}.ace-monokai .ace_gutter-active-line {background-color: #272727}.ace-monokai .ace_marker-layer .ace_selected-word {border: 1px solid #49483E}.ace-monokai .ace_invisible {color: #52524d}.ace-monokai .ace_entity.ace_name.ace_tag,.ace-monokai .ace_keyword,.ace-monokai .ace_meta.ace_tag,.ace-monokai .ace_storage {color: #F92672}.ace-monokai .ace_punctuation,.ace-monokai .ace_punctuation.ace_tag {color: #fff}.ace-monokai .ace_constant.ace_character,.ace-monokai .ace_constant.ace_language,.ace-monokai .ace_constant.ace_numeric,.ace-monokai .ace_constant.ace_other {color: #AE81FF}.ace-monokai .ace_invalid {color: #F8F8F0;background-color: #F92672}.ace-monokai .ace_invalid.ace_deprecated {color: #F8F8F0;background-color: #AE81FF}.ace-monokai .ace_support.ace_constant,.ace-monokai .ace_support.ace_function {color: #66D9EF}.ace-monokai .ace_fold {background-color: #A6E22E;border-color: #F8F8F2}.ace-monokai .ace_storage.ace_type,.ace-monokai .ace_support.ace_class,.ace-monokai .ace_support.ace_type {font-style: italic;color: #66D9EF}.ace-monokai .ace_entity.ace_name.ace_function,.ace-monokai .ace_entity.ace_other,.ace-monokai .ace_entity.ace_other.ace_attribute-name,.ace-monokai .ace_variable {color: #A6E22E}.ace-monokai .ace_variable.ace_parameter {font-style: italic;color: #FD971F}.ace-monokai .ace_string {color: #E6DB74}.ace-monokai .ace_comment {color: #75715E}.ace-monokai .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ0FD0ZXBzd/wPAAjVAoxeSgNeAAAAAElFTkSuQmCC) right repeat-y}",e("../lib/dom").importCssString(a.cssText,a.cssClass)}),ace.require(["ace/theme/monokai"],function(c){"object"==o(e)&&"object"==o(a)&&e&&(e.exports=c)})}).call(this,o("YuTi")(e))},YuTi:function(e,a){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}}},[[14,0]]]);

File diff suppressed because one or more lines are too long

2
public/js/vendor.js vendored

File diff suppressed because one or more lines are too long

View File

@ -1,18 +1,23 @@
{
"/js/manifest.js": "/js/manifest.js?id=01c8731923a46c30aaed",
"/js/vendor.js": "/js/vendor.js?id=cb03d3c4fd7d4093f5b1",
"/js/activity.js": "/js/activity.js?id=e9d373d06150ccd77557",
"/js/app.js": "/js/app.js?id=025bc09bbc4e2d1898e3",
"/js/vendor.js": "/js/vendor.js?id=2b3ccf793d7dbf41c3b8",
"/js/ace.js": "/js/ace.js?id=72ae94b2a68487d22caf",
"/js/activity.js": "/js/activity.js?id=7405cc1a22814a5b2a70",
"/js/app.js": "/js/app.js?id=2f034c84c06dbb3e511d",
"/css/app.css": "/css/app.css?id=461b8782fc167f734ffa",
"/css/appdark.css": "/css/appdark.css?id=34cd81dd9c8bc68cfd51",
"/css/landing.css": "/css/landing.css?id=1ea686af4c64df5018fc",
"/js/components.js": "/js/components.js?id=97c7f6876bb4e5c9ffd8",
"/js/compose.js": "/js/compose.js?id=cc26e811c30caa7793dc",
"/js/developers.js": "/js/developers.js?id=4dba6abdc3ae8ec8c222",
"/js/discover.js": "/js/discover.js?id=b9b5d3d054cadf63aed2",
"/js/loops.js": "/js/loops.js?id=d5c7e9d0d6a44553dd0d",
"/js/profile.js": "/js/profile.js?id=03815205b1472e5caf24",
"/js/search.js": "/js/search.js?id=95c893b755e132a1d7e1",
"/js/status.js": "/js/status.js?id=f18eb709c4c4abecf034",
"/js/timeline.js": "/js/timeline.js?id=18063ce62e0e78634c54"
"/css/quill.css": "/css/quill.css?id=81604d62610b0dbffad6",
"/js/components.js": "/js/components.js?id=0b7b6f606e590f4df10f",
"/js/compose.js": "/js/compose.js?id=475dac4628e2d1cb3dc9",
"/js/developers.js": "/js/developers.js?id=e4a227c87d1b09fc2dd9",
"/js/discover.js": "/js/discover.js?id=772fbc6c176aaa9039ec",
"/js/loops.js": "/js/loops.js?id=a2291e15b8b246621b07",
"/js/mode-dot.js": "/js/mode-dot.js?id=3c67c8f827dc52536a4b",
"/js/profile.js": "/js/profile.js?id=fe87d1e6d75323c9f7d9",
"/js/quill.js": "/js/quill.js?id=d2e82cff48024d45384a",
"/js/search.js": "/js/search.js?id=38a3a6a07e3b37a1e444",
"/js/status.js": "/js/status.js?id=8333e903aaf01fc6436d",
"/js/theme-monokai.js": "/js/theme-monokai.js?id=1f7b44b76af99c0b4e38",
"/js/timeline.js": "/js/timeline.js?id=3b2c69ca0262332e6542"
}

21606
resources/assets/js/lib/ace/ace.js vendored Executable file

File diff suppressed because it is too large Load Diff

417
resources/assets/js/lib/ace/mode-dot.js vendored Executable file
View File

@ -0,0 +1,417 @@
ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"], function(require, exports, module) {
"use strict";
var Range = require("../range").Range;
var MatchingBraceOutdent = function() {};
(function() {
this.checkOutdent = function(line, input) {
if (! /^\s+$/.test(line))
return false;
return /^\s*\}/.test(input);
};
this.autoOutdent = function(doc, row) {
var line = doc.getLine(row);
var match = line.match(/^(\s*\})/);
if (!match) return 0;
var column = match[1].length;
var openBracePos = doc.findMatchingBracket({row: row, column: column});
if (!openBracePos || openBracePos.row == row) return 0;
var indent = this.$getIndent(doc.getLine(openBracePos.row));
doc.replace(new Range(row, 0, row, column-1), indent);
};
this.$getIndent = function(line) {
return line.match(/^\s*/)[0];
};
}).call(MatchingBraceOutdent.prototype);
exports.MatchingBraceOutdent = MatchingBraceOutdent;
});
ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) {
"use strict";
var oop = require("../lib/oop");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
var DocCommentHighlightRules = function() {
this.$rules = {
"start" : [ {
token : "comment.doc.tag",
regex : "@[\\w\\d_]+" // TODO: fix email addresses
},
DocCommentHighlightRules.getTagRule(),
{
defaultToken : "comment.doc",
caseInsensitive: true
}]
};
};
oop.inherits(DocCommentHighlightRules, TextHighlightRules);
DocCommentHighlightRules.getTagRule = function(start) {
return {
token : "comment.doc.tag.storage.type",
regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b"
};
};
DocCommentHighlightRules.getStartRule = function(start) {
return {
token : "comment.doc", // doc comment
regex : "\\/\\*(?=\\*)",
next : start
};
};
DocCommentHighlightRules.getEndRule = function (start) {
return {
token : "comment.doc", // closing comment
regex : "\\*\\/",
next : start
};
};
exports.DocCommentHighlightRules = DocCommentHighlightRules;
});
ace.define("ace/mode/dot_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules","ace/mode/doc_comment_highlight_rules"], function(require, exports, module) {
"use strict";
var oop = require("../lib/oop");
var lang = require("../lib/lang");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
var DotHighlightRules = function() {
var keywords = lang.arrayToMap(
("strict|node|edge|graph|digraph|subgraph").split("|")
);
var attributes = lang.arrayToMap(
("damping|k|url|area|arrowhead|arrowsize|arrowtail|aspect|bb|bgcolor|center|charset|clusterrank|color|colorscheme|comment|compound|concentrate|constraint|decorate|defaultdist|dim|dimen|dir|diredgeconstraints|distortion|dpi|edgeurl|edgehref|edgetarget|edgetooltip|epsilon|esep|fillcolor|fixedsize|fontcolor|fontname|fontnames|fontpath|fontsize|forcelabels|gradientangle|group|headurl|head_lp|headclip|headhref|headlabel|headport|headtarget|headtooltip|height|href|id|image|imagepath|imagescale|label|labelurl|label_scheme|labelangle|labeldistance|labelfloat|labelfontcolor|labelfontname|labelfontsize|labelhref|labeljust|labelloc|labeltarget|labeltooltip|landscape|layer|layerlistsep|layers|layerselect|layersep|layout|len|levels|levelsgap|lhead|lheight|lp|ltail|lwidth|margin|maxiter|mclimit|mindist|minlen|mode|model|mosek|nodesep|nojustify|normalize|nslimit|nslimit1|ordering|orientation|outputorder|overlap|overlap_scaling|pack|packmode|pad|page|pagedir|pencolor|penwidth|peripheries|pin|pos|quadtree|quantum|rank|rankdir|ranksep|ratio|rects|regular|remincross|repulsiveforce|resolution|root|rotate|rotation|samehead|sametail|samplepoints|scale|searchsize|sep|shape|shapefile|showboxes|sides|size|skew|smoothing|sortv|splines|start|style|stylesheet|tailurl|tail_lp|tailclip|tailhref|taillabel|tailport|tailtarget|tailtooltip|target|tooltip|truecolor|vertices|viewport|voro_margin|weight|width|xlabel|xlp|z").split("|")
);
this.$rules = {
"start" : [
{
token : "comment",
regex : /\/\/.*$/
}, {
token : "comment",
regex : /#.*$/
}, {
token : "comment", // multi line comment
merge : true,
regex : /\/\*/,
next : "comment"
}, {
token : "string",
regex : "'(?=.)",
next : "qstring"
}, {
token : "string",
regex : '"(?=.)',
next : "qqstring"
}, {
token : "constant.numeric",
regex : /[+\-]?\d+(?:(?:\.\d*)?(?:[eE][+\-]?\d+)?)?\b/
}, {
token : "keyword.operator",
regex : /\+|=|\->/
}, {
token : "punctuation.operator",
regex : /,|;/
}, {
token : "paren.lparen",
regex : /[\[{]/
}, {
token : "paren.rparen",
regex : /[\]}]/
}, {
token: "comment",
regex: /^#!.*$/
}, {
token: function(value) {
if (keywords.hasOwnProperty(value.toLowerCase())) {
return "keyword";
}
else if (attributes.hasOwnProperty(value.toLowerCase())) {
return "variable";
}
else {
return "text";
}
},
regex: "\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"
}
],
"comment" : [
{
token : "comment", // closing comment
regex : "\\*\\/",
next : "start"
}, {
defaultToken : "comment"
}
],
"qqstring" : [
{
token : "string",
regex : '[^"\\\\]+',
merge : true
}, {
token : "string",
regex : "\\\\$",
next : "qqstring",
merge : true
}, {
token : "string",
regex : '"|$',
next : "start",
merge : true
}
],
"qstring" : [
{
token : "string",
regex : "[^'\\\\]+",
merge : true
}, {
token : "string",
regex : "\\\\$",
next : "qstring",
merge : true
}, {
token : "string",
regex : "'|$",
next : "start",
merge : true
}
]
};
};
oop.inherits(DotHighlightRules, TextHighlightRules);
exports.DotHighlightRules = DotHighlightRules;
});
ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"], function(require, exports, module) {
"use strict";
var oop = require("../../lib/oop");
var Range = require("../../range").Range;
var BaseFoldMode = require("./fold_mode").FoldMode;
var FoldMode = exports.FoldMode = function(commentRegex) {
if (commentRegex) {
this.foldingStartMarker = new RegExp(
this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
);
this.foldingStopMarker = new RegExp(
this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
);
}
};
oop.inherits(FoldMode, BaseFoldMode);
(function() {
this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
this._getFoldWidgetBase = this.getFoldWidget;
this.getFoldWidget = function(session, foldStyle, row) {
var line = session.getLine(row);
if (this.singleLineBlockCommentRe.test(line)) {
if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
return "";
}
var fw = this._getFoldWidgetBase(session, foldStyle, row);
if (!fw && this.startRegionRe.test(line))
return "start"; // lineCommentRegionStart
return fw;
};
this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
var line = session.getLine(row);
if (this.startRegionRe.test(line))
return this.getCommentRegionBlock(session, line, row);
var match = line.match(this.foldingStartMarker);
if (match) {
var i = match.index;
if (match[1])
return this.openingBracketBlock(session, match[1], row, i);
var range = session.getCommentFoldRange(row, i + match[0].length, 1);
if (range && !range.isMultiLine()) {
if (forceMultiline) {
range = this.getSectionRange(session, row);
} else if (foldStyle != "all")
range = null;
}
return range;
}
if (foldStyle === "markbegin")
return;
var match = line.match(this.foldingStopMarker);
if (match) {
var i = match.index + match[0].length;
if (match[1])
return this.closingBracketBlock(session, match[1], row, i);
return session.getCommentFoldRange(row, i, -1);
}
};
this.getSectionRange = function(session, row) {
var line = session.getLine(row);
var startIndent = line.search(/\S/);
var startRow = row;
var startColumn = line.length;
row = row + 1;
var endRow = row;
var maxRow = session.getLength();
while (++row < maxRow) {
line = session.getLine(row);
var indent = line.search(/\S/);
if (indent === -1)
continue;
if (startIndent > indent)
break;
var subRange = this.getFoldWidgetRange(session, "all", row);
if (subRange) {
if (subRange.start.row <= startRow) {
break;
} else if (subRange.isMultiLine()) {
row = subRange.end.row;
} else if (startIndent == indent) {
break;
}
}
endRow = row;
}
return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
};
this.getCommentRegionBlock = function(session, line, row) {
var startColumn = line.search(/\s*$/);
var maxRow = session.getLength();
var startRow = row;
var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
var depth = 1;
while (++row < maxRow) {
line = session.getLine(row);
var m = re.exec(line);
if (!m) continue;
if (m[1]) depth--;
else depth++;
if (!depth) break;
}
var endRow = row;
if (endRow > startRow) {
return new Range(startRow, startColumn, endRow, line.length);
}
};
}).call(FoldMode.prototype);
});
ace.define("ace/mode/dot",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/matching_brace_outdent","ace/mode/dot_highlight_rules","ace/mode/folding/cstyle"], function(require, exports, module) {
"use strict";
var oop = require("../lib/oop");
var TextMode = require("./text").Mode;
var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
var DotHighlightRules = require("./dot_highlight_rules").DotHighlightRules;
var DotFoldMode = require("./folding/cstyle").FoldMode;
var Mode = function() {
this.HighlightRules = DotHighlightRules;
this.$outdent = new MatchingBraceOutdent();
this.foldingRules = new DotFoldMode();
this.$behaviour = this.$defaultBehaviour;
};
oop.inherits(Mode, TextMode);
(function() {
this.lineCommentStart = ["//", "#"];
this.blockComment = {start: "/*", end: "*/"};
this.getNextLineIndent = function(state, line, tab) {
var indent = this.$getIndent(line);
var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
var tokens = tokenizedLine.tokens;
var endState = tokenizedLine.state;
if (tokens.length && tokens[tokens.length-1].type == "comment") {
return indent;
}
if (state == "start") {
var match = line.match(/^.*(?:\bcase\b.*:|[\{\(\[])\s*$/);
if (match) {
indent += tab;
}
}
return indent;
};
this.checkOutdent = function(state, line, input) {
return this.$outdent.checkOutdent(line, input);
};
this.autoOutdent = function(state, doc, row) {
this.$outdent.autoOutdent(doc, row);
};
this.$id = "ace/mode/dot";
}).call(Mode.prototype);
exports.Mode = Mode;
}); (function() {
ace.require(["ace/mode/dot"], function(m) {
if (typeof module == "object" && typeof exports == "object" && module) {
module.exports = m;
}
});
})();

112
resources/assets/js/lib/ace/theme-monokai.js vendored Executable file
View File

@ -0,0 +1,112 @@
ace.define("ace/theme/monokai",["require","exports","module","ace/lib/dom"], function(require, exports, module) {
exports.isDark = true;
exports.cssClass = "ace-monokai";
exports.cssText = ".ace-monokai .ace_gutter {\
background: #2F3129;\
color: #8F908A\
}\
.ace-monokai .ace_print-margin {\
width: 1px;\
background: #555651\
}\
.ace-monokai {\
background-color: #272822;\
color: #F8F8F2\
}\
.ace-monokai .ace_cursor {\
color: #F8F8F0\
}\
.ace-monokai .ace_marker-layer .ace_selection {\
background: #49483E\
}\
.ace-monokai.ace_multiselect .ace_selection.ace_start {\
box-shadow: 0 0 3px 0px #272822;\
}\
.ace-monokai .ace_marker-layer .ace_step {\
background: rgb(102, 82, 0)\
}\
.ace-monokai .ace_marker-layer .ace_bracket {\
margin: -1px 0 0 -1px;\
border: 1px solid #49483E\
}\
.ace-monokai .ace_marker-layer .ace_active-line {\
background: #202020\
}\
.ace-monokai .ace_gutter-active-line {\
background-color: #272727\
}\
.ace-monokai .ace_marker-layer .ace_selected-word {\
border: 1px solid #49483E\
}\
.ace-monokai .ace_invisible {\
color: #52524d\
}\
.ace-monokai .ace_entity.ace_name.ace_tag,\
.ace-monokai .ace_keyword,\
.ace-monokai .ace_meta.ace_tag,\
.ace-monokai .ace_storage {\
color: #F92672\
}\
.ace-monokai .ace_punctuation,\
.ace-monokai .ace_punctuation.ace_tag {\
color: #fff\
}\
.ace-monokai .ace_constant.ace_character,\
.ace-monokai .ace_constant.ace_language,\
.ace-monokai .ace_constant.ace_numeric,\
.ace-monokai .ace_constant.ace_other {\
color: #AE81FF\
}\
.ace-monokai .ace_invalid {\
color: #F8F8F0;\
background-color: #F92672\
}\
.ace-monokai .ace_invalid.ace_deprecated {\
color: #F8F8F0;\
background-color: #AE81FF\
}\
.ace-monokai .ace_support.ace_constant,\
.ace-monokai .ace_support.ace_function {\
color: #66D9EF\
}\
.ace-monokai .ace_fold {\
background-color: #A6E22E;\
border-color: #F8F8F2\
}\
.ace-monokai .ace_storage.ace_type,\
.ace-monokai .ace_support.ace_class,\
.ace-monokai .ace_support.ace_type {\
font-style: italic;\
color: #66D9EF\
}\
.ace-monokai .ace_entity.ace_name.ace_function,\
.ace-monokai .ace_entity.ace_other,\
.ace-monokai .ace_entity.ace_other.ace_attribute-name,\
.ace-monokai .ace_variable {\
color: #A6E22E\
}\
.ace-monokai .ace_variable.ace_parameter {\
font-style: italic;\
color: #FD971F\
}\
.ace-monokai .ace_string {\
color: #E6DB74\
}\
.ace-monokai .ace_comment {\
color: #75715E\
}\
.ace-monokai .ace_indent-guide {\
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ0FD0ZXBzd/wPAAjVAoxeSgNeAAAAAElFTkSuQmCC) right repeat-y\
}";
var dom = require("../lib/dom");
dom.importCssString(exports.cssText, exports.cssClass);
}); (function() {
ace.require(["ace/theme/monokai"], function(m) {
if (typeof module == "object" && typeof exports == "object" && module) {
module.exports = m;
}
});
})();

View File

@ -5,10 +5,90 @@
@section('section')
<div class="title">
<h3 class="font-weight-bold">Configuration Settings</h3>
@if($editor == false)
<hr>
<div class="card bg-light shadow-none rounded-0">
<div class="card-body text-center py-5">
<p class="lead text-muted font-weight-bold">Configuration Editor is disabled</p>
<p class="mb-0">To enable it, add <code>ADMIN_ENV_EDITOR=true</code> to <code>.env</code><br>then run <code>php artisan config:cache</code></p>
</div>
</div>
@else
<p class="lead">Edit configuration settings</p>
<p class="alert alert-warning">
<strong>Warning:</strong> If you have opcache enabled, you may need to restart php for the changes to take effect.
</p>
</div>
<hr>
<p class="alert alert-warning">
<strong>Feature Unavailable:</strong> This feature will be released in a future version.
</p>
@endsection
<div>
<div id="editor">{{$config}}</div>
<hr>
<div class="d-flex justify-content-between px-3">
@if($backup)
<button class="btn btn-outline-secondary font-weight-bold py-1 btn-restore">Restore backup .env</button>
@else
<div></div>
@endif
<button class="btn btn-primary font-weight-bold py-1 btn-save">Save</button>
</div>
</div>
@endif
@endsection
@if($editor == true)
@push('scripts')
<script src="{{mix('js/ace.js')}}"></script>
<script>
let editor = ace.edit("editor");
editor.session.setUseWrapMode(true);
editor.setTheme("ace/theme/monokai");
editor.session.setMode("ace/mode/dot");
$('.btn-restore').on('click', function(e) {
e.preventDefault();
let confirm = window.confirm('Are you sure you want to restore your backup .env?');
if(!confirm) {
swal('Cancelled', 'You have cancelled the .env backup restore.', 'warning');
return;
}
axios.post('/i/admin/settings/config/restore', {
}).then(res => {
swal('Success', 'Configuration successfully restored!', 'success');
setTimeout(function() {
window.location.href = window.location.href;
}, 3000);
});
})
$('.btn-save').on('click', function(e) {
e.preventDefault();
let confirm = window.confirm('Are you sure you want to overwrite your current .env?');
if(!confirm) {
swal('Cancelled', 'You have cancelled the .env update.', 'warning');
return;
}
axios.post('/i/admin/settings/config', {
res: editor.getValue()
}).then(res => {
swal('Success', 'Configuration successfully updated!', 'success');
setTimeout(function() {
window.location.href = window.location.href;
}, 3000);
});
})
</script>
@endpush
@push('styles')
<style type="text/css" media="screen">
#editor {
display: block;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
min-height: 400px;
}
</style>
@endpush
@endif

View File

@ -23,6 +23,8 @@ Route::domain(config('pixelfed.domain.admin'))->prefix('i/admin')->group(functio
Route::get('settings', 'AdminController@settings')->name('admin.settings');
Route::post('settings', 'AdminController@settingsHomeStore');
Route::get('settings/config', 'AdminController@settingsConfig')->name('admin.settings.config');
Route::post('settings/config', 'AdminController@settingsConfigStore');
Route::post('settings/config/restore', 'AdminController@settingsConfigRestore');
Route::get('settings/features', 'AdminController@settingsFeatures')->name('admin.settings.features');
Route::get('settings/pages', 'AdminController@settingsPages')->name('admin.settings.pages');
Route::get('settings/pages/edit', 'PageController@edit')->name('admin.settings.pages.edit');

3
webpack.mix.js vendored
View File

@ -25,6 +25,9 @@ mix.js('resources/assets/js/app.js', 'public/js')
.js('resources/assets/js/developers.js', 'public/js')
.js('resources/assets/js/loops.js', 'public/js')
.js('resources/assets/js/quill.js', 'public/js')
.js('resources/assets/js/lib/ace/ace.js', 'public/js')
.js('resources/assets/js/lib/ace/mode-dot.js', 'public/js')
.js('resources/assets/js/lib/ace/theme-monokai.js', 'public/js')
// .js('resources/assets/js/embed.js', 'public')
// .js('resources/assets/js/direct.js', 'public/js')
.extract([