diff --git a/l18n/l18n.go b/l18n/l18n.go index 65d0f70..3892326 100644 --- a/l18n/l18n.go +++ b/l18n/l18n.go @@ -189,6 +189,7 @@ var localizations = map[string]string{ "en.ui.list_heading": "List of hyphae", "en.ui.list_title": "List of pages", "en.ui.login": "Login", + "en.ui.logout_link": "Log out", "en.ui.media_download": "Download media", "en.ui.media_noaudio": "Your browser does not support audio.", "en.ui.media_noaudio_link": "Download audio", @@ -427,6 +428,7 @@ var localizations = map[string]string{ "ru.ui.list_heading": "Список гиф", "ru.ui.list_title": "Список страниц", "ru.ui.login": "Войти", + "ru.ui.logout_link": "Выйти", "ru.ui.media_download": "Скачать медиа", "ru.ui.media_noaudio": "Ваш браузер не поддерживает аудио.", "ru.ui.media_noaudio_link": "Скачать аудио", diff --git a/l18n_src/en/ui.json b/l18n_src/en/ui.json index b431f6c..480ea32 100644 --- a/l18n_src/en/ui.json +++ b/l18n_src/en/ui.json @@ -19,6 +19,7 @@ "list_desc+other": "hyphae", "edit_link": "Edit text", + "logout_link": "Log out", "history_link": "View history", "rename_link": "Rename", "delete_link": "Delete", diff --git a/l18n_src/ru/ui.json b/l18n_src/ru/ui.json index 3bc5a52..9ce8728 100644 --- a/l18n_src/ru/ui.json +++ b/l18n_src/ru/ui.json @@ -20,6 +20,7 @@ "list_desc+many": "гиф", "edit_link": "Редактировать", + "logout_link": "Выйти", "history_link": "История", "rename_link": "Переименовать", "delete_link": "Удалить", diff --git a/static/default.css b/static/default.css index 29b4464..89eaeb1 100644 --- a/static/default.css +++ b/static/default.css @@ -778,12 +778,12 @@ kbd { /* * Buttons beside the hypha title */ -.edit-btn { +.btn_navititle { float: right; margin: -0.25rem 0; padding: 0; } -.edit-btn__link { +.btn__link_navititle { display: block; text-decoration: none; color: inherit; diff --git a/util/util.go b/util/util.go index 5759a49..66fedd0 100644 --- a/util/util.go +++ b/util/util.go @@ -64,6 +64,13 @@ func CanonicalName(name string) string { return util.CanonicalName(name) } +// IsProfileName if the given hypha name is a profile name. It takes configuration into consideration. +// +// With default configuration, u/ is the prefix such names have. For example, u/wikimind matches. Note that u/wikimind/sub does not. +func IsProfileName(hyphaName string) bool { + return strings.HasPrefix(hyphaName, cfg.UserHypha+"/") && strings.Count(hyphaName, "/") == 1 +} + // HyphaNameFromRq extracts hypha name from http request. You have to also pass the action which is embedded in the url or several actions. For url /hypha/hypha, the action would be "hypha". func HyphaNameFromRq(rq *http.Request, actions ...string) string { p := rq.URL.Path diff --git a/views/readers.qtpl b/views/readers.qtpl index edf904b..b1fe0f2 100644 --- a/views/readers.qtpl +++ b/views/readers.qtpl @@ -91,9 +91,15 @@ If you rename .prevnext, change the docs too.
- {% if u.CanProceed("edit") %}
- {%s lc.Get("ui.edit_link") %} + + {% if u.CanProceed("edit") %}
+ {%s lc.Get("ui.edit_link") %}
{% endif %} + + {% if cfg.UseAuth && util.IsProfileName(h.Name) && u.Name == strings.TrimPrefix(h.Name, cfg.UserHypha + "/") %}
+ {%s lc.Get("ui.logout_link") %} +
{% endif %} + {%s= NaviTitleHTML(h) %} {% if h.Exists %} {%s= contents %} @@ -144,4 +150,4 @@ If you rename .prevnext, change the docs too. {% for _, scriptPath := range cfg.ViewScripts %} {% endfor %} -{% endfunc %} \ No newline at end of file +{% endfunc %} diff --git a/views/readers.qtpl.go b/views/readers.qtpl.go index 2ba62d9..37b8f1b 100644 --- a/views/readers.qtpl.go +++ b/views/readers.qtpl.go @@ -319,286 +319,304 @@ func StreamHyphaHTML(qw422016 *qt422016.Writer, rq *http.Request, lc *l18n.Local
+ `) -//line views/readers.qtpl:94 +//line views/readers.qtpl:95 if u.CanProceed("edit") { -//line views/readers.qtpl:94 - qw422016.N().S(`
- + `) -//line views/readers.qtpl:95 +//line views/readers.qtpl:96 qw422016.E().S(lc.Get("ui.edit_link")) -//line views/readers.qtpl:95 +//line views/readers.qtpl:96 qw422016.N().S(`
`) -//line views/readers.qtpl:96 +//line views/readers.qtpl:97 } -//line views/readers.qtpl:96 - qw422016.N().S(` - `) //line views/readers.qtpl:97 + qw422016.N().S(` + + `) +//line views/readers.qtpl:99 + if cfg.UseAuth && util.IsProfileName(h.Name) && u.Name == strings.TrimPrefix(h.Name, cfg.UserHypha+"/") { +//line views/readers.qtpl:99 + qw422016.N().S(`
+ `) +//line views/readers.qtpl:100 + qw422016.E().S(lc.Get("ui.logout_link")) +//line views/readers.qtpl:100 + qw422016.N().S(` +
`) +//line views/readers.qtpl:101 + } +//line views/readers.qtpl:101 + qw422016.N().S(` + + `) +//line views/readers.qtpl:103 qw422016.N().S(NaviTitleHTML(h)) -//line views/readers.qtpl:97 +//line views/readers.qtpl:103 qw422016.N().S(` `) -//line views/readers.qtpl:98 +//line views/readers.qtpl:104 if h.Exists { -//line views/readers.qtpl:98 +//line views/readers.qtpl:104 qw422016.N().S(` `) -//line views/readers.qtpl:99 +//line views/readers.qtpl:105 qw422016.N().S(contents) -//line views/readers.qtpl:99 +//line views/readers.qtpl:105 qw422016.N().S(` `) -//line views/readers.qtpl:100 +//line views/readers.qtpl:106 } else { -//line views/readers.qtpl:100 +//line views/readers.qtpl:106 qw422016.N().S(` `) -//line views/readers.qtpl:101 +//line views/readers.qtpl:107 streamnonExistentHyphaNotice(qw422016, h, u, lc) -//line views/readers.qtpl:101 +//line views/readers.qtpl:107 qw422016.N().S(` `) -//line views/readers.qtpl:102 +//line views/readers.qtpl:108 } -//line views/readers.qtpl:102 +//line views/readers.qtpl:108 qw422016.N().S(`
`) -//line views/readers.qtpl:105 +//line views/readers.qtpl:111 if prevHyphaName != "" { -//line views/readers.qtpl:105 +//line views/readers.qtpl:111 qw422016.N().S(` `) -//line views/readers.qtpl:107 +//line views/readers.qtpl:113 } -//line views/readers.qtpl:107 +//line views/readers.qtpl:113 qw422016.N().S(` `) -//line views/readers.qtpl:108 +//line views/readers.qtpl:114 if nextHyphaName != "" { -//line views/readers.qtpl:108 +//line views/readers.qtpl:114 qw422016.N().S(` `) -//line views/readers.qtpl:110 +//line views/readers.qtpl:116 } -//line views/readers.qtpl:110 +//line views/readers.qtpl:116 qw422016.N().S(`
`) -//line views/readers.qtpl:112 +//line views/readers.qtpl:118 StreamSubhyphaeHTML(qw422016, subhyphae, lc) -//line views/readers.qtpl:112 +//line views/readers.qtpl:118 qw422016.N().S(`
`) -//line views/readers.qtpl:117 +//line views/readers.qtpl:123 streamhyphaInfo(qw422016, rq, h) -//line views/readers.qtpl:117 +//line views/readers.qtpl:123 qw422016.N().S(`
`) -//line views/readers.qtpl:120 +//line views/readers.qtpl:126 streamsiblingHyphaeHTML(qw422016, siblings, lc) -//line views/readers.qtpl:120 +//line views/readers.qtpl:126 qw422016.N().S(`
`) -//line views/readers.qtpl:122 +//line views/readers.qtpl:128 streamviewScripts(qw422016) -//line views/readers.qtpl:122 +//line views/readers.qtpl:128 qw422016.N().S(` `) -//line views/readers.qtpl:123 +//line views/readers.qtpl:129 } -//line views/readers.qtpl:123 +//line views/readers.qtpl:129 func WriteHyphaHTML(qq422016 qtio422016.Writer, rq *http.Request, lc *l18n.Localizer, h *hyphae.Hypha, contents string) { -//line views/readers.qtpl:123 +//line views/readers.qtpl:129 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/readers.qtpl:123 +//line views/readers.qtpl:129 StreamHyphaHTML(qw422016, rq, lc, h, contents) -//line views/readers.qtpl:123 +//line views/readers.qtpl:129 qt422016.ReleaseWriter(qw422016) -//line views/readers.qtpl:123 +//line views/readers.qtpl:129 } -//line views/readers.qtpl:123 +//line views/readers.qtpl:129 func HyphaHTML(rq *http.Request, lc *l18n.Localizer, h *hyphae.Hypha, contents string) string { -//line views/readers.qtpl:123 +//line views/readers.qtpl:129 qb422016 := qt422016.AcquireByteBuffer() -//line views/readers.qtpl:123 +//line views/readers.qtpl:129 WriteHyphaHTML(qb422016, rq, lc, h, contents) -//line views/readers.qtpl:123 +//line views/readers.qtpl:129 qs422016 := string(qb422016.B) -//line views/readers.qtpl:123 +//line views/readers.qtpl:129 qt422016.ReleaseByteBuffer(qb422016) -//line views/readers.qtpl:123 +//line views/readers.qtpl:129 return qs422016 -//line views/readers.qtpl:123 +//line views/readers.qtpl:129 } -//line views/readers.qtpl:125 +//line views/readers.qtpl:131 func StreamRevisionHTML(qw422016 *qt422016.Writer, rq *http.Request, lc *l18n.Localizer, h *hyphae.Hypha, contents, revHash string) { -//line views/readers.qtpl:125 +//line views/readers.qtpl:131 qw422016.N().S(` `) -//line views/readers.qtpl:127 +//line views/readers.qtpl:133 siblings, subhyphae, _, _ := tree.Tree(h.Name) -//line views/readers.qtpl:128 +//line views/readers.qtpl:134 qw422016.N().S(`

`) -//line views/readers.qtpl:132 +//line views/readers.qtpl:138 qw422016.E().S(lc.Get("ui.revision_warning")) -//line views/readers.qtpl:132 +//line views/readers.qtpl:138 qw422016.N().S(` `) -//line views/readers.qtpl:132 +//line views/readers.qtpl:138 qw422016.E().S(lc.Get("ui.revision_link")) -//line views/readers.qtpl:132 +//line views/readers.qtpl:138 qw422016.N().S(`

`) -//line views/readers.qtpl:133 +//line views/readers.qtpl:139 qw422016.N().S(NaviTitleHTML(h)) -//line views/readers.qtpl:133 +//line views/readers.qtpl:139 qw422016.N().S(` `) -//line views/readers.qtpl:134 +//line views/readers.qtpl:140 qw422016.N().S(contents) -//line views/readers.qtpl:134 +//line views/readers.qtpl:140 qw422016.N().S(`
`) -//line views/readers.qtpl:136 +//line views/readers.qtpl:142 StreamSubhyphaeHTML(qw422016, subhyphae, lc) -//line views/readers.qtpl:136 +//line views/readers.qtpl:142 qw422016.N().S(`
`) -//line views/readers.qtpl:138 +//line views/readers.qtpl:144 streamsiblingHyphaeHTML(qw422016, siblings, lc) -//line views/readers.qtpl:138 +//line views/readers.qtpl:144 qw422016.N().S(`
`) -//line views/readers.qtpl:140 +//line views/readers.qtpl:146 streamviewScripts(qw422016) -//line views/readers.qtpl:140 +//line views/readers.qtpl:146 qw422016.N().S(` `) -//line views/readers.qtpl:141 +//line views/readers.qtpl:147 } -//line views/readers.qtpl:141 +//line views/readers.qtpl:147 func WriteRevisionHTML(qq422016 qtio422016.Writer, rq *http.Request, lc *l18n.Localizer, h *hyphae.Hypha, contents, revHash string) { -//line views/readers.qtpl:141 +//line views/readers.qtpl:147 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/readers.qtpl:141 +//line views/readers.qtpl:147 StreamRevisionHTML(qw422016, rq, lc, h, contents, revHash) -//line views/readers.qtpl:141 +//line views/readers.qtpl:147 qt422016.ReleaseWriter(qw422016) -//line views/readers.qtpl:141 +//line views/readers.qtpl:147 } -//line views/readers.qtpl:141 +//line views/readers.qtpl:147 func RevisionHTML(rq *http.Request, lc *l18n.Localizer, h *hyphae.Hypha, contents, revHash string) string { -//line views/readers.qtpl:141 +//line views/readers.qtpl:147 qb422016 := qt422016.AcquireByteBuffer() -//line views/readers.qtpl:141 +//line views/readers.qtpl:147 WriteRevisionHTML(qb422016, rq, lc, h, contents, revHash) -//line views/readers.qtpl:141 +//line views/readers.qtpl:147 qs422016 := string(qb422016.B) -//line views/readers.qtpl:141 +//line views/readers.qtpl:147 qt422016.ReleaseByteBuffer(qb422016) -//line views/readers.qtpl:141 +//line views/readers.qtpl:147 return qs422016 -//line views/readers.qtpl:141 +//line views/readers.qtpl:147 } -//line views/readers.qtpl:143 +//line views/readers.qtpl:149 func streamviewScripts(qw422016 *qt422016.Writer) { -//line views/readers.qtpl:143 +//line views/readers.qtpl:149 qw422016.N().S(` `) -//line views/readers.qtpl:144 +//line views/readers.qtpl:150 for _, scriptPath := range cfg.ViewScripts { -//line views/readers.qtpl:144 +//line views/readers.qtpl:150 qw422016.N().S(` `) -//line views/readers.qtpl:146 +//line views/readers.qtpl:152 } -//line views/readers.qtpl:146 +//line views/readers.qtpl:152 qw422016.N().S(` `) -//line views/readers.qtpl:147 +//line views/readers.qtpl:153 } -//line views/readers.qtpl:147 +//line views/readers.qtpl:153 func writeviewScripts(qq422016 qtio422016.Writer) { -//line views/readers.qtpl:147 +//line views/readers.qtpl:153 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/readers.qtpl:147 +//line views/readers.qtpl:153 streamviewScripts(qw422016) -//line views/readers.qtpl:147 +//line views/readers.qtpl:153 qt422016.ReleaseWriter(qw422016) -//line views/readers.qtpl:147 +//line views/readers.qtpl:153 } -//line views/readers.qtpl:147 +//line views/readers.qtpl:153 func viewScripts() string { -//line views/readers.qtpl:147 +//line views/readers.qtpl:153 qb422016 := qt422016.AcquireByteBuffer() -//line views/readers.qtpl:147 +//line views/readers.qtpl:153 writeviewScripts(qb422016) -//line views/readers.qtpl:147 +//line views/readers.qtpl:153 qs422016 := string(qb422016.B) -//line views/readers.qtpl:147 +//line views/readers.qtpl:153 qt422016.ReleaseByteBuffer(qb422016) -//line views/readers.qtpl:147 +//line views/readers.qtpl:153 return qs422016 -//line views/readers.qtpl:147 +//line views/readers.qtpl:153 }