- New editor nav - New backend nav - Support for drafts - Different footers on backendtags/v0.1.0
@@ -17,7 +17,7 @@ body { | |||
-moz-osx-font-smoothing: grayscale; | |||
color: #111; | |||
h1 { | |||
h1, header h2 { | |||
a { | |||
color: @headerTextColor; | |||
.transition-duration(0.2s); | |||
@@ -1161,9 +1161,11 @@ header { | |||
text-transform: uppercase; | |||
margin-left: 0.5em; | |||
margin-right: 0.5em; | |||
&.pro { | |||
color: @proSelectedCol; | |||
} | |||
} | |||
&.title { | |||
font-size: 1.6em; | |||
font-family: @serifFont; | |||
font-weight: bold; | |||
} | |||
} | |||
nav > ul > li:first-child { | |||
@@ -1188,9 +1190,22 @@ header { | |||
} | |||
} | |||
&.tabs { | |||
margin: 0 0 0 1em; | |||
} | |||
&+ nav.tabs { | |||
margin: 0; | |||
} | |||
} | |||
&.singleuser { | |||
margin: 0.5em 0.25em; | |||
nav#user-nav { | |||
nav > ul > li:first-child { | |||
img { | |||
top: -0.75em; | |||
} | |||
} | |||
} | |||
} | |||
.dash-nav { | |||
font-weight: bold; | |||
} | |||
@@ -39,7 +39,7 @@ body { | |||
header { | |||
margin: 1em; | |||
h1 { | |||
h1, h2 { | |||
display: inline; | |||
} | |||
nav { | |||
@@ -12,15 +12,23 @@ type nodeInfoResolver struct { | |||
db *datastore | |||
} | |||
func nodeInfoConfig(cfg *config.Config) *nodeinfo.Config { | |||
func nodeInfoConfig(db *datastore, cfg *config.Config) *nodeinfo.Config { | |||
name := cfg.App.SiteName | |||
desc := "Minimal, federated blogging platform." | |||
if cfg.App.SingleUser { | |||
// Fetch blog information, instead | |||
coll, err := db.GetCollectionByID(1) | |||
if err == nil { | |||
desc = coll.Description | |||
} | |||
} | |||
return &nodeinfo.Config{ | |||
BaseURL: cfg.App.Host, | |||
InfoURL: "/api/nodeinfo", | |||
Metadata: nodeinfo.Metadata{ | |||
NodeName: name, | |||
NodeDescription: "Minimal, federated blogging platform.", | |||
NodeDescription: desc, | |||
Private: cfg.App.Private, | |||
Software: nodeinfo.SoftwareMeta{ | |||
HomePage: softwareURL, | |||
@@ -14,6 +14,14 @@ func handleViewPad(app *app, w http.ResponseWriter, r *http.Request) error { | |||
action := vars["action"] | |||
slug := vars["slug"] | |||
collAlias := vars["collection"] | |||
if app.cfg.App.SingleUser { | |||
// TODO: refactor all of this, especially for single-user blogs | |||
c, err := app.db.GetCollectionByID(1) | |||
if err != nil { | |||
return err | |||
} | |||
collAlias = c.Alias | |||
} | |||
appData := &struct { | |||
page.StaticPage | |||
Post *RawPost | |||
@@ -52,6 +60,7 @@ func handleViewPad(app *app, w http.ResponseWriter, r *http.Request) error { | |||
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") | |||
w.Header().Set("Expires", "Thu, 04 Oct 1990 20:00:00 GMT") | |||
if slug != "" { | |||
// TODO: refactor all of this, especially for single-user blogs | |||
appData.Post = getRawCollectionPost(app, slug, collAlias) | |||
if appData.Post.OwnerID != appData.User.ID { | |||
// TODO: add ErrForbiddenEditPost message to flashes | |||
@@ -1,6 +1,6 @@ | |||
{{define "head"}}<title>Log in — {{.SiteName}}</title> | |||
<meta name="description" content="Log in to access your blogs, published posts, and linked accounts."> | |||
<meta itemprop="description" content="Log in to access your blogs, published posts, and linked accounts."> | |||
<meta name="description" content="Log in to {{.SiteName}}."> | |||
<meta itemprop="description" content="Log in to {{.SiteName}}."> | |||
<style>input{margin-bottom:0.5em;}</style> | |||
{{end}} | |||
{{define "content"}} | |||
@@ -18,7 +18,7 @@ | |||
<input type="submit" id="btn-login" value="Login" /> | |||
</form> | |||
<p style="text-align:center;font-size:0.9em;margin:3em auto;max-width:26em;">{{if .Message}}{{.Message}}{{else}}<em>No account yet?</em> <a href="/new/blog">Sign up</a> to start a blog.{{end}}</p> | |||
{{if and (not .SingleUser) .OpenRegistration}}<p style="text-align:center;font-size:0.9em;margin:3em auto;max-width:26em;">{{if .Message}}{{.Message}}{{else}}<em>No account yet?</em> <a href="/">Sign up</a> to start a blog.{{end}}</p>{{end}} | |||
<script type="text/javascript"> | |||
function disableSubmit() { | |||
@@ -27,7 +27,7 @@ var ( | |||
func (p *Post) formatContent(c *Collection, isOwner bool) { | |||
baseURL := c.CanonicalURL() | |||
if isOwner { | |||
if !isSingleUser { | |||
baseURL = "/" + c.Alias + "/" | |||
} | |||
newCon := hashtagReg.ReplaceAllFunc([]byte(p.Content), func(b []byte) []byte { | |||
@@ -1255,12 +1255,14 @@ func viewCollectionPost(app *app, w http.ResponseWriter, r *http.Request) error | |||
p.formatContent(cr.isCollOwner) | |||
tp := struct { | |||
*PublicPost | |||
page.StaticPage | |||
IsOwner bool | |||
IsPinned bool | |||
IsCustomDomain bool | |||
PinnedPosts *[]PublicPost | |||
}{ | |||
PublicPost: p, | |||
StaticPage: pageForReq(app, r), | |||
IsOwner: cr.isCollOwner, | |||
IsCustomDomain: cr.isCustomDomain, | |||
} | |||
@@ -39,7 +39,7 @@ func initRoutes(handler *Handler, r *mux.Router, cfg *config.Config, db *datasto | |||
// webfinger | |||
write.HandleFunc(webfinger.WebFingerPath, handler.LogHandlerFunc(http.HandlerFunc(wf.Webfinger))) | |||
// nodeinfo | |||
niCfg := nodeInfoConfig(cfg) | |||
niCfg := nodeInfoConfig(db, cfg) | |||
ni := nodeinfo.NewService(*niCfg, nodeInfoResolver{cfg, db}) | |||
write.HandleFunc(nodeinfo.NodeInfoPath, handler.LogHandlerFunc(http.HandlerFunc(ni.NodeInfoDiscover))) | |||
write.HandleFunc(niCfg.InfoURL, handler.LogHandlerFunc(http.HandlerFunc(ni.NodeInfo))) | |||
@@ -118,15 +118,17 @@ func initRoutes(handler *Handler, r *mux.Router, cfg *config.Config, db *datasto | |||
// Handle special pages first | |||
write.HandleFunc("/login", handler.Web(viewLogin, UserLevelNoneRequired)) | |||
draftEditPrefix := "" | |||
if cfg.App.SingleUser { | |||
draftEditPrefix = "/d" | |||
write.HandleFunc("/me/new", handler.Web(handleViewPad, UserLevelOptional)).Methods("GET") | |||
} else { | |||
write.HandleFunc("/new", handler.Web(handleViewPad, UserLevelOptional)).Methods("GET") | |||
} | |||
// All the existing stuff | |||
write.HandleFunc("/{action}/edit", handler.Web(handleViewPad, UserLevelOptional)).Methods("GET") | |||
write.HandleFunc("/{action}/meta", handler.Web(handleViewMeta, UserLevelOptional)).Methods("GET") | |||
write.HandleFunc(draftEditPrefix+"/{action}/edit", handler.Web(handleViewPad, UserLevelOptional)).Methods("GET") | |||
write.HandleFunc(draftEditPrefix+"/{action}/meta", handler.Web(handleViewMeta, UserLevelOptional)).Methods("GET") | |||
// Collections | |||
if cfg.App.SingleUser { | |||
RouteCollections(handler, write.PathPrefix("/").Subrouter()) | |||
@@ -135,8 +137,8 @@ func initRoutes(handler *Handler, r *mux.Router, cfg *config.Config, db *datasto | |||
write.HandleFunc("/{collection}/", handler.Web(handleViewCollection, UserLevelOptional)) | |||
RouteCollections(handler, write.PathPrefix("/{prefix:[@~$!\\-+]?}{collection}").Subrouter()) | |||
// Posts | |||
write.HandleFunc("/{post}", handler.Web(handleViewPost, UserLevelOptional)) | |||
} | |||
write.HandleFunc(draftEditPrefix+"/{post}", handler.Web(handleViewPost, UserLevelOptional)) | |||
write.HandleFunc("/", handler.Web(handleViewHome, UserLevelOptional)) | |||
} | |||
@@ -1,6 +1,6 @@ | |||
var postActions = function() { | |||
var $container = He.get('moving'); | |||
var MultiMove = function(el, id) { | |||
var MultiMove = function(el, id, singleUser) { | |||
var lbl = el.options[el.selectedIndex].textContent; | |||
var collAlias = el.options[el.selectedIndex].value; | |||
var $lbl = He.$('label[for=move-'+id+']')[0]; | |||
@@ -18,7 +18,11 @@ var postActions = function() { | |||
for (var i=0; i<resp.data.length; i++) { | |||
if (resp.data[i].code == 200) { | |||
$lbl.innerHTML = "moved to <strong>"+lbl+"</strong>"; | |||
var newPostURL = "/"+collAlias+"/"+resp.data[i].post.slug; | |||
var pre = "/"+collAlias; | |||
if (typeof singleUser !== 'undefined' && singleUser) { | |||
pre = ""; | |||
} | |||
var newPostURL = pre+"/"+resp.data[i].post.slug; | |||
try { | |||
// Posts page | |||
He.$('#post-'+resp.data[i].post.id+' > h3 > a')[0].href = newPostURL; | |||
@@ -27,7 +31,11 @@ var postActions = function() { | |||
var $article = He.get('post-'+resp.data[i].post.id); | |||
$article.className = 'norm moved'; | |||
if (collAlias == '|anonymous|') { | |||
$article.innerHTML = '<p><a href="/'+resp.data[i].post.id+'">Unpublished post</a>.</p>'; | |||
var draftPre = ""; | |||
if (typeof singleUser !== 'undefined' && singleUser) { | |||
draftPre = "d/"; | |||
} | |||
$article.innerHTML = '<p><a href="/'+draftPre+resp.data[i].post.id+'">Unpublished post</a>.</p>'; | |||
} else { | |||
$article.innerHTML = '<p>Moved to <a style="font-weight:bold" href="'+newPostURL+'">'+lbl+'</a>.</p>'; | |||
} | |||
@@ -44,7 +52,7 @@ var postActions = function() { | |||
He.postJSON("/api/collections/"+collAlias+"/collect", params, callback); | |||
} | |||
}; | |||
var Move = function(el, id, collAlias) { | |||
var Move = function(el, id, collAlias, singleUser) { | |||
var lbl = el.textContent; | |||
try { | |||
var m = lbl.match(/move to (.*)/); | |||
@@ -69,7 +77,11 @@ var postActions = function() { | |||
if (resp.data[i].code == 200) { | |||
el.innerHTML = "moved to <strong>"+lbl+"</strong>"; | |||
el.onclick = null; | |||
var newPostURL = "/"+collAlias+"/"+resp.data[i].post.slug; | |||
var pre = "/"+collAlias; | |||
if (typeof singleUser !== 'undefined' && singleUser) { | |||
pre = ""; | |||
} | |||
var newPostURL = pre+"/"+resp.data[i].post.slug; | |||
el.href = newPostURL; | |||
el.title = "View on "+lbl; | |||
try { | |||
@@ -80,7 +92,11 @@ var postActions = function() { | |||
var $article = He.get('post-'+resp.data[i].post.id); | |||
$article.className = 'norm moved'; | |||
if (collAlias == '|anonymous|') { | |||
$article.innerHTML = '<p><a href="/'+resp.data[i].post.id+'">Unpublished post</a>.</p>'; | |||
var draftPre = ""; | |||
if (typeof singleUser !== 'undefined' && singleUser) { | |||
draftPre = "d/"; | |||
} | |||
$article.innerHTML = '<p><a href="/'+draftPre+resp.data[i].post.id+'">Unpublished post</a>.</p>'; | |||
} else { | |||
$article.innerHTML = '<p>Moved to <a style="font-weight:bold" href="'+newPostURL+'">'+lbl+'</a>.</p>'; | |||
} | |||
@@ -14,11 +14,11 @@ | |||
<div id="overlay"></div> | |||
<header> | |||
<h2><a href="/">{{.SiteName}}</a></h2> | |||
{{if .HeaderNav}} | |||
{{if not .SingleUser}} | |||
<nav id="user-nav"> | |||
<nav class="tabs"> | |||
<a href="/about"{{if eq .Path "/about"}} class="selected"{{end}}>About</a> | |||
<a href="/login"{{if eq .Path "/login"}} class="selected"{{end}}>Log in</a> | |||
{{if and (not .SingleUser) (not .Username)}}<a href="/login"{{if eq .Path "/login"}} class="selected"{{end}}>Log in</a>{{end}} | |||
</nav> | |||
</nav> | |||
{{end}} | |||
@@ -54,10 +54,10 @@ | |||
<h1 dir="{{.Direction}}" id="blog-title"><a rel="author" href="{{if .IsTopLevel}}/{{else}}/{{.Collection.Alias}}/{{end}}" class="h-card p-author">{{.Collection.DisplayTitle}}</a></h1> | |||
<nav> | |||
{{if .PinnedPosts}} | |||
{{range .PinnedPosts}}<a class="pinned{{if eq .Slug.String $.Slug.String}} selected{{end}}" href="{{if $.IsOwner}}/{{$.Collection.Alias}}/{{.Slug.String}}{{else}}{{.CanonicalURL}}{{end}}">{{.PlainDisplayTitle}}</a>{{end}} | |||
{{range .PinnedPosts}}<a class="pinned{{if eq .Slug.String $.Slug.String}} selected{{end}}" href="{{if not $.SingleUser}}/{{$.Collection.Alias}}/{{.Slug.String}}{{else}}{{.CanonicalURL}}{{end}}">{{.PlainDisplayTitle}}</a>{{end}} | |||
{{end}} | |||
{{ if .IsOwner }}<span class="views" dir="ltr"><strong>{{largeNumFmt .Views}}</strong> {{pluralize "view" "views" .Views}}</span> | |||
<a class="xtra-feature" href="/{{.Collection.Alias}}/{{.Slug.String}}/edit" dir="{{.Direction}}">Edit</a> | |||
<a class="xtra-feature" href="/{{if not .SingleUser}}{{.Collection.Alias}}/{{end}}{{.Slug.String}}/edit" dir="{{.Direction}}">Edit</a> | |||
{{if .IsPinned}}<a class="xtra-feature unpin" href="/{{.Collection.Alias}}/{{.Slug.String}}/unpin" dir="{{.Direction}}" onclick="unpinPost(event, '{{.ID}}')">Unpin</a>{{end}} | |||
{{ end }} | |||
</nav> | |||
@@ -52,7 +52,7 @@ | |||
<h1 dir="{{.Direction}}" id="blog-title"><a href="{{if .IsTopLevel}}/{{else}}/{{.Collection.Alias}}/{{end}}" class="h-card p-author">{{.Collection.DisplayTitle}}</a></h1> | |||
<nav> | |||
{{if .PinnedPosts}} | |||
{{range .PinnedPosts}}<a class="pinned" href="{{if $.IsOwner}}/{{$.Collection.Alias}}/{{.Slug.String}}{{else}}{{.CanonicalURL}}{{end}}">{{.DisplayTitle}}</a>{{end}} | |||
{{range .PinnedPosts}}<a class="pinned" href="{{if not $.SingleUser}}/{{$.Collection.Alias}}/{{.Slug.String}}{{else}}{{.CanonicalURL}}{{end}}">{{.DisplayTitle}}</a>{{end}} | |||
{{end}} | |||
</nav> | |||
</header> | |||
@@ -46,11 +46,15 @@ | |||
{{if .IsOwner}}<nav id="manage"><ul> | |||
<li><a onclick="void(0)">☰ Menu</a> | |||
<ul> | |||
{{if .SingleUser}} | |||
<li><a href="/me/new">New Post</a></li> | |||
{{else}} | |||
<li><a href="/#{{.Alias}}" class="write">{{.SiteName}}</a></li> | |||
{{end}} | |||
<li><a href="/me/c/{{.Alias}}">Customize</a></li> | |||
<li><a href="/me/c/{{.Alias}}/stats">Stats</a></li> | |||
<li class="separator"><hr /></li> | |||
<li><a href="/me/c/"><img class="ic-18dp" src="/img/ic_blogs_dark@2x.png" /> View Blogs</a></li> | |||
{{if not .SingleUser}}<li><a href="/me/c/"><img class="ic-18dp" src="/img/ic_blogs_dark@2x.png" /> View Blogs</a></li>{{end}} | |||
<li><a href="/me/posts/"><img class="ic-18dp" src="/img/ic_list_dark@2x.png" /> View Drafts</a></li> | |||
</ul> | |||
</li> | |||
@@ -63,7 +67,7 @@ | |||
<!--p class="meta-note"><span>Private collection</span>. Only you can see this page.</p--> | |||
{{/*end*/}} | |||
{{if .PinnedPosts}}<nav> | |||
{{range .PinnedPosts}}<a class="pinned" href="{{if $.IsOwner}}/{{$.Alias}}/{{.Slug.String}}{{else}}{{.CanonicalURL}}{{end}}">{{.PlainDisplayTitle}}</a>{{end}}</nav> | |||
{{range .PinnedPosts}}<a class="pinned" href="{{if not $.SingleUser}}/{{$.Alias}}/{{.Slug.String}}{{else}}{{.CanonicalURL}}{{end}}">{{.PlainDisplayTitle}}</a>{{end}}</nav> | |||
{{end}} | |||
</header> | |||
@@ -96,7 +100,7 @@ | |||
<footer> | |||
<hr /> | |||
<nav dir="ltr"> | |||
<a class="home pubd" href="/">{{.SiteName}}</a> · powered by <a style="margin-left:0" href="https://writefreely.org">write freely</a> | |||
{{if not .SingleUser}}<a class="home pubd" href="/">{{.SiteName}}</a> · {{end}}powered by <a style="margin-left:0" href="https://writefreely.org">write freely</a> | |||
</nav> | |||
</footer> | |||
{{ end }} | |||
@@ -47,13 +47,13 @@ | |||
<div id="belt"> | |||
<div class="tool if-room"><a href="{{if .EditCollection}}{{.EditCollection.CanonicalURL}}{{.Post.Slug}}/edit{{else}}/{{.Post.Id}}/edit{{end}}" title="Edit post" id="edit"><img class="ic-24dp" src="/img/ic_edit_dark@2x.png" /></a></div> | |||
<div class="tool if-room room-2"><a href="#theme" title="Toggle theme" id="toggle-theme"><img class="ic-24dp" src="/img/ic_brightness_dark@2x.png" /></a></div> | |||
<div class="tool if-room room-1"><a href="{{if not .User}}/pad/posts{{else}}/me/posts/{{end}}" title="View posts" id="view-posts"><img class="ic-24dp" src="/img/ic_list_dark@2x.png" /></a></div> | |||
<div class="tool if-room room-1"><a href="/me/posts/" title="View posts" id="view-posts"><img class="ic-24dp" src="/img/ic_list_dark@2x.png" /></a></div> | |||
</div> | |||
</header> | |||
<div class="content-container tight"> | |||
<form action="/api/{{if .EditCollection}}collections/{{.EditCollection.Alias}}/{{end}}posts/{{.Post.Id}}" method="post" onsubmit="return updateMeta()"> | |||
<h2>Edit metadata: {{if .Post.Title}}{{.Post.Title}}{{else}}{{.Post.Id}}{{end}} <a href="/{{if .EditCollection}}{{.EditCollection.Alias}}/{{.Post.Slug}}{{else}}{{.Post.Id}}{{end}}">view post</a></h2> | |||
<h2>Edit metadata: {{if .Post.Title}}{{.Post.Title}}{{else}}{{.Post.Id}}{{end}} <a href="/{{if .EditCollection}}{{.EditCollection.Alias}}/{{.Post.Slug}}{{else}}{{if .SingleUser}}d/{{end}}{{.Post.Id}}{{end}}">view post</a></h2> | |||
{{if .Flashes}}<ul class="errors"> | |||
{{range .Flashes}}<li class="urgent">{{.}}</li>{{end}} | |||
@@ -1,6 +1,15 @@ | |||
{{define "footer"}} | |||
<footer class="contain-me"> | |||
<footer{{if not .SingleUser}} class="contain-me"{{end}}> | |||
<hr /> | |||
{{if .SingleUser}} | |||
<nav> | |||
<a class="home" href="/">{{.SiteName}}</a> | |||
<a href="https://writefreely.org/guide" target="guide">writer's guide</a> | |||
<a href="https://developers.write.as/" title="Build on Write Freely with our open developer API.">developers</a> | |||
<a href="https://github.com/writeas/writefreely">source code</a> | |||
<a href="https://writefreely.org">writefreely {{.Version}}</a> | |||
</nav> | |||
{{else}} | |||
<div class="marketing-section"> | |||
<div class="clearfix blurbs"> | |||
<div class="half"> | |||
@@ -21,5 +30,6 @@ | |||
</div> | |||
</div> | |||
</div> | |||
{{end}} | |||
</footer> | |||
{{end}} |
@@ -1,13 +1,13 @@ | |||
{{ define "posts" }} | |||
{{ range $el := .Posts }}<article id="post-{{.ID}}" class="{{.Font}} h-entry" itemscope itemtype="http://schema.org/BlogPosting"> | |||
{{if .IsScheduled}}<p class="badge">Scheduled</p>{{end}} | |||
{{if .Title.String}}<h2 class="post-title" itemprop="name" class="p-name">{{if .HasTitleLink}}{{.HTMLTitle}} <a class="user hidden action" href="{{if $.IsOwner}}/{{$.Alias}}/{{.Slug.String}}{{else}}{{$.CanonicalURL}}{{.Slug.String}}{{end}}">view</a>{{else}}<a href="{{if $.IsOwner}}/{{$.Alias}}/{{.Slug.String}}{{else}}{{$.CanonicalURL}}{{.Slug.String}}{{end}}" itemprop="url" class="u-url">{{.HTMLTitle}}</a>{{end}} | |||
{{if .Title.String}}<h2 class="post-title" itemprop="name" class="p-name">{{if .HasTitleLink}}{{.HTMLTitle}} <a class="user hidden action" href="{{if not $.SingleUser}}/{{$.Alias}}/{{.Slug.String}}{{else}}{{$.CanonicalURL}}{{.Slug.String}}{{end}}">view</a>{{else}}<a href="{{if not $.SingleUser}}/{{$.Alias}}/{{.Slug.String}}{{else}}{{$.CanonicalURL}}{{.Slug.String}}{{end}}" itemprop="url" class="u-url">{{.HTMLTitle}}</a>{{end}} | |||
{{if $.IsOwner}} | |||
<a class="user hidden action" href="/{{$.Alias}}/{{.Slug.String}}/edit">edit</a> | |||
<a class="user hidden action" href="/{{if not $.SingleUser}}{{$.Alias}}/{{end}}{{.Slug.String}}/edit">edit</a> | |||
{{if $.CanPin}}<a class="user hidden pin action" href="/{{$.Alias}}/{{.Slug.String}}/pin" onclick="pinPost(event, '{{.ID}}', '{{.Slug.String}}', '{{.PlainDisplayTitle}}')">pin</a>{{end}} | |||
<a class="user hidden delete action" onclick="delPost(event, '{{.ID}}')" href="/{{$.Alias}}/{{.Slug.String}}/delete">delete</a> | |||
{{if gt (len $.Collections) 1}}<div class="user hidden action flat-select"> | |||
<select id="move-{{.ID}}" onchange="postActions.multiMove(this, '{{.ID}}')" title="Move this post to another blog"> | |||
<select id="move-{{.ID}}" onchange="postActions.multiMove(this, '{{.ID}}', {{if $.SingleUser}}true{{else}}false{{end}})" title="Move this post to another blog"> | |||
<option style="display:none"></option> | |||
<option value="|anonymous|" style="font-style:italic">Draft</option> | |||
{{range $.Collections}}{{if ne .Alias $.Alias}}<option value="{{.Alias}}">{{.DisplayTitle}}</option>{{end}}{{end}} | |||
@@ -16,7 +16,7 @@ | |||
<img class="ic-18dp" src="/img/ic_down_arrow_dark@2x.png" /> | |||
</div>{{else}} | |||
{{range $.Collections}} | |||
<a class="user hidden action" href="/{{$el.ID}}" title="Change to a draft" onclick="postActions.move(this, '{{$el.ID}}', '|anonymous|');return false">change to <em>draft</em></a> | |||
<a class="user hidden action" href="/{{$el.ID}}" title="Change to a draft" onclick="postActions.move(this, '{{$el.ID}}', '|anonymous|', {{if $.SingleUser}}true{{else}}false{{end}});return false">change to <em>draft</em></a> | |||
{{end}} | |||
{{end}} | |||
{{end}} | |||
@@ -24,14 +24,14 @@ | |||
{{if $.Format.ShowDates}}<time class="dt-published" datetime="{{.Created}}" pubdate itemprop="datePublished" content="{{.Created}}">{{if not .Title.String}}<a href="{{$.CanonicalURL}}{{.Slug.String}}" itemprop="url">{{end}}{{.DisplayDate}}{{if not .Title.String}}</a>{{end}}</time>{{end}} | |||
{{else}} | |||
<h2 class="post-title" itemprop="name"> | |||
{{if $.Format.ShowDates}}<time class="dt-published" datetime="{{.Created}}" pubdate itemprop="datePublished" content="{{.Created}}"><a href="{{if $.IsOwner}}/{{$.Alias}}/{{.Slug.String}}{{else}}{{$.CanonicalURL}}{{.Slug.String}}{{end}}" itemprop="url" class="u-url">{{.DisplayDate}}</a></time>{{end}} | |||
{{if $.Format.ShowDates}}<time class="dt-published" datetime="{{.Created}}" pubdate itemprop="datePublished" content="{{.Created}}"><a href="{{if not $.SingleUser}}/{{$.Alias}}/{{.Slug.String}}{{else}}{{$.CanonicalURL}}{{.Slug.String}}{{end}}" itemprop="url" class="u-url">{{.DisplayDate}}</a></time>{{end}} | |||
{{if $.IsOwner}} | |||
{{if not $.Format.ShowDates}}<a class="user hidden action" href="{{if $.IsOwner}}/{{$.Alias}}/{{.Slug.String}}{{else}}{{$.CanonicalURL}}{{.Slug.String}}{{end}}">view</a>{{end}} | |||
<a class="user hidden action" href="/{{$.Alias}}/{{.Slug.String}}/edit">edit</a> | |||
{{if $.CanPin}}<a class="user hidden pin action" href="/{{$.Alias}}/{{.Slug.String}}/pin" onclick="pinPost(event, '{{.ID}}', '{{.Slug.String}}', '{{.PlainDisplayTitle}}')">pin</a>{{end}} | |||
{{if not $.Format.ShowDates}}<a class="user hidden action" href="{{if not $.SingleUser}}/{{$.Alias}}/{{.Slug.String}}{{else}}{{$.CanonicalURL}}{{.Slug.String}}{{end}}">view</a>{{end}} | |||
<a class="user hidden action" href="/{{if not $.SingleUser}}{{$.Alias}}/{{end}}{{.Slug.String}}/edit">edit</a> | |||
{{if $.CanPin}}<a class="user hidden pin action" href="/{{if not $.SingleUser}}{{$.Alias}}/{{end}}{{.Slug.String}}/pin" onclick="pinPost(event, '{{.ID}}', '{{.Slug.String}}', '{{.PlainDisplayTitle}}')">pin</a>{{end}} | |||
<a class="user hidden delete action" onclick="delPost(event, '{{.ID}}')" href="/{{$.Alias}}/{{.Slug.String}}/delete">delete</a> | |||
{{if gt (len $.Collections) 1}}<div class="user hidden action flat-select"> | |||
<select id="move-{{.ID}}" onchange="postActions.multiMove(this, '{{.ID}}')" title="Move this post to another blog"> | |||
<select id="move-{{.ID}}" onchange="postActions.multiMove(this, '{{.ID}}', {{if $.SingleUser}}true{{else}}false{{end}})" title="Move this post to another blog"> | |||
<option style="display:none"></option> | |||
<option value="|anonymous|" style="font-style:italic">Draft</option> | |||
{{range $.Collections}}{{if ne .Alias $.Alias}}<option value="{{.Alias}}">{{.DisplayTitle}}</option>{{end}}{{end}} | |||
@@ -40,7 +40,7 @@ | |||
<img class="ic-18dp" src="/img/ic_down_arrow_dark@2x.png" /> | |||
</div>{{else}} | |||
{{range $.Collections}} | |||
<a class="user hidden action" href="/{{$el.ID}}" title="Change to a draft" onclick="postActions.move(this, '{{$el.ID}}', '|anonymous|');return false">change to <em>draft</em></a> | |||
<a class="user hidden action" href="/{{$el.ID}}" title="Change to a draft" onclick="postActions.move(this, '{{$el.ID}}', '|anonymous|', {{if $.SingleUser}}true{{else}}false{{end}});return false">change to <em>draft</em></a> | |||
{{end}} | |||
{{end}} | |||
{{end}} | |||
@@ -19,9 +19,8 @@ | |||
<header id="tools"> | |||
<div id="clip"> | |||
<h1>{{if .User}}<a href="/me/c/" title="View blogs"><img class="ic-24dp" src="/img/ic_blogs_dark@2x.png" /></a>{{else}}<a href="/">w<span class="if-room">rite.as</span></a>{{end}} | |||
</h1> | |||
<nav id="target" class=""><ul> | |||
{{if not .SingleUser}}<h1><a href="/me/c/" title="View blogs"><img class="ic-24dp" src="/img/ic_blogs_dark@2x.png" /></a></h1>{{end}} | |||
<nav id="target" {{if .SingleUser}}style="margin-left:0"{{end}}><ul> | |||
{{if .Editing}}<li>{{if .EditCollection}}<a href="{{.EditCollection.CanonicalURL}}">{{.EditCollection.Title}}</a>{{else}}<a>Draft</a>{{end}}</li> | |||
{{else}}<li><a id="publish-to"><span id="target-name">Draft</span> <img class="ic-18dp" src="/img/ic_down_arrow_dark@2x.png" /></a> | |||
<ul> | |||
@@ -31,7 +30,13 @@ | |||
<li class="target" id="blog-{{.Alias}}"><a href="#{{.Alias}}"><i class="material-icons md-18">public</i> {{if .Title}}{{.Title}}{{else}}{{.Alias}}{{end}}</a></li> | |||
{{end}}{{end}} | |||
<li id="user-separator" class="separator"><hr /></li> | |||
{{ if .SingleUser }} | |||
<li><a href="/"><i class="material-icons md-18">launch</i> View Blog</a></li> | |||
<li><a href="/me/c/{{.Username}}"><i class="material-icons md-18">palette</i> Customize</a></li> | |||
<li><a href="/me/c/{{.Username}}/stats"><i class="material-icons md-18">trending_up</i> Stats</a></li> | |||
{{ else }} | |||
<li><a href="/me/c/"><i class="material-icons md-18">library_books</i> View Blogs</a></li> | |||
{{ end }} | |||
<li><a href="/me/posts/"><i class="material-icons md-18">view_list</i> View Drafts</a></li> | |||
<li><a href="/me/logout"><i class="material-icons md-18">power_settings_new</i> Log out</a></li> | |||
</ul> | |||
@@ -51,7 +56,7 @@ | |||
</div> | |||
<noscript style="margin-left: 2em;"><strong>NOTE</strong>: for now, you'll need Javascript enabled to post.</noscript> | |||
<div id="belt"> | |||
{{if .Editing}}<div class="tool hidden if-room"><a href="{{if .EditCollection}}{{.EditCollection.CanonicalURL}}{{.Post.Slug}}/edit/meta{{else}}/{{.Post.Id}}/meta{{end}}" title="Edit post metadata" id="edit-meta"><img class="ic-24dp" src="/img/ic_info_dark@2x.png" /></a></div>{{end}} | |||
{{if .Editing}}<div class="tool hidden if-room"><a href="{{if .EditCollection}}{{.EditCollection.CanonicalURL}}{{.Post.Slug}}/edit/meta{{else}}/{{if .SingleUser}}d/{{end}}{{.Post.Id}}/meta{{end}}" title="Edit post metadata" id="edit-meta"><img class="ic-24dp" src="/img/ic_info_dark@2x.png" /></a></div>{{end}} | |||
<div class="tool hidden if-room room-2"><a href="#theme" title="Toggle theme" id="toggle-theme"><img class="ic-24dp" src="/img/ic_brightness_dark@2x.png" /></a></div> | |||
<div class="tool if-room room-1"><a href="{{if not .User}}/pad/posts{{else}}/me/posts/{{end}}" title="View posts" id="view-posts"><img class="ic-24dp" src="/img/ic_list_dark@2x.png" /></a></div> | |||
<div class="tool"><a href="#publish" title="Publish" id="publish"><img class="ic-24dp" src="/img/ic_send_dark@2x.png" /></a></div> | |||
@@ -180,12 +185,12 @@ | |||
if (http.status == 200 || http.status == 201) { | |||
data = JSON.parse(http.responseText); | |||
id = data.data.id; | |||
nextURL = '/'+id; | |||
nextURL = '{{if .SingleUser}}/d{{end}}/'+id; | |||
{{ if not .Post.Id }} | |||
// Post created | |||
if (postTarget != 'anonymous') { | |||
nextURL = '/'+postTarget+'/'+data.data.slug; | |||
nextURL = {{if not .SingleUser}}'/'+postTarget+{{end}}'/'+data.data.slug; | |||
} | |||
editToken = data.data.token; | |||
@@ -42,7 +42,7 @@ | |||
{{if .IsCode}}<a href="/{{.ID}}.txt" rel="noindex" dir="{{.Direction}}">View raw</a>{{end}} | |||
{{ if .Username }} | |||
{{if .IsOwner}} | |||
<a href="/{{.ID}}/edit" dir="{{.Direction}}">Edit</a> | |||
<a href="/{{if .SingleUser}}d/{{end}}{{.ID}}/edit" dir="{{.Direction}}">Edit</a> | |||
{{end}} | |||
<a class="xtra-feature dash-nav" href="/me/posts/" dir="{{.Direction}}">Drafts</a> | |||
{{ end }} | |||
@@ -11,14 +11,14 @@ | |||
{{ if .AnonymousPosts }}<div class="atoms posts"> | |||
{{ range $el := .AnonymousPosts }}<div id="post-{{.ID}}" class="post"> | |||
<h3><a href="/{{.ID}}" itemprop="url">{{.DisplayTitle}}</a></h3> | |||
<h3><a href="/{{if $.SingleUser}}d/{{end}}{{.ID}}" itemprop="url">{{.DisplayTitle}}</a></h3> | |||
<h4> | |||
<date datetime="{{.Created}}" pubdate itemprop="datePublished" content="{{.Created}}">{{.DisplayDate}}</date> | |||
<a class="action" href="/{{.ID}}/edit">edit</a> | |||
<a class="action" href="/{{if $.SingleUser}}d/{{end}}{{.ID}}/edit">edit</a> | |||
<a class="delete action" href="/{{.ID}}" onclick="delPost(event, '{{.ID}}', true)">delete</a> | |||
{{ if $.Collections }} | |||
{{if gt (len $.Collections) 1}}<div class="action flat-select"> | |||
<select id="move-{{.ID}}" onchange="postActions.multiMove(this, '{{.ID}}')" title="Move this post to one of your blogs"> | |||
<select id="move-{{.ID}}" onchange="postActions.multiMove(this, '{{.ID}}', {{if $.SingleUser}}true{{else}}false{{end}})" title="Move this post to one of your blogs"> | |||
<option style="display:none"></option> | |||
{{range $.Collections}}<option value="{{.Alias}}">{{.DisplayTitle}}</option>{{end}} | |||
</select> | |||
@@ -26,7 +26,7 @@ | |||
<img class="ic-18dp" src="/img/ic_down_arrow_dark@2x.png" /> | |||
</div>{{else}} | |||
{{range $.Collections}} | |||
<a class="action" href="/{{$el.ID}}" title="Publish this post to your blog '{{.DisplayTitle}}'" onclick="postActions.move(this, '{{$el.ID}}', '{{.Alias}}');return false">move to {{.DisplayTitle}}</a> | |||
<a class="action" href="/{{$el.ID}}" title="Publish this post to your blog '{{.DisplayTitle}}'" onclick="postActions.move(this, '{{$el.ID}}', '{{.Alias}}', {{if $.SingleUser}}true{{else}}false{{end}});return false">move to {{.DisplayTitle}}</a> | |||
{{end}} | |||
{{end}} | |||
{{ end }} | |||
@@ -30,7 +30,7 @@ | |||
{{.FriendlyHost}}/<strong>{{.Alias}}</strong>/ | |||
</li> | |||
<li> | |||
<strong id="normal-handle-env" class="fedi-handle" {{if or (not .Federation) .SingleUser}}style="display:none"{{end}}>@<span id="fedi-handle">{{.Alias}}</span>@<span id="fedi-domain">{{.FriendlyHost}}</span></strong> | |||
<strong id="normal-handle-env" class="fedi-handle" {{if not .Federation}}style="display:none"{{end}}>@<span id="fedi-handle">{{.Alias}}</span>@<span id="fedi-domain">{{.FriendlyHost}}</span></strong> | |||
</li> | |||
</ul> | |||
</div> | |||
@@ -15,7 +15,28 @@ | |||
<link rel="apple-touch-icon" sizes="180x180" href="/img/touch-icon-180.png"> | |||
</head> | |||
<body id="me"> | |||
<header> | |||
<header{{if .SingleUser}} class="singleuser"{{end}}> | |||
{{if .SingleUser}} | |||
<nav id="user-nav"> | |||
<nav class="dropdown-nav"> | |||
<ul><li><a href="/" title="View blog" class="title">{{.SiteName}}</a> <img class="ic-18dp" src="/img/ic_down_arrow_dark@2x.png" /> | |||
<ul> | |||
<li><a href="/me/c/{{.Username}}">Customize</a></li> | |||
<li><a href="/me/c/{{.Username}}/stats">Stats</a></li> | |||
<li class="separator"><hr /></li> | |||
<li><a href="/me/settings">Settings</a></li> | |||
<li><a href="/me/export">Export</a></li> | |||
<li class="separator"><hr /></li> | |||
<li><a href="/me/logout">Log out</a></li> | |||
</ul></li> | |||
</ul> | |||
</nav> | |||
<nav class="tabs"> | |||
<a href="/me/posts/"{{if eq .Path "/me/posts/"}} class="selected"{{end}}>Drafts</a> | |||
<a href="/me/new">New Post</a> | |||
</nav> | |||
</nav> | |||
{{else}} | |||
<h1><a href="/" title="Return to editor">{{.SiteName}}</a></h1> | |||
<nav id="user-nav"> | |||
<nav class="dropdown-nav"> | |||
@@ -32,6 +53,7 @@ | |||
<a href="/me/posts/"{{if eq .Path "/me/posts/"}} class="selected"{{end}}>Drafts</a> | |||
</nav> | |||
</nav> | |||
{{end}} | |||
</header> | |||
<div id="official-writing"> | |||
{{end}} |