miniflux/template/views.go
Patrick 3e1e0b604f
Add generic OpenID Connect provider (OAuth2)
This adds the oauth2 provider `oidc`. It needs an additional argument, the OIDC discovery endpoint to figure out where the auth and token URLs are.

Configuration is similar to setting up the Google Authentication with these changes:

 * `OAUTH2_PROVIDER = oidc`
 * `OAUTH2_OIDC_DISCOVERY_ENDPOINT = https://auth.exampe.org/discovery`
2020-03-07 18:45:19 -08:00

1437 lines
61 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Code generated by go generate; DO NOT EDIT.
package template // import "miniflux.app/template"
var templateViewsMap = map[string]string{
"about": `{{ define "title"}}{{ t "page.about.title" }}{{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.about.title" }}</h1>
{{ template "settings_menu" dict "user" .user }}
</section>
<div class="panel">
<h3>Miniflux</h3>
<ul>
<li><strong>{{ t "page.about.version" }}</strong> {{ .version }}</li>
<li><strong>{{ t "page.about.build_date" }}</strong> {{ .build_date }}</li>
</ul>
</div>
<div class="panel">
<h3>{{ t "page.about.credits" }}</h3>
<ul>
<li><strong>{{ t "page.about.author" }}</strong> Frédéric Guillot</li>
<li><strong>{{ t "page.about.license" }}</strong> Apache 2.0</li>
</ul>
</div>
{{ end }}
`,
"add_subscription": `{{ define "title"}}{{ t "page.add_feed.title" }}{{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.add_feed.title" }}</h1>
{{ template "feed_menu" }}
</section>
{{ if not .categories }}
<p class="alert alert-error">{{ t "page.add_feed.no_category" }}</p>
{{ else }}
<form action="{{ route "submitSubscription" }}" method="post" autocomplete="off">
<input type="hidden" name="csrf" value="{{ .csrf }}">
{{ if .errorMessage }}
<div class="alert alert-error">{{ t .errorMessage }}</div>
{{ end }}
<label for="form-url">{{ t "page.add_feed.label.url" }}</label>
<input type="url" name="url" id="form-url" placeholder="https://domain.tld/" value="{{ .form.URL }}" required autofocus>
<label for="form-category">{{ t "form.feed.label.category" }}</label>
<select id="form-category" name="category_id">
{{ range .categories }}
<option value="{{ .ID }}" {{ if eq $.form.CategoryID .ID }}selected="selected"{{ end }}>{{ .Title }}</option>
{{ end }}
</select>
<details>
<summary>{{ t "page.add_feed.legend.advanced_options" }}</summary>
<div class="details-content">
<label><input type="checkbox" name="crawler" value="1" {{ if .form.Crawler }}checked{{ end }}> {{ t "form.feed.label.crawler" }}</label>
<label for="form-user-agent">{{ t "form.feed.label.user_agent" }}</label>
<input type="text" name="user_agent" id="form-user-agent" placeholder="{{ .defaultUserAgent }}" value="{{ .form.UserAgent }}" autocomplete="off">
<label for="form-feed-username">{{ t "form.feed.label.feed_username" }}</label>
<input type="text" name="feed_username" id="form-feed-username" value="{{ .form.Username }}">
<label for="form-feed-password">{{ t "form.feed.label.feed_password" }}</label>
<!--
We are using the type "text" otherwise Firefox always autocomplete this password:
- autocomplete="off" or autocomplete="new-password" doesn't change anything
- Changing the input ID doesn't change anything
- Using a different input name doesn't change anything
-->
<input type="text" name="feed_password" id="form-feed-password" value="{{ .form.Password }}">
<label for="form-scraper-rules">{{ t "form.feed.label.scraper_rules" }}</label>
<input type="text" name="scraper_rules" id="form-scraper-rules" value="{{ .form.ScraperRules }}">
<label for="form-rewrite-rules">{{ t "form.feed.label.rewrite_rules" }}</label>
<input type="text" name="rewrite_rules" id="form-rewrite-rules" value="{{ .form.RewriteRules }}">
</div>
</details>
<div class="buttons">
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.loading" }}">{{ t "page.add_feed.submit" }}</button>
</div>
</form>
{{ end }}
{{ end }}
`,
"api_keys": `{{ define "title"}}{{ t "page.api_keys.title" }}{{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.api_keys.title" }}</h1>
{{ template "settings_menu" dict "user" .user }}
</section>
{{ if .apiKeys }}
{{ range .apiKeys }}
<table>
<tr>
<th class="column-25">{{ t "page.api_keys.table.description" }}</th>
<td>{{ .Description }}</td>
</tr>
<tr>
<th>{{ t "page.api_keys.table.token" }}</th>
<td>{{ .Token }}</td>
</tr>
<tr>
<th>{{ t "page.api_keys.table.last_used_at" }}</th>
<td>
{{ if .LastUsedAt }}
<time datetime="{{ isodate .LastUsedAt }}" title="{{ isodate .LastUsedAt }}">{{ elapsed $.user.Timezone .LastUsedAt }}</time>
{{ else }}
{{ t "page.api_keys.never_used" }}
{{ end }}
</td>
</tr>
<tr>
<th>{{ t "page.api_keys.table.created_at" }}</th>
<td>
<time datetime="{{ isodate .CreatedAt }}" title="{{ isodate .CreatedAt }}">{{ elapsed $.user.Timezone .CreatedAt }}</time>
</td>
</tr>
<tr>
<th>{{ t "page.api_keys.table.actions" }}</th>
<td>
<a href="#"
data-confirm="true"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}"
data-url="{{ route "removeAPIKey" "keyID" .ID }}">{{ t "action.remove" }}</a>
</td>
</tr>
</table>
<br>
{{ end }}
{{ end }}
<h3>{{ t "page.integration.miniflux_api" }}</h3>
<div class="panel">
<ul>
<li>
{{ t "page.integration.miniflux_api_endpoint" }} = <strong>{{ baseURL }}/v1/</strong>
</li>
<li>
{{ t "page.integration.miniflux_api_username" }} = <strong>{{ .user.Username }}</strong>
</li>
<li>
{{ t "page.integration.miniflux_api_password" }} = <strong>{{ t "page.integration.miniflux_api_password_value" }}</strong>
</li>
</ul>
</div>
<p>
<a href="{{ route "createAPIKey" }}" class="button button-primary">{{ t "menu.create_api_key" }}</a>
</p>
{{ end }}
`,
"bookmark_entries": `{{ define "title"}}{{ t "page.starred.title" }} ({{ .total }}){{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.starred.title" }} ({{ .total }})</h1>
</section>
{{ if not .entries }}
<p class="alert alert-info">{{ t "alert.no_bookmark" }}</p>
{{ else }}
<div class="items">
{{ range .entries }}
<article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
<div class="item-header">
<span class="item-title">
{{ if ne .Feed.Icon.IconID 0 }}
<img src="{{ route "icon" "iconID" .Feed.Icon.IconID }}" width="16" height="16" loading="lazy" alt="{{ .Feed.Title }}">
{{ end }}
<a href="{{ route "starredEntry" "entryID" .ID }}">{{ .Title }}</a>
</span>
<span class="category"><a href="{{ route "categoryEntries" "categoryID" .Feed.Category.ID }}">{{ .Feed.Category.Title }}</a></span>
</div>
{{ template "item_meta" dict "user" $.user "entry" . "hasSaveEntry" $.hasSaveEntry }}
</article>
{{ end }}
</div>
{{ template "pagination" .pagination }}
{{ end }}
{{ end }}
`,
"categories": `{{ define "title"}}{{ t "page.categories.title" }} ({{ .total }}){{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.categories.title" }} ({{ .total }})</h1>
<ul>
<li>
<a href="{{ route "createCategory" }}">{{ t "menu.create_category" }}</a>
</li>
</ul>
</section>
{{ if not .categories }}
<p class="alert alert-error">{{ t "alert.no_category" }}</p>
{{ else }}
<div class="items">
{{ range .categories }}
<article class="item">
<div class="item-header">
<span class="item-title">
<a href="{{ route "categoryEntries" "categoryID" .ID }}">{{ .Title }}</a>
</span>
(<span title="{{ if eq .FeedCount 0 }}{{ t "page.categories.no_feed" }}{{ else }}{{ plural "page.categories.feed_count" .FeedCount .FeedCount }}{{ end }}">{{ .FeedCount }}</span>)
</div>
<div class="item-meta">
<ul>
<li>
<a href="{{ route "categoryFeeds" "categoryID" .ID }}">{{ t "page.categories.feeds" }}</a>
</li>
<li>
<a href="{{ route "editCategory" "categoryID" .ID }}">{{ t "menu.edit_category" }}</a>
</li>
{{ if eq .FeedCount 0 }}
<li>
<a href="#"
data-confirm="true"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}"
data-url="{{ route "removeCategory" "categoryID" .ID }}">{{ t "action.remove" }}</a>
</li>
{{ end }}
</ul>
</div>
</article>
{{ end }}
</div>
{{ end }}
{{ end }}
`,
"category_entries": `{{ define "title"}}{{ .category.Title }} ({{ .total }}){{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ .category.Title }} ({{ .total }})</h1>
<ul>
{{ if .entries }}
<li>
<a href="#"
data-action="markPageAsRead"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}"
data-show-only-unread="{{ if .showOnlyUnreadEntries }}1{{ end }}">{{ t "menu.mark_page_as_read" }}</a>
</li>
{{ end }}
{{ if .showOnlyUnreadEntries }}
<li>
<a href="{{ route "categoryEntriesAll" "categoryID" .category.ID }}">{{ t "menu.show_all_entries" }}</a>
</li>
{{ else }}
<li>
<a href="{{ route "categoryEntries" "categoryID" .category.ID }}">{{ t "menu.show_only_unread_entries" }}</a>
</li>
{{ end }}
<li>
<a href="{{ route "categoryFeeds" "categoryID" .category.ID }}">{{ t "menu.feeds" }}</a>
</li>
</ul>
</section>
{{ if not .entries }}
<p class="alert">{{ t "alert.no_category_entry" }}</p>
{{ else }}
<div class="items">
{{ range .entries }}
<article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
<div class="item-header">
<span class="item-title">
{{ if ne .Feed.Icon.IconID 0 }}
<img src="{{ route "icon" "iconID" .Feed.Icon.IconID }}" width="16" height="16" loading="lazy" alt="{{ .Feed.Title }}">
{{ end }}
<a href="{{ route "categoryEntry" "categoryID" .Feed.Category.ID "entryID" .ID }}">{{ .Title }}</a>
</span>
<span class="category"><a href="{{ route "categoryEntries" "categoryID" .Feed.Category.ID }}">{{ .Feed.Category.Title }}</a></span>
</div>
{{ template "item_meta" dict "user" $.user "entry" . "hasSaveEntry" $.hasSaveEntry }}
</article>
{{ end }}
</div>
<section class="page-footer">
{{ if .entries }}
<ul>
<li>
<a href="#"
data-action="markPageAsRead"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}"
data-show-only-unread="{{ if .showOnlyUnreadEntries }}1{{ end }}">{{ t "menu.mark_page_as_read" }}</a>
</li>
</ul>
{{ end }}
</section>
{{ template "pagination" .pagination }}
{{ end }}
{{ end }}
`,
"category_feeds": `{{ define "title"}}{{ .category.Title }} &gt; {{ t "page.feeds.title" }} ({{ .total }}){{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ .category.Title }} &gt; {{ t "page.feeds.title" }} ({{ .total }})</h1>
<ul>
<li>
<a href="{{ route "categories" }}">{{ t "menu.categories" }}</a>
</li>
<li>
<a href="{{ route "editCategory" "categoryID" .category.ID }}">{{ t "menu.edit_category" }}</a>
</li>
{{ if eq .total 0 }}
<li>
<a href="#"
data-confirm="true"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}"
data-redirect-url="{{ route "categories" }}"
data-url="{{ route "removeCategory" "categoryID" .category.ID }}">{{ t "action.remove" }}</a>
</li>
{{ end }}
</ul>
</section>
{{ if not .feeds }}
<p class="alert">{{ t "alert.no_feed_in_category" }}</p>
{{ else }}
{{ template "feed_list" dict "user" .user "feeds" .feeds "ParsingErrorCount" .ParsingErrorCount }}
{{ end }}
{{ end }}
`,
"choose_subscription": `{{ define "title"}}{{ t "page.add_feed.title" }}{{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.add_feed.title" }}</h1>
{{ template "feed_menu" }}
</section>
<form action="{{ route "chooseSubscription" }}" method="POST">
<input type="hidden" name="csrf" value="{{ .csrf }}">
<input type="hidden" name="category_id" value="{{ .form.CategoryID }}">
<input type="hidden" name="user_agent" value="{{ .form.UserAgent }}">
<input type="hidden" name="feed_username" value="{{ .form.Username }}">
<input type="hidden" name="feed_password" value="{{ .form.Password }}">
<input type="hidden" name="scraper_rules" value="{{ .form.ScraperRules }}">
<input type="hidden" name="rewrite_rules" value="{{ .form.RewriteRules }}">
{{ if .form.Crawler }}
<input type="hidden" name="crawler" value="1">
{{ end }}
<h3>{{ t "page.add_feed.choose_feed" }}</h3>
{{ range .subscriptions }}
<div class="radio-group">
<label title="{{ .URL | safeURL }}"><input type="radio" name="url" value="{{ .URL | safeURL }}"> {{ .Title }}</label> ({{ .Type }})
<small title="Type = {{ .Type }}"><a href="{{ .URL | safeURL }}" target="_blank" rel="noopener noreferrer" referrerpolicy="no-referrer">{{ .URL | safeURL }}</a></small>
</div>
{{ end }}
<div class="buttons">
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.loading" }}">{{ t "action.subscribe" }}</button>
</div>
</form>
{{ end }}
`,
"create_api_key": `{{ define "title"}}{{ t "page.new_api_key.title" }}{{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.new_api_key.title" }}</h1>
{{ template "settings_menu" dict "user" .user }}
</section>
<form action="{{ route "saveAPIKey" }}" method="post" autocomplete="off">
<input type="hidden" name="csrf" value="{{ .csrf }}">
{{ if .errorMessage }}
<div class="alert alert-error">{{ t .errorMessage }}</div>
{{ end }}
<label for="form-description">{{ t "form.api_key.label.description" }}</label>
<input type="text" name="description" id="form-description" value="{{ .form.Description }}" required autofocus>
<div class="buttons">
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.save" }}</button> {{ t "action.or" }} <a href="{{ route "apiKeys" }}">{{ t "action.cancel" }}</a>
</div>
</form>
{{ end }}
`,
"create_category": `{{ define "title"}}{{ t "page.new_category.title" }}{{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.new_category.title" }}</h1>
<ul>
<li>
<a href="{{ route "categories" }}">{{ t "menu.categories" }}</a>
</li>
</ul>
</section>
<form action="{{ route "saveCategory" }}" method="post" autocomplete="off">
<input type="hidden" name="csrf" value="{{ .csrf }}">
{{ if .errorMessage }}
<div class="alert alert-error">{{ t .errorMessage }}</div>
{{ end }}
<label for="form-title">{{ t "form.category.label.title" }}</label>
<input type="text" name="title" id="form-title" value="{{ .form.Title }}" required autofocus>
<div class="buttons">
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.save" }}</button> {{ t "action.or" }} <a href="{{ route "categories" }}">{{ t "action.cancel" }}</a>
</div>
</form>
{{ end }}
`,
"create_user": `{{ define "title"}}{{ t "page.new_user.title" }}{{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.new_user.title" }}</h1>
{{ template "settings_menu" dict "user" .user }}
</section>
<form action="{{ route "saveUser" }}" method="post" autocomplete="off">
<input type="hidden" name="csrf" value="{{ .csrf }}">
{{ if .errorMessage }}
<div class="alert alert-error">{{ t .errorMessage }}</div>
{{ end }}
<label for="form-username">{{ t "form.user.label.username" }}</label>
<input type="text" name="username" id="form-username" value="{{ .form.Username }}" autocomplete="new-password" required autofocus>
<label for="form-password">{{ t "form.user.label.password" }}</label>
<input type="password" name="password" id="form-password" value="{{ .form.Password }}" autocomplete="new-password" required>
<label for="form-confirmation">{{ t "form.user.label.confirmation" }}</label>
<input type="password" name="confirmation" id="form-confirmation" value="{{ .form.Confirmation }}" required>
<label><input type="checkbox" name="is_admin" value="1" {{ if .form.IsAdmin }}checked{{ end }}> {{ t "form.user.label.admin" }}</label>
<div class="buttons">
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.save" }}</button> {{ t "action.or" }} <a href="{{ route "users" }}">{{ t "action.cancel" }}</a>
</div>
</form>
{{ end }}
`,
"edit_category": `{{ define "title"}}{{ t "page.edit_category.title" .category.Title }}{{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.edit_category.title" .category.Title }}</h1>
<ul>
<li>
<a href="{{ route "categories" }}">{{ t "menu.categories" }}</a>
</li>
<li>
<a href="{{ route "categoryFeeds" "categoryID" .category.ID }}">{{ t "menu.feeds" }}</a>
</li>
<li>
<a href="{{ route "createCategory" }}">{{ t "menu.create_category" }}</a>
</li>
</ul>
</section>
<form action="{{ route "updateCategory" "categoryID" .category.ID }}" method="post" autocomplete="off">
<input type="hidden" name="csrf" value="{{ .csrf }}">
{{ if .errorMessage }}
<div class="alert alert-error">{{ t .errorMessage }}</div>
{{ end }}
<label for="form-title">{{ t "form.category.label.title" }}</label>
<input type="text" name="title" id="form-title" value="{{ .form.Title }}" required autofocus>
<div class="buttons">
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button>
</div>
</form>
{{ end }}
`,
"edit_feed": `{{ define "title"}}{{ t "page.edit_feed.title" .feed.Title }}{{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ .feed.Title }}</h1>
<ul>
<li>
<a href="{{ route "feeds" }}">{{ t "menu.feeds" }}</a>
</li>
<li>
<a href="{{ route "feedEntries" "feedID" .feed.ID }}">{{ t "menu.feed_entries" }}</a>
</li>
<li>
<a href="{{ route "refreshFeed" "feedID" .feed.ID }}">{{ t "menu.refresh_feed" }}</a>
</li>
</ul>
</section>
{{ if not .categories }}
<p class="alert alert-error">{{ t "page.add_feed.no_category" }}</p>
{{ else }}
{{ if ne .feed.ParsingErrorCount 0 }}
<div class="alert alert-error">
<h3>{{ t "page.edit_feed.last_parsing_error" }}</h3>
<p>{{ t .feed.ParsingErrorMsg }}</p>
</div>
{{ end }}
<form action="{{ route "updateFeed" "feedID" .feed.ID }}" method="post" autocomplete="off">
<input type="hidden" name="csrf" value="{{ .csrf }}">
{{ if .errorMessage }}
<div class="alert alert-error">{{ t .errorMessage }}</div>
{{ end }}
<label for="form-title">{{ t "form.feed.label.title" }}</label>
<input type="text" name="title" id="form-title" value="{{ .form.Title }}" required autofocus>
<label for="form-site-url">{{ t "form.feed.label.site_url" }}</label>
<input type="url" name="site_url" id="form-site-url" placeholder="https://domain.tld/" value="{{ .form.SiteURL }}" required>
<label for="form-feed-url">{{ t "form.feed.label.feed_url" }}</label>
<input type="url" name="feed_url" id="form-feed-url" placeholder="https://domain.tld/" value="{{ .form.FeedURL }}" required>
<label for="form-feed-username">{{ t "form.feed.label.feed_username" }}</label>
<input type="text" name="feed_username" id="form-feed-username" value="{{ .form.Username }}">
<label for="form-feed-password">{{ t "form.feed.label.feed_password" }}</label>
<!--
We are using the type "text" otherwise Firefox always autocomplete this password:
- autocomplete="off" or autocomplete="new-password" doesn't change anything
- Changing the input ID doesn't change anything
- Using a different input name doesn't change anything
-->
<input type="text" name="feed_password" id="form-feed-password" value="{{ .form.Password }}">
<label for="form-user-agent">{{ t "form.feed.label.user_agent" }}</label>
<input type="text" name="user_agent" id="form-user-agent" placeholder="{{ .defaultUserAgent }}" value="{{ .form.UserAgent }}">
<label for="form-scraper-rules">{{ t "form.feed.label.scraper_rules" }}</label>
<input type="text" name="scraper_rules" id="form-scraper-rules" value="{{ .form.ScraperRules }}">
<label for="form-rewrite-rules">{{ t "form.feed.label.rewrite_rules" }}</label>
<input type="text" name="rewrite_rules" id="form-rewrite-rules" value="{{ .form.RewriteRules }}">
<label for="form-category">{{ t "form.feed.label.category" }}</label>
<select id="form-category" name="category_id">
{{ range .categories }}
<option value="{{ .ID }}" {{ if eq .ID $.form.CategoryID }}selected="selected"{{ end }}>{{ .Title }}</option>
{{ end }}
</select>
<label><input type="checkbox" name="crawler" value="1" {{ if .form.Crawler }}checked{{ end }}> {{ t "form.feed.label.crawler" }}</label>
<label><input type="checkbox" name="disabled" value="1" {{ if .form.Disabled }}checked{{ end }}> {{ t "form.feed.label.disabled" }}</label>
<div class="buttons">
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button> {{ t "action.or" }} <a href="{{ route "feeds" }}">{{ t "action.cancel" }}</a>
</div>
</form>
<div class="panel">
<ul>
<li><strong>{{ t "page.edit_feed.last_check" }} </strong><time datetime="{{ isodate .feed.CheckedAt }}" title="{{ isodate .feed.CheckedAt }}">{{ elapsed $.user.Timezone .feed.CheckedAt }}</time></li>
<li><strong>{{ t "page.edit_feed.etag_header" }} </strong>{{ if .feed.EtagHeader }}{{ .feed.EtagHeader }}{{ else }}{{ t "page.edit_feed.no_header" }}{{ end }}</li>
<li><strong>{{ t "page.edit_feed.last_modified_header" }} </strong>{{ if .feed.LastModifiedHeader }}{{ .feed.LastModifiedHeader }}{{ else }}{{ t "page.edit_feed.no_header" }}{{ end }}</li>
</ul>
</div>
<div class="alert alert-error">
<a href="#"
data-confirm="true"
data-action="remove-feed"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}"
data-url="{{ route "removeFeed" "feedID" .feed.ID }}"
data-redirect-url="{{ route "feeds" }}">{{ t "action.remove_feed" }}</a>
</div>
{{ end }}
{{ end }}
`,
"edit_user": `{{ define "title"}}{{ t "page.edit_user.title" .selected_user.Username }}{{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.edit_user.title" .selected_user.Username }}</h1>
{{ template "settings_menu" dict "user" .user }}
</section>
<form action="{{ route "updateUser" "userID" .selected_user.ID }}" method="post" autocomplete="off">
<input type="hidden" name="csrf" value="{{ .csrf }}">
{{ if .errorMessage }}
<div class="alert alert-error">{{ t .errorMessage }}</div>
{{ end }}
<label for="form-username">{{ t "form.user.label.username" }}</label>
<input type="text" name="username" id="form-username" value="{{ .form.Username }}" autocomplete="new-password" required autofocus>
<label for="form-password">{{ t "form.user.label.password" }}</label>
<input type="password" name="password" id="form-password" value="{{ .form.Password }}" autocomplete="new-password">
<label for="form-confirmation">{{ t "form.user.label.confirmation" }}</label>
<input type="password" name="confirmation" id="form-confirmation" value="{{ .form.Confirmation }}" autocomplete="new-password">
<label><input type="checkbox" name="is_admin" value="1" {{ if .form.IsAdmin }}checked{{ end }}> {{ t "form.user.label.admin" }}</label>
<div class="buttons">
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button> {{ t "action.or" }} <a href="{{ route "users" }}">{{ t "action.cancel" }}</a>
</div>
</form>
{{ end }}
`,
"entry": `{{ define "title"}}{{ .entry.Title }}{{ end }}
{{ define "content"}}
<section class="entry" data-id="{{ .entry.ID }}">
<header class="entry-header">
<h1>
<a href="{{ .entry.URL | safeURL }}" target="_blank" rel="noopener noreferrer" referrerpolicy="no-referrer">{{ .entry.Title }}</a>
</h1>
<div class="entry-actions">
<ul>
<li>
<a href="#"
title="{{ t "entry.status.title" }}"
data-toggle-status="true"
data-label-read="✔&#xfe0e;&nbsp;{{ t "entry.status.read" }}"
data-label-unread="✘&nbsp;{{ t "entry.status.unread" }}"
data-toast-read="✔︎&nbsp;{{ t "entry.status.toast.read" }}"
data-toast-unread="✘&nbsp;{{ t "entry.status.toast.unread" }}"
data-value="{{ if eq .entry.Status "read" }}read{{ else }}unread{{ end }}"
>{{ if eq .entry.Status "read" }}✘&nbsp;{{ t "entry.status.unread" }}{{ else }}✔&#xfe0e;&nbsp;{{ t "entry.status.read" }}{{ end }}</a>
</li>
<li>
<a href="#"
data-toggle-bookmark="true"
data-bookmark-url="{{ route "toggleBookmark" "entryID" .entry.ID }}"
data-label-loading="{{ t "entry.state.saving" }}"
data-label-star="☆&nbsp;{{ t "entry.bookmark.toggle.on" }}"
data-label-unstar="★&nbsp;{{ t "entry.bookmark.toggle.off" }}"
data-toast-star="★&nbsp;{{ t "entry.bookmark.toast.on" }}"
data-toast-unstar="☆&nbsp;{{ t "entry.bookmark.toast.off" }}"
data-value="{{ if .entry.Starred }}star{{ else }}unstar{{ end }}"
>{{ if .entry.Starred }}★&nbsp;{{ t "entry.bookmark.toggle.off" }}{{ else }}☆&nbsp;{{ t "entry.bookmark.toggle.on" }}{{ end }}</a>
</li>
{{ if .hasSaveEntry }}
<li>
<a href="#"
title="{{ t "entry.save.title" }}"
data-save-entry="true"
data-save-url="{{ route "saveEntry" "entryID" .entry.ID }}"
data-label-loading="{{ t "entry.state.saving" }}"
data-label-done="{{ t "entry.save.completed" }}"
data-toast-done="{{ t "entry.save.toast.completed" }}"
>{{ t "entry.save.title" }}</a>
</li>
{{ end }}
<li>
<a href="#"
title="{{ t "entry.scraper.title" }}"
data-fetch-content-entry="true"
data-fetch-content-url="{{ route "fetchContent" "entryID" .entry.ID }}"
data-label-loading="{{ t "entry.state.loading" }}"
data-label-done="{{ t "entry.scraper.completed" }}"
>{{ t "entry.scraper.label" }}</a>
</li>
{{ if .entry.CommentsURL }}
<li>
<a href="{{ .entry.CommentsURL | safeURL }}" title="{{ t "entry.comments.title" }}" target="_blank" rel="noopener noreferrer" referrerpolicy="no-referrer" data-comments-link="true">{{ t "entry.comments.label" }}</a>
</li>
{{ end }}
</ul>
</div>
<div class="entry-meta">
<span class="entry-website">
{{ if ne .entry.Feed.Icon.IconID 0 }}
<img src="{{ route "icon" "iconID" .entry.Feed.Icon.IconID }}" width="16" height="16" loading="lazy" alt="{{ .entry.Feed.Title }}">
{{ end }}
<a href="{{ route "feedEntries" "feedID" .entry.Feed.ID }}">{{ .entry.Feed.Title }}</a>
</span>
{{ if .entry.Author }}
<span class="entry-author">
{{ if isEmail .entry.Author }}
- <a href="mailto:{{ .entry.Author }}">{{ .entry.Author }}</a>
{{ else }}
<em>{{ .entry.Author }}</em>
{{ end }}
</span>
{{ end }}
<span class="category">
<a href="{{ route "categoryEntries" "categoryID" .entry.Feed.Category.ID }}">{{ .entry.Feed.Category.Title }}</a>
</span>
</div>
<div class="entry-date">
<time datetime="{{ isodate .entry.Date }}" title="{{ isodate .entry.Date }}">{{ elapsed $.user.Timezone .entry.Date }}</time>
</div>
</header>
{{ if gt (len .entry.Content) 120 }}
<div class="pagination-top">
{{ template "entry_pagination" . }}
</div>
{{ end }}
<article class="entry-content">
{{ noescape (proxyFilter .entry.Content) }}
</article>
{{ if .entry.Enclosures }}
<details class="entry-enclosures">
<summary>{{ t "page.entry.attachments" }} ({{ len .entry.Enclosures }})</summary>
{{ range .entry.Enclosures }}
{{ if ne .URL "" }}
<div class="entry-enclosure">
{{ if hasPrefix .MimeType "audio/" }}
<div class="enclosure-audio">
<audio controls preload="metadata">
<source src="{{ .URL }}" type="{{ .MimeType }}">
</audio>
</div>
{{ else if hasPrefix .MimeType "video/" }}
<div class="enclosure-video">
<video controls preload="metadata">
<source src="{{ .URL }}" type="{{ .MimeType }}">
</video>
</div>
{{ else if hasPrefix .MimeType "image/" }}
<div class="enclosure-image">
<img src="{{ proxyURL .URL }}" title="{{ .URL }} ({{ .MimeType }})" loading="lazy" alt="{{ .URL }} ({{ .MimeType }})">
</div>
{{ end }}
<div class="entry-enclosure-download">
<a href="{{ .URL | safeURL }}" title="{{ t "action.download" }}{{ if gt .Size 0 }} - {{ formatFileSize .Size }}{{ end }} ({{ .MimeType }})" target="_blank" rel="noopener noreferrer" referrerpolicy="no-referrer">{{ .URL | safeURL }}</a>
<small>{{ if gt .Size 0 }} - <strong>{{ formatFileSize .Size }}</strong>{{ end }}</small>
</div>
</div>
{{ end }}
{{ end }}
</details>
{{ end }}
</section>
<div class="pagination-bottom">
{{ template "entry_pagination" . }}
</div>
{{ end }}
`,
"feed_entries": `{{ define "title"}}{{ .feed.Title }} ({{ .total }}){{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ .feed.Title }} ({{ .total }})</h1>
<ul>
{{ if .entries }}
<li>
<a href="#"
data-action="markPageAsRead"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}"
data-show-only-unread="{{ if .showOnlyUnreadEntries }}1{{ end }}">{{ t "menu.mark_page_as_read" }}</a>
</li>
{{ end }}
{{ if .showOnlyUnreadEntries }}
<li>
<a href="{{ route "feedEntriesAll" "feedID" .feed.ID }}">{{ t "menu.show_all_entries" }}</a>
</li>
{{ else }}
<li>
<a href="{{ route "feedEntries" "feedID" .feed.ID }}">{{ t "menu.show_only_unread_entries" }}</a>
</li>
{{ end }}
<li>
<a href="{{ route "refreshFeed" "feedID" .feed.ID }}">{{ t "menu.refresh_feed" }}</a>
</li>
<li>
<a href="{{ route "editFeed" "feedID" .feed.ID }}">{{ t "menu.edit_feed" }}</a>
</li>
<li>
<a href="#"
data-confirm="true"
data-action="remove-feed"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}"
data-url="{{ route "removeFeed" "feedID" .feed.ID }}"
data-redirect-url="{{ route "feeds" }}">{{ t "action.remove_feed" }}</a>
</li>
</ul>
</section>
{{ if ne .feed.ParsingErrorCount 0 }}
<div class="alert alert-error">
<h3>{{ t "alert.feed_error" }}</h3>
<p>{{ t .feed.ParsingErrorMsg }}</p>
</div>
{{ end }}
{{ if not .entries }}
{{ if .showOnlyUnreadEntries }}
<p class="alert">{{ t "alert.no_unread_entry" }}</p>
{{ else }}
<p class="alert">{{ t "alert.no_feed_entry" }}</p>
{{ end }}
{{ else }}
<div class="items">
{{ range .entries }}
<article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
<div class="item-header">
<span class="item-title">
{{ if ne .Feed.Icon.IconID 0 }}
<img src="{{ route "icon" "iconID" .Feed.Icon.IconID }}" width="16" height="16" loading="lazy" alt="{{ .Feed.Title }}">
{{ end }}
<a href="{{ route "feedEntry" "feedID" .Feed.ID "entryID" .ID }}">{{ .Title }}</a>
</span>
<span class="category"><a href="{{ route "categoryEntries" "categoryID" .Feed.Category.ID }}">{{ .Feed.Category.Title }}</a></span>
</div>
{{ template "item_meta" dict "user" $.user "entry" . "hasSaveEntry" $.hasSaveEntry }}
</article>
{{ end }}
</div>
<section class="page-footer">
{{ if .entries }}
<ul>
<li>
<a href="#"
data-action="markPageAsRead"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}"
data-show-only-unread="{{ if .showOnlyUnreadEntries }}1{{ end }}">{{ t "menu.mark_page_as_read" }}</a>
</li>
</ul>
{{ end }}
</section>
{{ template "pagination" .pagination }}
{{ end }}
{{ end }}
`,
"feeds": `{{ define "title"}}{{ t "page.feeds.title" }} ({{ .total }}){{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.feeds.title" }} ({{ .total }})</h1>
{{ template "feed_menu" }}
</section>
{{ if not .feeds }}
<p class="alert">{{ t "alert.no_feed" }}</p>
{{ else }}
{{ template "feed_list" dict "user" .user "feeds" .feeds "ParsingErrorCount" .ParsingErrorCount }}
{{ end }}
{{ end }}
`,
"history_entries": `{{ define "title"}}{{ t "page.history.title" }} ({{ .total }}){{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.history.title" }} ({{ .total }})</h1>
{{ if .entries }}
<ul>
<li>
<a href="#"
data-confirm="true"
data-url="{{ route "flushHistory" }}"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}">{{ t "menu.flush_history" }}</a>
</li>
</ul>
{{ end }}
</section>
{{ if not .entries }}
<p class="alert alert-info">{{ t "alert.no_history" }}</p>
{{ else }}
<div class="items">
{{ range .entries }}
<article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
<div class="item-header">
<span class="item-title">
{{ if ne .Feed.Icon.IconID 0 }}
<img src="{{ route "icon" "iconID" .Feed.Icon.IconID }}" width="16" height="16" loading="lazy" alt="{{ .Feed.Title }}">
{{ end }}
<a href="{{ route "readEntry" "entryID" .ID }}">{{ .Title }}</a>
</span>
<span class="category"><a href="{{ route "categoryEntries" "categoryID" .Feed.Category.ID }}">{{ .Feed.Category.Title }}</a></span>
</div>
{{ template "item_meta" dict "user" $.user "entry" . "hasSaveEntry" $.hasSaveEntry }}
</article>
{{ end }}
</div>
{{ template "pagination" .pagination }}
{{ end }}
{{ end }}
`,
"import": `{{ define "title"}}{{ t "page.import.title" }}{{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.import.title" }}</h1>
{{ template "feed_menu" }}
</section>
{{ if .errorMessage }}
<div class="alert alert-error">{{ t .errorMessage }}</div>
{{ end }}
<form action="{{ route "uploadOPML" }}" method="post" enctype="multipart/form-data">
<input type="hidden" name="csrf" value="{{ .csrf }}">
<label for="form-file">{{ t "form.import.label.file" }}</label>
<input type="file" name="file" id="form-file">
<div class="buttons">
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.import" }}</button>
</div>
</form>
<hr>
<form action="{{ route "fetchOPML" }}" method="post" enctype="multipart/form-data">
<input type="hidden" name="csrf" value="{{ .csrf }}">
<label for="form-url">{{ t "form.import.label.url" }}</label>
<input type="url" name="url" id="form-url" required>
<div class="buttons">
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.import" }}</button>
</div>
</form>
{{ end }}
`,
"integrations": `{{ define "title"}}{{ t "page.integrations.title" }}{{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.integrations.title" }}</h1>
{{ template "settings_menu" dict "user" .user }}
</section>
<form method="post" autocomplete="off" action="{{ route "updateIntegration" }}">
<input type="hidden" name="csrf" value="{{ .csrf }}">
{{ if .errorMessage }}
<div class="alert alert-error">{{ t .errorMessage }}</div>
{{ end }}
<h3>Fever</h3>
<div class="form-section">
<label>
<input type="checkbox" name="fever_enabled" value="1" {{ if .form.FeverEnabled }}checked{{ end }}> {{ t "form.integration.fever_activate" }}
</label>
<label for="form-fever-username">{{ t "form.integration.fever_username" }}</label>
<input type="text" name="fever_username" id="form-fever-username" value="{{ .form.FeverUsername }}">
<label for="form-fever-password">{{ t "form.integration.fever_password" }}</label>
<input type="password" name="fever_password" id="form-fever-password" value="{{ .form.FeverPassword }}" autocomplete="new-password">
<p>{{ t "form.integration.fever_endpoint" }} <strong>{{ rootURL }}{{ route "feverEndpoint" }}</strong></p>
</div>
<h3>Pinboard</h3>
<div class="form-section">
<label>
<input type="checkbox" name="pinboard_enabled" value="1" {{ if .form.PinboardEnabled }}checked{{ end }}> {{ t "form.integration.pinboard_activate" }}
</label>
<label for="form-pinboard-token">{{ t "form.integration.pinboard_token" }}</label>
<input type="password" name="pinboard_token" id="form-pinboard-token" value="{{ .form.PinboardToken }}" autocomplete="new-password">
<label for="form-pinboard-tags">{{ t "form.integration.pinboard_tags" }}</label>
<input type="text" name="pinboard_tags" id="form-pinboard-tags" value="{{ .form.PinboardTags }}">
<label>
<input type="checkbox" name="pinboard_mark_as_unread" value="1" {{ if .form.PinboardMarkAsUnread }}checked{{ end }}> {{ t "form.integration.pinboard_bookmark" }}
</label>
</div>
<h3>Instapaper</h3>
<div class="form-section">
<label>
<input type="checkbox" name="instapaper_enabled" value="1" {{ if .form.InstapaperEnabled }}checked{{ end }}> {{ t "form.integration.instapaper_activate" }}
</label>
<label for="form-instapaper-username">{{ t "form.integration.instapaper_username" }}</label>
<input type="text" name="instapaper_username" id="form-instapaper-username" value="{{ .form.InstapaperUsername }}">
<label for="form-instapaper-password">{{ t "form.integration.instapaper_password" }}</label>
<input type="password" name="instapaper_password" id="form-instapaper-password" value="{{ .form.InstapaperPassword }}" autocomplete="new-password">
</div>
<h3>Pocket</h3>
<div class="form-section">
<label>
<input type="checkbox" name="pocket_enabled" value="1" {{ if .form.PocketEnabled }}checked{{ end }}> {{ t "form.integration.pocket_activate" }}
</label>
{{ if not .hasPocketConsumerKeyConfigured }}
<label for="form-pocket-consumer-key">{{ t "form.integration.pocket_consumer_key" }}</label>
<input type="text" name="pocket_consumer_key" id="form-pocket-consumer-key" value="{{ .form.PocketConsumerKey }}">
{{ end }}
<label for="form-pocket-access-token">{{ t "form.integration.pocket_access_token" }}</label>
<input type="password" name="pocket_access_token" id="form-pocket-access-token" value="{{ .form.PocketAccessToken }}" autocomplete="new-password">
{{ if not .form.PocketAccessToken }}
<p><a href="{{ route "pocketAuthorize" }}">{{ t "form.integration.pocket_connect_link" }}</a></p>
{{ end }}
</div>
<h3>Wallabag</h3>
<div class="form-section">
<label>
<input type="checkbox" name="wallabag_enabled" value="1" {{ if .form.WallabagEnabled }}checked{{ end }}> {{ t "form.integration.wallabag_activate" }}
</label>
<label for="form-wallabag-url">{{ t "form.integration.wallabag_endpoint" }}</label>
<input type="url" name="wallabag_url" id="form-wallabag-url" value="{{ .form.WallabagURL }}" placeholder="http://v2.wallabag.org/">
<label for="form-wallabag-client-id">{{ t "form.integration.wallabag_client_id" }}</label>
<input type="text" name="wallabag_client_id" id="form-wallabag-client-id" value="{{ .form.WallabagClientID }}">
<label for="form-wallabag-client-secret">{{ t "form.integration.wallabag_client_secret" }}</label>
<input type="password" name="wallabag_client_secret" id="form-wallabag-client-secret" value="{{ .form.WallabagClientSecret }}" autocomplete="new-password">
<label for="form-wallabag-username">{{ t "form.integration.wallabag_username" }}</label>
<input type="text" name="wallabag_username" id="form-wallabag-username" value="{{ .form.WallabagUsername }}">
<label for="form-wallabag-password">{{ t "form.integration.wallabag_password" }}</label>
<input type="password" name="wallabag_password" id="form-wallabag-password" value="{{ .form.WallabagPassword }}" autocomplete="new-password">
</div>
<h3>Nunux Keeper</h3>
<div class="form-section">
<label>
<input type="checkbox" name="nunux_keeper_enabled" value="1" {{ if .form.NunuxKeeperEnabled }}checked{{ end }}> {{ t "form.integration.nunux_keeper_activate" }}
</label>
<label for="form-nunux-keeper-url">{{ t "form.integration.nunux_keeper_endpoint" }}</label>
<input type="url" name="nunux_keeper_url" id="form-nunux-keeper-url" value="{{ .form.NunuxKeeperURL }}" placeholder="https://api.nunux.org/keeper">
<label for="form-nunux-keeper-api-key">{{ t "form.integration.nunux_keeper_api_key" }}</label>
<input type="text" name="nunux_keeper_api_key" id="form-nunux-keeper-api-key" value="{{ .form.NunuxKeeperAPIKey }}">
</div>
<div class="buttons">
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button>
</div>
</form>
<h3>{{ t "page.integration.bookmarklet" }}</h3>
<div class="panel">
<p>{{ t "page.integration.bookmarklet.help" }}</p>
<div class="bookmarklet">
<a href="javascript:location.href='{{ rootURL }}{{ route "bookmarklet" }}?uri='+encodeURIComponent(window.location.href)">{{ t "page.integration.bookmarklet.name" }}</a>
</div>
<p>{{ t "page.integration.bookmarklet.instructions" }}</p>
</div>
{{ end }}
`,
"login": `{{ define "title"}}{{ t "page.login.title" }}{{ end }}
{{ define "content"}}
<section class="login-form">
<form action="{{ route "checkLogin" }}" method="post">
<input type="hidden" name="csrf" value="{{ .csrf }}">
{{ if .errorMessage }}
<div class="alert alert-error">{{ t .errorMessage }}</div>
{{ end }}
<label for="form-username">{{ t "form.user.label.username" }}</label>
<input type="text" name="username" id="form-username" value="{{ .form.Username }}" required autofocus>
<label for="form-password">{{ t "form.user.label.password" }}</label>
<input type="password" name="password" id="form-password" value="{{ .form.Password }}" required>
<div class="buttons">
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.loading" }}">{{ t "action.login" }}</button>
</div>
</form>
{{ if hasOAuth2Provider "google" }}
<div class="oauth2">
<a href="{{ route "oauth2Redirect" "provider" "google" }}">{{ t "page.login.google_signin" }}</a>
</div>
{{ else if hasOAuth2Provider "oidc" }}
<div class="oauth2">
<a href="{{ route "oauth2Redirect" "provider" "oidc" }}">{{ t "page.login.oidc_signin" }}</a>
</div>
{{ end }}
</section>
<footer id="prompt-home-screen">
<a href="#" id="btn-add-to-home-screen">★ {{ t "action.home_screen" }}</a>
</footer>
{{ end }}
`,
"search_entries": `{{ define "title"}}{{ t "page.search.title" }} ({{ .total }}){{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.search.title" }} ({{ .total }})</h1>
</section>
{{ if not .entries }}
<p class="alert alert-info">{{ t "alert.no_search_result" }}</p>
{{ else }}
<div class="items">
{{ range .entries }}
<article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
<div class="item-header">
<span class="item-title">
{{ if ne .Feed.Icon.IconID 0 }}
<img src="{{ route "icon" "iconID" .Feed.Icon.IconID }}" width="16" height="16" loading="lazy" alt="{{ .Feed.Title }}">
{{ end }}
<a href="{{ route "searchEntry" "entryID" .ID }}?q={{ $.searchQuery }}">{{ .Title }}</a>
</span>
<span class="category"><a href="{{ route "categoryEntries" "categoryID" .Feed.Category.ID }}">{{ .Feed.Category.Title }}</a></span>
</div>
{{ template "item_meta" dict "user" $.user "entry" . "hasSaveEntry" $.hasSaveEntry }}
</article>
{{ end }}
</div>
{{ template "pagination" .pagination }}
{{ end }}
{{ end }}
`,
"sessions": `{{ define "title"}}{{ t "page.sessions.title" }}{{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.sessions.title" }}</h1>
{{ template "settings_menu" dict "user" .user }}
</section>
<table>
<tr>
<th>{{ t "page.sessions.table.date" }}</th>
<th>{{ t "page.sessions.table.ip" }}</th>
<th>{{ t "page.sessions.table.user_agent" }}</th>
<th>{{ t "page.sessions.table.actions" }}</th>
</tr>
{{ range .sessions }}
<tr {{ if eq .Token $.currentSessionToken }}class="row-highlighted"{{ end }}>
<td class="column-20" title="{{ isodate .CreatedAt }}">{{ elapsed $.user.Timezone .CreatedAt }}</td>
<td class="column-20" title="{{ .IP }}">{{ .IP }}</td>
<td title="{{ .UserAgent }}">{{ .UserAgent }}</td>
<td class="column-20">
{{ if eq .Token $.currentSessionToken }}
{{ t "page.sessions.table.current_session" }}
{{ else }}
<a href="#"
data-confirm="true"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}"
data-url="{{ route "removeSession" "sessionID" .ID }}">{{ t "action.remove" }}</a>
{{ end }}
</td>
</tr>
{{ end }}
</table>
{{ end }}
`,
"settings": `{{ define "title"}}{{ t "page.settings.title" }}{{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.settings.title" }}</h1>
{{ template "settings_menu" dict "user" .user }}
</section>
<form method="post" autocomplete="off" action="{{ route "updateSettings" }}">
<input type="hidden" name="csrf" value="{{ .csrf }}">
{{ if .errorMessage }}
<div class="alert alert-error">{{ t .errorMessage }}</div>
{{ end }}
<label for="form-username">{{ t "form.user.label.username" }}</label>
<input type="text" name="username" id="form-username" value="{{ .form.Username }}" required>
<label for="form-password">{{ t "form.user.label.password" }}</label>
<input type="password" name="password" id="form-password" value="{{ .form.Password }}" autocomplete="new-password">
<label for="form-confirmation">{{ t "form.user.label.confirmation" }}</label>
<input type="password" name="confirmation" id="form-confirmation" value="{{ .form.Confirmation }}" autocomplete="new-password">
<label for="form-language">{{ t "form.prefs.label.language" }}</label>
<select id="form-language" name="language">
{{ range $key, $value := .languages }}
<option value="{{ $key }}" {{ if eq $key $.form.Language }}selected="selected"{{ end }}>{{ $value }}</option>
{{ end }}
</select>
<label for="form-timezone">{{ t "form.prefs.label.timezone" }}</label>
<select id="form-timezone" name="timezone">
{{ range $key, $value := .timezones }}
<option value="{{ $key }}" {{ if eq $key $.form.Timezone }}selected="selected"{{ end }}>{{ $value }}</option>
{{ end }}
</select>
<label for="form-theme">{{ t "form.prefs.label.theme" }}</label>
<select id="form-theme" name="theme">
{{ range $key, $value := .themes }}
<option value="{{ $key }}" {{ if eq $key $.form.Theme }}selected="selected"{{ end }}>{{ $value }}</option>
{{ end }}
</select>
<label for="form-entry-direction">{{ t "form.prefs.label.entry_sorting" }}</label>
<select id="form-entry-direction" name="entry_direction">
<option value="asc" {{ if eq "asc" $.form.EntryDirection }}selected="selected"{{ end }}>{{ t "form.prefs.select.older_first" }}</option>
<option value="desc" {{ if eq "desc" $.form.EntryDirection }}selected="selected"{{ end }}>{{ t "form.prefs.select.recent_first" }}</option>
</select>
<label><input type="checkbox" name="keyboard_shortcuts" value="1" {{ if .form.KeyboardShortcuts }}checked{{ end }}> {{ t "form.prefs.label.keyboard_shortcuts" }}</label>
<div class="buttons">
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button>
</div>
</form>
{{ if hasOAuth2Provider "google" }}
<div class="panel">
{{ if hasKey .user.Extra "google_id" }}
<a href="{{ route "oauth2Unlink" "provider" "google" }}">{{ t "page.settings.unlink_google_account" }}</a>
{{ else }}
<a href="{{ route "oauth2Redirect" "provider" "google" }}">{{ t "page.settings.link_google_account" }}</a>
{{ end }}
</div>
{{ else if hasOAuth2Provider "oidc" }}
<div class="panel">
{{ if hasKey .user.Extra "oidc_id" }}
<a href="{{ route "oauth2Unlink" "provider" "oidc" }}">{{ t "page.settings.unlink_oidc_account" }}</a>
{{ else }}
<a href="{{ route "oauth2Redirect" "provider" "oidc" }}">{{ t "page.settings.link_oidc_account" }}</a>
{{ end }}
</div>
{{ end }}
{{ end }}
`,
"unread_entries": `{{ define "title"}}{{ t "page.unread.title" }} {{ if gt .countUnread 0 }}({{ .countUnread }}){{ end }} {{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.unread.title" }} (<span class="unread-counter">{{ .countUnread }}</span>)</h1>
{{ if .entries }}
<ul>
<li>
<a href="#"
data-action="markPageAsRead"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}">{{ t "menu.mark_page_as_read" }}</a>
</li>
<li>
<a href="#"
data-confirm="true"
data-url="{{ route "markAllAsRead" }}"
data-redirect-url="{{ route "unread" }}"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}">{{ t "menu.mark_all_as_read" }}</a>
</li>
</ul>
{{ end }}
</section>
{{ if not .entries }}
<p class="alert">{{ t "alert.no_unread_entry" }}</p>
{{ else }}
<div class="items hide-read-items">
{{ range .entries }}
<article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
<div class="item-header">
<span class="item-title">
{{ if ne .Feed.Icon.IconID 0 }}
<img src="{{ route "icon" "iconID" .Feed.Icon.IconID }}" width="16" height="16" loading="lazy" alt="{{ .Feed.Title }}">
{{ end }}
<a href="{{ route "unreadEntry" "entryID" .ID }}">{{ .Title }}</a>
</span>
<span class="category"><a href="{{ route "categoryEntries" "categoryID" .Feed.Category.ID }}">{{ .Feed.Category.Title }}</a></span>
</div>
{{ template "item_meta" dict "user" $.user "entry" . "hasSaveEntry" $.hasSaveEntry }}
</article>
{{ end }}
</div>
<section class="page-footer">
{{ if .entries }}
<ul>
<li>
<a href="#"
data-action="markPageAsRead"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}">{{ t "menu.mark_page_as_read" }}</a>
</li>
</ul>
{{ end }}
</section>
{{ template "pagination" .pagination }}
{{ end }}
{{ end }}`,
"users": `{{ define "title"}}{{ t "page.users.title" }}{{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.users.title" }}</h1>
{{ template "settings_menu" dict "user" .user }}
</section>
{{ if eq (len .users) 1 }}
<p class="alert">{{ t "alert.no_user" }}</p>
{{ else }}
<table>
<tr>
<th class="column-20">{{ t "page.users.username" }}</th>
<th>{{ t "page.users.is_admin" }}</th>
<th>{{ t "page.users.last_login" }}</th>
<th>{{ t "page.users.actions" }}</th>
</tr>
{{ range .users }}
{{ if ne .ID $.user.ID }}
<tr>
<td>{{ .Username }}</td>
<td>{{ if eq .IsAdmin true }}{{ t "page.users.admin.yes" }}{{ else }}{{ t "page.users.admin.no" }}{{ end }}</td>
<td>
{{ if .LastLoginAt }}
<time datetime="{{ isodate .LastLoginAt }}" title="{{ isodate .LastLoginAt }}">{{ elapsed $.user.Timezone .LastLoginAt }}</time>
{{ else }}
{{ t "page.users.never_logged" }}
{{ end }}
</td>
<td>
<a href="{{ route "editUser" "userID" .ID }}">{{ t "action.edit" }}</a>,
<a href="#"
data-confirm="true"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}"
data-url="{{ route "removeUser" "userID" .ID }}">{{ t "action.remove" }}</a>
</td>
</tr>
{{ end }}
{{ end }}
</table>
<br>
{{ end }}
<p>
<a href="{{ route "createUser" }}" class="button button-primary">{{ t "menu.add_user" }}</a>
</p>
{{ end }}
`,
}
var templateViewsMapChecksums = map[string]string{
"about": "4035658497363d7af7f79be83190404eb21ec633fe8ec636bdfc219d9fc78cfc",
"add_subscription": "0dbea93b6fc07423fa066122ad960c69616b829533371a2dbadec1e22d4f1ae0",
"api_keys": "27d401b31a72881d5232486ba17eb47edaf5246eaedce81de88698c15ebb2284",
"bookmark_entries": "65588da78665699dd3f287f68325e9777d511f1a57fee4131a5bb6d00bb68df8",
"categories": "2c5dd0ed6355bd5acc393bbf6117d20458b5581aab82036008324f6bbbe2af75",
"category_entries": "dee7b9cd60c6c46f01dd4289940679df31c1fce28ce4aa7249fa459023e1eeb4",
"category_feeds": "527c2ffbc4fcec775071424ba1022ae003525dba53a28cc41f48fb7b30aa984b",
"choose_subscription": "84c9730cadd78e6ee5a6b4c499aab33acddb4324ac01924d33387543eec4d702",
"create_api_key": "5f74d4e92a6684927f5305096378c8be278159a5cd88ce652c7be3280a7d1685",
"create_category": "6b22b5ce51abf4e225e23a79f81be09a7fb90acb265e93a8faf9446dff74018d",
"create_user": "9b73a55233615e461d1f07d99ad1d4d3b54532588ab960097ba3e090c85aaf3a",
"edit_category": "b1c0b38f1b714c5d884edcd61e5b5295a5f1c8b71c469b35391e4dcc97cc6d36",
"edit_feed": "cc0b5dbb73f81398410958b41771ed38246bc7ae4bd548228f0d48c49a598c2a",
"edit_user": "c692db9de1a084c57b93e95a14b041d39bf489846cbb91fc982a62b72b77062a",
"entry": "513183f0f0b11a199630562f5a85eb9a5646051aae278cbc682bac13d62e65cc",
"feed_entries": "9c70b82f55e4b311eff20be1641733612e3c1b406ce8010861e4c417d97b6dcc",
"feeds": "ec7d3fa96735bd8422ba69ef0927dcccddc1cc51327e0271f0312d3f881c64fd",
"history_entries": "87e17d39de70eb3fdbc4000326283be610928758eae7924e4b08dcb446f3b6a9",
"import": "1b59b3bd55c59fcbc6fbb346b414dcdd26d1b4e0c307e437bb58b3f92ef01ad1",
"integrations": "30329452743b35c668278f519245fd9be05c1726856e0384ba542f7c307f2788",
"login": "79ff2ca488c0a19b37c8fa227a21f73e94472eb357a51a077197c852f7713f11",
"search_entries": "274950d03298c24f3942e209c0faed580a6d57be9cf76a6c236175a7e766ac6a",
"sessions": "5d5c677bddbd027e0b0c9f7a0dd95b66d9d95b4e130959f31fb955b926c2201c",
"settings": "d949ecdd28a33eadafaa3a727e548b3466c5aa44b0a4bbf86cc49784704ff7f6",
"unread_entries": "e38f7ffce17dfad3151b08cd33771a2cefe8ca9db42df04fc98bd1d675dd6075",
"users": "d7ff52efc582bbad10504f4a04fa3adcc12d15890e45dff51cac281e0c446e45",
}