Bladeren bron

Support editing houses

tags/v1.0
Matt Baer 8 jaren geleden
bovenliggende
commit
6f3db83e1c
6 gewijzigde bestanden met toevoegingen van 179 en 34 verwijderingen
  1. +42
    -4
      app.go
  2. +43
    -3
      construction.go
  3. +7
    -1
      static/css/core.less
  4. +24
    -0
      static/default.html
  5. +23
    -0
      templates.go
  6. +40
    -26
      templates/editor.html

+ 42
- 4
app.go Bestand weergeven

@@ -2,6 +2,9 @@ package htmlhouse

import (
"database/sql"
"fmt"
"html/template"
"io/ioutil"
"net/http"

"github.com/gorilla/mux"
@@ -9,10 +12,11 @@ import (
)

type app struct {
cfg *config
router *mux.Router
db *sql.DB
session sessionManager
cfg *config
router *mux.Router
db *sql.DB
session sessionManager
templates map[string]*template.Template
}

func newApp() (*app, error) {
@@ -35,6 +39,8 @@ func newApp() (*app, error) {
return app, err
}

app.initTemplates()

app.initRouter()

return app, nil
@@ -49,11 +55,43 @@ func (app *app) initRouter() {

api := app.router.PathPrefix("/⌂/").Subrouter()
api.HandleFunc("/create", app.handler(createHouse)).Methods("POST").Name("create")
api.HandleFunc("/{house:[A-Za-z0-9.-]{8}}", app.handler(renovateHouse)).Methods("POST").Name("update")

app.router.HandleFunc("/", app.handler(getEditor)).Methods("GET").Name("index")
app.router.HandleFunc("/edit/{house:[A-Za-z0-9.-]{8}}.html", app.handler(getEditor)).Methods("GET").Name("edit")
app.router.HandleFunc("/{house:[A-Za-z0-9.-]{8}}.html", app.handler(getHouse)).Methods("GET").Name("get")
app.router.PathPrefix("/").Handler(http.FileServer(http.Dir(app.cfg.StaticDir)))
}

type EditorPage struct {
ID string
Content string
}

func getEditor(app *app, w http.ResponseWriter, r *http.Request) error {
vars := mux.Vars(r)
house := vars["house"]

if house == "" {
defaultPage, err := ioutil.ReadFile(app.cfg.StaticDir + "/default.html")
if err != nil {
fmt.Printf("\n%s\n", err)
defaultPage = []byte("<!DOCTYPE html>\n<html>\n</html>")
}
app.templates["editor"].ExecuteTemplate(w, "editor", &EditorPage{"", string(defaultPage)})

return nil
}

html, err := getHouseHTML(app, house)
if err != nil {
return err
}

app.templates["editor"].ExecuteTemplate(w, "editor", &EditorPage{house, html})
return nil
}

type handlerFunc func(app *app, w http.ResponseWriter, r *http.Request) error

func (app *app) handler(h handlerFunc) http.HandlerFunc {


+ 43
- 3
construction.go Bestand weergeven

@@ -33,18 +33,58 @@ func createHouse(app *app, w http.ResponseWriter, r *http.Request) error {
return impart.WriteSuccess(w, resUser, http.StatusCreated)
}

func getHouse(app *app, w http.ResponseWriter, r *http.Request) error {
func renovateHouse(app *app, w http.ResponseWriter, r *http.Request) error {
vars := mux.Vars(r)
houseID := vars["house"]
html := r.FormValue("html")
if strings.TrimSpace(html) == "" {
return impart.HTTPError{http.StatusBadRequest, "Supply something to publish."}
}

// Fetch HTML
authHouseID, err := app.session.readToken(r)
if err != nil {
return err
}

if authHouseID != houseID {
return impart.HTTPError{http.StatusUnauthorized, "Bad token for this ⌂ house ⌂."}
}

_, err = app.db.Exec("UPDATE houses SET html = ? WHERE id = ?", html, houseID)
if err != nil {
return err
}

if err = app.session.writeToken(w, houseID); err != nil {
return err
}

resUser := newSessionInfo(houseID)

return impart.WriteSuccess(w, resUser, http.StatusCreated)
}

func getHouseHTML(app *app, houseID string) (string, error) {
var html string
err := app.db.QueryRow("SELECT html FROM houses WHERE id = ?", houseID).Scan(&html)
switch {
case err == sql.ErrNoRows:
return impart.HTTPError{http.StatusNotFound, "Return to sender. Address unknown."}
return "", impart.HTTPError{http.StatusNotFound, "Return to sender. Address unknown."}
case err != nil:
fmt.Printf("Couldn't fetch: %v\n", err)
return "", err
}

return html, nil
}

func getHouse(app *app, w http.ResponseWriter, r *http.Request) error {
vars := mux.Vars(r)
houseID := vars["house"]

// Fetch HTML
html, err := getHouseHTML(app, houseID)
if err != nil {
return err
}



+ 7
- 1
static/css/core.less Bestand weergeven

@@ -30,6 +30,12 @@ body {
h1 {
display: inline;
}
a {
margin: 0 0 0 1em;
&:link, &:visited {
color: blue;
}
}
nav {
display: inline;
margin: 0 1em;
@@ -37,7 +43,7 @@ body {
span, a {
margin: 0 0 0 1em;
}
a {
a, a:link, a:visited {
color: #999;
&.current {
color: #666;


+ 24
- 0
static/default.html Bestand weergeven

@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>

<title>HTMLhouse</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<style type="text/css">
body {
font-family: Helvetica, Tahoma, Arial, sans-serif;
font-size: 100%;
margin: 1em;
}
img {
max-width: 100%;
}
</style>

</head>
<body>
<h1>HTMLhouse</h1>
<p>Welcome!</p>
</body>
</html>

+ 23
- 0
templates.go Bestand weergeven

@@ -0,0 +1,23 @@
package htmlhouse

import (
"fmt"
"html/template"
)

const (
templatesDir = "templates/"
)

func initTemplate(app *app, name string) {
fmt.Printf("Loading %s%s.html\n", templatesDir, name)

app.templates[name] = template.Must(template.New("").ParseFiles(templatesDir + name + ".html"))
}

func (app *app) initTemplates() {
app.templates = map[string]*template.Template{}

// Initialize dynamic pages
initTemplate(app, "editor")
}

static/index.html → templates/editor.html Bestand weergeven

@@ -1,4 +1,4 @@
<!DOCTYPE HTML>
{{define "editor"}}<!DOCTYPE HTML>
<html>
<head>

@@ -30,32 +30,15 @@
<header>
<h1>HTMLhouse</h1>
<nav>
{{if .ID}}<a class="home" href="/">&lt;&#8962;/&gt;</a>{{end}}
<a href="/about.html">about</a>
<a href="mailto:hello@html.house">contact</a>
</nav>
<a id="publish" href="#">publish</a>
{{if .ID}}<a href="/{{.ID}}.html">view</a>{{end}}
<a id="publish" href="#">{{if .ID}}update{{else}}publish{{end}}</a>
</header>

<pre id="editor">&lt;!DOCTYPE html>
&lt;html>
&lt;head>

&lt;title>HTMLhouse&lt;/title>

&lt;style type="text/css">
body {
font-family: Helvetica, Tahoma, Arial, sans-serif;
font-size: 100%;
margin: 1em;
}
&lt;/style>

&lt;/head>
&lt;body>
&lt;h1>HTMLhouse&lt;/h1>
&lt;p>Welcome!&lt;/p>
&lt;/body>
&lt;/html></pre>
<pre id="editor">{{.Content}}</pre>

<div id="preview-wrap">
<iframe id="preview"></iframe>
@@ -63,8 +46,10 @@

<script src="https://code.jquery.com/jquery-2.1.4.min.js" type="text/javascript" charset="utf-8"></script>
<script src="/js/ace.js" type="text/javascript" charset="utf-8"></script>
<script src="https://write.as/js/h.js"></script>
<script>
//var $view = window.frames['preview'].document.getElementsByTag("body")[0];
var typingTimer;
function updatePreview() {
// $view.innerHTML = editor.getSession().getValue();
$view.contents().find('body').html(editor.getSession().getValue());
@@ -76,11 +61,40 @@ editor.session.setMode("ace/mode/html");
editor.getSession().on('change', updatePreview);
updatePreview();

var publishing = false;
$("#publish").on('click', function(e) {
e.preventDefault();
$.post("/⌂/create", {html: editor.getSession().getValue()}, function(data, status, xhr) {
if (data.meta.code == 201) {
window.location = '/' + data.data.id + '.html';
if (publishing) {
return;
}
var token;
var houses = JSON.parse(H.get('neighborhood', '[]'));
for (var i=0; i<houses.length; i++) {
if (houses[i].id == "{{.ID}}") {
token = houses[i].token;
break;
}
}
publishing = true;
$.ajax({
type: "POST",
url: "/⌂/{{if .ID}}{{.ID}}{{else}}create{{end}}",{{if .ID}}
beforeSend: function (request) {
request.setRequestHeader("Authorization", token);
},{{end}}
data: {html: editor.getSession().getValue()},
success: function(data, status, xhr) {
publishing = false;
if (data.meta.code == 201) {
var houses = JSON.parse(H.get('neighborhood', '[]'));
houses.push({id: data.data.id, token: xhr.getResponseHeader('Authorization')});
H.set('neighborhood', JSON.stringify(houses));

window.location = '/' + data.data.id + '.html';
}
},
failure: function(data, status, xhr) {
publishing = false;
}
});
});
@@ -95,4 +109,4 @@ $("#publish").on('click', function(e) {
ga('send', 'pageview');
</script>
</body>
</html>
</html>{{end}}

Laden…
Annuleren
Opslaan