Skip to content

Commit

Permalink
Refactor theme page and make it work with htmx
Browse files Browse the repository at this point in the history
Via vanilla color input, users can easily select colors and even extract
colors from screen, and thus farbtastic is not needed any more.

Besides that, now the color input value automatically changes to current
value that's specified in "Custom CSS" when a section is selected.
  • Loading branch information
sunnavy committed Dec 26, 2024
1 parent 27442d0 commit ac9553b
Show file tree
Hide file tree
Showing 11 changed files with 51 additions and 561 deletions.
7 changes: 0 additions & 7 deletions devel/third-party/README
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,6 @@ Origin: https://github.com/NicolasCARPi/dropzone
License: MIT
Note that this version is in a new, maintained fork from the original project.


* eyedropper.svg
Description: color picker icon
Origin: http://thenounproject.com/noun/eye-dropper/ (The Noun Project)
Author: The Noun Project
License: CC BY 3.0

* htmx-2.0.3
Description: htmx gives you access to AJAX, CSS Transitions, WebSockets and Server Sent Events directly in HTML, using attributes, so you can build modern user interfaces with the simplicity and power of hypertext
Origin: https://github.com/bigskysoftware/htmx
Expand Down
13 changes: 0 additions & 13 deletions devel/third-party/eyedropper.svg

This file was deleted.

3 changes: 0 additions & 3 deletions lib/RT/Interface/Web/MenuBuilder.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1485,9 +1485,6 @@ sub _BuildAdminTopMenu {
title => loc('Theme'),
description => loc('Customize the look of your RT'),
path => '/Admin/Tools/Theme.html',
attributes => {
'hx-boost' => 'false',
},
);
if (RT->Config->Get('StatementLog')
&& $current_user->HasRight( Right => 'SuperUser', Object => RT->System )) {
Expand Down
148 changes: 50 additions & 98 deletions share/html/Admin/Tools/Theme.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,12 @@
<& /Elements/Tabs &>
<& /Elements/ListActions, actions => \@results &>

<script type="text/javascript" src="<%RT->Config->Get('WebPath')%>/static/js/farbtastic.js"></script>

<div class="row">

<div id="simple-customize" class="col-6">
<div id="upload-logo">
<h2>Logo</h2>
<h3>Logo</h3>
<& /Elements/Logo, id => 'logo-theme-editor', ShowName => 0 &>
<button onclick="setLogoSize()" class="button btn btn-primary form-control" id="logo-size"><&|/l&>Full Size</&></button>

<form method="POST" enctype="multipart/form-data" action="">
<div class="row mt-2">
Expand All @@ -82,7 +79,7 @@ <h2>Logo</h2>
</div>

<div id="custom-css" class="col-6">
<h2><&|/l&>Custom CSS (Advanced)</&></h2>
<h3><&|/l&>Custom CSS (Advanced)</&></h3>

<form method="POST" id="custom-css-form" action="">
<textarea class="form-control mb-2" rows="20" id="user_css" name="user_css" wrap="off"><% $user_css %></textarea>
Expand All @@ -98,21 +95,19 @@ <h2><&|/l&>Custom CSS (Advanced)</&></h2>

<div class="row">
<div id="customize-theme" class="col-6">
<h2><&|/l&>Customize the RT theme</&></h2>
<ol class="list-group-compact list-group">
<li class="list-group-item">
<label for="section"><&|/l&>Select a section</&>:</label>
<select class="selectpicker" id="section"></select>
</li>
<li class="list-group-item">
<div class="description">
<&|/l&>Select a color for the section</&>:
<div id="logo-picker-hint" style="display: none;">
<&|/l&>You can also click on the logo above to get colors!</&>
</div>
</div>
<h3><&|/l&>Customize the RT theme</&></h3>
<&| /Elements/LabeledValue, Label => loc('Select a section') &>
<select class="form-select selectpicker" id="section" name="section">
% for my $section ( @sections ) {
<option value="<% $section->[0] %>"><% $section->[0] %></option>
% };
</select>
</&>

<&| /Elements/LabeledValue, Label => loc('Select a color for the section') &>
<div class="row">
% if ($colors) {
<div class="button btn btn-primary primary-colors">
<div class="col button btn btn-primary primary-colors">
% for (@$colors) {
% my $fg = $_->{l} >= $text_threshold ? 'black' : 'white';
<button type="button" class="button btn btn-primary color-template form-control"
Expand All @@ -122,10 +117,11 @@ <h2><&|/l&>Customize the RT theme</&></h2>
% }
</div>
% }
<div id="color-picker"></div>
<canvas id="logo-color-picker" title="<&|/l&>Click to choose a color</&>"></canvas>
</li>
</ol>
<div class="col">
<input type="color" class="form-control" id="color-picker" />
</div>
</div>
</&>
</div>
</div>

Expand All @@ -146,25 +142,11 @@ <h2><&|/l&>Customize the RT theme</&></h2>
</%ONCE>
<script type="text/javascript">
var section_css_mapping = <% JSON(\@sections) |n%>;

jQuery(function($) {

jQuery.each(section_css_mapping, function(i,v){
$('select#section').append($("<option/>")
.attr('value', v[0])
.text(v[0]));
});
// Refresh selectpicker so we have a default value, at least for Firefox
$('select#section').val(section_css_mapping[0][0]);

function update_sitecss(text) {
if (!text)
text = $('#user_css').val();

// IE 8 doesn't let us update the innerHTML of <style> tags (with jQuery.text())
// see: http://stackoverflow.com/questions/2692770/style-style-textcss-appendtohead-does-not-work-in-ie/2692861#2692861
$("style#sitecss").remove();
$("<style id='sitecss' type='text/css' media='all'>" + text + "</style>").appendTo('head');
$("style#sitecss").text(text);
}

update_sitecss();
Expand Down Expand Up @@ -225,73 +207,43 @@ <h2><&|/l&>Customize the RT theme</&></h2>
update_sitecss(css);
}

$('#color-picker').farbtastic(function(color){ change_color(color, this.hsl[2] > <% $text_threshold %> ? '#000' : '#fff') });
document.querySelector('#color-picker').addEventListener('change', function() {
const red = parseInt('0x' + this.value.substr(1,2));
const green = parseInt('0x' + this.value.substr(3,2));
const blue = parseInt('0x' + this.value.substr(5,2));
const lightness = (Math.max(red, green, blue) + Math.min(red, green, blue))/2/255;
change_color(this.value, lightness > <% $text_threshold %> ? '#000' : '#fff');
});

$('button.color-template').click(function() {
change_color($(this).css('background-color'), $(this).css('color'));
});

});

