This work was done with Claude. Added bundling of CSS & JS with WebPack. This also means minimization. --------- Co-authored-by: Martin Slachta <martin.slachta@outlook.com> Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
+3
-2
@@ -1,9 +1,10 @@
|
||||
node_modules
|
||||
build
|
||||
build/
|
||||
vendor/
|
||||
dist
|
||||
dist/
|
||||
|
||||
# Editors
|
||||
.claude/
|
||||
.idea/
|
||||
.zed/
|
||||
.pytest_cache/
|
||||
|
||||
+1
-1
@@ -2,6 +2,6 @@
|
||||
* Utilities for calling the API
|
||||
*/
|
||||
|
||||
function get_rest_url(resource) {
|
||||
export function get_rest_url(resource) {
|
||||
return ReservairServiceAPI.restUrl + '/' + resource;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const RsvDataSource = {
|
||||
export const RsvDataSource = {
|
||||
create_rsv_resource(base_url, { nonce } = {}) {
|
||||
function request(url, method, body) {
|
||||
const headers = { 'Content-Type': 'application/json' };
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
const RsvFormDefinitionResource = () =>
|
||||
import { RsvDataSource } from './RsvDataSource.js';
|
||||
|
||||
export const RsvFormDefinitionResource = () =>
|
||||
RsvDataSource.create_rsv_resource(ReservairServiceAPI.restUrl + '/form-definition');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const RsvReservationClient = {
|
||||
export const RsvReservationClient = {
|
||||
accept(reservation_id) {
|
||||
return this._post(reservation_id, 'accept');
|
||||
},
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
const RsvReservationResource = () =>
|
||||
import { RsvDataSource } from './RsvDataSource.js';
|
||||
|
||||
export const RsvReservationResource = () =>
|
||||
RsvDataSource.create_rsv_resource(ReservairServiceAPI.restUrl + '/reservation');
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
const RsvTimetableCapacityResource = (id) =>
|
||||
import { RsvDataSource } from './RsvDataSource.js';
|
||||
|
||||
export const RsvTimetableCapacityResource = (id) =>
|
||||
RsvDataSource.create_rsv_resource(ReservairServiceAPI.restUrl + `/timetable/${id}/capacity`);
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
const RsvTimetableReservationResource = (id) =>
|
||||
import { RsvDataSource } from './RsvDataSource.js';
|
||||
|
||||
export const RsvTimetableReservationResource = (id) =>
|
||||
RsvDataSource.create_rsv_resource(ReservairServiceAPI.restUrl + `/timetable/${id}/reservation`);
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
const RsvTimetableResource = () =>
|
||||
import { RsvDataSource } from './RsvDataSource.js';
|
||||
|
||||
export const RsvTimetableResource = () =>
|
||||
RsvDataSource.create_rsv_resource(ReservairServiceAPI.restUrl + '/timetable');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const RsvCalendarPicker = (() => {
|
||||
export const RsvCalendarPicker = (() => {
|
||||
|
||||
function get_first_day_of_month(date) {
|
||||
const day = new Date(date.getFullYear(), date.getMonth(), 1).getDay();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* RSV Dynamic datagrid
|
||||
* Allows fetching with JS instead of page reload.
|
||||
*/
|
||||
window.RsvDataGrid = window.RsvDataGrid || {
|
||||
const RsvDataGrid = {
|
||||
create_header(self, columns, has_actions) {
|
||||
let thead = document.createElement('thead');
|
||||
|
||||
@@ -419,4 +419,6 @@ window.RsvDataGrid = window.RsvDataGrid || {
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export { RsvDataGrid };
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { RsvCalendarPicker } from './RsvCalendar.js';
|
||||
|
||||
class RsvReservationSelector extends HTMLElement {
|
||||
static get observedAttributes() {
|
||||
return ['timetable-id', 'name', 'price-per-block'];
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { RsvTimetableService } from '../services/RsvTimetableService.js';
|
||||
|
||||
class RsvTimeline extends HTMLElement {
|
||||
static get observedAttributes() {
|
||||
return ['timetable-id', 'date'];
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import { RsvFormEncoder } from './RsvFormEncoder.js';
|
||||
import { show_notice } from '../../../src/components/admin.js';
|
||||
|
||||
/*
|
||||
* RsvAdminForm — shared submit handler for wp-admin forms.
|
||||
*
|
||||
@@ -13,7 +16,7 @@
|
||||
* refresh: () => my_datagrid.refresh(),
|
||||
* });
|
||||
*/
|
||||
const RsvAdminForm = {
|
||||
export const RsvAdminForm = {
|
||||
// Attach a submit listener that sends the form as JSON.
|
||||
bind(form, options = {}) {
|
||||
if (!form) return;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const RsvFormEncoder = {
|
||||
export const RsvFormEncoder = {
|
||||
// Serialize form element into a plain JS object supporting arrays.
|
||||
// - Nested keys supported with dot notation: 'meta.email'
|
||||
// - Array notation supported with trailing [] (e.g. 'times[]') or multiple inputs with same name
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const RsvFormSender = {
|
||||
export const RsvFormSender = {
|
||||
get_form_url(form_id) {
|
||||
return ReservairServiceAPI.restUrl + '/form/' + form_id;
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const RsvInlineFormBuilder = {
|
||||
export const RsvInlineFormBuilder = {
|
||||
match_p(name, value) {
|
||||
return (form) => String(form[name]) === String(value);
|
||||
},
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
const RsvTimetableService = {
|
||||
import { get_rest_url } from '../RsvApi.js';
|
||||
|
||||
export const RsvTimetableService = {
|
||||
get_all() {
|
||||
return fetch(get_rest_url('timetable'), { method: 'GET' })
|
||||
.then(r => {
|
||||
|
||||
@@ -5,44 +5,21 @@
|
||||
* admin and the default user.
|
||||
*/
|
||||
|
||||
function rsv_asset_url(string $relative): string {
|
||||
return plugin_dir_url(__FILE__) . '../assets/' . $relative;
|
||||
function rsv_build_url(string $file): string {
|
||||
return plugin_dir_url(__FILE__) . '../build/' . $file;
|
||||
}
|
||||
|
||||
function rsv_asset_file(string $relative): string {
|
||||
return plugin_dir_path(__FILE__) . '../assets/' . $relative;
|
||||
function rsv_build_file(string $file): string {
|
||||
return plugin_dir_path(__FILE__) . '../build/' . $file;
|
||||
}
|
||||
|
||||
function rsv_js(string $handle, string $relative, array $deps = []): void {
|
||||
wp_enqueue_script($handle, rsv_asset_url($relative), $deps, filemtime(rsv_asset_file($relative)));
|
||||
}
|
||||
|
||||
function rsv_css(string $handle, string $relative): void {
|
||||
wp_enqueue_style($handle, rsv_asset_url($relative), [], filemtime(rsv_asset_file($relative)));
|
||||
}
|
||||
|
||||
// --- Shared between frontend and admin ---
|
||||
|
||||
function rsv_enqueue_shared_assets(): void {
|
||||
rsv_js('rsv_calendar', 'js/elements/RsvCalendar.js');
|
||||
rsv_js('rsv_timeline', 'js/elements/RsvTimeline.js');
|
||||
rsv_js('rsv_api', 'js/RsvApi.js');
|
||||
rsv_js('reservation_selector', 'js/elements/RsvReservationSelector.js');
|
||||
rsv_js('rsv_reservation_summary', 'js/elements/RsvReservationSummary.js');
|
||||
rsv_js('rsv_data_source', 'js/datasource/RsvDataSource.js');
|
||||
rsv_js('rsv_reservation_resource', 'js/datasource/RsvReservationResource.js');
|
||||
rsv_js('rsv_form_definition_resource', 'js/datasource/RsvFormDefinitionResource.js');
|
||||
rsv_js('rsv_timetable_resource', 'js/datasource/RsvTimetableResource.js');
|
||||
rsv_js('rsv_timetable_capacity_resource', 'js/datasource/RsvTimetableCapacityResource.js');
|
||||
rsv_js('rsv_timetable_reservation_resource', 'js/datasource/RsvTimetableReservationResource.js');
|
||||
rsv_js('rsv_reservation_client', 'js/datasource/RsvReservationClient.js');
|
||||
|
||||
wp_localize_script('rsv_api', 'ReservairServiceAPI', [
|
||||
function rsv_localize_api(string $handle): void {
|
||||
wp_localize_script($handle, 'ReservairServiceAPI', [
|
||||
'restUrl' => rest_url('reservations/v1'),
|
||||
'nonce' => wp_create_nonce('wp_rest'),
|
||||
]);
|
||||
|
||||
wp_localize_script('rsv_api', 'ReservairStrings', [
|
||||
wp_localize_script($handle, 'ReservairStrings', [
|
||||
'timeline' => [
|
||||
'not_reservable' => 'Tento objekt nelze rezervovat.',
|
||||
'no_blocks' => 'Tento den není dostupný žádný blok. Vyberte jiné datum.',
|
||||
@@ -63,35 +40,20 @@ function rsv_enqueue_shared_assets(): void {
|
||||
'error_generic' => 'Něco se pokazilo. Zkuste to prosím znovu.',
|
||||
],
|
||||
]);
|
||||
|
||||
rsv_css('reservations-styles', 'css/RsvMainStyle.css');
|
||||
rsv_css('rsv-form-summary-styles', 'css/components/RsvFormSummaryStyles.css');
|
||||
rsv_css('rsv-calendar-styles', 'css/components/RsvCalendarStyles.css');
|
||||
rsv_css('rsv-form-styles', 'css/components/RsvFormStyles.css');
|
||||
rsv_css('rsv-time-slot-styles', 'css/components/RsvTimeSlotsStyles.css');
|
||||
}
|
||||
|
||||
// --- Public hooks ---
|
||||
|
||||
function rsv_enqueue_assets(): void {
|
||||
rsv_enqueue_shared_assets();
|
||||
wp_enqueue_script('rsv-client', rsv_build_url('client.js'), [], filemtime(rsv_build_file('client.js')));
|
||||
wp_enqueue_style('rsv-client', rsv_build_url('client.css'), [], filemtime(rsv_build_file('client.css')));
|
||||
|
||||
rsv_js('rsv_timetable_service', 'js/services/RsvTimetableService.js');
|
||||
rsv_js('rsv_form_sender', 'js/forms/RsvFormSender.js');
|
||||
rsv_js('rsv_form_encoder', 'js/forms/RsvFormEncoder.js');
|
||||
rsv_localize_api('rsv-client');
|
||||
}
|
||||
|
||||
function rsv_enqueue_admin_assets(): void {
|
||||
rsv_enqueue_shared_assets();
|
||||
wp_enqueue_script('rsv-admin', rsv_build_url('admin.js'), [], filemtime(rsv_build_file('admin.js')));
|
||||
wp_enqueue_style('rsv-admin', rsv_build_url('admin.css'), [], filemtime(rsv_build_file('admin.css')));
|
||||
|
||||
$admin_js = plugin_dir_path(__FILE__) . '../src/components/admin.js';
|
||||
wp_enqueue_script('admin', plugin_dir_url(__FILE__) . '../src/components/admin.js', [], filemtime($admin_js));
|
||||
|
||||
rsv_js('rsv_inline_form_builder', 'js/forms/RsvInlineFormBuilder.js');
|
||||
rsv_js('datagrid', 'js/elements/RsvDatagrid.js');
|
||||
rsv_js('rsv_form_encoder', 'js/forms/RsvFormEncoder.js');
|
||||
// RsvAdminForm needs the encoder, the localized nonce (rsv_api), and
|
||||
// show_notice() (admin) — declare them as deps so load order is correct.
|
||||
rsv_js('rsv_admin_form', 'js/forms/RsvAdminForm.js', ['rsv_form_encoder', 'rsv_api', 'admin']);
|
||||
rsv_css('rsv-admin-style', 'css/RsvAdminStyle.css');
|
||||
rsv_localize_api('rsv-admin');
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import './client.js';
|
||||
|
||||
import '../assets/css/RsvAdminStyle.css';
|
||||
|
||||
import { RsvDataGrid } from '../assets/js/elements/RsvDatagrid.js';
|
||||
import { RsvInlineFormBuilder } from '../assets/js/forms/RsvInlineFormBuilder.js';
|
||||
import './components/admin.js';
|
||||
import { RsvAdminForm } from '../assets/js/forms/RsvAdminForm.js';
|
||||
import { RsvReservationResource } from '../assets/js/datasource/RsvReservationResource.js';
|
||||
import { RsvTimetableResource } from '../assets/js/datasource/RsvTimetableResource.js';
|
||||
import { RsvTimetableCapacityResource } from '../assets/js/datasource/RsvTimetableCapacityResource.js';
|
||||
import { RsvTimetableReservationResource } from '../assets/js/datasource/RsvTimetableReservationResource.js';
|
||||
import { RsvReservationClient } from '../assets/js/datasource/RsvReservationClient.js';
|
||||
|
||||
window.RsvDataGrid = RsvDataGrid;
|
||||
window.RsvInlineFormBuilder = RsvInlineFormBuilder;
|
||||
window.RsvAdminForm = RsvAdminForm;
|
||||
window.RsvReservationResource = RsvReservationResource;
|
||||
window.RsvTimetableResource = RsvTimetableResource;
|
||||
window.RsvTimetableCapacityResource = RsvTimetableCapacityResource;
|
||||
window.RsvTimetableReservationResource = RsvTimetableReservationResource;
|
||||
window.RsvReservationClient = RsvReservationClient;
|
||||
@@ -0,0 +1,20 @@
|
||||
import '../assets/css/RsvMainStyle.css';
|
||||
import '../assets/css/components/RsvCalendarStyles.css';
|
||||
import '../assets/css/components/RsvFormStyles.css';
|
||||
import '../assets/css/components/RsvFormSummaryStyles.css';
|
||||
import '../assets/css/components/RsvTimeSlotsStyles.css';
|
||||
|
||||
import '../assets/js/elements/RsvTimeline.js';
|
||||
import '../assets/js/elements/RsvReservationSelector.js';
|
||||
import '../assets/js/elements/RsvReservationSummary.js';
|
||||
|
||||
import { RsvReservationResource } from '../assets/js/datasource/RsvReservationResource.js';
|
||||
import { RsvFormDefinitionResource } from '../assets/js/datasource/RsvFormDefinitionResource.js';
|
||||
import { RsvTimetableResource } from '../assets/js/datasource/RsvTimetableResource.js';
|
||||
import { RsvTimetableCapacityResource } from '../assets/js/datasource/RsvTimetableCapacityResource.js';
|
||||
import { RsvTimetableReservationResource } from '../assets/js/datasource/RsvTimetableReservationResource.js';
|
||||
import { RsvReservationClient } from '../assets/js/datasource/RsvReservationClient.js';
|
||||
import { RsvFormEncoder } from '../assets/js/forms/RsvFormEncoder.js';
|
||||
import { RsvFormSender } from '../assets/js/forms/RsvFormSender.js';
|
||||
|
||||
window.RsvFormSender = RsvFormSender;
|
||||
@@ -1,3 +1,5 @@
|
||||
import { get_rest_url } from '../../assets/js/RsvApi.js';
|
||||
|
||||
async function fetch_reservations_to_confirm(object_id) {
|
||||
const url = `/wordpress/wp-json/reservations/v1/object/${object_id}/timetable/reservation/unconfirmed`;
|
||||
return await fetch(url, {
|
||||
@@ -100,7 +102,7 @@ function create_notice(id, type, mesg) {
|
||||
return container;
|
||||
}
|
||||
|
||||
function show_notice(target, type, mesg) {
|
||||
export function show_notice(target, type, mesg) {
|
||||
target.querySelectorAll('.notice').forEach(x => x.remove());
|
||||
const notice = create_notice('test', type, mesg);
|
||||
target.prepend(notice);
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
const defaultConfig = require('@wordpress/scripts/config/webpack.config');
|
||||
|
||||
const defaultEntry = defaultConfig.entry;
|
||||
|
||||
module.exports = {
|
||||
...defaultConfig,
|
||||
entry: async () => {
|
||||
const entries = typeof defaultEntry === 'function'
|
||||
? await defaultEntry()
|
||||
: defaultEntry;
|
||||
return {
|
||||
...entries,
|
||||
client: './src/client.js',
|
||||
admin: './src/admin.js',
|
||||
};
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user