-
-
Notifications
You must be signed in to change notification settings - Fork 299
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
migrate to Bootstrap v4 #773
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,33 @@ | ||
/* overriding icon-button text color with theme color */ | ||
form.icon button { | ||
color: inherit; | ||
} | ||
|
||
/* fixing table layout */ | ||
.list-buttons-column {width: 0} | ||
.list-buttons-column .icon:last-child {margin-right: 10px} | ||
|
||
.filters .filter-op {width: var(--filter-op) !important} | ||
.filters .filter-val {width: calc(var(--filters) - var(--filter-op) - var(--filter-buttons) - var(--filter-type)) !important} | ||
#filter_form[action^='/tag/'] {--filter-type: var(--filter-type-tags)} | ||
|
||
:root {--filters: 645px; --filter-op: 9em; --filter-buttons: 12.5em; --filter-type: 5.5em; --filter-type-tags: 9em} | ||
:root {--filters: 510px; --filter-op: 9rem; --filter-buttons: 12.5rem; --filter-type: 6rem; --filter-type-tags: 9.5rem} | ||
/* due to how flask-admin filters are set up, each language requires manual adjustments for full-width sizes */ | ||
html[lang=de] {--filter-buttons: 19em} | ||
html[lang=fr] {--filter-buttons: 17em} | ||
html[lang=ru] {--filter-buttons: 16.5em; --filter-type: 8.5em; --filter-type-tags: 11em} | ||
html[lang=de] {--filter-buttons: 18rem} | ||
html[lang=fr] {--filter-buttons: 16rem} | ||
html[lang=ru] {--filter-buttons: 16.5rem; --filter-type: 8.5rem; --filter-type-tags: 11.5rem} | ||
|
||
@media (max-width: 767px) { | ||
.filters .filter-val {width: calc(var(--filters) - var(--filter-op) - var(--filter-type)) !important} | ||
#filter_form .pull-right:first-child {margin: .5ex 0} | ||
} | ||
@media (min-width: 768px) { | ||
:root {--filters: 710px; --filter-op: 11.5em} | ||
:root {--filters: 690px; --filter-op: 11.5rem} | ||
} | ||
@media (min-width: 992px) { | ||
:root {--filters: 930px; --filter-op: 20em} | ||
:root {--filters: 930px; --filter-op: 20rem} | ||
} | ||
@media (min-width: 1200px) { | ||
:root {--filters: 1130px; --filter-op: 20em} | ||
html[lang=ru] #filter_form[action^='/bookmark/'] {--filter-op: 25em} /* the last 'buku' filter has a rather long name */ | ||
:root {--filters: 1110px; --filter-op: 20rem} | ||
html[lang=ru] #filter_form[action^='/bookmark/'] {--filter-op: 25rem} /* the last 'buku' filter has a rather long name */ | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,7 @@ body.modal-open { | |
|
||
/* limit dialog height with a scrollbox */ | ||
.modal-content { | ||
max-height: calc(100vh - 60px); | ||
max-height: calc(100vh - 3.5rem); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bootstrap4 uses |
||
display: flex; | ||
flex-direction: column; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ | |
{{ buku.limit_navigation_if_popup() }} | ||
{{ buku.script('bookmark.js') }} | ||
{{ buku.fetch_checkbox(form.fetch.data) }} | ||
{{ buku.horizontal_form(excluding_popups=True) }} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As I mentioned, all forms were originally vertical in Bootstrap4 templates |
||
{{ buku.focus() }} | ||
{{ buku.link_saved() }} | ||
{% endblock %} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ | |
|
||
{% block edit_form %} | ||
{{ super() }} | ||
<form method="POST" action="{{ get_url('.delete_view') }}" class="delete-form" style="display: inline-block; float: right"> | ||
<form method="POST" action="{{ get_url('.delete_view') }}" class="delete-form d-inline-block float-right"> | ||
<input type="hidden" name="id" value="{{ request.args.get('id') }}"/> | ||
<input type="hidden" name="url" value="{{ return_url }}"/> | ||
{% if csrf_token %} | ||
|
@@ -24,7 +24,8 @@ | |
{{ buku.set_lang() }} | ||
{{ buku.limit_navigation_if_popup() }} | ||
{{ buku.script('bookmark.js') }} | ||
<script>$('.submit-row').append($('.delete-form'))</script> | ||
{{ buku.horizontal_form(excluding_popups=True) }} | ||
{{ buku.focus() }} | ||
{{ buku.link_saved() }} | ||
<script>$('.submit-row').append($('.delete-form'))</script> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adding the Delete button was moved to before making the form horizontal (which in turn is placed before changing keyboard focus) |
||
{% endblock %} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
javascript:void%20function(){var%20e=location.href,t=document.title.trim()||%22%22,o=document.getSelection().toString().trim()||(document.querySelector(%22meta[name$=description%20i],%20meta[property$=description%20i]%22)||{}).content||%22%22;o.length%3E4e3%26%26(o=o.substr(0,4e3)+%22...%22,alert(%22The%20selected%20text%20is%20too%20long,%20it%20will%20be%20truncated.%22)),e=%22{{url}}%3Furl=%22+encodeURIComponent(e)+%22%26title=%22+encodeURIComponent(t)+%22%26description=%22+encodeURIComponent(o),window.open(e,%22_blank%22,%22menubar=no,%20height=600,%20width=800,%20toolbar=no,%20scrollbars=yes,%20status=no,%20dialog=1%22)}(); | ||
javascript:void%20function(){var%20e=location.href,t=document.title.trim()||%22%22,o=document.getSelection().toString().trim()||(document.querySelector(%22meta[name$=description%20i],%20meta[property$=description%20i]%22)||{}).content||%22%22;o.length%3E4e3%26%26(o=o.substr(0,4e3)+%22...%22,alert(%22The%20selected%20text%20is%20too%20long,%20it%20will%20be%20truncated.%22)),e=%22{{url}}%3Furl=%22+encodeURIComponent(e)+%22%26title=%22+encodeURIComponent(t)+%22%26description=%22+encodeURIComponent(o),window.open(e,%22_blank%22,%22menubar=no,%20height=700,%20width=800,%20toolbar=no,%20scrollbars=yes,%20status=no,%20dialog=1%22)}(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,51 +9,50 @@ | |
|
||
{% block menu_links %} | ||
{{ super() }} | ||
<form class="navbar-form navbar-right" action="{{ url_for('admin.search') }}" method="POST"> | ||
<div class="form-group"> | ||
<input class="form-control" id="inputKeywords" placeholder="{{ _('Search bookmark') }}" name="keyword"> | ||
<form class="form-inline navbar-right" style="gap:.5ex" action="{{ url_for('admin.search') }}" method="POST"> | ||
<div class="d-inline-block align-middle"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
<input class="form-control" id="inputKeywords" placeholder="{{ _('Search bookmark') }}" name="keyword"/> | ||
<input type="hidden" name="markers" value="true"/> | ||
<input type="hidden" name="all_keywords" value="true"/> | ||
</div> | ||
<button type="submit" class="btn btn-default">{{ _gettext('Search') }}</button> | ||
<button type="submit" class="btn btn-secondary">{{ _gettext('Search') }}</button> | ||
</form> | ||
{% endblock %} | ||
|
||
{% block body %} | ||
{{ super() }} | ||
<main class="container text-center"> | ||
<div style="padding: 40px 15px"> | ||
<main class="container text-center p-4"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using native Bootstrap4 padding classes |
||
<h1>BUKU</h1> | ||
<p class="lead">{{ _('Bookmark manager like a text-based mini-web') }}</p> | ||
<p> | ||
<a class="btn btn-lg btn-success" href="{{ url_for('bookmark.index_view') }}" role="button">{{ _('Bookmarks') }}</a> | ||
<a class="btn btn-lg btn-success" href="{{ url_for('tag.index_view') }}" role="button">{{ _('Tags') }}</a> | ||
<a class="btn btn-lg btn-success" href="{{ url_for('statistic.index') }}" role="button">{{ _('Statistic') }}</a> | ||
</p> | ||
<div class="col-md-4 col-md-offset-4"> | ||
<div class="col-md-4 offset-md-4"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Spacing classes got renamed as well |
||
<form action="{{ url_for('admin.search') }}" method="POST"> | ||
<div class="form-group"> | ||
{{ form.keyword.label }} | ||
{{ form.keyword(class_='form-control', style='display: inline; width: auto') }} | ||
{{ form.keyword(class_='form-control d-inline', style='width: auto') }} | ||
</div> | ||
<div class="text-left col-sm-offset-3"> | ||
<div class="text-left"> | ||
{% for field in [form.all_keywords, form.markers, form.deep, form.regex] -%} | ||
<div class="checkbox" title="{{ field.description }}" data-toggle="tooltip" data-placement="bottom"> {{field()}} {{field.label}} </div> | ||
<div class="form-check" title="{{ field.description }}" data-toggle="tooltip" data-placement="bottom"> {{field()}} {{field.label}} </div> | ||
{%- endfor %} | ||
</div> | ||
<button type="submit" class="btn btn-default">{{ _gettext('Search') }}</button> | ||
<button type="submit" class="btn btn-secondary">{{ _gettext('Search') }}</button> | ||
</form> | ||
</div> | ||
<div class="col-md-4 col-md-offset-4"> | ||
<p style="padding-top: 2em"> {{_('Bookmarklet')}}: | ||
<div class="col-md-4 offset-md-4"> | ||
<p class="pt-4"> {{_('Bookmarklet')}}: | ||
<a title="Drag this link to your bookmarks toolbar" href="{{ buku.bookmarklet() }}"> | ||
<b>✚ {{ _('Add to Buku') }}</b> | ||
</a><br/> | ||
<em style="font-size: smaller">{{ _("Note: if you select text on the page before activating the bookmarklet, it'll be used as description instead of page metadata.") }}</em> | ||
</p> | ||
</div> | ||
|
||
<details class="col-md-6 col-md-offset-3"> | ||
<details class="col-md-6 offset-md-3"> | ||
<summary style="display: list-item; cursor: pointer"> <em><strong>{{ _('Location Bar (keyboard-only) shortcut') }}</strong></em> </summary> | ||
<dl> | ||
<dt>{{ _('in Firefox:') }}</dt> | ||
|
@@ -76,15 +75,14 @@ <h1>BUKU</h1> | |
</dd> | ||
</dl> | ||
</details> | ||
</div> | ||
</main> | ||
{% endblock %} | ||
|
||
{% block tail %} | ||
{{ buku.set_lang() }} | ||
<script> | ||
$(`[data-toggle="tooltip"]`).attr('data-html', 'true').each(function () { | ||
this.title = this.title.replace(/'(.*?)'/g, `'<strong><tt>$1</tt></strong>'`) | ||
this.title = this.title.replace(/'(.*?)'/g, `'<strong><code>$1</code></strong>'`) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
.replace(/(?<=^|[^\p{L}]){{ _('FULL') }}(?=$|[^\p{L}])/g, `<strong><em>{{ _('FULL')|lower }}</em></strong>`); | ||
}).attr('data-container', 'body').attr('data-trigger', 'hover').tooltip(); | ||
</script> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,8 +17,9 @@ | |
{% macro limit_navigation_if_popup() %} | ||
<style> | ||
.popup .navbar-brand {pointer-events: none} | ||
.popup :is(#admin-navbar-collapse, .navbar-toggle) {display: none !important} | ||
.popup .nav-tabs :is(:first-child, :nth-child(2):not(.active)) > * {display: none} | ||
.popup #admin-navbar-collapse {display: block} | ||
.popup :is(.navbar-nav, .navbar-toggler) {display: none} | ||
.popup .nav-tabs :is(:first-child, :nth-child(2)) > .nav-link:not(.active) {display: none} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
</style> | ||
<script>opener && (opener !== window) && document.body.classList.add('popup')</script> | ||
{% endmacro %} | ||
|
@@ -31,17 +32,37 @@ | |
{% endif %} | ||
{% endmacro %} | ||
|
||
{% macro fetch_checkbox(checked=True) %} | ||
{% macro fetch_checkbox(checked=True, modal=False) %} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
<script> | ||
$('.admin-form [name=fetch]').remove(); | ||
$('.admin-form').append( | ||
$(`<div class="form-group"><label style="display: block"><span class="col-md-2 text-right">{{ _('Fetch') }} </span>` | ||
+`<span class="col-md-10"><input type="checkbox" name="fetch"{% if checked %} checked{% endif %}></span></label></div>`)); | ||
$('.admin-form fieldset{% if modal %} .modal-footer{% endif %}').{% if modal %}prepend{% else %}append{% endif %}( | ||
$(`<div class="form-group {{ 'mb-0' if modal else '' }}"{% if modal %} style="flex-grow: 1"{% endif %}>` | ||
+`<label class="control-label {{ 'mb-0' if modal else '' }}">{{ _('Fetch') }} </label>` | ||
+`<input type="checkbox" name="fetch"{% if checked %} checked{% endif %}></div>`)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rearranging it similarly to how checkbox inputs are generated by |
||
</script> | ||
{% endmacro %} | ||
|
||
{% macro horizontal_form(excluding_popups=False) %} | ||
<script> | ||
$('.admin-form .form-group').each(function () { | ||
if ($('.submit-row', this).length > 0{% if excluding_popups %} || document.body.matches('.popup'){% endif %}) { | ||
$('.submit-row', this).addClass(document.body.matches('.popup') ? 'col-md-12' : 'offset-md-2'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Within popups, the buttons row is made full-width instead ( |
||
} else if ($('input[type=checkbox], input[type=radio]', this).length > 0) { | ||
$('label', this).addClass('form-row').css({cursor: 'pointer'}).html(`<span>${ $('label', this).html() }</span>`); | ||
$('label span', this).addClass('col-md-2 col-form-label text-right d-inline-block'); | ||
$('input', this).appendTo($('label', this)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Checkboxes/radiobuttons need custom rearrangement |
||
} else { | ||
$(this).addClass('form-row'); | ||
$('input, textarea, select', this).addClass('col-md-10'); | ||
$('label', this).addClass('col-md-2 col-form-label text-right'); | ||
} | ||
}); | ||
</script> | ||
{% endmacro %} | ||
|
||
{% macro details_formatting(prefix='') %} | ||
<script> | ||
$(`.modal-header h3`).wrapInner('<h5 class="modal-title">').children(0).unwrap(); // flask-admin #2505 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can be removed once the related bug is fixed in upstream (…and ends up in the released version, of course) |
||
$(`body.popup {{prefix}} a`).attr('target', '_blank'); | ||
</script> | ||
{% endmacro %} | ||
|
@@ -94,20 +115,18 @@ | |
$(document).ready(function() { | ||
const SIZES = [20, 50, 100]; // hardcoded list; see page_size_form() in admin/model/layout.html | ||
let pageSize = url => new URL(url || location.host).searchParams.get('page_size'); | ||
$(`.actions-nav .dropdown-menu`).each(function () { | ||
let _sizes = $(`li a`, this).map(function () {return pageSize(this.href)}).get(); | ||
$(`.nav.nav-tabs .dropdown-menu`).each(function () { | ||
let _sizes = $(`a.dropdown-item`, this).map(function () {return pageSize(this.href)}).get(); | ||
if (SIZES.every((x, i) => x == _sizes[i])) | ||
$(`li`, this).last().clone().each(function () { | ||
$('a', this).text({{ _('custom')|tojson }}).attr('href', `#`).on('click', () => { | ||
let page = prompt({{ _('Set custom page size (empty for default)')|tojson }}, pageSize(location) || ''); | ||
if ((page == "") || (Number(page) >= 1)) { | ||
let search = new URL(location).searchParams; | ||
(page ? search.set('page_size', parseInt(page)) : search.delete('page_size')); | ||
location.search = search; | ||
} else if (page != null) | ||
alert({{ _('Invalid page size')|tojson }} + `: "${page}"`); | ||
return false; | ||
}); | ||
$('a', this).last().clone().text({{ _('custom')|tojson }}).attr('href', `#`).on('click', () => { | ||
let page = prompt({{ _('Set custom page size (empty for default)')|tojson }}, pageSize(location) || ''); | ||
if (Number(page) || (page == "")) { | ||
let search = new URL(location).searchParams; | ||
(page ? search.set('page_size', page) : search.delete('page_size')); | ||
location.search = search; | ||
} else if (page != null) | ||
alert({{ _('Invalid page size')|tojson }} + `: "${page}"`); | ||
return false; | ||
}).appendTo(this); | ||
}) | ||
}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fixes the Delete button in bookmarks/tags lists not matching theme color