Skip to content

Commit 1ea947c

Browse files
committed
Add preview modal
1 parent f28a28d commit 1ea947c

9 files changed

+245
-6
lines changed

amd/build/snippetsdetailsmodal.min.js

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

amd/build/snippetsdetailsmodal.min.js.map

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

amd/src/snippetsdetailsmodal.js

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// This file is part of Moodle - http://moodle.org/
2+
//
3+
// Moodle is free software: you can redistribute it and/or modify
4+
// it under the terms of the GNU General Public License as published by
5+
// the Free Software Foundation, either version 3 of the License, or
6+
// (at your option) any later version.
7+
//
8+
// Moodle is distributed in the hope that it will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
// GNU General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU General Public License
14+
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
15+
16+
/**
17+
* Theme Boost Union - JS code for snippets details modal.
18+
*
19+
* @module theme_boost_union/snippetsdetailsmodal
20+
* @copyright 2024 Alexander Bias, lern.link GmbH <[email protected]>
21+
* based on core_admin/themeselector/preview_modal by David Woloszyn <[email protected]>
22+
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23+
*/
24+
25+
import ModalCancel from 'core/modal_cancel';
26+
import Notification from 'core/notification';
27+
import Templates from 'core/templates';
28+
import {getString} from 'core/str';
29+
30+
const SELECTORS = {
31+
SNIPPETS_CONTAINER: 'theme_boost_union_snippets',
32+
DETAILS: '[data-action="details"]',
33+
};
34+
35+
/**
36+
* Entrypoint of the js.
37+
*
38+
* @method init
39+
*/
40+
export const init = () => {
41+
registerListenerEvents();
42+
};
43+
44+
/**
45+
* Register snippet related event listeners.
46+
*
47+
* @method registerListenerEvents
48+
*/
49+
const registerListenerEvents = () => {
50+
document.addEventListener('click', (e) => {
51+
const details = e.target.closest(SELECTORS.DETAILS);
52+
if (details) {
53+
buildModal(details).catch(Notification.exception);
54+
}
55+
});
56+
};
57+
58+
/**
59+
* Build the modal with the provided data.
60+
*
61+
* @method buildModal
62+
* @param {object} element
63+
*/
64+
const buildModal = async(element) => {
65+
66+
// Prepare data for modal.
67+
const data = {
68+
title: element.getAttribute('data-title'),
69+
description: element.getAttribute('data-description'),
70+
image: element.getAttribute('data-image'),
71+
source: element.getAttribute('data-source'),
72+
goal: element.getAttribute('data-goal'),
73+
scope: element.getAttribute('data-scope'),
74+
};
75+
76+
await ModalCancel.create({
77+
title: data.title,
78+
body: Templates.render('theme_boost_union/snippetsdetailsmodal', data),
79+
large: true,
80+
buttons: {
81+
'cancel': getString('closebuttontitle', 'moodle'),
82+
},
83+
show: true,
84+
});
85+
};

classes/snippets.php

