mirror of
https://github.com/mediacms-io/mediacms.git
synced 2025-11-20 21:46:04 -05:00
feat: RBAC + SAML support
This commit is contained in:
151
static/jazzmin/js/change_form.js
Normal file
151
static/jazzmin/js/change_form.js
Normal file
@@ -0,0 +1,151 @@
|
||||
(function($) {
|
||||
'use strict';
|
||||
|
||||
function FixSelectorHeight() {
|
||||
$('.selector .selector-chosen').each(function () {
|
||||
let selector_chosen = $(this);
|
||||
let selector_available = selector_chosen.siblings('.selector-available');
|
||||
|
||||
let selector_chosen_select = selector_chosen.find('select').first();
|
||||
let selector_available_select = selector_available.find('select').first();
|
||||
let selector_available_filter = selector_available.find('p.selector-filter').first();
|
||||
|
||||
selector_chosen_select.height(selector_available_select.height() + selector_available_filter.outerHeight());
|
||||
selector_chosen_select.css('border-top', selector_chosen_select.css('border-bottom'));
|
||||
});
|
||||
}
|
||||
|
||||
function handleCarousel($carousel) {
|
||||
const errors = $('.errorlist li', $carousel);
|
||||
const hash = document.location.hash;
|
||||
|
||||
// If we have errors, open that tab first
|
||||
if (errors.length) {
|
||||
const errorCarousel = errors.eq(0).closest('.carousel-item');
|
||||
$carousel.carousel(errorCarousel.data('carouselid'));
|
||||
$('.carousel-fieldset-label', $carousel).text(errorCarousel.data()["label"]);
|
||||
} else if (hash) {
|
||||
// If we have a tab hash, open that
|
||||
const activeCarousel = $('.carousel-item[data-target="' + hash + '"]', $carousel);
|
||||
$carousel.carousel(activeCarousel.data()["carouselid"]);
|
||||
$('.carousel-fieldset-label', $carousel).text(activeCarousel.data()["label"]);
|
||||
}
|
||||
|
||||
// Update page hash/history on slide
|
||||
$carousel.on('slide.bs.carousel', function (e) {
|
||||
|
||||
FixSelectorHeight();
|
||||
// call resize in change view after tab switch
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
|
||||
if (e.relatedTarget.dataset.hasOwnProperty("label")) {
|
||||
$('.carousel-fieldset-label', $carousel).text(e.relatedTarget.dataset.label);
|
||||
}
|
||||
const hash = e.relatedTarget.dataset.target;
|
||||
|
||||
if (history.pushState) {
|
||||
history.pushState(null, null, hash);
|
||||
} else {
|
||||
location.hash = hash;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleTabs($tabs) {
|
||||
const errors = $('.change-form .errorlist li');
|
||||
const hash = document.location.hash;
|
||||
|
||||
// If we have errors, open that tab first
|
||||
if (errors.length) {
|
||||
const tabId = errors.eq(0).closest('.tab-pane').attr('id');
|
||||
$('a[href="#' + tabId + '"]').tab('show');
|
||||
} else if (hash) {
|
||||
// If we have a tab hash, open that
|
||||
$('a[href="' + hash + '"]', $tabs).tab('show');
|
||||
}
|
||||
|
||||
// Change hash for page-reload
|
||||
$('a', $tabs).on('shown.bs.tab', function (e) {
|
||||
|
||||
FixSelectorHeight();
|
||||
// call resize in change view after tab switch
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
|
||||
e.preventDefault();
|
||||
if (history.pushState) {
|
||||
history.pushState(null, null, e.target.hash);
|
||||
} else {
|
||||
location.hash = e.target.hash;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleCollapsible($collapsible) {
|
||||
const errors = $('.errorlist li', $collapsible);
|
||||
const hash = document.location.hash;
|
||||
|
||||
// If we have errors, open that tab first
|
||||
if (errors.length) {
|
||||
$('.panel-collapse', $collapsible).collapse('hide');
|
||||
errors.eq(0).closest('.panel-collapse').collapse('show');
|
||||
|
||||
} else if (hash) {
|
||||
// If we have a tab hash, open that
|
||||
$('.panel-collapse', $collapsible).collapse('hide');
|
||||
$(hash, $collapsible).collapse('show');
|
||||
}
|
||||
|
||||
// Change hash for page-reload
|
||||
$collapsible.on('shown.bs.collapse', function (e) {
|
||||
|
||||
FixSelectorHeight();
|
||||
// call resize in change view after tab switch
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
|
||||
if (history.pushState) {
|
||||
history.pushState(null, null, '#' + e.target.id);
|
||||
} else {
|
||||
location.hash = '#' + e.target.id;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function applySelect2() {
|
||||
// Apply select2 to any select boxes that don't yet have it
|
||||
// and are not part of the django's empty-form inline
|
||||
const noSelect2 = '.empty-form select, .select2-hidden-accessible, .selectfilter, .selector-available select, .selector-chosen select, select[data-autocomplete-light-function=select2]';
|
||||
$('select').not(noSelect2).select2({ width: 'element' });
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
const $carousel = $('#content-main form #jazzy-carousel');
|
||||
const $tabs = $('#content-main form #jazzy-tabs');
|
||||
const $collapsible = $('#content-main form #jazzy-collapsible');
|
||||
|
||||
// Ensure all raw_id_fields have the search icon in them
|
||||
$('.related-lookup').append('<i class="fa fa-search"></i>');
|
||||
|
||||
// Style the inline fieldset button
|
||||
$('.inline-related fieldset.module .add-row a').addClass('btn btn-sm btn-default float-right');
|
||||
$('div.add-row>a').addClass('btn btn-sm btn-default float-right');
|
||||
|
||||
// Ensure we preserve the tab the user was on using the url hash, even on page reload
|
||||
if ($tabs.length) { handleTabs($tabs); }
|
||||
else if ($carousel.length) { handleCarousel($carousel); }
|
||||
else if ($collapsible.length) { handleCollapsible($collapsible); }
|
||||
|
||||
applySelect2();
|
||||
|
||||
$('body').on('change', '.related-widget-wrapper select', function(e) {
|
||||
const event = $.Event('django:update-related');
|
||||
$(this).trigger(event);
|
||||
if (!event.isDefaultPrevented() && typeof(window.updateRelatedObjectLinks) !== 'undefined') {
|
||||
updateRelatedObjectLinks(this);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Apply select2 to all select boxes when new inline row is created
|
||||
django.jQuery(document).on('formset:added', applySelect2);
|
||||
|
||||
})(jQuery);
|
||||
64
static/jazzmin/js/change_list.js
Normal file
64
static/jazzmin/js/change_list.js
Normal file
@@ -0,0 +1,64 @@
|
||||
(function($) {
|
||||
'use strict';
|
||||
|
||||
$.fn.search_filters = function () {
|
||||
$(this).change(function () {
|
||||
const $field = $(this);
|
||||
const $option = $field.find('option:selected');
|
||||
const select_name = $option.data('name');
|
||||
if (select_name) {
|
||||
$field.attr('name', select_name);
|
||||
} else {
|
||||
$field.removeAttr('name');
|
||||
}
|
||||
});
|
||||
$(this).trigger('change');
|
||||
};
|
||||
|
||||
function getMinimuInputLength(element) {
|
||||
return window.filterInputLength[element.data('name')] ?? window.filterInputLengthDefault;
|
||||
}
|
||||
|
||||
function searchFilters() {
|
||||
// Make search filters select2 and ensure they work for filtering
|
||||
const $ele = $('.search-filter');
|
||||
$ele.search_filters();
|
||||
$ele.each(function () {
|
||||
const $this = $(this);
|
||||
$this.select2({ width: '100%', minimumInputLength: getMinimuInputLength($this) });
|
||||
});
|
||||
|
||||
// Use select2 for mptt dropdowns
|
||||
const $mptt = $('.search-filter-mptt');
|
||||
if ($mptt.length) {
|
||||
$mptt.search_filters();
|
||||
$mptt.select2({
|
||||
width: '100%',
|
||||
minimumInputLength: getMinimuInputLength($mptt),
|
||||
templateResult: function (data) {
|
||||
// https://stackoverflow.com/questions/30820215/selectable-optgroups-in-select2#30948247
|
||||
// rewrite templateresult for build tree hierarchy
|
||||
if (!data.element) {
|
||||
return data.text;
|
||||
}
|
||||
const $element = $(data.element);
|
||||
let $wrapper = $('<span></span>');
|
||||
$wrapper.attr('style', $($element[0]).attr('style'));
|
||||
$wrapper.text(data.text);
|
||||
return $wrapper;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
// Ensure all raw_id_fields have the search icon in them
|
||||
$('.related-lookup').append('<i class="fa fa-search"></i>')
|
||||
|
||||
// Allow for styling of selects
|
||||
$('.actions select').addClass('form-control').select2({ width: 'element' });
|
||||
|
||||
searchFilters();
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
67
static/jazzmin/js/main.js
Normal file
67
static/jazzmin/js/main.js
Normal file
@@ -0,0 +1,67 @@
|
||||
(function($) {
|
||||
'use strict';
|
||||
|
||||
function setCookie(key, value) {
|
||||
const expires = new Date();
|
||||
expires.setTime(expires.getTime() + (value * 24 * 60 * 60 * 1000));
|
||||
document.cookie = key + '=' + value + ';expires=' + expires.toUTCString() + '; SameSite=Strict;path=/';
|
||||
}
|
||||
|
||||
function getCookie(key) {
|
||||
const keyValue = document.cookie.match('(^|;) ?' + key + '=([^;]*)(;|$)');
|
||||
return keyValue ? keyValue[2] : null;
|
||||
}
|
||||
|
||||
function handleMenu() {
|
||||
$('[data-widget=pushmenu]').bind('click', function () {
|
||||
const menuClosed = getCookie('jazzy_menu') === 'closed';
|
||||
if (!menuClosed) {
|
||||
setCookie('jazzy_menu', 'closed');
|
||||
} else {
|
||||
setCookie('jazzy_menu', 'open');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function setActiveLinks() {
|
||||
/*
|
||||
Set the currently active menu item based on the current url, or failing that, find the parent
|
||||
item from the breadcrumbs
|
||||
*/
|
||||
const url = window.location.pathname;
|
||||
const $breadcrumb = $('.breadcrumb a').last();
|
||||
const $link = $('a[href="' + url + '"]');
|
||||
const $parent_link = $('a[href="' + $breadcrumb.attr('href') + '"]');
|
||||
|
||||
if ($link.length) {
|
||||
$link.addClass('active');
|
||||
} else if ($parent_link.length) {
|
||||
$parent_link.addClass('active');
|
||||
};
|
||||
|
||||
const $a_active = $('a.nav-link.active');
|
||||
const $main_li_parent = $a_active.closest('li.nav-item.has-treeview');
|
||||
const $ul_child = $main_li_parent.children('ul');
|
||||
|
||||
$ul_child.show();
|
||||
$main_li_parent.addClass('menu-is-opening menu-open');
|
||||
};
|
||||
|
||||
$(document).ready(function () {
|
||||
// Set active status on links
|
||||
setActiveLinks()
|
||||
|
||||
// When we use the menu, store its state in a cookie to preserve it
|
||||
handleMenu();
|
||||
|
||||
// Add minimal changelist styling to templates that we have been unable to override (e.g MPTT)
|
||||
// Needs to be here and not in change_list.js because this is the only JS we are guaranteed to run
|
||||
// (as its included in base.html)
|
||||
const $changeListTable = $('#changelist .results table');
|
||||
if ($changeListTable.length && !$changeListTable.hasClass('table table-striped')) {
|
||||
$changeListTable.addClass('table table-striped');
|
||||
};
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
188
static/jazzmin/js/related-modal.js
Normal file
188
static/jazzmin/js/related-modal.js
Normal file
@@ -0,0 +1,188 @@
|
||||
(function($) {
|
||||
'use strict';
|
||||
|
||||
let relatedModalCounter = 0;
|
||||
|
||||
function checkIfInIframe() {
|
||||
return window.top !== window.self;
|
||||
}
|
||||
|
||||
// create the function that will close the modal
|
||||
function dismissModal() {
|
||||
if (checkIfInIframe()) {
|
||||
const parentWindow = window.parent;
|
||||
parentWindow.dismissModal();
|
||||
return;
|
||||
}
|
||||
|
||||
$('.related-modal-' + relatedModalCounter).modal('hide');
|
||||
|
||||
relatedModalCounter-=1;
|
||||
}
|
||||
|
||||
// create the function that will show the modal
|
||||
function showModal(title, body, e) {
|
||||
if (checkIfInIframe()) {
|
||||
const parentWindow = window.parent;
|
||||
parentWindow.showModal(title, body, e);
|
||||
return;
|
||||
}
|
||||
|
||||
relatedModalCounter+=1;
|
||||
|
||||
|
||||
$.showModal({
|
||||
title: title,
|
||||
body: body,
|
||||
backdrop: false,
|
||||
modalDialogClass: "modal-dialog-centered modal-lg",
|
||||
modalClass: "fade modal-wide related-modal-" + relatedModalCounter,
|
||||
onDispose: function() {
|
||||
// add focus to the previous modal (if exists) when the current one is closed
|
||||
var lastModal = $("div[class*='related-modal-']").last();
|
||||
if (lastModal) {
|
||||
lastModal.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const modalEl = $("div[class*='related-modal-']");
|
||||
const iframeEl = modalEl.find('#related-modal-iframe');
|
||||
|
||||
if (e.data.lookup === true) {
|
||||
// set current window as iframe opener because
|
||||
// the callback is called on the opener window
|
||||
iframeEl.on('load', function() {
|
||||
const iframeObj = $(this).get(0);
|
||||
const iframeWindow = iframeObj.contentWindow;
|
||||
iframeWindow.opener = window;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function dismissRelatedLookupModal(win, chosenId) {
|
||||
const windowName = win.name;
|
||||
const widgetName = windowName.replace(/^(change|add|delete|lookup)_/, '');
|
||||
let widgetEl;
|
||||
|
||||
if (checkIfInIframe) {
|
||||
// select second to last iframe in the main parent document
|
||||
const secondLastIframe = $('iframe.related-iframe', win.parent.document).eq(-2);
|
||||
let documentContext;
|
||||
|
||||
// if second to last iframe exists get its contents
|
||||
if (secondLastIframe.length) {
|
||||
documentContext = secondLastIframe.contents();
|
||||
|
||||
// else get main parent document
|
||||
} else {
|
||||
documentContext = $(win.parent.document);
|
||||
}
|
||||
|
||||
// find and select widget from the specified document context
|
||||
widgetEl = documentContext.find('#' + widgetName);
|
||||
|
||||
// else select widget from the main document
|
||||
} else {
|
||||
widgetEl = $('#' + widgetName);
|
||||
}
|
||||
|
||||
const widgetVal = widgetEl.val();
|
||||
if (widgetEl.hasClass('vManyToManyRawIdAdminField') && Boolean(widgetVal)) {
|
||||
widgetEl.val(widgetVal + ', ' + chosenId);
|
||||
} else {
|
||||
widgetEl.val(chosenId);
|
||||
}
|
||||
dismissModal();
|
||||
}
|
||||
|
||||
// assign functions to global variables
|
||||
window.dismissRelatedObjectModal = dismissModal;
|
||||
window.dismissRelatedLookupPopup = dismissRelatedLookupModal;
|
||||
window.showModal = showModal;
|
||||
|
||||
function presentRelatedObjectModal(e) {
|
||||
let linkEl = $(this);
|
||||
let href = (linkEl.attr('href') || '');
|
||||
|
||||
if (href === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
// open the popup as modal
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
|
||||
// remove focus from clicked link
|
||||
linkEl.blur();
|
||||
|
||||
// use the clicked link id as iframe name
|
||||
// it will be available as window.name in the loaded iframe
|
||||
let iframeName = linkEl.attr('id');
|
||||
let iframeSrc = href;
|
||||
const modalTitle = linkEl.attr('title');
|
||||
|
||||
if (e.data.lookup !== true) {
|
||||
// browsers stop loading nested iframes having the same src url
|
||||
// create a random parameter and append it to the src url to prevent it
|
||||
// this workaround doesn't work with related lookup url
|
||||
let iframeSrcRandom = String(Math.round(Math.random() * 999999));
|
||||
if (iframeSrc.indexOf('?') === -1) {
|
||||
iframeSrc += '?_modal=' + iframeSrcRandom;
|
||||
} else {
|
||||
iframeSrc += '&_modal=' + iframeSrcRandom;
|
||||
}
|
||||
}
|
||||
|
||||
if (iframeSrc.indexOf('_popup=1') === -1) {
|
||||
if (iframeSrc.indexOf('?') === -1) {
|
||||
iframeSrc += '?_popup=1';
|
||||
} else {
|
||||
iframeSrc += '&_popup=1';
|
||||
}
|
||||
}
|
||||
|
||||
// build the iframe html
|
||||
let iframeHTML = '<iframe id="related-modal-iframe" name="' + iframeName + '" src="' + iframeSrc + '" frameBorder="0" class="related-iframe"></iframe>';
|
||||
|
||||
// the modal css class
|
||||
let iframeInternalModalClass = 'related-modal';
|
||||
|
||||
// if the current window is inside an iframe, it means that it is already in a modal,
|
||||
// append an additional css class to the modal to offer more customization
|
||||
if (window.top !== window.self) {
|
||||
iframeInternalModalClass += ' related-modal__nested';
|
||||
}
|
||||
|
||||
// open the modal using dynamic bootstrap modal
|
||||
showModal(modalTitle, iframeHTML, e);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// listen click events on related links
|
||||
function presentRelatedObjectModalOnClickOn(selector, lookup) {
|
||||
let el = $(selector);
|
||||
el.removeAttr('onclick');
|
||||
el.unbind('click');
|
||||
el.click({lookup: lookup}, presentRelatedObjectModal);
|
||||
}
|
||||
|
||||
function init() {
|
||||
presentRelatedObjectModalOnClickOn('a.related-widget-wrapper-link', false);
|
||||
|
||||
// raw_id_fields support
|
||||
presentRelatedObjectModalOnClickOn('a.related-lookup', true);
|
||||
|
||||
// django-dynamic-raw-id support - #61
|
||||
// https://github.com/lincolnloop/django-dynamic-raw-id
|
||||
presentRelatedObjectModalOnClickOn('a.dynamic_raw_id-related-lookup', true);
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
init()
|
||||
});
|
||||
|
||||
django.jQuery(document).on('formset:added', init);
|
||||
|
||||
})(jQuery);
|
||||
343
static/jazzmin/js/ui-builder.js
Normal file
343
static/jazzmin/js/ui-builder.js
Normal file
@@ -0,0 +1,343 @@
|
||||
(function ($) {
|
||||
'use strict';
|
||||
|
||||
const $body = $('body');
|
||||
const $footer = $('footer');
|
||||
const $sidebar_ul = $('aside#jazzy-sidebar nav ul:first-child');
|
||||
const $sidebar = $('aside#jazzy-sidebar');
|
||||
const $navbar = $('nav#jazzy-navbar');
|
||||
const $logo = $('#jazzy-logo');
|
||||
const $actions = $('#jazzy-actions');
|
||||
const buttons = [
|
||||
"primary",
|
||||
"secondary",
|
||||
"info",
|
||||
"warning",
|
||||
"danger",
|
||||
"success",
|
||||
]
|
||||
const darkThemes = ["darkly", "cyborg", "slate", "solar", "superhero"]
|
||||
|
||||
window.ui_changes = window.ui_changes || {'button_classes': {}};
|
||||
|
||||
function miscListeners() {
|
||||
$('#footer-fixed').on('click', function () {
|
||||
$body.toggleClass('layout-footer-fixed');
|
||||
if (this.checked) {
|
||||
$('#layout-boxed:checked').click();
|
||||
}
|
||||
window.ui_changes['footer_fixed'] = this.checked;
|
||||
});
|
||||
|
||||
$('#layout-boxed').on('click', function () {
|
||||
$body.toggleClass('layout-boxed');
|
||||
|
||||
// We cannot combine these options with layout boxed
|
||||
if (this.checked) {
|
||||
$('#navbar-fixed:checked').click();
|
||||
$('#footer-fixed:checked').click();
|
||||
}
|
||||
window.ui_changes['layout_boxed'] = this.checked;
|
||||
});
|
||||
|
||||
$('#actions-fixed').on('click', function () {
|
||||
$actions.toggleClass('sticky-top');
|
||||
window.ui_changes['actions_sticky_top'] = this.checked;
|
||||
});
|
||||
|
||||
// Colour pickers
|
||||
$('#accent-colours div').on('click', function () {
|
||||
$(this).removeClass('inactive').addClass('active').parent().find(
|
||||
'div'
|
||||
).not(this).removeClass('active').addClass('inactive');
|
||||
|
||||
const newClasses = $(this).data('classes');
|
||||
|
||||
$body.removeClass(function (index, className) {
|
||||
return (className.match(/(^|\s)accent-\S+/g) || []).join(' ');
|
||||
}).addClass(newClasses);
|
||||
|
||||
window.ui_changes['accent'] = newClasses;
|
||||
});
|
||||
|
||||
$('#brand-logo-variants div').on('click', function () {
|
||||
$(this).removeClass('inactive').addClass('active').parent().find(
|
||||
'div'
|
||||
).not(this).removeClass('active').addClass('inactive');
|
||||
|
||||
let newClasses = $(this).data('classes');
|
||||
|
||||
$logo.removeClass(function (index, className) {
|
||||
return (className.match(/(^|\s)navbar-\S+/g) || []).join(' ');
|
||||
}).addClass(newClasses);
|
||||
|
||||
if (newClasses === "") {
|
||||
newClasses = false;
|
||||
$(this).parent().find('div').removeClass('active inactive');
|
||||
}
|
||||
|
||||
window.ui_changes['brand_colour'] = newClasses;
|
||||
});
|
||||
|
||||
// show code
|
||||
$("#codeBox").on('show.bs.modal', function () {
|
||||
$('.modal-body code', this).html(
|
||||
'JAZZMIN_UI_TWEAKS = ' + JSON.stringify(
|
||||
window.ui_changes, null, 4
|
||||
).replace(
|
||||
/true/g, 'True'
|
||||
).replace(
|
||||
/false/g, 'False'
|
||||
).replace(
|
||||
/null/g, 'None'
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function themeSpecificTweaks(theme) {
|
||||
if (darkThemes.indexOf(theme) > -1) {
|
||||
$('#navbar-variants .bg-dark').click();
|
||||
$("#jazzmin-btn-style-primary").val('btn-primary').change();
|
||||
$("#jazzmin-btn-style-secondary").val('btn-secondary').change();
|
||||
$body.addClass('dark-mode');
|
||||
} else {
|
||||
$('#navbar-variants .bg-white').click();
|
||||
$("#jazzmin-btn-style-primary").val('btn-outline-primary').change();
|
||||
$("#jazzmin-btn-style-secondary").val('btn-outline-secondary').change();
|
||||
$body.removeClass('dark-mode');
|
||||
}
|
||||
}
|
||||
|
||||
function themeChooserListeners() {
|
||||
// Theme chooser (standard)
|
||||
$("#jazzmin-theme-chooser").on('change', function () {
|
||||
let $themeCSS = $('#jazzmin-theme');
|
||||
|
||||
// If we are using the default theme, there will be no theme css, just the bundled one in adminlte
|
||||
if (!$themeCSS.length) {
|
||||
const staticSrc = $('#adminlte-css').attr('href').split('vendor')[0]
|
||||
$themeCSS = $('<link>').attr({
|
||||
'href': staticSrc + 'vendor/bootswatch/default/bootstrap.min.css',
|
||||
'rel': 'stylesheet',
|
||||
'id': 'jazzmin-theme'
|
||||
}).appendTo('head');
|
||||
}
|
||||
|
||||
const currentSrc = $themeCSS.attr('href');
|
||||
const currentTheme = currentSrc.split('/')[4];
|
||||
let newTheme = $(this).val();
|
||||
|
||||
$themeCSS.attr('href', currentSrc.replace(currentTheme, newTheme));
|
||||
|
||||
$body.removeClass (function (index, className) {
|
||||
return (className.match (/(^|\s)theme-\S+/g) || []).join(' ');
|
||||
});
|
||||
$body.addClass('theme-' + newTheme);
|
||||
|
||||
themeSpecificTweaks(newTheme);
|
||||
|
||||
window.ui_changes['theme'] = newTheme;
|
||||
});
|
||||
|
||||
// Theme chooser (dark mode)
|
||||
$("#jazzmin-dark-mode-theme-chooser").on('change', function () {
|
||||
let $themeCSS = $('#jazzmin-dark-mode-theme');
|
||||
// If we are using the default theme, there will be no theme css, just the bundled one in adminlte
|
||||
|
||||
if (this.value === "") {
|
||||
$themeCSS.remove();
|
||||
window.ui_changes['dark_mode_theme'] = null;
|
||||
return
|
||||
}
|
||||
|
||||
if (!$themeCSS.length) {
|
||||
const staticSrc = $('#adminlte-css').attr('href').split('vendor')[0]
|
||||
$themeCSS = $('<link>').attr({
|
||||
'href': staticSrc + 'vendor/bootswatch/darkly/bootstrap.min.css',
|
||||
'rel': 'stylesheet',
|
||||
'id': 'jazzmin-dark-mode-theme',
|
||||
'media': '(prefers-color-scheme: dark)'
|
||||
}).appendTo('head');
|
||||
}
|
||||
|
||||
const currentSrc = $themeCSS.attr('href');
|
||||
const currentTheme = currentSrc.split('/')[4];
|
||||
const newTheme = $(this).val();
|
||||
|
||||
$themeCSS.attr('href', currentSrc.replace(currentTheme, newTheme));
|
||||
|
||||
themeSpecificTweaks(newTheme);
|
||||
|
||||
window.ui_changes['dark_mode_theme'] = newTheme;
|
||||
});
|
||||
}
|
||||
|
||||
function navBarTweaksListeners() {
|
||||
$('#navbar-fixed').on('click', function () {
|
||||
$body.toggleClass('layout-navbar-fixed');
|
||||
if (this.checked) {$('#layout-boxed:checked').click();}
|
||||
window.ui_changes['navbar_fixed'] = this.checked;
|
||||
});
|
||||
|
||||
$('#no-navbar-border').on('click', function () {
|
||||
$navbar.toggleClass('border-bottom-0');
|
||||
window.ui_changes['no_navbar_border'] = $navbar.hasClass('border-bottom-0');
|
||||
});
|
||||
|
||||
// Colour picker
|
||||
$('#navbar-variants div').on('click', function () {
|
||||
$(this).removeClass('inactive').addClass('active').parent().find(
|
||||
'div'
|
||||
).not(this).removeClass('active').addClass('inactive');
|
||||
|
||||
const newClasses = $(this).data('classes');
|
||||
|
||||
$navbar.removeClass(function (index, className) {
|
||||
return (className.match(/(^|\s)navbar-\S+/g) || []).join(' ');
|
||||
}).addClass('navbar-expand ' + newClasses);
|
||||
|
||||
window.ui_changes['navbar'] = newClasses;
|
||||
});
|
||||
}
|
||||
|
||||
function sideBarTweaksListeners() {
|
||||
$('#sidebar-nav-flat-style').on('click', function () {
|
||||
$sidebar_ul.toggleClass('nav-flat');
|
||||
window.ui_changes['sidebar_nav_flat_style'] = this.checked;
|
||||
});
|
||||
|
||||
$('#sidebar-nav-legacy-style').on('click', function () {
|
||||
$sidebar_ul.toggleClass('nav-legacy');
|
||||
window.ui_changes['sidebar_nav_legacy_style'] = this.checked;
|
||||
});
|
||||
|
||||
$('#sidebar-nav-compact').on('click', function () {
|
||||
$sidebar_ul.toggleClass('nav-compact');
|
||||
window.ui_changes['sidebar_nav_compact_style'] = this.checked;
|
||||
});
|
||||
|
||||
$('#sidebar-nav-child-indent').on('click', function () {
|
||||
$sidebar_ul.toggleClass('nav-child-indent');
|
||||
window.ui_changes['sidebar_nav_child_indent'] = this.checked;
|
||||
});
|
||||
|
||||
$('#main-sidebar-disable-hover-focus-auto-expand').on('click', function () {
|
||||
$sidebar.toggleClass('sidebar-no-expand');
|
||||
window.ui_changes['sidebar_disable_expand'] = this.checked;
|
||||
});
|
||||
|
||||
$('#sidebar-fixed').on('click', function () {
|
||||
$body.toggleClass('layout-fixed');
|
||||
window.ui_changes['sidebar_fixed'] = this.checked;
|
||||
});
|
||||
|
||||
// Colour pickers
|
||||
$('#dark-sidebar-variants div, #light-sidebar-variants div').on('click', function () {
|
||||
$(this).removeClass('inactive').addClass('active').parent().find(
|
||||
'div'
|
||||
).not(this).removeClass('active').addClass('inactive');
|
||||
|
||||
const newClasses = $(this).data('classes');
|
||||
|
||||
$sidebar.removeClass(function (index, className) {
|
||||
return (className.match(/(^|\s)sidebar-[\S|-]+/g) || []).join(' ');
|
||||
}).addClass(newClasses);
|
||||
|
||||
window.ui_changes['sidebar'] = newClasses.trim();
|
||||
});
|
||||
}
|
||||
|
||||
function smallTextListeners() {
|
||||
$('#navbar-small-text').on('click', function () {
|
||||
$navbar.toggleClass('text-sm');
|
||||
window.ui_changes['navbar_small_text'] = this.checked;
|
||||
});
|
||||
|
||||
$('#brand-small-text').on('click', function () {
|
||||
$logo.toggleClass('text-sm');
|
||||
window.ui_changes['brand_small_text'] = this.checked;
|
||||
});
|
||||
|
||||
$('#body-small-text').on('click', function () {
|
||||
$body.toggleClass('text-sm');
|
||||
window.ui_changes['body_small_text'] = this.checked;
|
||||
const $smallTextControls = $('#navbar-small-text, #brand-small-text, #footer-small-text, #sidebar-nav-small-text');
|
||||
if (this.checked) {
|
||||
window.ui_changes['navbar_small_text'] = false;
|
||||
window.ui_changes['brand_small_text'] = false;
|
||||
window.ui_changes['footer_small_text'] = false;
|
||||
window.ui_changes['sidebar_nav_small_text'] = false;
|
||||
$smallTextControls.prop({'checked': false, 'disabled': 'disabled'});
|
||||
} else {
|
||||
$smallTextControls.prop({'checked': false, 'disabled': ''});
|
||||
}
|
||||
});
|
||||
|
||||
$('#footer-small-text').on('click', function () {
|
||||
$footer.toggleClass('text-sm');
|
||||
window.ui_changes['footer_small_text'] = this.checked;
|
||||
});
|
||||
|
||||
$('#sidebar-nav-small-text').on('click', function () {
|
||||
$sidebar_ul.toggleClass('text-sm');
|
||||
window.ui_changes['sidebar_nav_small_text'] = this.checked;
|
||||
});
|
||||
}
|
||||
|
||||
function buttonStyleListeners() {
|
||||
buttons.forEach(function(btn) {
|
||||
$("#jazzmin-btn-style-" + btn).on('change', function () {
|
||||
const btnClasses = ['btn-' + btn, 'btn-outline-' + btn];
|
||||
const selectorClasses = '.btn-' + btn + ', .btn-outline-' + btn;
|
||||
$(selectorClasses).removeClass(btnClasses).addClass(this.value);
|
||||
window.ui_changes['button_classes'][btn] = this.value;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setFromExisting() {
|
||||
$('#jazzmin-theme-chooser').val(window.ui_changes['theme']);
|
||||
$('#jazzmin-dark-mode-theme-chooser').val(window.ui_changes['dark_mode_theme']);
|
||||
$('#theme-condition').val(window.ui_changes['theme_condition']);
|
||||
$('#body-small-text').get(0).checked = window.ui_changes['body_small_text'];
|
||||
$('#footer-small-text').get(0).checked = window.ui_changes['footer_small_text'];
|
||||
$('#sidebar-nav-small-text').get(0).checked = window.ui_changes['sidebar_nav_small_text'];
|
||||
$('#sidebar-nav-legacy-style').get(0).checked = window.ui_changes['sidebar_nav_legacy_style'];
|
||||
$('#sidebar-nav-compact').get(0).checked = window.ui_changes['sidebar_nav_compact_style'];
|
||||
$('#sidebar-nav-child-indent').get(0).checked = window.ui_changes['sidebar_nav_child_indent'];
|
||||
$('#main-sidebar-disable-hover-focus-auto-expand').get(0).checked = window.ui_changes['sidebar_disable_expand'];
|
||||
$('#no-navbar-border').get(0).checked = window.ui_changes['no_navbar_border'];
|
||||
$('#navbar-small-text').get(0).checked = window.ui_changes['navbar_small_text'];
|
||||
$('#brand-small-text').get(0).checked = window.ui_changes['brand_small_text'];
|
||||
|
||||
// deactivate colours
|
||||
$('#navbar-variants div, #accent-colours div, #dark-sidebar-variants div, #light-sidebar-variants div, #brand-logo-variants div').addClass('inactive');
|
||||
|
||||
// set button styles
|
||||
buttons.forEach(function(btn) {
|
||||
$("#jazzmin-btn-style-" + btn).val(window.ui_changes['button_classes'][btn]);
|
||||
});
|
||||
|
||||
// set colours
|
||||
$('#navbar-variants div[data-classes="' + window.ui_changes['navbar'] + '"]').addClass('active');
|
||||
$('#accent-colours div[data-classes="' + window.ui_changes['accent'] + '"]').addClass('active');
|
||||
$('#dark-sidebar-variants div[data-classes="' + window.ui_changes['sidebar'] + '"]').addClass('active');
|
||||
$('#light-sidebar-variants div[data-classes="' + window.ui_changes['sidebar'] + '"]').addClass('active');
|
||||
$('#brand-logo-variants div[data-classes="' + window.ui_changes['brand_colour'] + '"]').addClass('active');
|
||||
}
|
||||
|
||||
/*
|
||||
Don't call if it is inside an iframe
|
||||
*/
|
||||
if (!$body.hasClass("popup")) {
|
||||
setFromExisting();
|
||||
themeChooserListeners();
|
||||
miscListeners();
|
||||
navBarTweaksListeners();
|
||||
sideBarTweaksListeners();
|
||||
smallTextListeners();
|
||||
buttonStyleListeners();
|
||||
}
|
||||
|
||||
})(jQuery);
|
||||
Reference in New Issue
Block a user