BTHLABS-56: _Copy share link_ button in view association page
Co-authored-by: Tomek Wójcik <labs@tomekwojcik.pl> Co-committed-by: Tomek Wójcik <labs@tomekwojcik.pl>
This commit is contained in:
parent
ab84f685c0
commit
d1e60babf4
|
@ -0,0 +1,58 @@
|
|||
/*!
|
||||
* HotPocket by BTHLabs (https://hotpocket.app/)
|
||||
* Copyright 2025-present BTHLabs <contact@bthlabs.pl> (https://bthlabs.pl/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
((HotPocket) => {
|
||||
class HotPocketUIPasteboardLinkPlugin {
|
||||
constructor (app) {
|
||||
}
|
||||
onLoad (event) {
|
||||
let canCopy = false;
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
canCopy = true;
|
||||
}
|
||||
|
||||
for (let pasteboardLink of document.querySelectorAll('.ui-pasteboard-link')) {
|
||||
if (canCopy === false) {
|
||||
pasteboardLink.classList.add('d-none');
|
||||
} else {
|
||||
pasteboardLink.addEventListener('click', this.onClick);
|
||||
}
|
||||
}
|
||||
}
|
||||
onClick = (event) => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
const icon = event.target.querySelector('i.bi');
|
||||
icon.classList.replace('bi-clipboard-fill', 'bi-clipboard');
|
||||
|
||||
navigator.clipboard.writeText(event.target.href).
|
||||
then(() => {
|
||||
icon.classList.replace('bi-clipboard', 'bi-clipboard-fill');
|
||||
}).
|
||||
catch((reason) => {
|
||||
console.error('HotPocket.UI.PasteboardLink.onClick()', reason);
|
||||
window.alert('Could not copy the link :(');
|
||||
});
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
HotPocket.addPlugin('UI.PasteboardLink', (app) => {
|
||||
return new HotPocketUIPasteboardLinkPlugin(app);
|
||||
});
|
||||
})(window.HotPocket);
|
|
@ -41,7 +41,20 @@
|
|||
if (navigator.share) {
|
||||
shareButton.addEventListener('click', this.onShareButtonClick);
|
||||
} else {
|
||||
shareButton.addClass('d-none');
|
||||
shareButton.remove();
|
||||
}
|
||||
}
|
||||
|
||||
const uiPlugin = this.app.plugin('UI');
|
||||
for (let controlButton of document.querySelectorAll('#ViewAssociationView .ui-controls > a.btn')) {
|
||||
if (uiPlugin.jsEnabled === true) {
|
||||
if (controlButton.classList.contains('ui-noscript-show')) {
|
||||
controlButton.remove();
|
||||
}
|
||||
} else {
|
||||
if (controlButton.classList.contains('ui-noscript-hide')) {
|
||||
controlButton.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -59,12 +72,9 @@
|
|||
onShareButtonClick = (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
const shareUrl = new URL(window.location.href);
|
||||
shareUrl.searchParams.set('share', 'true');
|
||||
|
||||
navigator.share({
|
||||
title: document.title,
|
||||
url: shareUrl.toString(),
|
||||
url: event.target.href,
|
||||
});
|
||||
|
||||
return false;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
class HotPocketUIPlugin {
|
||||
constructor (app) {
|
||||
document.body.classList.add('ui-js-enabled');
|
||||
this.jsEnabled = document.body.classList.contains('ui-js-enabled');
|
||||
|
||||
if (window.navigator.standalone === true) {
|
||||
document.querySelector('body').classList.add('ui-mode-standalone');
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
</a>
|
||||
</p>
|
||||
{% if show_controls %}
|
||||
<p class="mb-3 text-center">
|
||||
{% spaceless %}
|
||||
<div class="d-flex justify-content-center mb-3">
|
||||
<div class="btn-group ui-controls" role="group">
|
||||
<a
|
||||
class="btn btn-primary btn-sm"
|
||||
href="{% url 'ui.associations.edit' pk=association.pk %}"
|
||||
|
@ -35,14 +35,29 @@
|
|||
<i class="bi bi-pencil"></i> {% translate 'Edit' %}
|
||||
</a>
|
||||
<a
|
||||
class="btn btn-secondary btn-sm ms-2 ui-noscript-hide ui-share-button"
|
||||
href="#"
|
||||
class="btn btn-secondary btn-sm ui-noscript-hide ui-share-button"
|
||||
href="{{ share_url }}"
|
||||
role="button"
|
||||
>
|
||||
<i class="bi bi-box-arrow-up"></i> {% translate 'Share' %}
|
||||
</a>
|
||||
{% endspaceless %}
|
||||
</p>
|
||||
<a
|
||||
class="btn btn-secondary btn-sm ui-noscript-hide ui-pasteboard-link"
|
||||
href="{{ share_url }}"
|
||||
role="button"
|
||||
>
|
||||
<i class="bi bi-clipboard"></i> {% translate 'Copy share link' %}
|
||||
</a>
|
||||
<a
|
||||
class="btn btn-secondary btn-sm ui-noscript-show"
|
||||
href="{{ share_url }}"
|
||||
rel="noopener noreferer"
|
||||
target="_blank"
|
||||
>
|
||||
<i class="bi bi-link-45deg"></i> {% translate 'Share link' %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if association.description %}
|
||||
<div class="row mb-3">
|
||||
|
|
|
@ -152,6 +152,7 @@
|
|||
<script src="{% static 'ui/js/hotpocket-backend.ui.ViewAssociationView.js' %}" type="text/javascript"></script>
|
||||
<script src="{% static 'ui/js/hotpocket-backend.ui.BrowseAccountAppsView.js' %}" type="text/javascript"></script>
|
||||
<script src="{% static 'ui/js/hotpocket-backend.ui.InlineCreateSaveForm.js' %}" type="text/javascript"></script>
|
||||
<script src="{% static 'ui/js/hotpocket-backend.ui.PasteboardLink.js' %}" type="text/javascript"></script>
|
||||
{% block page_scripts %}{% endblock %}
|
||||
<script type="text/javascript">
|
||||
(() => {
|
||||
|
|
|
@ -198,12 +198,21 @@ def view(request: HttpRequest, pk: uuid.UUID) -> HttpResponse:
|
|||
if is_share is True:
|
||||
show_controls = show_controls and False
|
||||
|
||||
share_url = reverse(
|
||||
'ui.associations.view',
|
||||
args=(association.pk,),
|
||||
query=[
|
||||
('share', 'true'),
|
||||
],
|
||||
)
|
||||
|
||||
return render(
|
||||
request,
|
||||
'ui/associations/view.html',
|
||||
{
|
||||
'association': association,
|
||||
'show_controls': show_controls,
|
||||
'share_url': share_url,
|
||||
},
|
||||
)
|
||||
|
||||
|
|
|
@ -27,6 +27,14 @@ def test_authenticated_ok(authenticated_client: Client,
|
|||
assert hasattr(result.context['association'], 'target') is True
|
||||
assert result.context['association'].target.pk == association_out.target.pk
|
||||
assert result.context['show_controls'] is True
|
||||
assert 'share_url' in result.context
|
||||
|
||||
expected_share_url = reverse(
|
||||
'ui.associations.view',
|
||||
args=(association_out.pk,),
|
||||
query=[('share', 'true')],
|
||||
)
|
||||
assert result.context['share_url'] == expected_share_url
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
|
|
Loading…
Reference in New Issue
Block a user