+46-3
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,55 @@ public static function get_snippet_file($path, $source): string|null {
6565
global $CFG;
6666

6767
// Get the snippet file based on the different sources.
68-
if ('theme_boost_union' === $source) {
69-
// Builtin CSS SNippets.
68+
// Builtin CSS Snippets.
69+
if ($source === 'theme_boost_union') {
70+
// Compose the file path.
7071
$file = $CFG->dirroot . self::BUILTIN_SNIPPETS_BASE_PATH . $path;
71-
} else {
72+
7273
// Other snippet sources (which are currently not supported).
74+
} else {
7375
return null;
7476
}
77+
7578
return is_readable($file) ? $file : null;
7679
}
7780

81+
/**
82+
* Gets the snippet's preview file URL.
83+
*
84+
* @param string $path The snippet's path.
85+
* @param string $source The snippet's source.
86+
*
87+
* @return string|null
88+
*/
89+
public static function get_snippet_preview_url($path, $source): string|null {
90+
global $CFG;
91+
92+
// Get the snippet file based on the different sources.
93+
// Builtin CSS Snippets.
94+
if ($source === 'theme_boost_union') {
95+
// Replace the .scss suffix with a .png suffix in the path.
96+
$search = '.scss';
97+
$pos = strrpos($path, $search);
98+
if ($pos !== false) {
99+
$path = substr_replace($path, '.png', $pos, strlen($search));
100+
} else {
101+
// In this case the .scss suffix was not found, so anything is broken.
102+
return null;
103+
}
104+
105+
// Compose the file path and URL.
106+
$file = $CFG->dirroot . self::BUILTIN_SNIPPETS_BASE_PATH . $path;
107+
$url = new \moodle_url(self::BUILTIN_SNIPPETS_BASE_PATH . $path);
108+
109+
// Other snippet sources (which are currently not supported).
110+
} else {
111+
return null;
112+
}
113+
114+
return is_readable($file) ? $url : null;
115+
}
116+
78117
/**
79118
* Get the SCSS of a snippet based on its path and source.
80119
*
@@ -127,13 +166,17 @@ public static function get_snippet_meta($path, $source): stdClass|null {
127166
return null;
128167
}
129168

169+
// Get the preview image as well.
170+
$image = self::get_snippet_preview_url($path, $source);
171+
130172
// Create an object containing the metadata.
131173
$snippet = new stdClass();
132174
$snippet->title = $headers['Snippet Title'];
133175
$snippet->description = $headers['Description'];
134176
$snippet->scope = $headers['Scope'];
135177
$snippet->goal = $headers['Goal'];
136178
$snippet->source = $source;
179+
$snippet->image = $image;
137180

138181
return $snippet;
139182
}

classes/table/snippets_overview.php

+22-3
Original file line numberDiff line numberDiff line change
@@ -59,21 +59,19 @@ class snippets_overview extends \table_sql {
5959
* @throws \coding_exception
6060
*/
6161
public function __construct() {
62-
global $DB;
62+
global $DB, $PAGE;
6363

6464
// Call parent constructor.
6565
parent::__construct('snippets');
6666

6767
// Define the headers and columns.
6868
$headers[] = get_string('snippetstitle', 'theme_boost_union');
69-
$headers[] = get_string('snippetsdescription', 'theme_boost_union');
7069
$headers[] = get_string('snippetssource', 'theme_boost_union');
7170
$headers[] = get_string('snippetsscope', 'theme_boost_union');
7271
$headers[] = get_string('snippetsgoal', 'theme_boost_union');
7372
$headers[] = get_string('up') .'/'. get_string('down');
7473
$headers[] = get_string('actions');
7574
$columns[] = 'title';
76-
$columns[] = 'description';
7775
$columns[] = 'source';
7876
$columns[] = 'scope';
7977
$columns[] = 'goal';
@@ -86,6 +84,12 @@ public function __construct() {
8684
$this->define_headers($headers);
8785
$this->define_header_column('title');
8886

87+
// Add CSS class which will help the preview modal JS later.
88+
$this->set_attribute('id', 'theme_boost_union_snippets');
89+
90+
// Add JS for the snippets details modal.
91+
$PAGE->requires->js_call_amd('theme_boost_union/snippetsdetailsmodal', 'init');
92+
8993
// Initialize values for the updown feature.
9094
$this->count = 0;
9195
$this->totalsnippets = $DB->count_records('theme_boost_union_snippets');
@@ -225,6 +229,21 @@ public function col_actions($data) {
225229
];
226230
}
227231

232+
// Details.
233+
$actions[] = [
234+
'url' => '#',
235+
'icon' => new \pix_icon('info', get_string('snippetsshowdetails', 'theme_boost_union'), 'theme_boost_union'),
236+
'attributes' => ['class' => 'action-details',
237+
'data-action' => 'details',
238+
'data-title' => $data->title,
239+
'data-source' => $this->pick_and_build_badge('snippetssource'.$data->source),
240+
'data-goal' => $this->pick_and_build_badge('snippetsgoal'.$data->goal),
241+
'data-scope' => $this->pick_and_build_badge('snippetsscope'.$data->scope),
242+
'data-description' => $data->description,
243+
'data-image' => $data->image,
244+
],
245+
];
246+
228247
// Compose action icons for all actions.
229248
$actionshtml = [];
230249
foreach ($actions as $action) {

lang/en/theme_boost_union.php

+3
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,8 @@
11061106
// Settings: CSS snippets page.
11071107
$string['configtitlesnippets'] = 'CSS snippets';
11081108
$string['snippetsdescription'] = 'Description';
1109+
$string['snippetsdetails'] = 'Details';
1110+
$string['snippetsdetailspreview'] = 'Preview';
11091111
$string['snippetsdisable'] = 'Disable';
11101112
$string['snippetsenable'] = 'Enable';
11111113
$string['snippetsexperimental'] = 'Please note: The CSS snippets functionality is fully usable in the current state of implementation, but has to be <em>considered as extendible</em> as currently only snippets which are built into or added to the Boost Union plugin codebase can be used.';
@@ -1121,6 +1123,7 @@
11211123
$string['snippetsscopecourse'] = 'Course';
11221124
$string['snippetsscopedashboard'] = 'Dashboard';
11231125
$string['snippetsscopeglobal'] = 'Global';
1126+
$string['snippetsshowdetails'] = 'Show details';
11241127
$string['snippetssnippets'] = 'CSS snippets';
11251128
$string['snippetssource'] = 'Source';
11261129
$string['snippetssourcetheme_boost_union'] = 'Boost Union built-in';

lib.php

+13
Original file line numberDiff line numberDiff line change
@@ -667,3 +667,16 @@ function theme_boost_union_after_config() {
667667
theme_boost_union_manipulate_hooks();
668668
}
669669
}
670+
671+
/**
672+
* Get icon mapping for FontAwesome.
673+
* This function is only processed when the Moodle cache is cleared and not on every page load.
674+
*/
675+
function theme_boost_union_get_fontawesome_icon_map() {
676+
// Create the icon map with the icons.
677+
$iconmapping = [
678+
'theme_boost_union:info' => 'fa-info-circle',
679+
];
680+
681+
return $iconmapping;
682+
}
Loading
+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{{!
2+
This file is part of Moodle - http://moodle.org/
3+
Moodle is free software: you can redistribute it and/or modify
4+
it under the terms of the GNU General Public License as published by
5+
the Free Software Foundation, either version 3 of the License, or
6+
(at your option) any later version.
7+
Moodle is distributed in the hope that it will be useful,
8+
but WITHOUT ANY WARRANTY; without even the implied warranty of
9+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10+
GNU General Public License for more details.
11+
You should have received a copy of the GNU General Public License
12+
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
13+
}}
14+
{{!
15+
@template theme_boost_union/snippetsdetailsmodal
16+
17+
Boost Union CSS snippets details modal template.
18+
19+
Example context (json):
20+
{
21+
"description": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
22+
"goal": "Bugfix",
23+
"image": "https://raw.githubusercontent.com/moodle-an-hochschulen/moodle-theme_boost_union/main/pix/screenshot.png",
24+
"scope": "Global",
25+
"source": "Boost Union built-in"
26+
}
27+
}}
28+
<div>
29+
{{#description}}
30+
<div class="mb-4">
31+
<h6>{{#str}}snippetsdescription, theme_boost_union{{/str}}</h6>
32+
<p>{{{description}}}</p>
33+
</div>
34+
{{/description}}
35+
{{#image}}
36+
<div class="mb-4">
37+
<h6>{{#str}}snippetsdetailspreview, theme_boost_union{{/str}}</h6>
38+
<img src="{{image}}" alt="{{#str}}snippetsdetailspreview, theme_boost_union{{/str}}" class="w-100 p-2 border rounded">
39+
</div>
40+
{{/image}}
41+
<h6>{{#str}}snippetsdetails, theme_boost_union{{/str}}</h6>
42+
<table class="table table-striped">
43+
<tbody>
44+
{{#source}}
45+
<tr>
46+
<th scope="row">{{#str}}snippetssource, theme_boost_union{{/str}}</th>
47+
<td>{{{source}}}</td>
48+
</tr>
49+
{{/source}}
50+
{{#goal}}
51+
<tr>
52+
<th scope="row">{{#str}}snippetsgoal, theme_boost_union{{/str}}</th>
53+
<td>{{{goal}}}</td>
54+
</tr>
55+
{{/goal}}
56+
{{#scope}}
57+
<tr>
58+
<th scope="row">{{#str}}snippetsscope, theme_boost_union{{/str}}</th>
59+
<td>{{{scope}}}</td>
60+
</tr>
61+
{{/scope}}
62+
</tbody>
63+
</table>
64+
</div>

0 commit comments

Comments
 (0)