Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions assets/js/src/components/admin/ShortcodesDocs.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,15 +229,15 @@ const ShortcodesDocs = () => {
</tr>
<tr>
<td>categories</td>
<td>Comma-separated list of category slugs that should be available in the form. Prefix a category with a minus sign (-) to exclude it.</td>
<td>Comma-separated list of category slugs that should be available in the form. Prefix a category with a minus sign (-) to exclude it. Use <code>none</code> to hide the Categories section entirely.</td>
<td>empty (all categories)</td>
<td>e.g., <pre>meetings,workshops</pre> to show only meetings and workshops, or <pre>-meetings,-workshops</pre> to show all categories except meetings and workshops</td>
<td>e.g., <pre>meetings,workshops</pre> to show only meetings and workshops, <pre>-meetings,-workshops</pre> to show all categories except meetings and workshops, or <pre>none</pre> to hide the section</td>
</tr>
<tr>
<td>tags</td>
<td>Comma-separated list of tag slugs that should be available in the form. Prefix a tag with a minus sign (-) to exclude it. Tag slugs are always compared in lowercase.</td>
<td>Comma-separated list of tag slugs that should be available in the form. Prefix a tag with a minus sign (-) to exclude it. Tag slugs are always compared in lowercase. Use <code>none</code> to hide the Tags section entirely.</td>
<td>empty (all tags)</td>
<td>e.g., <pre>featured,ticketed</pre> to show only featured and ticketed tags, or <pre>-featured,-ticketed</pre> to show all tags except featured and ticketed</td>
<td>e.g., <pre>featured,ticketed</pre> to show only featured and ticketed tags, <pre>-featured,-ticketed</pre> to show all tags except featured and ticketed, or <pre>none</pre> to hide the section</td>
</tr>
<tr>
<td>default_service_bodies</td>
Expand Down
178 changes: 103 additions & 75 deletions assets/js/src/components/public/EventForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ const EventForm = () => {
// Split tags into included and excluded
const includedTags = useMemo(() => tagsFilter.filter(slug => !slug.startsWith('-')), [tagsFilter]);
const excludedTags = useMemo(() => tagsFilter.filter(slug => slug.startsWith('-')).map(slug => slug.substring(1)), [tagsFilter]);

// "none" hides the entire taxonomy section (header and fields)
const showCategories = categoriesParam.trim().toLowerCase() !== 'none';
const showTags = tagsParam.trim().toLowerCase() !== 'none';

// Helper function to decode HTML entities
const decodeHtmlEntities = (text) => {
Expand Down Expand Up @@ -187,49 +191,69 @@ const EventForm = () => {

useEffect(() => {
const fetchTaxonomies = async () => {
if (!showCategories && !showTags) {
setCategories([]);
setTags([]);
return;
}

try {
const [categoriesRes, tagsRes] = await Promise.all([
fetch('/wp-json/wp/v2/categories?hide_empty=false&per_page=100'),
fetch('/wp-json/wp/v2/tags?hide_empty=false&per_page=100')
showCategories
? fetch('/wp-json/wp/v2/categories?hide_empty=false&per_page=100')
: Promise.resolve(null),
showTags
? fetch('/wp-json/wp/v2/tags?hide_empty=false&per_page=100')
: Promise.resolve(null)
]);

if (!categoriesRes.ok || !tagsRes.ok) {
if ((showCategories && !categoriesRes.ok) || (showTags && !tagsRes.ok)) {
throw new Error('Failed to fetch taxonomies');
}

const categoriesData = await categoriesRes.json();
const tagsData = await tagsRes.json();

// Filter categories based on included and excluded categories
const filteredCategories = categoriesData.filter(cat => {
const catSlug = (cat.slug || '').toLowerCase();
if (includedCategories.length > 0) {
// If there are included categories, only show those
return includedCategories.includes(catSlug);
} else if (excludedCategories.length > 0) {
// If there are excluded categories, show all except those
return !excludedCategories.includes(catSlug);
}
// If no restrictions, show all categories
return true;
});

// Filter tags based on included and excluded tags
const filteredTags = tagsData.filter(tag => {
const tagSlug = (tag.slug || '').toLowerCase();
if (includedTags.length > 0) {
// If there are included tags, only show those
return includedTags.includes(tagSlug);
} else if (excludedTags.length > 0) {
// If there are excluded tags, show all except those
return !excludedTags.includes(tagSlug);
}
// If no restrictions, show all tags
return true;
});

setCategories(Array.isArray(filteredCategories) ? filteredCategories : []);
setTags(Array.isArray(filteredTags) ? filteredTags : []);
if (showCategories) {
const categoriesData = await categoriesRes.json();

// Filter categories based on included and excluded categories
const filteredCategories = categoriesData.filter(cat => {
const catSlug = (cat.slug || '').toLowerCase();
if (includedCategories.length > 0) {
// If there are included categories, only show those
return includedCategories.includes(catSlug);
} else if (excludedCategories.length > 0) {
// If there are excluded categories, show all except those
return !excludedCategories.includes(catSlug);
}
// If no restrictions, show all categories
return true;
});

setCategories(Array.isArray(filteredCategories) ? filteredCategories : []);
} else {
setCategories([]);
}

if (showTags) {
const tagsData = await tagsRes.json();

// Filter tags based on included and excluded tags
const filteredTags = tagsData.filter(tag => {
const tagSlug = (tag.slug || '').toLowerCase();
if (includedTags.length > 0) {
// If there are included tags, only show those
return includedTags.includes(tagSlug);
} else if (excludedTags.length > 0) {
// If there are excluded tags, show all except those
return !excludedTags.includes(tagSlug);
}
// If no restrictions, show all tags
return true;
});

setTags(Array.isArray(filteredTags) ? filteredTags : []);
} else {
setTags([]);
}
} catch (error) {
console.error('Error fetching taxonomies:', error);
// Set empty arrays as fallback
Expand All @@ -239,7 +263,7 @@ const EventForm = () => {
};

fetchTaxonomies();
}, [includedCategories, excludedCategories, includedTags, excludedTags]);
}, [includedCategories, excludedCategories, includedTags, excludedTags, showCategories, showTags]);

const handleSubmit = async (e) => {
e.preventDefault();
Expand Down Expand Up @@ -958,47 +982,51 @@ const EventForm = () => {
/>
</div>

<div className="mayo-form-field">
<label>{__('Categories', 'mayo-events-manager')}</label>
<div className="mayo-taxonomy-list">
{Array.isArray(categories) && categories.map(category => (
<label key={category?.id} className="mayo-taxonomy-item">
<input
type="checkbox"
checked={formData.categories.includes(category?.id)}
onChange={(e) => {
const newCategories = e.target.checked
? [...formData.categories, category?.id]
: formData.categories.filter(id => id !== category?.id);
setFormData({...formData, categories: newCategories});
}}
/>
{category?.name ? decodeHtmlEntities(category.name) : __('Unnamed Category', 'mayo-events-manager')}
</label>
))}
{showCategories && categories.length > 0 && (
<div className="mayo-form-field">
<label>{__('Categories', 'mayo-events-manager')}</label>
<div className="mayo-taxonomy-list">
{categories.map(category => (
<label key={category?.id} className="mayo-taxonomy-item">
<input
type="checkbox"
checked={formData.categories.includes(category?.id)}
onChange={(e) => {
const newCategories = e.target.checked
? [...formData.categories, category?.id]
: formData.categories.filter(id => id !== category?.id);
setFormData({...formData, categories: newCategories});
}}
/>
{category?.name ? decodeHtmlEntities(category.name) : __('Unnamed Category', 'mayo-events-manager')}
</label>
))}
</div>
</div>
</div>
)}

<div className="mayo-form-field">
<label>{__('Tags', 'mayo-events-manager')}</label>
<div className="mayo-taxonomy-list">
{Array.isArray(tags) && tags.map(tag => (
<label key={tag?.id || 'default'} className="mayo-taxonomy-item">
<input
type="checkbox"
checked={formData.tags.includes(tag?.name)}
onChange={(e) => {
const newTags = e.target.checked
? [...formData.tags, tag?.name]
: formData.tags.filter(name => name !== tag?.name);
setFormData({...formData, tags: newTags});
}}
/>
{tag?.name ? decodeHtmlEntities(tag.name) : __('Unnamed Tag', 'mayo-events-manager')}
</label>
))}
{showTags && tags.length > 0 && (
<div className="mayo-form-field">
<label>{__('Tags', 'mayo-events-manager')}</label>
<div className="mayo-taxonomy-list">
{tags.map(tag => (
<label key={tag?.id || 'default'} className="mayo-taxonomy-item">
<input
type="checkbox"
checked={formData.tags.includes(tag?.name)}
onChange={(e) => {
const newTags = e.target.checked
? [...formData.tags, tag?.name]
: formData.tags.filter(name => name !== tag?.name);
setFormData({...formData, tags: newTags});
}}
/>
{tag?.name ? decodeHtmlEntities(tag.name) : __('Unnamed Tag', 'mayo-events-manager')}
</label>
))}
</div>
</div>
</div>
)}

<button
type="submit"
Expand Down
1 change: 1 addition & 0 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ This project is licensed under the GPL v2 or later.
== Changelog ==

= 1.9.4 =
* Fixed event submission form showing empty Categories or Tags section headers when `categories="none"` or `tags="none"` is used in `[mayo_event_form]`. [#325]
* Documented that category and tag names with spaces should use dashes in shortcode parameters (e.g., a category named "Cell Awareness" is specified as `cell-awareness` in `[mayo_announcement_form]`). [#321]
* Fixed required start/end date and time fields on the announcement submission form not showing an asterisk (*) on their labels when marked required via `additional_required_fields`. The optional "Leave empty to…" hints are now hidden when those fields are required. [#319]
* Fixed the event filters resetting the calendar back to the current month: selecting a Service Body, Category, Tag, or Event Type filter now keeps the month you had navigated to instead of jumping back to today. [#251]
Expand Down