Adding faces

This commit is contained in:
m15o 2021-11-30 21:50:10 +01:00
parent 95dacca678
commit fa5e12c0f7
16 changed files with 311 additions and 67 deletions

View file

@ -3,12 +3,14 @@ body {
margin: 0 auto;
padding: 1em;
font-family: Verdana;
background-color: azure;
color: midnightblue;
}
section {
padding: 1em;
background-color: lightblue;
}
/*section {*/
/* padding: 1em;*/
/* background-color: lightblue;*/
/*}*/
.flash {
background-color: lightgreen;
@ -50,13 +52,13 @@ dd {
margin-bottom: 1em;
}
nav {
margin-bottom: 1em;
}
/*nav {*/
/* margin-bottom: 1em;*/
/*}*/
h1, h2 {
margin-top: 0;
}
/*h1, h2 {*/
/* !*margin-top: 0;*!*/
/*}*/
.tools {
list-style-position: inside;
@ -65,11 +67,12 @@ h1, h2 {
@media (min-width: 650px) {
.cols {
grid-template-columns: repeat(2, 1fr);
grid-gap: 1em;
grid-template-columns: 1fr 2fr;
grid-gap: 2em;
}
}
.radio { display: inline-block }
.field { margin-bottom: 1rem; max-width: 500px; }
.field > label { margin-bottom: .25rem; }
.field > * { display: block; width: 100%; box-sizing: border-box; }

View file

@ -10,6 +10,7 @@ type Status struct {
Id int64
User string
Content string
Face string
CreatedAt time.Time
}

View file

@ -7,7 +7,7 @@ import (
"strconv"
)
const schemaVersion = 7
const schemaVersion = 8
func Migrate(db *sql.DB) {
var currentVersion int

View file

@ -40,4 +40,6 @@ alter column about TYPE TEXT;`,
add column picture varchar(500) not null DEFAULT '';`,
"schema_version_7": `alter table users
add column email varchar(500) not null DEFAULT '';`,
"schema_version_8": `alter table statuses
add column face varchar(1) not null DEFAULT '🙂';`,
}

View file

@ -0,0 +1,2 @@
alter table statuses
add column face varchar(1) not null DEFAULT '🙂';

View file

@ -15,7 +15,7 @@ type statusQueryBuilder struct {
}
func (p statusQueryBuilder) build() string {
query := []string{`SELECT id, author, content, created_at from statuses`}
query := []string{`SELECT id, author, content, created_at, face from statuses`}
if p.where != "" {
query = append(query, `WHERE`, p.where)
}
@ -31,7 +31,7 @@ func (p statusQueryBuilder) build() string {
func (s *Storage) populateStatus(rows *sql.Rows) (model.Status, error) {
var status model.Status
err := rows.Scan(&status.Id, &status.User, &status.Content, &status.CreatedAt)
err := rows.Scan(&status.Id, &status.User, &status.Content, &status.CreatedAt, &status.Face)
if err != nil {
return status, err
}
@ -45,8 +45,8 @@ func (s *Storage) CreateStatus(status model.Status) error {
if err != nil {
return err
}
if err := tx.QueryRowContext(ctx, `INSERT INTO statuses (author, content) VALUES ($1, $2) RETURNING id`,
status.User, status.Content).Scan(&statusId); err != nil {
if err := tx.QueryRowContext(ctx, `INSERT INTO statuses (author, content, face) VALUES ($1, $2, $3) RETURNING id`,
status.User, status.Content, status.Face).Scan(&statusId); err != nil {
tx.Rollback()
return err
}
@ -121,7 +121,8 @@ func (s *Storage) LatestStatuses() ([]model.Status, error) {
statuses.id,
users.name,
statuses.content,
statuses.created_at
statuses.created_at,
statuses.face
from
users
inner join statuses
@ -143,11 +144,11 @@ func (s *Storage) LatestStatuses() ([]model.Status, error) {
}
func (s *Storage) UpdateStatus(status model.Status) error {
stmt, err := s.db.Prepare(`UPDATE statuses SET content = $1 WHERE id = $2 and author = $3;`)
stmt, err := s.db.Prepare(`UPDATE statuses SET content = $1, face = $2 WHERE id = $3 and author = $4;`)
if err != nil {
return err
}
_, err = stmt.Exec(status.Content, status.Id, status.User)
_, err = stmt.Exec(status.Content, status.Face, status.Id, status.User)
return err
}
@ -186,7 +187,13 @@ func (s *Storage) DeleteStatus(id int64, author string) error {
tx.Rollback()
return err
}
} else {
if _, err := tx.ExecContext(ctx, `UPDATE users set status_id=$1 where name=$2`, latestId, author); err != nil {
tx.Rollback()
return err
}
}
err = tx.Commit()
return err
}

View file

@ -42,7 +42,7 @@ var TplCommonMap = map[string]string{
{{ define "head" }}{{ end }}
`,
"status": `{{ define "status" }}
<div class="status-username"><a href="/users/{{ .User }}">{{ .User }}</a>, {{ .TimeAgo }}</div>
<div class="status-username"><a href="/users/{{ .User }}">{{ .User }}</a> {{ .Face }} {{ .TimeAgo }}</div>
<p class="status-content">{{ .Content }}</p>
{{ end }}`,
}

View file

@ -8,6 +8,7 @@ import (
type StatusForm struct {
Id int64
Content string
Face string
Error string
}
@ -17,5 +18,6 @@ func NewStatusForm(r *http.Request) *StatusForm {
return &StatusForm{
Id: id,
Content: r.FormValue("content"),
Face: r.FormValue("face"),
}
}

View file

@ -63,6 +63,19 @@ var TplMap = map[string]string{
</body>
</html>`,
"current_status": `{{ define "content" }}
<style>
#statuscafe {
padding: .5em;
background-color: lightblue;
border: 1px solid;
}
#statuscafe-username {
margin-bottom: .5em;
}
#statuscafe-content {
margin: 0 1em 0.5em 1em;
}
</style>
<div class="cols">
<section>
<h1>Current Status Widget</h1>
@ -79,7 +92,21 @@ var TplMap = map[string]string{
</table>
</form>
<p>Past this code into your HTML file:</p>
<textarea id="code-html" style="width: 100%; height: 75px;"></textarea>
<textarea style="width: 100%; height: 75px;"><script src="https://status.cafe/current-status.js?name={{ .name }}"></script></textarea>
<p>Past this code into your CSS file:</p>
<textarea style="width: 100%; height: 75px;">#statuscafe {
padding: .5em;
background-color: lightblue;
border: 1px solid;
}
#statuscafe-username {
margin-bottom: .5em;
}
#statuscafe-content {
margin: 0 1em 0.5em 1em;
}
</textarea>
<p>Make it your own! The CSS above is only an example. Tweak it so that it integrates well with your sites's colors.</p>
</section>
<section>
<h2>Preview</h2>
@ -90,19 +117,6 @@ var TplMap = map[string]string{
{{ end }}
</section>
</div>
<script>
function getHTML(name) {
return '<s'+'cript src="https://status.cafe/current-status.js?name=' + name + '"></s'+'cript>'
}
function preview() {
const name = document.getElementById("name").value
if (name) {
const code = getHTML(document.getElementById("name").value)
document.getElementById("code-html").value = code
}
}
preview()
</script>
{{ end }}`,
"edit_status": `{{ define "content" }}
<section>
@ -112,10 +126,58 @@ var TplMap = map[string]string{
{{ end }}
{{ template "flash" .flash }}
<form action="/edit?id={{ .status.Id }}" method="post">
<div class="field">
<div class="field">
<textarea name="content" placeholder="What's new?" required style="width: 100%; box-sizing: border-box;" autofocus>{{ .status.Content }}</textarea>
<div style="margin-bottom: 1em">
<div class="radio">
<input type="radio" id="face1" name="face" value="🙂" checked>
<label for="face1">🙂</label>
</div>
<div class="radio">
<input type="radio" id="face2" name="face" value="😎">
<label for="face2">😎</label>
</div>
<div class="radio">
<input type="radio" id="face3" name="face" value="😛">
<label for="face3">😛</label>
</div>
<div class="radio">
<input type="radio" id="face4" name="face" value="🥰">
<label for="face4">🥰</label>
</div>
<div class="radio">
<input type="radio" id="face5" name="face" value="👽">
<label for="face5">👽</label>
</div>
<div class="radio">
<input type="radio" id="face6" name="face" value="😱">
<label for="face6">😱</label>
</div>
<div class="radio">
<input type="radio" id="face7" name="face" value="🤗">
<label for="face7">🤗</label>
</div>
<div class="radio">
<input type="radio" id="face8" name="face" value="😯">
<label for="face8">😯</label>
</div>
<div class="radio">
<input type="radio" id="face9" name="face" value="🤒">
<label for="face9">🤒</label>
</div>
<div class="radio">
<input type="radio" id="face10" name="face" value="😡">
<label for="face10">😡</label>
</div>
<div class="radio">
<input type="radio" id="face11" name="face" value="🥺">
<label for="face11">🥺</label>
</div>
<div class="radio">
<input type="radio" id="face12" name="face" value="🥳">
<label for="face12">🥳</label>
</div>
</div>
<div class="field">
<textarea name="content" placeholder="What's new?" required style="width: 100%; box-sizing: border-box;" autofocus>{{ .status.Content }}</textarea>
</div>
<input type="submit" value="Submit">
</form>
@ -130,15 +192,65 @@ var TplMap = map[string]string{
{{ end }}
{{ template "flash" .flash }}
<form action="/add" method="post">
<div style="margin-bottom: 1em">
<div class="radio">
<input type="radio" id="face1" name="face" value="🙂" checked>
<label for="face1">🙂</label>
</div>
<div class="radio">
<input type="radio" id="face2" name="face" value="😎">
<label for="face2">😎</label>
</div>
<div class="radio">
<input type="radio" id="face3" name="face" value="😛">
<label for="face3">😛</label>
</div>
<div class="radio">
<input type="radio" id="face4" name="face" value="🥰">
<label for="face4">🥰</label>
</div>
<div class="radio">
<input type="radio" id="face5" name="face" value="👽">
<label for="face5">👽</label>
</div>
<div class="radio">
<input type="radio" id="face6" name="face" value="😱">
<label for="face6">😱</label>
</div>
<div class="radio">
<input type="radio" id="face7" name="face" value="🤗">
<label for="face7">🤗</label>
</div>
<div class="radio">
<input type="radio" id="face8" name="face" value="😯">
<label for="face8">😯</label>
</div>
<div class="radio">
<input type="radio" id="face9" name="face" value="🤒">
<label for="face9">🤒</label>
</div>
<div class="radio">
<input type="radio" id="face10" name="face" value="😡">
<label for="face10">😡</label>
</div>
<div class="radio">
<input type="radio" id="face11" name="face" value="🥺">
<label for="face11">🥺</label>
</div>
<div class="radio">
<input type="radio" id="face12" name="face" value="🥳">
<label for="face12">🥳</label>
</div>
</div>
<div class="field">
<textarea name="content" maxlength="140" placeholder="What's new?" required style="width: 100%; box-sizing: border-box; height: 100px;" autofocus></textarea>
</div>
<input type="submit" value="Submit">
<ul class="tools">
<li>Install the <a href="/about/status-updater">status updater</a> bookmarklet</li>
<li>Add the <a href="/current-status">current status widget</a> to your homepage</li>
</ul>
</form>
<ul class="tools">
<li><a href="/about/status-updater">status updater</a> bookmarklet</li>
<li><a href="/current-status">status widget</a> for your homepage</li>
</ul>
</section>
<section>
<h2>Status stream</h2>
@ -149,7 +261,8 @@ var TplMap = map[string]string{
{{ end }}
</section>
</div>
{{ end }}`,
{{ end }}
`,
"intro": `{{ define "content" }}
<section>
<h1>Introduction</h1>

View file

@ -1,4 +1,4 @@
{{ define "status" }}
<div class="status-username"><a href="/users/{{ .User }}">{{ .User }}</a>, {{ .TimeAgo }}</div>
<div class="status-username"><a href="/users/{{ .User }}">{{ .User }}</a> {{ .Face }} {{ .TimeAgo }}</div>
<p class="status-content">{{ .Content }}</p>
{{ end }}

View file

@ -1,4 +1,17 @@
{{ define "content" }}
<style>
#statuscafe {
padding: .5em;
background-color: lightblue;
border: 1px solid;
}
#statuscafe-username {
margin-bottom: .5em;
}
#statuscafe-content {
margin: 0 1em 0.5em 1em;
}
</style>
<div class="cols">
<section>
<h1>Current Status Widget</h1>
@ -15,7 +28,21 @@
</table>
</form>
<p>Past this code into your HTML file:</p>
<textarea id="code-html" style="width: 100%; height: 75px;"></textarea>
<textarea style="width: 100%; height: 75px;"><script src="https://status.cafe/current-status.js?name={{ .name }}"></script></textarea>
<p>Past this code into your CSS file:</p>
<textarea style="width: 100%; height: 75px;">#statuscafe {
padding: .5em;
background-color: lightblue;
border: 1px solid;
}
#statuscafe-username {
margin-bottom: .5em;
}
#statuscafe-content {
margin: 0 1em 0.5em 1em;
}
</textarea>
<p>Make it your own! The CSS above is only an example. Tweak it so that it integrates well with your sites's colors.</p>
</section>
<section>
<h2>Preview</h2>
@ -26,17 +53,4 @@
{{ end }}
</section>
</div>
<script>
function getHTML(name) {
return '<s'+'cript src="https://status.cafe/current-status.js?name=' + name + '"></s'+'cript>'
}
function preview() {
const name = document.getElementById("name").value
if (name) {
const code = getHTML(document.getElementById("name").value)
document.getElementById("code-html").value = code
}
}
preview()
</script>
{{ end }}

View file

@ -6,10 +6,58 @@
{{ end }}
{{ template "flash" .flash }}
<form action="/edit?id={{ .status.Id }}" method="post">
<div class="field">
<div class="field">
<textarea name="content" placeholder="What's new?" required style="width: 100%; box-sizing: border-box;" autofocus>{{ .status.Content }}</textarea>
<div style="margin-bottom: 1em">
<div class="radio">
<input type="radio" id="face1" name="face" value="🙂" checked>
<label for="face1">🙂</label>
</div>
<div class="radio">
<input type="radio" id="face2" name="face" value="😎">
<label for="face2">😎</label>
</div>
<div class="radio">
<input type="radio" id="face3" name="face" value="😛">
<label for="face3">😛</label>
</div>
<div class="radio">
<input type="radio" id="face4" name="face" value="🥰">
<label for="face4">🥰</label>
</div>
<div class="radio">
<input type="radio" id="face5" name="face" value="👽">
<label for="face5">👽</label>
</div>
<div class="radio">
<input type="radio" id="face6" name="face" value="😱">
<label for="face6">😱</label>
</div>
<div class="radio">
<input type="radio" id="face7" name="face" value="🤗">
<label for="face7">🤗</label>
</div>
<div class="radio">
<input type="radio" id="face8" name="face" value="😯">
<label for="face8">😯</label>
</div>
<div class="radio">
<input type="radio" id="face9" name="face" value="🤒">
<label for="face9">🤒</label>
</div>
<div class="radio">
<input type="radio" id="face10" name="face" value="😡">
<label for="face10">😡</label>
</div>
<div class="radio">
<input type="radio" id="face11" name="face" value="🥺">
<label for="face11">🥺</label>
</div>
<div class="radio">
<input type="radio" id="face12" name="face" value="🥳">
<label for="face12">🥳</label>
</div>
</div>
<div class="field">
<textarea name="content" placeholder="What's new?" required style="width: 100%; box-sizing: border-box;" autofocus>{{ .status.Content }}</textarea>
</div>
<input type="submit" value="Submit">
</form>

View file

@ -7,15 +7,65 @@
{{ end }}
{{ template "flash" .flash }}
<form action="/add" method="post">
<div style="margin-bottom: 1em">
<div class="radio">
<input type="radio" id="face1" name="face" value="🙂" checked>
<label for="face1">🙂</label>
</div>
<div class="radio">
<input type="radio" id="face2" name="face" value="😎">
<label for="face2">😎</label>
</div>
<div class="radio">
<input type="radio" id="face3" name="face" value="😛">
<label for="face3">😛</label>
</div>
<div class="radio">
<input type="radio" id="face4" name="face" value="🥰">
<label for="face4">🥰</label>
</div>
<div class="radio">
<input type="radio" id="face5" name="face" value="👽">
<label for="face5">👽</label>
</div>
<div class="radio">
<input type="radio" id="face6" name="face" value="😱">
<label for="face6">😱</label>
</div>
<div class="radio">
<input type="radio" id="face7" name="face" value="🤗">
<label for="face7">🤗</label>
</div>
<div class="radio">
<input type="radio" id="face8" name="face" value="😯">
<label for="face8">😯</label>
</div>
<div class="radio">
<input type="radio" id="face9" name="face" value="🤒">
<label for="face9">🤒</label>
</div>
<div class="radio">
<input type="radio" id="face10" name="face" value="😡">
<label for="face10">😡</label>
</div>
<div class="radio">
<input type="radio" id="face11" name="face" value="🥺">
<label for="face11">🥺</label>
</div>
<div class="radio">
<input type="radio" id="face12" name="face" value="🥳">
<label for="face12">🥳</label>
</div>
</div>
<div class="field">
<textarea name="content" maxlength="140" placeholder="What's new?" required style="width: 100%; box-sizing: border-box; height: 100px;" autofocus></textarea>
</div>
<input type="submit" value="Submit">
<ul class="tools">
<li>Install the <a href="/about/status-updater">status updater</a> bookmarklet</li>
<li>Add the <a href="/current-status">current status widget</a> to your homepage</li>
</ul>
</form>
<ul class="tools">
<li><a href="/about/status-updater">status updater</a> bookmarklet</li>
<li><a href="/current-status">status widget</a> for your homepage</li>
</ul>
</section>
<section>
<h2>Status stream</h2>
@ -26,4 +76,4 @@
{{ end }}
</section>
</div>
{{ end }}
{{ end }}

View file

@ -16,6 +16,7 @@ func (h *Handler) saveStatus(w http.ResponseWriter, r *http.Request) {
status := model.Status{
User: user,
Content: f.Content,
Face: f.Face,
}
if err := status.Validate(); err != nil {
f.Error = err.Error()

View file

@ -30,6 +30,7 @@ func (h *Handler) updateStatus(w http.ResponseWriter, r *http.Request) {
}
f := form.NewStatusForm(r)
status.Content = f.Content
status.Face = f.Face
if err := status.Validate(); err != nil {
f.Error = err.Error()
h.renderLayout(w, "edit_post", map[string]interface{}{

View file

@ -15,7 +15,7 @@ fetch("https://status.cafe/users/` + name + `/status.json")
document.getElementById("statuscafe-content").innerHTML = "No status yet."
return
}
document.getElementById("statuscafe-username").innerHTML = '<a href="https://status.cafe/users/` + name + `">' + r.author + '</a>\'s status, updated ' + r.timeAgo
document.getElementById("statuscafe-username").innerHTML = '<a href="https://status.cafe/users/` + name + `">' + r.author + '</a>, ' + r.timeAgo
document.getElementById("statuscafe-content").innerHTML = r.content
})
`))