labelbase/django/templates/_base.html
Xavier Fiechter 86f971b066 .
2025-12-19 20:59:52 +01:00

581 lines
24 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% load i18n %}
{% load labelbase_tags %}
{% load sekizai_tags %}
{% load bootstrap %}
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta property="og:type" content="website" />
<meta property="og:url" content="https://labelbase.space/" />
<meta property="og:title" content="Labelbase" />
<meta property="og:description" content="All-in-one coin control/label management service for Bitcoin. Add, import, export labels. REST API for integration. Supports BIP-329 format. Stay organized!" />
<meta property="og:image" content="https://labelbase.space{% static 'ogimg.png' %}" />
<!-- twitter card tags additive with the og: tags -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:domain" value="labelbase.space" />
<meta name="twitter:title" value="Labelbase" />
<meta name="twitter:description" value="All-in-one coin control/label management service for Bitcoin. Add, import, export labels. REST API for integration. Supports BIP-329 format. Stay organized!" />
<meta name="twitter:image" content="https://labelbase.space{% static 'ogimg.png' %}" />
<meta name="twitter:url" value="https://labelbase.space/" />
<title>{% if user.is_authenticated %}
{% for labelbase in user.profile.labelbases %}
{% if labelbase.id == active_labelbase_id %}
{% if labelbase.name %}{{ labelbase.name }}{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% block title %}{% endblock %} | Labelbase</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet"
integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD"
crossorigin="anonymous">
<link href="{% static 'css/dataTables.bootstrap5.min.css' %}" rel="stylesheet">
<link href="{% static 'css/labelbase.css' %}" rel="stylesheet">
{% block extra_media %}{% endblock %}
<style media="screen">
{% block css %}{% endblock %}
{% render_block "css" %}
</style>
<style>
.search-container {
position: relative;
margin-top:6px;
margin-bottom:6px;
}
.search-button {
position: absolute;
right: 0;
top: 0;
bottom: 0;
display: none;
}
.search-container {
display: none !important;
}
</style>
</head>
<body>
<!-- v1 -->
{% if latest_status_message %}
<div style="background: {{ latest_status_message.color }}; z-index: 999999;position: relative;" class="d-block px-3 py-1 text-center text-bold skippy">
<a href="#" class="text-white text-decoration-none">{{ latest_status_message.message }}</a>
</div>
{% endif %}
<!-- end v1 -->
<!-- v2 --
<div style="background: rgb(33, 37, 41);z-index: 999999;position: relative;/*! padding: 11px; */" class="d-block px-3 py-1 text-center text-bold skippy">
<span style="background: goldenrod;display: inline-block;padding: 10px 20px;border-radius: 20px;/*! background-color: #007bff; */marign-top: -7px;margin: 10px;font-weight: bold;"> <a href="#" class="text-white text-decoration-none">💥 Run your self-hosted Labelbase! <u>Learn more</u></a></span>
</div>
<!-- end v2 -->
{% block content_wrapper %}
{% url 'registration' as reg_url %}
{% url 'two_factor:login' as login_url %}
{% url 'logout' as logout_url %}
{% url 'secret' as secret_url %}
<header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
<div class="container-fluid" style="padding-left: 0;">
<a class="navbar-brand col-md-3 col-lg-2 me-0 px-3 fs-6" href="{% url 'home' %}" style="background-color: transparent;">
<img style="width:210px" src="{% static 'labelbase-logo-white.png' %}">
</a>
<div class="navbar-nav ms-auto">
<div class="nav-item text-nowrap">
{% if user.is_authenticated %}
{% else %}
<div class="d-none d-md-inline">
<a href="{{ login_url }}" class="btn btn-outline-light btn-sm">Log in</a>
<a href="{{ reg_url }}" class="btn btn-primary btn-sm" style="margin-left: 5px; margin-right: -5px;">Get Started</a>
</div>
{% endif %}
</div>
</div>
{% if user.is_authenticated %}
<div class="search-container" style="margin-right: 16px; min-width: 21rem;">
<input type="text" id="searchInput" style="padding: .35rem !important; "
placeholder="Search your Labelbases" aria-label="Search"
class="form-control form-control-dark d-none d-md-flex">
<button type="submit" id="searchButton" class="btn btn-primary search-button">Search</button>
</div>
<div class="dropdown text-end d-none d-md-inline dd-avatar">
<a href="#" class="d-block link-body-emphasis text-decoration-none dropdown-toggle dd-avatar"
data-bs-toggle="dropdown" aria-expanded="true">
<img src="{{ user.profile.avatar_url }}" alt="you" width="40" height="40" class="rounded-circle">
</a>
{% include '_dropdown_profile.html' %}
</div>
<div class="dropdown text-end d-md-none ms-auto dd-avatar" style="margin-right: 72px;">
<a href="#" class="d-block link-body-emphasis text-decoration-none dropdown-toggle dd-avatar"
data-bs-toggle="dropdown" aria-expanded="true">
<img src="{{ user.profile.avatar_url }}" alt="you" width="40" height="40" class="rounded-circle">
</a>
{% include '_dropdown_profile.html' %}
</div>
{% else %}
<div class="d-flex d-md-none ms-auto" style="padding-right: 75px;">
<a href="{{ login_url }}" class="btn btn-outline-light btn-sm" "><span data-feather="log-in" class="align-text-bottom"></span></a>
<button href="{{ reg_url }}" class="btn btn-primary btn-sm" style="margin-left: 10px;">Get Started</button>
</div>
{% endif %}
<button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation" style="margin-right: -5px;">
<span class="navbar-toggler-icon"></span>
</button>
</div>
</header>
<!-- small screen search -->
<div class="d-block d-md-none px-3 py-2 bg-dark w-100">
<div class="search-container w-100" >
<input type="text" id="mobileSearchInput"
placeholder="Search your Labelbases"
aria-label="Search" class="form-control form-control-dark w-100">
<button type="submit" id="mobileSearchButton" class="btn btn-primary search-button w-auto">Search</button>
</div>
</div>
<!-- search ends here -->
<div class="container-fluid">
<div class="row">
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse" style="z-index:103">
<div class="position-sticky pt-3 sidebar-sticky" style="margin-top: 1rem;"> <!-- +1 rem, when news -->
{% if user.is_authenticated %}
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted text-uppercase">
<span>Labelbases</span>
<a class="link-secondary" data-bs-toggle="modal" data-bs-target="#addLabelbaseModal" href="#" aria-label="Add a new wallet">
<span data-feather="plus-circle" class="align-text-bottom"></span>
</a>
</h6>
{% endif %}
<ul class="nav flex-column mb-2">
{% if user.is_authenticated %}
{% for labelbase in user.profile.labelbases %}
<li class="nav-item">
<a class="nav-link" href="{{ labelbase.get_absolute_url }}">
<span data-feather="database" class="align-text-bottom"></span>
{% if labelbase.name %}{{ labelbase.name }}{% endif %} {% if  labelbase.fingerprint %}<br><span style="padding-left:2rem;"><small><tt>{{ labelbase.fingerprint }}</tt></small></span>{% endif %}
</a>
{% if labelbase.id == active_labelbase_id %}
<ul style="list-style-type: none;">
<li><a class="nav-link" href="{{ labelbase.get_absolute_url }}" style="font-size: .875rem;"><span data-feather="tag" class="align-text-bottom"></span> Labels</a></li>
{% with xpub_url=labelbase.get_xpub_url %}
{% if xpub_url %}
<li><a class="nav-link" href="{{ xpub_url }}derive-addresses/" style="font-size: .875rem;"><span data-feather="list" class="align-text-bottom"></span> Addresses</a></li>
{% endif %}
{% endwith %}
<li><a class="nav-link" style="font-size: .875rem;" href="{% url "labelbase_fix_and_manage" labelbase_id=labelbase.id %}"><span data-feather="git-merge" class="align-text-bottom"></span> Fix & Manage</a></li>
<li><a class="nav-link" style="font-size: .875rem;" href="{% url "fill_missing_data" labelbase_id=labelbase.id %}"><span data-feather="refresh-cw" class="align-text-bottom"></span> Sync Fields</a></li>
{% if request.user.profile.use_fiatfinances %}
<li><a class="nav-link" style="font-size: .875rem;" href="{% url "currency_sync" labelbase_id=labelbase.id %}"><span data-feather="dollar-sign" class="align-text-bottom"></span> Fiat Finances</a></li>
{% endif %}
{% comment %}<li><a class="nav-link" style="font-size: .875rem;" href="{% url "labelbase_health" labelbase_id=labelbase.id %}"><span data-feather="activity" class="align-text-bottom"></span>UTXOs Health</a></li>{% endcomment %}
<li><a class="nav-link" style="font-size: .875rem;" href="{% url "labelbase_tree_maps" pk=labelbase.id %}unspent-outputs/"><span data-feather="grid" class="align-text-bottom"></span> Tree Map</a></li>
{% comment %}<li><a class="nav-link" style="font-size: .875rem;" href="{% url "labelbase_stats_and_kpi" labelbase_id=labelbase.id %}"><span data-feather="pie-chart" class="align-text-bottom"></span> Stats & KPIs</a></li>{% endcomment %}
<li><a class="nav-link" style="font-size: .875rem;" data-bs-toggle="modal" data-bs-target="#importLabelbaseModal"><span data-feather="upload-cloud" class="align-text-bottom"></span> Import</a></li>
<li><a class="nav-link" style="font-size: .875rem;" data-bs-toggle="modal" data-bs-target="#exportLabelbaseModal"><span data-feather="download-cloud" class="align-text-bottom"></span> Export</a></li>
{% if labelbase.user.profile.use_hashtags %}
<li><a href="{{ labelbase.get_hashtags_url }}" class="nav-link" style="font-size: .875rem;"><span data-feather="hash" class="align-text-bottom"></span> Hashtags</a></li>
{% endif %}
</ul>
{% endif %}
</li>
{% empty %}
<!-- empty, no labelbases -->
{% endfor %}
{% else %}
<!-- empty, no session -->
{% endif %}
</ul>
<!-- -->
<div class="" style="padding-bottom:2.1rem;">
{% comment %}
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted text-uppercase">
<span>Your account</span>
</h6>
<ul class="nav flex-column mb-2">
{% if user.is_authenticated %}
<li class="nav-item">
<a class="nav-link {% block nav_userprofile %}{% endblock %}" href="{% url 'userprofile' %}"><span data-feather="user" class="align-text-bottom"></span> {{ user }}'s Profile</a>
</li>
<li class="nav-item">
<a class="nav-link {% block nav_profile %}{% endblock %}" href="{% url 'two_factor:profile' %}">{% if user.otp_device %}<span data-feather="shield" class="align-text-bottom"></span>{% else %}<span data-feather="shield-off" class="align-text-bottom"></span>{% endif %} {% trans "Account Security" %}</a></li>
<li class="nav-item">
<a class="nav-link {% block nav_apikey %}{% endblock %}" href="{% url 'apikey' %}"><span data-feather="send" class="align-text-bottom"></span> API Key & Reference</a>
<li>
<li class="nav-item">
<a class="nav-link" href="{{ logout_url }}"><span data-feather="log-out" class="align-text-bottom"></span> {% trans "Logout" %}</a>
</li>
{% else %}
<li class="nav-item"> <a class="nav-link" href="{{ login_url }}"><span data-feather="log-in" class="align-text-bottom"></span> Log in</a>
</li>
<li class="nav-item"> <a class="nav-link" href="{{  reg_url }}"><span data-feather="user-plus" class="align-text-bottom"></span> Create an account</a>
</li>
{% endif %}
</ul>
{% endcomment %}
<ul class="nav flex-column mb-2">
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted text-uppercase">
<span>Community</span>
</h6>
<li class="nav-item ">
<a class="nav-link" href="{% url "donate" %}"><span data-feather="heart" class="align-text-bottom"></span> Donate</a>
<li>
<li class="nav-item ">
<a class="nav-link" href="https://labelbase.space/newsletter/"><span data-feather="mail" class="align-text-bottom"></span> Newsletter</a>
<li>
<!--li class="nav-item ">
<a class="nav-link" href="https://labelbase.space/#/"><span data-feather="mic" class="align-text-bottom"></span> Podcast</a>
<li-->
<li class="nav-item ">
<a class="nav-link" href="https://github.com/Labelbase/Labelbase/"><span data-feather="github" class="align-text-bottom"></span> Code on GitHub</a>
<li>
<li class="nav-item ">
<a class="nav-link" href="https://twitter.com/labelbase_space"><span data-feather="twitter" class="align-text-bottom"></span> Follow us on Twitter</a>
<li>
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted text-uppercase">
<span>Resources</span>
</h6>
<!--
<li class="nav-item ">
<a class="nav-link" href="{% url 'about' %}">About</a>
<li>
-->
<li class="nav-item ">
<a class="nav-link" href="{% url 'kb-index' %}"><span data-feather="book" class="align-text-bottom"></span> Knowledge Base</a>
<li>
<li class="nav-item ">
<a class="nav-link" href="{% url 'privacy_policy' %}"><span data-feather="list" class="align-text-bottom"></span> Privacy Policy</a>
<li>
<li class="nav-item ">
<a class="nav-link" href="{% url 'terms' %}"><span data-feather="list" class="align-text-bottom"></span> Terms</a>
<li>
<li class="nav-item ">
<a class="nav-link" href="https://bip329.org"><span data-feather="external-link" class="align-text-bottom"></span> bip329.org</a>
<li>
</ul>
</div>
</div>
</nav>
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
{% include "_messages.html" %}
{% if user.is_authenticated %}
{% include "_intro.html" %}
{% endif %}
{% block content %}{% endblock %}
</main>
</div>
</div>
{% if user.is_authenticated %}
<!-- modal -->
<div class="modal" tabindex="-1" id="addLabelbaseModal">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<form action="{% url 'labelbase_new' %}" method="post">
{% csrf_token %}
<div class="modal-header">
<h5 class="modal-title">Create New Labelbase</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
{% labelbaseform as form %}
{{ form|bootstrap }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">OK</button>
</div>
</form>
</div>
</div>
</div>
{% endif %}
{% endblock %}
{% csrf_token %}
{% include "_modal_importWizzardModal.html" %}
{% include "_modal_exportLabelbaseModal.html" %}
<script src="{% static 'js/jquery-3.5.1.min.js' %}"></script>
<script src="{% static 'js/qrcode.min.js' %}"></script>
<script src="{% static 'js/bootstrap.bundle.min.js' %}"></script>
<script src="{% static 'js/feather.min.js' %}"></script>
<script src="{% static 'js/jquery.dataTables.min.js' %}"></script>
<script src="{% static 'js/chart.js' %}"></script>
<script src="{% static 'js/pdfobject.min.js' %}"></script>
<script src="{% static 'js/dataTables.bootstrap5.min.js' %}"></script>
<script src="{% static 'lightbox/js/lightbox.js' %}"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
var searchInput = document.getElementById("searchInput");
var searchButton = document.getElementById("searchButton");
var mobileSearchInput = document.getElementById("mobileSearchInput");
var mobileSearchButton = document.getElementById("mobileSearchButton");
function toggleButtonVisibility(input, button) {
if (input.value.trim() !== "") {
button.style.display = "block";
} else {
button.style.display = "none";
}
}
searchInput.addEventListener("input", function() {
toggleButtonVisibility(searchInput, searchButton);
});
mobileSearchInput.addEventListener("input", function() {
toggleButtonVisibility(mobileSearchInput, mobileSearchButton);
});
toggleButtonVisibility(searchInput, searchButton);
toggleButtonVisibility(mobileSearchInput, mobileSearchButton);
});
</script>
<script type="text/javascript">
/* globals Chart:false, feather:false */
(() => {
'use strict'
feather.replace({ 'aria-hidden': 'true' })
})()
{% block js %}{% endblock %}
{% render_block "js" %}
/* dark mode */
/*!
* Color mode toggler for Bootstrap's docs (https://getbootstrap.com/)
* Copyright 2011-2023 The Bootstrap Authors
* Licensed under the Creative Commons Attribution 3.0 Unported License.
*/
(() => {
'use strict'
const getStoredTheme = () => localStorage.getItem('theme')
const setStoredTheme = theme => localStorage.setItem('theme', theme)
const getPreferredTheme = () => {
const storedTheme = getStoredTheme()
if (storedTheme) {
return storedTheme
}
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
}
const setTheme = theme => {
if (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.setAttribute('data-bs-theme', 'dark')
} else {
document.documentElement.setAttribute('data-bs-theme', theme)
}
}
setTheme(getPreferredTheme())
const showActiveTheme = (theme, focus = false) => {
const themeSwitcher = document.querySelector('#bd-theme')
if (!themeSwitcher) {
return
}
const themeSwitcherText = document.querySelector('#bd-theme-text')
const activeThemeIcon = document.querySelector('.theme-icon-active use')
const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`)
const svgOfActiveBtn = btnToActive.querySelector('svg use').getAttribute('href')
document.querySelectorAll('[data-bs-theme-value]').forEach(element => {
element.classList.remove('active')
element.setAttribute('aria-pressed', 'false')
})
btnToActive.classList.add('active')
btnToActive.setAttribute('aria-pressed', 'true')
activeThemeIcon.setAttribute('href', svgOfActiveBtn)
const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})`
themeSwitcher.setAttribute('aria-label', themeSwitcherLabel)
if (focus) {
themeSwitcher.focus()
}
}
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
const storedTheme = getStoredTheme()
if (storedTheme !== 'light' && storedTheme !== 'dark') {
setTheme(getPreferredTheme())
}
})
window.addEventListener('DOMContentLoaded', () => {
showActiveTheme(getPreferredTheme())
document.querySelectorAll('[data-bs-theme-value]')
.forEach(toggle => {
toggle.addEventListener('click', () => {
const theme = toggle.getAttribute('data-bs-theme-value')
setStoredTheme(theme)
setTheme(theme)
showActiveTheme(theme, true)
})
})
})
})()
/* end dark mode */
$('#openImporterOptionsLink').click(function(e) {
e.preventDefault(); // Prevent the link from navigating to a different page
$('#chooseImporterOptionModal').modal('show');
});
function loadChat(hide_modal_and_store=true) {
var BASE_URL="https://app.chatwoot.com";
var g=document.createElement('script'),s=document.getElementsByTagName('script')[0];
g.src=BASE_URL+"/packs/js/sdk.js";
g.defer = true;
g.async = true;
s.parentNode.insertBefore(g,s);
g.onload=function(){
window.chatwootSDK.run({
websiteToken: '3FzpAuguuLCaaEcBf5awz6EG',
baseUrl: BASE_URL
})
}
// Hide the modal after loading chat
if (hide_modal_and_store == true) {
var csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;
$('#chatModal').modal('hide');
$.ajax({
type: 'POST',
url: '{% url "userprofile" %}',
headers: { 'X-CSRFToken': csrftoken },
data: { toggleId: 'use_chatwoot', toggleValue: 'true' },
success: function (response) {
show_message("success", "<strong>Success!</strong> " + response.message)
window.$chatwoot.toggle("open");
},
error: function (xhr, status, error) {
console.error(error);
show_message("error", "<strong>Failed to update!</strong> " + error)
}
});
}
}
$(document).ready(function () {
// Disable the Origin field by default if not Tx
{% if label.type == "tx" %}
{% else %}
$('#id_origin').prop('disabled', true);
{% endif %}
// Disable the Spendable field by default if not output
{% if label.type == "output" %}
{% else %}
$('#id_spendable').prop('disabled', true);
{% endif %}
// Monitor changes in the Type dropdown
$('#id_type').change(function () {
var selectedType = $(this).val();
// Enable or disable the Origin field based on the selected Type
if (selectedType === 'tx') {
$('#id_origin').prop('disabled', false);
$('#id_origin').val('');
} else {
$('#id_origin').prop('disabled', true);
}
// Enable or disable the Spendable field based on the selected Type
if (selectedType === 'output') {
$('#id_spendable').prop('disabled', false);
} else {
$('#id_spendable').val("unknown").change();
$('#id_spendable').prop('disabled', true);
}
});
{% if request.user.profile.use_chatwoot %}
loadChat(false);
{% endif %}
});
</script>
</body>
</html>