update
parent
e3ac3a6a4b
commit
85aea63307
|
@ -66,7 +66,10 @@ func Execute(w http.ResponseWriter, r *http.Request) (int, error) {
|
|||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write([]byte("{}"))
|
||||
go commands.Execute()
|
||||
|
||||
if r.Header.Get("X-Save-Mode") == "Publish" {
|
||||
go commands.Execute()
|
||||
}
|
||||
} else {
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
log.Print(err)
|
||||
|
|
|
@ -16,16 +16,42 @@ func Pretty(content []byte) (interface{}, error) {
|
|||
return []string{}, err
|
||||
}
|
||||
|
||||
return rawToPretty(front, ""), nil
|
||||
return rawToPretty(front, "", ""), nil
|
||||
}
|
||||
|
||||
type frontmatter struct {
|
||||
Name string
|
||||
Content interface{}
|
||||
SubContent bool
|
||||
Name string
|
||||
Content interface{}
|
||||
Parent string
|
||||
Type string
|
||||
}
|
||||
|
||||
func rawToPretty(config interface{}, master string) interface{} {
|
||||
func rawToPretty(config interface{}, master string, parent string) interface{} {
|
||||
if utils.IsSlice(config) {
|
||||
settings := make([]interface{}, len(config.([]interface{})))
|
||||
|
||||
for index, element := range config.([]interface{}) {
|
||||
c := new(frontmatter)
|
||||
c.Name = master
|
||||
c.Parent = parent
|
||||
|
||||
if utils.IsMap(element) {
|
||||
c.Type = "object"
|
||||
c.Content = rawToPretty(element, c.Name, "object")
|
||||
} else if utils.IsSlice(element) {
|
||||
c.Type = "array"
|
||||
c.Content = rawToPretty(element, c.Name, "array")
|
||||
} else {
|
||||
c.Type = "text"
|
||||
c.Content = element
|
||||
}
|
||||
|
||||
settings[index] = c
|
||||
}
|
||||
|
||||
return settings
|
||||
}
|
||||
|
||||
var mapsNames []string
|
||||
var stringsNames []string
|
||||
|
||||
|
@ -46,14 +72,18 @@ func rawToPretty(config interface{}, master string) interface{} {
|
|||
for index := range names {
|
||||
c := new(frontmatter)
|
||||
c.Name = names[index]
|
||||
c.SubContent = false
|
||||
c.Parent = parent
|
||||
|
||||
i := config.(map[string]interface{})[names[index]]
|
||||
|
||||
if utils.IsMap(i) {
|
||||
c.Content = rawToPretty(i, c.Name)
|
||||
c.SubContent = true
|
||||
c.Type = "object"
|
||||
c.Content = rawToPretty(i, c.Name, "object")
|
||||
} else if utils.IsSlice(i) {
|
||||
c.Type = "array"
|
||||
c.Content = rawToPretty(i, c.Name, "array")
|
||||
} else {
|
||||
c.Type = "text"
|
||||
c.Content = i
|
||||
}
|
||||
|
||||
|
|
|
@ -11,15 +11,13 @@ header {
|
|||
left: 0;
|
||||
height: 3em;
|
||||
width: 100%;
|
||||
background-color: #EEE;
|
||||
background-color: #263238;
|
||||
padding: 0 2em;
|
||||
box-sizing: border-box;
|
||||
z-index: 999;
|
||||
color: #555;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
header nav {}
|
||||
|
||||
header nav ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
@ -63,7 +61,49 @@ header nav ul li a:hover {
|
|||
|
||||
main {
|
||||
top: 3em;
|
||||
position: relative;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
.container {
|
||||
box-sizing: border-box;
|
||||
top: 3em;
|
||||
height: auto;
|
||||
max-height: 100%;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.container.left {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
width: 25%;
|
||||
background-color: #37474F;
|
||||
overflow: auto;
|
||||
color: #eee;
|
||||
padding: 1.5em 1.5em;
|
||||
}
|
||||
|
||||
.container.main {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
width: 75%;
|
||||
overflow: auto;
|
||||
padding: 0;
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
|
||||
.container *:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.container.main textarea {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 2em 5em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.content {
|
||||
|
@ -75,16 +115,15 @@ main {
|
|||
textarea {
|
||||
width: 100%;
|
||||
min-height: 50em;
|
||||
resize: vertical;
|
||||
border: 0;
|
||||
resize: vertical;
|
||||
box-sizing: content-box;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
|
||||
/* FORMS */
|
||||
|
||||
form {}
|
||||
|
||||
form input {
|
||||
color: rgba(0, 0, 0, 0.41);
|
||||
width: 15em;
|
||||
|
@ -92,6 +131,7 @@ form input {
|
|||
margin: .5em 0;
|
||||
border: 1px solid #fff;
|
||||
transition: .5s ease-out all;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
form input:focus {
|
||||
|
@ -103,4 +143,69 @@ form input:focus {
|
|||
form label {
|
||||
width: 10.5em;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
form fieldset {
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
form legend {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
form .container.left input {
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
border-radius: 5px;
|
||||
padding: .5em 1em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
form .container.left input:focus {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
form .container.left label {}
|
||||
|
||||
form .container.left legend {
|
||||
font-size: 1em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.action-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 75%;
|
||||
background-color: #455A64;
|
||||
height: 3em;
|
||||
display: flex;
|
||||
padding: 0.5em 1em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.action-bar .left {
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.action-bar *:last-child {
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
button, input[type="submit"] {
|
||||
border: 0;
|
||||
color: #fff;
|
||||
margin: 0;
|
||||
padding: .5em 1em;
|
||||
border-radius: 10px;
|
||||
font-size: .9em;
|
||||
width: auto;
|
||||
line-height: 1em;
|
||||
background-color: #BBB;
|
||||
}
|
||||
|
||||
button.default, input[type="submit"].default {
|
||||
background-color: #2196F3;
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
/* perfect-scrollbar v0.6.5 */
|
||||
|
||||
.ps-container {
|
||||
-ms-touch-action: none;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
.ps-container.ps-active-x > .ps-scrollbar-x-rail, .ps-container.ps-active-y > .ps-scrollbar-y-rail {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ps-container.ps-in-scrolling {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.ps-container.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail {
|
||||
background-color: #eee;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.ps-container.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x {
|
||||
background-color: #999;
|
||||
}
|
||||
|
||||
.ps-container.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail {
|
||||
background-color: #eee;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.ps-container.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y {
|
||||
background-color: #999;
|
||||
}
|
||||
|
||||
.ps-container > .ps-scrollbar-x-rail {
|
||||
display: none;
|
||||
position: absolute;
|
||||
/* please don't change 'position' */
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
-ms-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
opacity: 0;
|
||||
-webkit-transition: background-color .2s linear, opacity .2s linear;
|
||||
-moz-transition: background-color .2s linear, opacity .2s linear;
|
||||
-o-transition: background-color .2s linear, opacity .2s linear;
|
||||
transition: background-color .2s linear, opacity .2s linear;
|
||||
bottom: 3px;
|
||||
/* there must be 'bottom' for ps-scrollbar-x-rail */
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
.ps-container > .ps-scrollbar-x-rail > .ps-scrollbar-x {
|
||||
position: absolute;
|
||||
/* please don't change 'position' */
|
||||
background-color: #aaa;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
-ms-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
-webkit-transition: background-color .2s linear;
|
||||
-moz-transition: background-color .2s linear;
|
||||
-o-transition: background-color .2s linear;
|
||||
transition: background-color .2s linear;
|
||||
bottom: 0;
|
||||
/* there must be 'bottom' for ps-scrollbar-x */
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
.ps-container > .ps-scrollbar-y-rail {
|
||||
display: none;
|
||||
position: absolute;
|
||||
/* please don't change 'position' */
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
-ms-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
opacity: 0;
|
||||
-webkit-transition: background-color .2s linear, opacity .2s linear;
|
||||
-moz-transition: background-color .2s linear, opacity .2s linear;
|
||||
-o-transition: background-color .2s linear, opacity .2s linear;
|
||||
transition: background-color .2s linear, opacity .2s linear;
|
||||
right: 3px;
|
||||
/* there must be 'right' for ps-scrollbar-y-rail */
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.ps-container > .ps-scrollbar-y-rail > .ps-scrollbar-y {
|
||||
position: absolute;
|
||||
/* please don't change 'position' */
|
||||
background-color: #aaa;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
-ms-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
-webkit-transition: background-color .2s linear;
|
||||
-moz-transition: background-color .2s linear;
|
||||
-o-transition: background-color .2s linear;
|
||||
transition: background-color .2s linear;
|
||||
right: 0;
|
||||
/* there must be 'right' for ps-scrollbar-y */
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.ps-container:hover.ps-in-scrolling {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.ps-container:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail {
|
||||
background-color: #eee;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.ps-container:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x {
|
||||
background-color: #999;
|
||||
}
|
||||
|
||||
.ps-container:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail {
|
||||
background-color: #eee;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.ps-container:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y {
|
||||
background-color: #999;
|
||||
}
|
||||
|
||||
.ps-container:hover > .ps-scrollbar-x-rail, .ps-container:hover > .ps-scrollbar-y-rail {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.ps-container:hover > .ps-scrollbar-x-rail:hover {
|
||||
background-color: #eee;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.ps-container:hover > .ps-scrollbar-x-rail:hover > .ps-scrollbar-x {
|
||||
background-color: #999;
|
||||
}
|
||||
|
||||
.ps-container:hover > .ps-scrollbar-y-rail:hover {
|
||||
background-color: #eee;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.ps-container:hover > .ps-scrollbar-y-rail:hover > .ps-scrollbar-y {
|
||||
background-color: #999;
|
||||
}
|
|
@ -1,18 +1,21 @@
|
|||
$(document).ready(function() {
|
||||
$('.scroll').perfectScrollbar();
|
||||
|
||||
|
||||
$('form').submit(function(event) {
|
||||
var data = JSON.stringify($(this).serializeField())
|
||||
var url = $(this).attr('action')
|
||||
var action = $(this).find("input[type=submit]:focus").val();
|
||||
|
||||
console.log(data)
|
||||
console.log(data);
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: url,
|
||||
data: data,
|
||||
beforeSend: function(xhr) {
|
||||
// add publish and save
|
||||
xhr.setRequestHeader('X-Save-Mode', 'publish');
|
||||
}
|
||||
xhr.setRequestHeader('X-Save-Mode', action);
|
||||
},
|
||||
dataType: 'json',
|
||||
encode: true,
|
||||
}).done(function(data) {
|
||||
|
@ -47,12 +50,20 @@ $(document).ready(function() {
|
|||
$.fn.serializeField = function() {
|
||||
var result = {};
|
||||
this.each(function() {
|
||||
$(this).find("> *").each(function() {
|
||||
$(this).find(".container > *").each(function() {
|
||||
var $this = $(this);
|
||||
var name = $this.attr("name");
|
||||
|
||||
if ($this.is("fieldset") && name) {
|
||||
result[name] = $this.serializeField();
|
||||
if ($this.attr("type") == "array") {
|
||||
result[this.name] = [];
|
||||
|
||||
$.each($this.serializeArray(), function() {
|
||||
result[this.name].push(this.value);
|
||||
});
|
||||
} else {
|
||||
result[name] = $this.serializeField();
|
||||
}
|
||||
} else {
|
||||
$.each($this.serializeArray(), function() {
|
||||
result[this.name] = this.value;
|
||||
|
|
|
@ -12,9 +12,11 @@
|
|||
|
||||
<link rel="stylesheet" href="/admin/static/css/normalize.css">
|
||||
<link rel="stylesheet" href="/admin/static/css/main.css">
|
||||
<link rel="stylesheet" href="/admin/static/css/scrollbar.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
|
||||
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.perfect-scrollbar/0.6.5/js/min/perfect-scrollbar.jquery.min.js"></script>
|
||||
<script src="/admin/static/js/app.js"></script>
|
||||
</head>
|
||||
|
||||
|
@ -38,4 +40,4 @@
|
|||
</footer>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -1,14 +1,24 @@
|
|||
{{ define "content" }} {{ with .Body }}
|
||||
|
||||
<div class="content">
|
||||
<h1>Editing {{ .Name }}</h1>
|
||||
|
||||
<form method="POST" action="">
|
||||
{{ template "frontmatter" .FrontMatter }}
|
||||
<textarea name="content">{{ .Content }}</textarea>
|
||||
<input type="submit" value="Save">
|
||||
</form>
|
||||
<form method="POST" action="">
|
||||
|
||||
<div class="container left scroll">
|
||||
<h2>Metadata</h2>
|
||||
{{ template "frontmatter" .FrontMatter }}
|
||||
</div>
|
||||
|
||||
{{ end }} {{ end }}
|
||||
<div class="container main">
|
||||
<textarea name="content" class="scroll">
|
||||
{{ .Content }}
|
||||
</textarea>
|
||||
</div>
|
||||
|
||||
<div class="action-bar">
|
||||
<button id="preview" class="left">Preview</button>
|
||||
<input type="submit" value="Save">
|
||||
<input type="submit" class="default" value="Publish">
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
{{ end }} {{ end }}
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
{{ define "frontmatter" }}
|
||||
{{ range $key, $value := . }}
|
||||
{{ if $value.SubContent }}
|
||||
<fieldset name="{{ $value.Name }}">
|
||||
{{ if or (eq $value.Type "object") (eq $value.Type "array") }}
|
||||
<fieldset name="{{ $value.Name }}" type="{{ $value.Type }}">
|
||||
<legend>{{ splitCapitalize $value.Name }}</legend>
|
||||
{{ template "frontmatter" $value.Content }}
|
||||
<button><i class="fa fa-plus"></i> Add field</button>
|
||||
</fieldset>
|
||||
{{ else}}
|
||||
{{ else }}
|
||||
{{ if not (eq $value.Parent "array") }}
|
||||
<label for="{{ $value.Name }}">{{ splitCapitalize $value.Name }}</label>
|
||||
{{ end }}
|
||||
<input name="{{ $value.Name }}" id="{{ $value.Name }}" value="{{ $value.Content }}"></input><br>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
|
|
@ -27,6 +27,14 @@ func IsMap(sth interface{}) bool {
|
|||
return reflect.ValueOf(sth).Kind() == reflect.Map
|
||||
}
|
||||
|
||||
func IsSlice(sth interface{}) bool {
|
||||
return reflect.ValueOf(sth).Kind() == reflect.Slice
|
||||
}
|
||||
|
||||
func IsArray(sth interface{}) bool {
|
||||
return reflect.ValueOf(sth).Kind() == reflect.Array
|
||||
}
|
||||
|
||||
func SplitCapitalize(name string) string {
|
||||
var words []string
|
||||
l := 0
|
||||
|
|
Loading…
Reference in New Issue