Save worktree changes
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
<div class="page-header">
|
||||
<div>
|
||||
<h2>Add API source</h2>
|
||||
<p>Capture an API URL, refresh interval, and store the latest JSON response.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card card-outline card-primary admin-form-card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">API source details</h3>
|
||||
</div>
|
||||
<form id="api-source-form" method="post" action="/data-sources/api-sources" data-async-save data-async-save-close-url="/data-sources/api-sources" data-async-save-new-url="/data-sources/api-sources/new">
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<label for="api-source-name" class="form-label">Name</label>
|
||||
<input id="api-source-name" name="name" class="form-control" value="{{apiSource.name}}" required />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="api-source-url" class="form-label">API URL</label>
|
||||
<input id="api-source-url" name="api_url" type="url" class="form-control" value="{{apiSource.apiUrl}}" placeholder="https://example.com/api.json" required />
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
<div class="col-12 col-md-4">
|
||||
<label for="api-source-interval" class="form-label">Update interval</label>
|
||||
<input id="api-source-interval" name="update_interval_value" type="number" min="1" class="form-control" value="{{apiSource.updateIntervalValue}}" required />
|
||||
</div>
|
||||
<div class="col-12 col-md-4">
|
||||
<label for="api-source-interval-unit" class="form-label">Unit</label>
|
||||
<select id="api-source-interval-unit" name="update_interval_unit" class="form-select">
|
||||
<option value="seconds" {{#if (eq apiSource.updateIntervalUnit 'seconds')}}selected{{/if}}>Seconds</option>
|
||||
<option value="minutes" {{#if (eq apiSource.updateIntervalUnit 'minutes')}}selected{{/if}}>Minutes</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer d-flex justify-content-end">
|
||||
<div class="btn-group" role="group" aria-label="API source actions">
|
||||
{{{saveActionButtons formId="api-source-form" saveLabel="Save" saveAndCloseLabel="Save and Close" saveAndNewLabel="Save and New" saveAndCloseValue="close" saveAndNewValue="new"}}}
|
||||
<a class="btn btn-warning" href="/data-sources/api-sources" data-confirm-unsaved="You have unsaved changes. Leave this page?">Cancel</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,94 @@
|
||||
<div class="page-header">
|
||||
<div>
|
||||
<h2>Edit API source - {{apiSource.name}}</h2>
|
||||
<p>Adjust the endpoint or refresh cadence and review the latest JSON response.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card card-outline card-primary admin-form-card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">API source details</h3>
|
||||
</div>
|
||||
<form id="api-source-form" method="post" action="/data-sources/api-sources/{{apiSource.id}}" data-async-save data-async-save-refresh-target="#api-source-response-panel" data-async-save-refresh-state-url="/data-sources/api-sources/{{apiSource.id}}/state" data-async-save-close-url="/data-sources/api-sources" data-async-save-new-url="/data-sources/api-sources/new">
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<label for="api-source-name" class="form-label">Name</label>
|
||||
<input id="api-source-name" name="name" class="form-control" value="{{apiSource.name}}" required />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="api-source-url" class="form-label">API URL</label>
|
||||
<input id="api-source-url" name="api_url" type="url" class="form-control" value="{{apiSource.apiUrl}}" placeholder="https://example.com/api.json" required />
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
<div class="col-12 col-md-4">
|
||||
<label for="api-source-interval" class="form-label">Update interval</label>
|
||||
<input id="api-source-interval" name="update_interval_value" type="number" min="1" class="form-control" value="{{apiSource.updateIntervalValue}}" required />
|
||||
</div>
|
||||
<div class="col-12 col-md-4">
|
||||
<label for="api-source-interval-unit" class="form-label">Unit</label>
|
||||
<select id="api-source-interval-unit" name="update_interval_unit" class="form-select">
|
||||
<option value="seconds" {{#if (eq apiSource.updateIntervalUnit 'seconds')}}selected{{/if}}>Seconds</option>
|
||||
<option value="minutes" {{#if (eq apiSource.updateIntervalUnit 'minutes')}}selected{{/if}}>Minutes</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer d-flex justify-content-end">
|
||||
<div class="btn-group" role="group" aria-label="API source actions">
|
||||
{{{saveActionButtons formId="api-source-form" saveLabel="Save" saveAndCloseLabel="Save and Close" saveAndNewLabel="Save and New" saveAndCloseValue="close" saveAndNewValue="new"}}}
|
||||
<a class="btn btn-warning" href="/data-sources/api-sources" data-confirm-unsaved="You have unsaved changes. Leave this page?">Cancel</a>
|
||||
<button type="submit" class="btn btn-danger" form="delete-api-source-form">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="card card-outline card-secondary mt-4" id="api-source-response-panel">
|
||||
<div class="card-header d-flex align-items-center gap-2">
|
||||
<h3 class="card-title mb-0">Latest response</h3>
|
||||
{{#if apiSource.lastResponseJson}}
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-outline-secondary btn-sm ms-auto"
|
||||
data-json-toggle
|
||||
data-json-toggle-label-formatted="Format JSON"
|
||||
data-json-toggle-label-compact="Unformat JSON"
|
||||
aria-pressed="false"
|
||||
>
|
||||
<i class="bi bi-filetype-json me-1"></i>
|
||||
<span data-json-toggle-label>Format JSON</span>
|
||||
</button>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{{#if apiSource.lastPullError}}
|
||||
<div class="alert alert-warning">{{apiSource.lastPullError}}</div>
|
||||
{{/if}}
|
||||
<dl class="row">
|
||||
<dt class="col-12 col-md-3">Last pulled</dt>
|
||||
<dd class="col-12 col-md-9">
|
||||
{{#if apiSource.lastPulledAtValue}}
|
||||
<time data-local-datetime datetime="{{apiSource.lastPulledAtValue}}">{{#if apiSource.lastPulledAtLabel}}{{apiSource.lastPulledAtLabel}}{{else}}{{apiSource.lastPulledAtValue}}{{/if}}</time>
|
||||
{{else}}
|
||||
-
|
||||
{{/if}}
|
||||
</dd>
|
||||
|
||||
<dt class="col-12 col-md-3">Status</dt>
|
||||
<dd class="col-12 col-md-9">{{#if apiSource.lastResponseStatus}}{{apiSource.lastResponseStatus}}{{else}}-{{/if}}</dd>
|
||||
|
||||
<dt class="col-12 col-md-3">Content type</dt>
|
||||
<dd class="col-12 col-md-9">{{#if apiSource.lastResponseContentType}}{{apiSource.lastResponseContentType}}{{else}}-{{/if}}</dd>
|
||||
</dl>
|
||||
{{#if apiSource.lastResponseJson}}
|
||||
<div data-json-toggle-panel>
|
||||
<script type="application/json" data-json-toggle-source>{{json apiSource.lastResponseJson}}</script>
|
||||
<pre class="mb-0 small bg-body-tertiary border rounded p-3" style="white-space: pre-wrap; word-break: break-word;" data-json-toggle-output>{{apiSource.lastResponseJson}}</pre>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="alert alert-secondary mb-0">No JSON response is stored yet.</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form id="delete-api-source-form" method="post" action="/data-sources/api-sources/{{apiSource.id}}/delete" data-confirm-message="Delete this API source?"></form>
|
||||
@@ -0,0 +1,77 @@
|
||||
<div class="page-header">
|
||||
<div>
|
||||
<h2>API sources</h2>
|
||||
<p>Store API endpoints, refresh cadence, and the latest JSON response pulled from each endpoint.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card card-outline card-primary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Saved sources</h3>
|
||||
{{#if (hasPermission currentUser 'api-sources.create')}}
|
||||
<div class="card-tools">
|
||||
<a class="btn btn-primary btn-sm" href="/data-sources/api-sources/new">Add API source</a>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="card-body table-responsive p-0">
|
||||
<table class="table table-striped w-100 mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>API URL</th>
|
||||
<th>Refresh interval</th>
|
||||
<th>Last pulled</th>
|
||||
<th>Last response</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#if apiSources.length}}
|
||||
{{#each apiSources}}
|
||||
<tr>
|
||||
<td data-label="Name">{{name}}</td>
|
||||
<td data-label="API URL" class="text-break">{{api_url}}</td>
|
||||
<td data-label="Refresh interval">{{intervalLabel}}</td>
|
||||
<td data-label="Last pulled">
|
||||
{{#if lastPulledAtValue}}
|
||||
<time data-local-datetime datetime="{{lastPulledAtValue}}">{{lastPullLabel}}</time>
|
||||
{{else}}
|
||||
{{lastPullLabel}}
|
||||
{{/if}}
|
||||
</td>
|
||||
<td data-label="Last response">
|
||||
{{#if last_pull_error}}
|
||||
<span class="text-danger">Failed</span>
|
||||
{{else if last_response_status}}
|
||||
<span>{{last_response_status}}</span>
|
||||
{{#if last_response_content_type}}<span class="text-muted small ms-2">{{last_response_content_type}}</span>{{/if}}
|
||||
{{else}}
|
||||
<span class="empty">-</span>
|
||||
{{/if}}
|
||||
</td>
|
||||
<td data-label="Actions">
|
||||
{{#if (anyPermission ../currentUser 'api-sources.update' 'api-sources.delete')}}
|
||||
<div class="actions">
|
||||
{{#if (hasPermission ../currentUser 'api-sources.update')}}
|
||||
<a class="btn btn-sm btn-primary" href="/data-sources/api-sources/{{id}}/edit">Edit</a>
|
||||
{{/if}}
|
||||
{{#if (hasPermission ../currentUser 'api-sources.delete')}}
|
||||
<form class="inline-form" method="post" action="/data-sources/api-sources/{{id}}/delete" data-confirm-message="Delete this API source?">
|
||||
<button class="btn btn-sm btn-danger" type="submit">Delete</button>
|
||||
</form>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{else}}
|
||||
<span class="empty">-</span>
|
||||
{{/if}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
<tr><td colspan="6" class="empty">No API sources yet.</td></tr>
|
||||
{{/if}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,47 @@
|
||||
<div class="page-header">
|
||||
<div>
|
||||
<h2>Add RSS feed</h2>
|
||||
<p>Capture a feed URL, refresh interval, and the number of items to store.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card card-outline card-primary admin-form-card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">RSS feed details</h3>
|
||||
</div>
|
||||
<form id="rss-feed-form" method="post" action="/data-sources/rss-feeds" data-async-save data-async-save-close-url="/data-sources/rss-feeds" data-async-save-new-url="/data-sources/rss-feeds/new">
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<label for="rss-feed-name" class="form-label">Name</label>
|
||||
<input id="rss-feed-name" name="name" class="form-control" value="{{rssFeed.name}}" required />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="rss-feed-url" class="form-label">Feed URL</label>
|
||||
<input id="rss-feed-url" name="feed_url" type="url" class="form-control" value="{{rssFeed.feedUrl}}" placeholder="https://example.com/feed.xml" required />
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
<div class="col-12 col-md-4">
|
||||
<label for="rss-feed-interval" class="form-label">Update interval</label>
|
||||
<input id="rss-feed-interval" name="update_interval_value" type="number" min="1" class="form-control" value="{{rssFeed.updateIntervalValue}}" required />
|
||||
</div>
|
||||
<div class="col-12 col-md-4">
|
||||
<label for="rss-feed-interval-unit" class="form-label">Unit</label>
|
||||
<select id="rss-feed-interval-unit" name="update_interval_unit" class="form-select">
|
||||
<option value="seconds" {{#if (eq rssFeed.updateIntervalUnit 'seconds')}}selected{{/if}}>Seconds</option>
|
||||
<option value="minutes" {{#if (eq rssFeed.updateIntervalUnit 'minutes')}}selected{{/if}}>Minutes</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12 col-md-4">
|
||||
<label for="rss-feed-item-limit" class="form-label">Items pulled</label>
|
||||
<input id="rss-feed-item-limit" name="item_limit" type="number" min="1" class="form-control" value="{{rssFeed.itemLimit}}" required />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer d-flex justify-content-end">
|
||||
<div class="btn-group" role="group" aria-label="RSS feed actions">
|
||||
{{{saveActionButtons formId="rss-feed-form" saveLabel="Save" saveAndCloseLabel="Save and Close" saveAndNewLabel="Save and New" saveAndCloseValue="close" saveAndNewValue="new"}}}
|
||||
<a class="btn btn-warning" href="/data-sources/rss-feeds" data-confirm-unsaved="You have unsaved changes. Leave this page?">Cancel</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,185 @@
|
||||
<div class="page-header">
|
||||
<div>
|
||||
<h2>Edit RSS feed - {{rssFeed.name}}</h2>
|
||||
<p>Adjust the source URL, refresh interval, or item count.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card card-outline card-primary admin-form-card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">RSS feed details</h3>
|
||||
</div>
|
||||
<form id="rss-feed-form" method="post" action="/data-sources/rss-feeds/{{rssFeed.id}}" data-async-save data-async-save-refresh-target="#rss-feed-items-panel" data-async-save-refresh-state-url="/data-sources/rss-feeds/{{rssFeed.id}}/state" data-async-save-close-url="/data-sources/rss-feeds" data-async-save-new-url="/data-sources/rss-feeds/new">
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<label for="rss-feed-name" class="form-label">Name</label>
|
||||
<input id="rss-feed-name" name="name" class="form-control" value="{{rssFeed.name}}" required />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="rss-feed-url" class="form-label">Feed URL</label>
|
||||
<input id="rss-feed-url" name="feed_url" type="url" class="form-control" value="{{rssFeed.feedUrl}}" placeholder="https://example.com/feed.xml" required />
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
<div class="col-12 col-md-4">
|
||||
<label for="rss-feed-interval" class="form-label">Update interval</label>
|
||||
<input id="rss-feed-interval" name="update_interval_value" type="number" min="1" class="form-control" value="{{rssFeed.updateIntervalValue}}" required />
|
||||
</div>
|
||||
<div class="col-12 col-md-4">
|
||||
<label for="rss-feed-interval-unit" class="form-label">Unit</label>
|
||||
<select id="rss-feed-interval-unit" name="update_interval_unit" class="form-select">
|
||||
<option value="seconds" {{#if (eq rssFeed.updateIntervalUnit 'seconds')}}selected{{/if}}>Seconds</option>
|
||||
<option value="minutes" {{#if (eq rssFeed.updateIntervalUnit 'minutes')}}selected{{/if}}>Minutes</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12 col-md-4">
|
||||
<label for="rss-feed-item-limit" class="form-label">Items pulled</label>
|
||||
<input id="rss-feed-item-limit" name="item_limit" type="number" min="1" class="form-control" value="{{rssFeed.itemLimit}}" required />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer d-flex justify-content-end">
|
||||
<div class="btn-group" role="group" aria-label="RSS feed actions">
|
||||
{{{saveActionButtons formId="rss-feed-form" saveLabel="Save" saveAndCloseLabel="Save and Close" saveAndNewLabel="Save and New" saveAndCloseValue="close" saveAndNewValue="new"}}}
|
||||
<a class="btn btn-warning" href="/data-sources/rss-feeds" data-confirm-unsaved="You have unsaved changes. Leave this page?">Cancel</a>
|
||||
<button type="submit" class="btn btn-danger" form="delete-rss-feed-form">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="card card-outline card-secondary mt-4" id="rss-feed-items-panel">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Pulled items</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{{#if pullError}}
|
||||
<div class="alert alert-warning">{{pullError}}</div>
|
||||
{{/if}}
|
||||
{{#if pulledItems.length}}
|
||||
<div class="accordion rss-feed-items-accordion" id="rss-feed-items-accordion">
|
||||
{{#each pulledItems}}
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="rss-feed-item-heading-{{id}}-{{position}}">
|
||||
<button class="accordion-button {{#unless @first}}collapsed{{/unless}}" type="button" data-bs-toggle="collapse" data-bs-target="#rss-feed-item-collapse-{{id}}-{{position}}" aria-expanded="{{#if @first}}true{{else}}false{{/if}}" aria-controls="rss-feed-item-collapse-{{id}}-{{position}}">
|
||||
<span class="me-2">{{title}}</span>
|
||||
<span class="text-muted small">{{#if pubDate}}• {{pubDate}}{{/if}}</span>
|
||||
</button>
|
||||
</h2>
|
||||
<div id="rss-feed-item-collapse-{{id}}-{{position}}" class="accordion-collapse collapse {{#if @first}}show{{/if}}" aria-labelledby="rss-feed-item-heading-{{id}}-{{position}}" data-bs-parent="#rss-feed-items-accordion">
|
||||
<div class="accordion-body">
|
||||
<dl class="row mb-0">
|
||||
<dt class="col-12 col-md-3">Title</dt>
|
||||
<dd class="col-12 col-md-9">{{title}}</dd>
|
||||
|
||||
<dt class="col-12 col-md-3">Link</dt>
|
||||
<dd class="col-12 col-md-9">
|
||||
{{#if link}}
|
||||
<a href="{{link}}" target="_blank" rel="noopener noreferrer">{{link}}</a>
|
||||
{{else}}
|
||||
<span class="empty">-</span>
|
||||
{{/if}}
|
||||
</dd>
|
||||
|
||||
<dt class="col-12 col-md-3">Published</dt>
|
||||
<dd class="col-12 col-md-9">{{#if pubDate}}{{pubDate}}{{else}}-{{/if}}</dd>
|
||||
|
||||
<dt class="col-12 col-md-3">Author</dt>
|
||||
<dd class="col-12 col-md-9">{{#if itemJson.author}}{{itemJson.author}}{{else}}-{{/if}}</dd>
|
||||
|
||||
<dt class="col-12 col-md-3">GUID</dt>
|
||||
<dd class="col-12 col-md-9">{{#if itemJson.guid}}{{itemJson.guid}}{{else}}-{{/if}}</dd>
|
||||
|
||||
<dt class="col-12 col-md-3">Comments</dt>
|
||||
<dd class="col-12 col-md-9">
|
||||
{{#if itemJson.comments}}
|
||||
<a href="{{itemJson.comments}}" target="_blank" rel="noopener noreferrer">{{itemJson.comments}}</a>
|
||||
{{else}}
|
||||
<span class="empty">-</span>
|
||||
{{/if}}
|
||||
</dd>
|
||||
|
||||
<dt class="col-12 col-md-3">Description</dt>
|
||||
<dd class="col-12 col-md-9">{{#if description}}{{description}}{{else}}<span class="empty">-</span>{{/if}}</dd>
|
||||
|
||||
<dt class="col-12 col-md-3">Categories</dt>
|
||||
<dd class="col-12 col-md-9">
|
||||
{{#if itemJson.categories.length}}
|
||||
<ul class="list-group list-group-flush border rounded">
|
||||
{{#each itemJson.categories}}
|
||||
<li class="list-group-item d-flex justify-content-between align-items-start">
|
||||
<span>{{value}}</span>
|
||||
{{#if domain}}<span class="text-muted small ms-3">{{domain}}</span>{{/if}}
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{else}}
|
||||
<span class="empty">-</span>
|
||||
{{/if}}
|
||||
</dd>
|
||||
|
||||
<dt class="col-12 col-md-3">Enclosure</dt>
|
||||
<dd class="col-12 col-md-9">
|
||||
{{#if itemJson.enclosure}}
|
||||
<dl class="row mb-0">
|
||||
<dt class="col-12 col-lg-4">URL</dt>
|
||||
<dd class="col-12 col-lg-8">
|
||||
{{#if itemJson.enclosure.url}}
|
||||
<a href="{{itemJson.enclosure.url}}" target="_blank" rel="noopener noreferrer">{{itemJson.enclosure.url}}</a>
|
||||
{{else}}
|
||||
<span class="empty">-</span>
|
||||
{{/if}}
|
||||
</dd>
|
||||
<dt class="col-12 col-lg-4">Length</dt>
|
||||
<dd class="col-12 col-lg-8">{{#if itemJson.enclosure.length}}{{itemJson.enclosure.length}}{{else}}-{{/if}}</dd>
|
||||
<dt class="col-12 col-lg-4">Type</dt>
|
||||
<dd class="col-12 col-lg-8">{{#if itemJson.enclosure.type}}{{itemJson.enclosure.type}}{{else}}-{{/if}}</dd>
|
||||
</dl>
|
||||
{{else}}
|
||||
<span class="empty">-</span>
|
||||
{{/if}}
|
||||
</dd>
|
||||
|
||||
<dt class="col-12 col-md-3">Source</dt>
|
||||
<dd class="col-12 col-md-9 mb-0">
|
||||
{{#if itemJson.source}}
|
||||
<dl class="row mb-0">
|
||||
<dt class="col-12 col-lg-4">Title</dt>
|
||||
<dd class="col-12 col-lg-8">{{#if itemJson.source.title}}{{itemJson.source.title}}{{else}}-{{/if}}</dd>
|
||||
<dt class="col-12 col-lg-4">URL</dt>
|
||||
<dd class="col-12 col-lg-8">
|
||||
{{#if itemJson.source.url}}
|
||||
<a href="{{itemJson.source.url}}" target="_blank" rel="noopener noreferrer">{{itemJson.source.url}}</a>
|
||||
{{else}}
|
||||
<span class="empty">-</span>
|
||||
{{/if}}
|
||||
</dd>
|
||||
</dl>
|
||||
{{else}}
|
||||
<span class="empty">-</span>
|
||||
{{/if}}
|
||||
</dd>
|
||||
|
||||
<dt class="col-12 col-md-3">Raw item XML</dt>
|
||||
<dd class="col-12 col-md-9 mb-0">
|
||||
{{#if itemJson.rawXml}}
|
||||
<details>
|
||||
<summary class="small text-muted">Show raw XML</summary>
|
||||
<pre class="mb-0 mt-2 small bg-body-tertiary border rounded p-3 text-wrap">{{itemJson.rawXml}}</pre>
|
||||
</details>
|
||||
{{else}}
|
||||
<span class="empty">-</span>
|
||||
{{/if}}
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="alert alert-secondary mb-0">No feed items could be loaded.</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form id="delete-rss-feed-form" method="post" action="/data-sources/rss-feeds/{{rssFeed.id}}/delete" data-confirm-message="Delete this RSS feed?"></form>
|
||||
@@ -0,0 +1,60 @@
|
||||
<div class="page-header">
|
||||
<div>
|
||||
<h2>RSS feeds</h2>
|
||||
<p>Store feed sources, refresh cadence, and how many entries to pull each time.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card card-outline card-primary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Saved feeds</h3>
|
||||
{{#if (hasPermission currentUser 'rss-feeds.create')}}
|
||||
<div class="card-tools">
|
||||
<a class="btn btn-primary btn-sm" href="/data-sources/rss-feeds/new">Add RSS feed</a>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="card-body table-responsive p-0">
|
||||
<table class="table table-striped w-100 mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Feed URL</th>
|
||||
<th>Refresh interval</th>
|
||||
<th>Items pulled</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#if rssFeeds.length}}
|
||||
{{#each rssFeeds}}
|
||||
<tr>
|
||||
<td data-label="Name">{{name}}</td>
|
||||
<td data-label="Feed URL" class="text-break">{{feed_url}}</td>
|
||||
<td data-label="Refresh interval">{{intervalLabel}}</td>
|
||||
<td data-label="Items pulled">{{itemLabel}}</td>
|
||||
<td data-label="Actions">
|
||||
{{#if (anyPermission ../currentUser 'rss-feeds.update' 'rss-feeds.delete')}}
|
||||
<div class="actions">
|
||||
{{#if (hasPermission ../currentUser 'rss-feeds.update')}}
|
||||
<a class="btn btn-sm btn-primary" href="/data-sources/rss-feeds/{{id}}/edit">Edit</a>
|
||||
{{/if}}
|
||||
{{#if (hasPermission ../currentUser 'rss-feeds.delete')}}
|
||||
<form class="inline-form" method="post" action="/data-sources/rss-feeds/{{id}}/delete" data-confirm-message="Delete this RSS feed?">
|
||||
<button class="btn btn-sm btn-danger" type="submit">Delete</button>
|
||||
</form>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{else}}
|
||||
<span class="empty">-</span>
|
||||
{{/if}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
<tr><td colspan="5" class="empty">No RSS feeds yet.</td></tr>
|
||||
{{/if}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user