PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.15
Yatra – Travel Booking & Tour Operator Software v3.0.15
3.0.15 3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 2.0.1 2.0.10 All 83 releases
yatra / assets / dist / blocks / activity.js

activity.js in Yatra – Travel Booking & Tour Operator Software 3.0.15, at assets/dist/blocks/activity.js

432 lines 13.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function(element, blocks, blockEditor, components, i18n, ServerSideRender, apiFetch) {
2 "use strict";
3 const listWrapStyle = {
4 maxHeight: 220,
5 overflowY: "auto",
6 marginTop: 8,
7 padding: "4px 0",
8 border: "1px solid #94949451",
9 borderRadius: 2
10 };
11 function ClassificationMultiSelect({
12 taxonomy,
13 label,
14 help,
15 value,
16 onChange
17 }) {
18 const [items, setItems] = element.useState([]);
19 const [loading, setLoading] = element.useState(true);
20 const [loadError, setLoadError] = element.useState(false);
21 const [search, setSearch] = element.useState("");
22 const [scope, setScope] = element.useState(
23 () => value.length > 0 ? "narrow" : "all"
24 );
25 element.useEffect(() => {
26 if (value.length > 0) {
27 setScope("narrow");
28 }
29 }, [value.length]);
30 element.useEffect(() => {
31 let cancelled = false;
32 setLoading(true);
33 setLoadError(false);
34 apiFetch({
35 path: `/yatra/v1/block-editor/taxonomy-choices?taxonomy=${encodeURIComponent(
36 taxonomy
37 )}`
38 }).then((response) => {
39 if (!cancelled) {
40 setItems(response.items ?? []);
41 }
42 }).catch(() => {
43 if (!cancelled) {
44 setItems([]);
45 setLoadError(true);
46 }
47 }).finally(() => {
48 if (!cancelled) {
49 setLoading(false);
50 }
51 });
52 return () => {
53 cancelled = true;
54 };
55 }, [taxonomy]);
56 const filteredItems = element.useMemo(() => {
57 const q = search.trim().toLowerCase();
58 if (q === "") {
59 return items;
60 }
61 return items.filter((i) => i.name.toLowerCase().includes(q));
62 }, [items, search]);
63 const selectedSet = element.useMemo(() => new Set(value), [value]);
64 const toggleId = (id, checked) => {
65 const next = new Set(selectedSet);
66 if (checked) {
67 next.add(id);
68 } else {
69 next.delete(id);
70 }
71 onChange([...next].sort((a, b) => a - b));
72 };
73 const onScopeChange = (next) => {
74 if (next === "all") {
75 setScope("all");
76 onChange([]);
77 setSearch("");
78 } else {
79 setScope("narrow");
80 }
81 };
82 if (loading) {
83 return /* @__PURE__ */ element.createElement(
84 "fieldset",
85 {
86 className: "yatra-block-taxonomy-field",
87 style: { margin: "0 0 16px", border: "none", padding: 0 }
88 },
89 /* @__PURE__ */ element.createElement(
90 "legend",
91 {
92 className: "components-base-control__label",
93 style: { padding: 0 }
94 },
95 label
96 ),
97 /* @__PURE__ */ element.createElement(components.Spinner, null)
98 );
99 }
100 return /* @__PURE__ */ element.createElement(
101 "fieldset",
102 {
103 className: "yatra-block-taxonomy-field",
104 style: { margin: "0 0 16px", border: "none", padding: 0 }
105 },
106 /* @__PURE__ */ element.createElement("legend", { className: "components-base-control__label", style: { padding: 0 } }, label),
107 /* @__PURE__ */ element.createElement(
108 "p",
109 {
110 className: "components-base-control__help",
111 style: { marginTop: 4, marginBottom: 10 }
112 },
113 help
114 ),
115 loadError && /* @__PURE__ */ element.createElement("p", { style: { color: "#b32d2e", fontSize: 12, marginBottom: 8 } }, i18n.__(
116 "Could not load options. Confirm you can edit posts and Yatra REST is available.",
117 "yatra"
118 )),
119 /* @__PURE__ */ element.createElement(
120 components.RadioControl,
121 {
122 label: i18n.__("Listing scope", "yatra"),
123 selected: scope,
124 options: [
125 {
126 label: i18n.__("All published (no restriction)", "yatra"),
127 value: "all"
128 },
129 {
130 label: i18n.__("Only selected (search below)", "yatra"),
131 value: "narrow"
132 }
133 ],
134 onChange: onScopeChange
135 }
136 ),
137 scope === "all" && /* @__PURE__ */ element.createElement("p", { className: "components-base-control__help", style: { marginTop: 4 } }, i18n.__(
138 "The frontend will include every matching published item.",
139 "yatra"
140 )),
141 scope === "narrow" && /* @__PURE__ */ element.createElement(element.Fragment, null, /* @__PURE__ */ element.createElement(
142 components.SearchControl,
143 {
144 label: i18n.sprintf(
145 /* translators: %d = number of loaded taxonomy items */
146 i18n.__("Filter items (%d loaded)", "yatra"),
147 items.length
148 ),
149 hideLabelFromVision: true,
150 placeholder: i18n.__("Type to filter the list…", "yatra"),
151 value: search,
152 onChange: (s) => setSearch(s),
153 __nextHasNoMarginBottom: true
154 }
155 ), value.length > 0 && /* @__PURE__ */ element.createElement(
156 "p",
157 {
158 className: "components-base-control__help",
159 style: { marginTop: 4 }
160 },
161 i18n.sprintf(
162 /* translators: %d = number of selected taxonomy items */
163 i18n.__("%d selected", "yatra"),
164 value.length
165 )
166 ), items.length === 0 && !loadError ? /* @__PURE__ */ element.createElement("p", { className: "components-base-control__help" }, i18n.__("No published items of this type yet.", "yatra")) : /* @__PURE__ */ element.createElement("div", { role: "group", "aria-label": label, style: listWrapStyle }, filteredItems.length === 0 ? /* @__PURE__ */ element.createElement("p", { style: { padding: "8px 12px", margin: 0, fontSize: 12 } }, i18n.__("No matching items.", "yatra")) : filteredItems.map((item) => {
167 const cid = Number(item.id);
168 return /* @__PURE__ */ element.createElement("div", { key: cid, style: { padding: "2px 8px" } }, /* @__PURE__ */ element.createElement(
169 components.CheckboxControl,
170 {
171 label: `${item.name} (${cid})`,
172 checked: selectedSet.has(cid),
173 onChange: (checked) => toggleId(cid, checked === true),
174 __nextHasNoMarginBottom: true
175 }
176 ));
177 })), value.length > 0 && /* @__PURE__ */ element.createElement(
178 components.Button,
179 {
180 variant: "link",
181 style: { paddingLeft: 0, marginTop: 6 },
182 onClick: () => onChange([])
183 },
184 i18n.__("Clear selected", "yatra")
185 ), /* @__PURE__ */ element.createElement("p", { className: "components-base-control__help", style: { marginTop: 6 } }, i18n.__(
186 "If none are checked, the block behaves like “All” (no taxonomy filter).",
187 "yatra"
188 )))
189 );
190 }
191 function migrateNumericCsvPairToIds(legacyA, legacyB) {
192 const raw = [legacyA ?? "", legacyB ?? ""].find(
193 (s) => String(s).trim() !== ""
194 );
195 if (raw === void 0) {
196 return [];
197 }
198 const parts = String(raw).split(",").map((s) => s.trim()).filter(Boolean);
199 const ids = [];
200 for (const p of parts) {
201 if (!/^\d+$/.test(p)) {
202 return [];
203 }
204 const n = parseInt(p, 10);
205 if (n > 0) {
206 ids.push(n);
207 }
208 }
209 return [...new Set(ids)];
210 }
211 function normalizeIds(arr) {
212 return Array.isArray(arr) ? [...new Set(arr.map((n) => parseInt(String(n), 10)).filter((n) => n > 0))] : [];
213 }
214 function Edit({ attributes: attributes2, setAttributes }) {
215 const migratedOnce = element.useRef(false);
216 element.useEffect(() => {
217 if (migratedOnce.current) {
218 return;
219 }
220 migratedOnce.current = true;
221 let ids = normalizeIds(attributes2.activityIds);
222 if (ids.length === 0) {
223 ids = migrateNumericCsvPairToIds(
224 attributes2.activity_ids,
225 attributes2.activity
226 );
227 }
228 if (ids.length === 0) {
229 return;
230 }
231 setAttributes({
232 activityIds: ids,
233 activity: "",
234 activity_ids: ""
235 });
236 }, [setAttributes]);
237 const activityIds = normalizeIds(attributes2.activityIds);
238 return /* @__PURE__ */ element.createElement(element.Fragment, null, /* @__PURE__ */ element.createElement(blockEditor.InspectorControls, null, /* @__PURE__ */ element.createElement(components.PanelBody, { title: i18n.__("Activity Settings", "yatra"), initialOpen: true }, /* @__PURE__ */ element.createElement(
239 components.TextControl,
240 {
241 label: i18n.__("Title", "yatra"),
242 value: attributes2.title,
243 onChange: (value) => setAttributes({ title: value })
244 }
245 ), /* @__PURE__ */ element.createElement(
246 components.SelectControl,
247 {
248 label: i18n.__("Order", "yatra"),
249 value: attributes2.order,
250 options: [
251 { label: i18n.__("Ascending", "yatra"), value: "asc" },
252 { label: i18n.__("Descending", "yatra"), value: "desc" }
253 ],
254 onChange: (value) => setAttributes({ order: value })
255 }
256 ), /* @__PURE__ */ element.createElement(
257 components.RangeControl,
258 {
259 label: i18n.__("Number of Activities", "yatra"),
260 value: attributes2.per_page,
261 onChange: (value) => setAttributes({
262 per_page: value !== void 0 && value !== null ? value : 10
263 }),
264 min: 1,
265 max: 50
266 }
267 ), /* @__PURE__ */ element.createElement(
268 components.RangeControl,
269 {
270 label: i18n.__("Columns", "yatra"),
271 value: attributes2.columns,
272 onChange: (value) => setAttributes({
273 columns: value !== void 0 && value !== null ? value : 3
274 }),
275 min: 1,
276 max: 6
277 }
278 ), /* @__PURE__ */ element.createElement(
279 components.ToggleControl,
280 {
281 label: i18n.__("Show pagination", "yatra"),
282 checked: attributes2.show_pagination,
283 onChange: (value) => setAttributes({ show_pagination: value })
284 }
285 ), /* @__PURE__ */ element.createElement(
286 ClassificationMultiSelect,
287 {
288 taxonomy: "activity",
289 label: i18n.__("Activities to show", "yatra"),
290 help: i18n.__(
291 'Use "All published" or narrow with search and checkboxes.',
292 "yatra"
293 ),
294 value: activityIds,
295 onChange: (ids) => setAttributes({ activityIds: ids })
296 }
297 )), /* @__PURE__ */ element.createElement(components.PanelBody, { title: i18n.__("Display options", "yatra"), initialOpen: false }, /* @__PURE__ */ element.createElement(
298 components.ToggleControl,
299 {
300 label: i18n.__("Show trip count", "yatra"),
301 checked: attributes2.show_trip_count,
302 onChange: (value) => setAttributes({ show_trip_count: value })
303 }
304 ), /* @__PURE__ */ element.createElement(
305 components.ToggleControl,
306 {
307 label: i18n.__("Show description", "yatra"),
308 checked: attributes2.show_description,
309 onChange: (value) => setAttributes({ show_description: value })
310 }
311 ), /* @__PURE__ */ element.createElement(
312 components.ToggleControl,
313 {
314 label: i18n.__("Show image", "yatra"),
315 checked: attributes2.show_image,
316 onChange: (value) => setAttributes({ show_image: value })
317 }
318 ), /* @__PURE__ */ element.createElement(
319 components.ToggleControl,
320 {
321 label: i18n.__("Hide empty activities", "yatra"),
322 help: i18n.__(
323 "Skip activities that have no published trips assigned. Off by default — turn on for a tighter live catalog, leave off for editorial / onboarding views.",
324 "yatra"
325 ),
326 checked: attributes2.hide_empty,
327 onChange: (value) => setAttributes({ hide_empty: value })
328 }
329 ))), /* @__PURE__ */ element.createElement("div", { className: "yatra-block-editor-preview" }, /* @__PURE__ */ element.createElement(
330 ServerSideRender,
331 {
332 block: "yatra/activity",
333 attributes: attributes2,
334 key: JSON.stringify(attributes2)
335 }
336 )));
337 }
338 const $schema = "https://schemas.wp.org/trunk/block.json";
339 const apiVersion = 3;
340 const name = "yatra/activity";
341 const title = "Activity";
342 const category = "yatra";
343 const icon = "universal-access";
344 const description = "Display activity listings with customizable options";
345 const keywords = [
346 "activity",
347 "adventure",
348 "yatra"
349 ];
350 const textdomain = "yatra";
351 const attributes = {
352 order: {
353 type: "string",
354 "default": "asc"
355 },
356 columns: {
357 type: "number",
358 "default": 3
359 },
360 per_page: {
361 type: "number",
362 "default": 10
363 },
364 title: {
365 type: "string",
366 "default": "Activity Listings"
367 },
368 show_pagination: {
369 type: "boolean",
370 "default": true
371 },
372 activityIds: {
373 type: "array",
374 "default": []
375 },
376 hide_empty: {
377 type: "boolean",
378 "default": false,
379 description: "When on, activities with zero published trips are skipped. Off by default to preserve the historical 'show everything' behavior."
380 },
381 show_trip_count: {
382 type: "boolean",
383 "default": true
384 },
385 show_description: {
386 type: "boolean",
387 "default": true
388 },
389 show_image: {
390 type: "boolean",
391 "default": true
392 }
393 };
394 const supports = {
395 html: false,
396 inserter: true,
397 align: [
398 "wide",
399 "full"
400 ]
401 };
402 const editorScript = "yatra-activity-block-editor";
403 const blockMetadata = {
404 $schema,
405 apiVersion,
406 name,
407 title,
408 category,
409 icon,
410 description,
411 keywords,
412 textdomain,
413 attributes,
414 supports,
415 editorScript
416 };
417 const {
418 $schema: _$schema,
419 editorScript: _$editorScript,
420 ...metadata
421 } = blockMetadata;
422 if (blocks.getBlockType(metadata.name)) {
423 blocks.unregisterBlockType(metadata.name);
424 }
425 blocks.registerBlockType(metadata.name, {
426 ...metadata,
427 edit: Edit,
428 save: () => null
429 });
430 })(wp.element, wp.blocks, wp.blockEditor, wp.components, wp.i18n, wp.serverSideRender, wp.apiFetch);
431 //# sourceMappingURL=activity.js.map
432