// Setup the canvas color picker
jQuery(window).on('load',function() {
var $ = jQuery;
var logo = $("#logo-theme-editor img");
var canvas = $("#logo-color-picker");
var el_canvas = canvas.get(0);
});

if (!el_canvas.getContext) return;

setLogoSize();
document.getElementById('section').addEventListener('change', event => {
const section = event.target.value;
const selector = section_css_mapping.filter( a => { return a[0] == section })[0][1][0];
const specials = new RegExp("([.*+?|()\\[\\]{}\\\\])", "g");
const escaped_selector = selector.replace(specials, "\\$1");
const rule = new RegExp('^'+escaped_selector+'\\s*\{\\s*background:\\s*(#\\w+|rgb\\((\\d+),\\s*(\\d+),\\s*(\\d+)\\))', "m");
const css = document.getElementById('user_css').value;
const result = css.match(rule);
if ( result ) {
if ( result[2] ) {
document.getElementById('color-picker').value =
'#' + result.slice(2, 5).map(num => parseInt(num).toString(16).padStart(2, '0')).join('');
}
else {
document.getElementById('color-picker').value = result[1];
}
}
else {
document.getElementById('color-picker').value = '#ffffff';
}
});
document.getElementById('section').dispatchEvent(new Event('change'));
});

function setLogoSize() {
var logo = jQuery("#logo-theme-editor img");
var canvas = jQuery("#logo-color-picker");
var el_canvas = canvas.get(0);

if (!el_canvas.getContext) return;
// Set logo to same size as CSS input
var container = jQuery('#user_css');

var context = el_canvas.getContext("2d");
var button = jQuery('#logo-size');

if ( button.text() == '<&|/l&>Preview</&>' ) {
var ratio = Math.min(container.width() / logo.width(), container.height() / logo.height());

el_canvas.width = logo.width()*ratio;
el_canvas.height = logo.height()*ratio;

// Re-draw our scaled down image
context.drawImage(logo.get(0), 0, 0, logo.width()*ratio, logo.height()*ratio );

button.text( "<&|/l&>Full Size</&>" );
}
else {
el_canvas.width = logo.width();
el_canvas.height = logo.height();

context.drawImage(logo.get(0), 0, 0);
button.text( "<&|/l&>Preview</&>" );
}

logo.hide().after(canvas);
canvas.show().click(function(ev) {
ev.preventDefault();
var R = 0,
G = 1,
B = 2,
A = 3;
var pixel = this.getContext("2d").getImageData(ev.offsetX, ev.offsetY, 1, 1).data;
// Farbtastic expects values in the range of 0..1
var rgba = jQuery.makeArray(pixel).map(function(v,i) { return v / 255 });
var wheel = jQuery.farbtastic("#color-picker");
wheel.setHSL( wheel.RGBToHSL( rgba.slice(R,A) ) );
// XXX TODO factor in the alpha channel too
});
jQuery('#logo-picker-hint').show();
}
</script>
<%INIT>
unless ($session{'CurrentUser'}->HasRight( Object=> RT->System, Right => 'SuperUser')) {
Expand Down
51 changes: 0 additions & 51 deletions share/static/css/elevator/farbtastic.css

This file was deleted.

1 change: 0 additions & 1 deletion share/static/css/elevator/main.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
@import "jquery-ui.css";
@import "jquery-ui-timepicker-addon.css";
@import "tablesorter.css";
@import "farbtastic.css";
@import "bootstrap.css";
@import "bootstrap-combobox.css";
@import "dropzone.css";
Expand Down
42 changes: 1 addition & 41 deletions share/static/css/elevator/theme-editor.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,53 +5,13 @@

#logo-theme-editor a img {
border: none;
max-width: 100%;
}

#custom-css textarea {
width: 100%;
}

#customize-theme ol li {
font-size: 1.2em;
font-weight: bold;
}

#customize-theme ol li .description,
#customize-theme ol li label
{
font-weight: normal;
}

#customize-theme #section {
font-size: 1em;
}

.color-template {
height: 2em;
margin: 0 0 0.5em 0;
}

.primary-colors, #color-picker {
margin-top: 0.5em;
}

.primary-colors {
float: left;
width: 20%;
}

#color-picker {
float: right;
width: 78%;
}

#logo-color-picker {
display: none; /* unhidden by javascript */
cursor: url(../../../static/images/eyedropper.png), crosshair;
z-index: 1;
position: relative;
}

#custom-css-form {
z-index: 2;
position: relative;
Expand Down
Binary file removed share/static/images/farbtastic/marker.png
Binary file not shown.
Binary file removed share/static/images/farbtastic/mask.png
Binary file not shown.
Binary file removed share/static/images/farbtastic/wheel.png
Binary file not shown.
Loading

0 comments on commit ac9553b

Please sign in to comment.