Fixed mastodon checkbox on new entry page
This commit is contained in:
@@ -9,11 +9,13 @@
|
|||||||
* Ability to minimize settings panels to only show headers in the Admin and Profile interfaces for easy navigation
|
* Ability to minimize settings panels to only show headers in the Admin and Profile interfaces for easy navigation
|
||||||
* Styled settings panel headers with distinct theme accent colors for visual distinction
|
* Styled settings panel headers with distinct theme accent colors for visual distinction
|
||||||
* Settings panels are collapsed by default when opening the Admin and Profile pages
|
* Settings panels are collapsed by default when opening the Admin and Profile pages
|
||||||
|
* Show checked-by-default Mastodon publishing on New Entry only for configured users
|
||||||
### Fixed
|
### Fixed
|
||||||
* Fixed element ID conflict on the Admin page so Available Themes load correctly
|
* Fixed element ID conflict on the Admin page so Available Themes load correctly
|
||||||
* Positioned new-entry tag checkboxes after their label text
|
* Positioned new-entry tag checkboxes after their label text
|
||||||
* Kept new-entry tag checkboxes immediately left of their labels at all viewport sizes
|
* Kept new-entry tag checkboxes immediately left of their labels at all viewport sizes
|
||||||
* Prevented the new-entry form grid from placing tag checkboxes above their labels
|
* Prevented the new-entry form grid from placing tag checkboxes above their labels
|
||||||
|
* Kept unconfigured New Entry Mastodon publishing controls hidden
|
||||||
|
|
||||||
## Version v0.1.1
|
## Version v0.1.1
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1358,3 +1358,15 @@ The checkbox takes the full width of the grid which forces the label to be print
|
|||||||
|
|
||||||
### Assistant outcome
|
### Assistant outcome
|
||||||
Fixed the actual layout conflict: `.form-section label` uses a grid layout whose selector overrode the tag label's flex layout. Added the more specific `.form-section label.tag-checkbox` inline-flex rule and reset its checkbox margin, keeping each checkbox directly left of its tag text. The focused API test module passed with 35 tests and `git diff --check` passed.
|
Fixed the actual layout conflict: `.form-section label` uses a grid layout whose selector overrode the tag label's flex layout. Added the more specific `.form-section label.tag-checkbox` inline-flex rule and reset its checkbox margin, keeping each checkbox directly left of its tag text. The focused API test module passed with 35 tests and `git diff --check` passed.
|
||||||
|
|
||||||
|
### User
|
||||||
|
Only show the Mastodon publishing on new page if the user has Mastodon posting configured. Then default the checkbox to yes
|
||||||
|
|
||||||
|
### Assistant outcome
|
||||||
|
Added a safe `configured` status to the authenticated Mastodon configuration response. New Entry now hides its Mastodon publishing section unless the current user has both an instance and access token configured; when shown, its checkbox defaults to checked. Link creation accepts `post_to_mastodon`, allowing an unchecked control to skip Mastodon while preserving dispatch of other plugins. Added posting and configuration regression coverage.
|
||||||
|
|
||||||
|
### User
|
||||||
|
In the currently running contaier the user olaf has no mastodon configured but the mastodon checkbox is still visible
|
||||||
|
|
||||||
|
### Assistant outcome
|
||||||
|
Found that `.form-section { display: grid; }` appeared later in the stylesheet than `.hidden { display: none; }`, overriding the initial hidden state of the Mastodon fieldset. Added `.form-section.hidden { display: none; }`, so the publishing control stays hidden until the authenticated configuration check explicitly reveals it.
|
||||||
|
|||||||
@@ -242,6 +242,8 @@
|
|||||||
223. On the new-entry page the checkbox should be following the labels - now they are positioned above.
|
223. On the new-entry page the checkbox should be following the labels - now they are positioned above.
|
||||||
224. The checkboxes should be immediately to the left of the label not below left
|
224. The checkboxes should be immediately to the left of the label not below left
|
||||||
225. The checkbox takes the full width of the grid which forces the label to be printed underneath instead of directly next to it.
|
225. The checkbox takes the full width of the grid which forces the label to be printed underneath instead of directly next to it.
|
||||||
|
226. Only show the Mastodon publishing on new page if the user has Mastodon posting configured. Then default the checkbox to yes
|
||||||
|
227. In the currently running contaier the user olaf has no mastodon configured but the mastodon checkbox is still visible
|
||||||
|
|
||||||
## Future entries
|
## Future entries
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ class LinkCreate(BaseModel):
|
|||||||
comment: str = ''
|
comment: str = ''
|
||||||
timestamp: str | None = None
|
timestamp: str | None = None
|
||||||
tags: list[str] = []
|
tags: list[str] = []
|
||||||
|
post_to_mastodon: bool = True
|
||||||
|
|
||||||
|
|
||||||
class LinkUpdate(BaseModel):
|
class LinkUpdate(BaseModel):
|
||||||
@@ -89,7 +90,11 @@ def create_link_endpoint(payload: LinkCreate, response: Response, authorization:
|
|||||||
raise HTTPException(status_code=422, detail=str(error)) from error
|
raise HTTPException(status_code=422, detail=str(error)) from error
|
||||||
if duplicate:
|
if duplicate:
|
||||||
response.status_code = status.HTTP_200_OK
|
response.status_code = status.HTTP_200_OK
|
||||||
plugin_results = plugin_manager.dispatch({'type': 'link_created', **record})
|
plugin_results = plugin_manager.dispatch({
|
||||||
|
'type': 'link_created',
|
||||||
|
'post_to_mastodon': payload.post_to_mastodon,
|
||||||
|
**record,
|
||||||
|
})
|
||||||
mastodon_result = next((result for result in plugin_results if result.get('plugin') == 'mastodon'), None)
|
mastodon_result = next((result for result in plugin_results if result.get('plugin') == 'mastodon'), None)
|
||||||
if mastodon_result and mastodon_result.get('status') == 'posted':
|
if mastodon_result and mastodon_result.get('status') == 'posted':
|
||||||
mark_mastodon_posted(record['id'], info['user_id'], mastodon_result.get('post_id'))
|
mark_mastodon_posted(record['id'], info['user_id'], mastodon_result.get('post_id'))
|
||||||
|
|||||||
@@ -390,6 +390,8 @@ def get_user_plugin_config(plugin_name: str, user: dict = Depends(get_current_us
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
config = json.loads(row['config']) if row['config'] else {}
|
config = json.loads(row['config']) if row['config'] else {}
|
||||||
|
if plugin_name == 'mastodon':
|
||||||
|
config['configured'] = bool(config.get('instance') and config.get('access_token'))
|
||||||
if config.get('access_token'):
|
if config.get('access_token'):
|
||||||
config.pop('access_token')
|
config.pop('access_token')
|
||||||
return config
|
return config
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ class MastodonPlugin(BasePlugin):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def handle_event(self, event):
|
def handle_event(self, event):
|
||||||
|
if not event.get('post_to_mastodon', True):
|
||||||
|
return {'status': 'skipped', 'plugin': self.name, 'reason': 'not_requested'}
|
||||||
|
|
||||||
config = dict(self.config)
|
config = dict(self.config)
|
||||||
user_id = event.get('user_id')
|
user_id = event.get('user_id')
|
||||||
if user_id:
|
if user_id:
|
||||||
|
|||||||
@@ -889,6 +889,18 @@ def test_link_submission_posts_to_enabled_mastodon_plugin():
|
|||||||
server.server_close()
|
server.server_close()
|
||||||
|
|
||||||
|
|
||||||
|
def test_link_submission_can_skip_mastodon_posting():
|
||||||
|
with patch('backend.app.api.links.plugin_manager.dispatch', return_value=[]) as dispatch:
|
||||||
|
response = client.post('/api/links', headers=login_headers(), json={
|
||||||
|
'title': 'Private share',
|
||||||
|
'url': 'https://example.com/private-share',
|
||||||
|
'post_to_mastodon': False,
|
||||||
|
})
|
||||||
|
|
||||||
|
assert response.status_code == 201
|
||||||
|
assert dispatch.call_args.args[0]['post_to_mastodon'] is False
|
||||||
|
|
||||||
|
|
||||||
def test_mastodon_post_without_title_omits_source_line():
|
def test_mastodon_post_without_title_omits_source_line():
|
||||||
from backend.app.services.plugin_manager import MastodonPlugin
|
from backend.app.services.plugin_manager import MastodonPlugin
|
||||||
|
|
||||||
@@ -922,6 +934,7 @@ def test_plugin_config_can_be_saved_for_mastodon():
|
|||||||
payload = client.get('/api/user/plugins/mastodon', headers=headers).json()
|
payload = client.get('/api/user/plugins/mastodon', headers=headers).json()
|
||||||
assert payload['instance'] == 'mastodon.social'
|
assert payload['instance'] == 'mastodon.social'
|
||||||
assert payload['post_prefix'] == 'From my #LinkLog: '
|
assert payload['post_prefix'] == 'From my #LinkLog: '
|
||||||
|
assert payload['configured'] is True
|
||||||
|
|
||||||
admin_update = client.put('/api/admin/plugins/mastodon', headers=headers, json={
|
admin_update = client.put('/api/admin/plugins/mastodon', headers=headers, json={
|
||||||
'enabled': True,
|
'enabled': True,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
const commentInput = document.getElementById('comment-input');
|
const commentInput = document.getElementById('comment-input');
|
||||||
const newTagsInput = document.getElementById('new-tags-input');
|
const newTagsInput = document.getElementById('new-tags-input');
|
||||||
const existingTagsEl = document.getElementById('existing-tags');
|
const existingTagsEl = document.getElementById('existing-tags');
|
||||||
|
const mastodonPublishing = document.getElementById('mastodon-publishing');
|
||||||
const mastodonEnabledCheckbox = document.getElementById('mastodon-enabled');
|
const mastodonEnabledCheckbox = document.getElementById('mastodon-enabled');
|
||||||
const scrapeButton = document.getElementById('scrape-button');
|
const scrapeButton = document.getElementById('scrape-button');
|
||||||
const scrapeStatus = document.getElementById('scrape-status');
|
const scrapeStatus = document.getElementById('scrape-status');
|
||||||
@@ -46,7 +47,7 @@
|
|||||||
.then((user) => {
|
.then((user) => {
|
||||||
currentUser = user;
|
currentUser = user;
|
||||||
entryForm.classList.remove('hidden');
|
entryForm.classList.remove('hidden');
|
||||||
loadTags();
|
Promise.all([loadTags(), loadMastodonPublishing()]);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
localStorage.removeItem('linklogAccessToken');
|
localStorage.removeItem('linklogAccessToken');
|
||||||
@@ -66,6 +67,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function loadMastodonPublishing() {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/user/plugins/mastodon', {
|
||||||
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
|
});
|
||||||
|
if (!response.ok) return;
|
||||||
|
const config = await response.json();
|
||||||
|
mastodonEnabledCheckbox.checked = Boolean(config.configured);
|
||||||
|
mastodonPublishing.classList.toggle('hidden', !config.configured);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Could not load Mastodon configuration:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Render tag checkboxes
|
// Render tag checkboxes
|
||||||
function renderTags() {
|
function renderTags() {
|
||||||
existingTagsEl.innerHTML = '';
|
existingTagsEl.innerHTML = '';
|
||||||
@@ -171,6 +186,7 @@
|
|||||||
url,
|
url,
|
||||||
comment,
|
comment,
|
||||||
tags,
|
tags,
|
||||||
|
post_to_mastodon: mastodonEnabledCheckbox.checked,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1006,6 +1006,10 @@ button:disabled {
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form-section.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.form-section label {
|
.form-section label {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
|
|||||||
@@ -80,11 +80,11 @@
|
|||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset class="form-section">
|
<fieldset id="mastodon-publishing" class="form-section hidden">
|
||||||
<legend>Mastodon Publishing</legend>
|
<legend>Mastodon Publishing</legend>
|
||||||
<label>
|
<label>
|
||||||
<input id="mastodon-enabled" type="checkbox" />
|
<input id="mastodon-enabled" type="checkbox" checked />
|
||||||
Post to Mastodon (if configured)
|
Post to Mastodon
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
@@ -102,6 +102,6 @@
|
|||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script src="/static/auth-header.js"></script>
|
<script src="/static/auth-header.js"></script>
|
||||||
<script src="/static/new-entry.js"></script>
|
<script src="/static/new-entry.js?v=2"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user