Skip to content
40 changes: 20 additions & 20 deletions dt-assets/build/components/index.es.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
import { E as s, C as e, w as D, B as o, D as i, a as l, b as n, d as r, e as c, f as u, u as p, A as C, g as M, x as T, h as m, i as x, j as S, y as g, k as B, t as d, r as h, l as v, m as A, n as L, o as b, p as f, z as y, q as F, c as j, v as k } from "./index-B5P35fmQ.js";
import { E as e, C as s, x as D, B as o, D as l, a as i, b as n, d as r, e as c, f as p, u, w as C, A as M, g as T, h as m, i as x, j as S, y as d, k as g, t as B, r as h, l as v, m as A, n as b, o as F, p as L, z as f, q as y, c as U, v as j } from "./index-DpLFOrwQ.js";
export {
s as ApiService,
e as ComponentService,
e as ApiService,
s as ComponentService,
D as DtAlert,
o as DtBase,
i as DtButton,
l as DtChurchHealthCircle,
l as DtButton,
i as DtChurchHealthCircle,
n as DtConnection,
r as DtCopyText,
c as DtDate,
u as DtDatetime,
p as DtFormBase,
C as DtIcon,
M as DtLabel,
T as DtList,
p as DtDatetime,
u as DtFileUpload,
C as DtFormBase,
M as DtIcon,
T as DtLabel,
m as DtLocation,
x as DtLocationMap,
S as DtMapModal,
g as DtModal,
B as DtMultiSelect,
d as DtMultiSelectButtonGroup,
d as DtModal,
g as DtMultiSelect,
B as DtMultiSelectButtonGroup,
h as DtMultiText,
v as DtNumberField,
A as DtSingleSelect,
L as DtTags,
b as DtText,
f as DtTextArea,
y as DtTile,
F as DtToggle,
j as DtUsersConnection,
k as version
b as DtTags,
F as DtText,
L as DtTextArea,
f as DtTile,
y as DtToggle,
U as DtUsersConnection,
j as version
};
2,158 changes: 1,184 additions & 974 deletions dt-assets/build/components/index.js

Large diffs are not rendered by default.

2,142 changes: 1,176 additions & 966 deletions dt-assets/build/components/index.umd.cjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dt-assets/build/css/light.min.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dt-assets/build/css/style.min.css

Large diffs are not rendered by default.

190 changes: 48 additions & 142 deletions dt-assets/js/modular-list-bulk.js
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,11 @@
// For boolean fields, include even if false (false is a valid value)
if (fieldType === 'boolean') {
updatePayload[fieldKey] = fieldValue === true;
} else if (fieldType === 'user_select') {
const normalizedUser = normalizeUserSelectValue(fieldValue);
if (normalizedUser !== null) {
updatePayload[fieldKey] = normalizedUser;
}
} else {
updatePayload[fieldKey] = fieldValue;
}
Expand Down Expand Up @@ -918,6 +923,18 @@
return Array.isArray(value) ? value : [];
}

function normalizeUserSelectValue(rawValue) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kodinkat this looks like a whole lot of code handling maybes.
Can we double check the actual values being passed arround?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kodinkat, my question still stands. Why handle every single possible value, instead of pulling from what the component actually returns?

if (!rawValue) return null;
if (typeof rawValue === 'number') {
return rawValue > 0 ? `user-${rawValue}` : null;
}
const str = String(rawValue).trim();
if (!str) return null;
if (str.startsWith('user-')) return str;
if (/^\d+$/.test(str)) return `user-${str}`;
return null;
}

/**
* Update bulkEditSelectedFields for the share field from dt-users-connection value.
* Called on initial value and on change; lives at module scope to avoid redefining per render.
Expand Down Expand Up @@ -1100,32 +1117,6 @@
return null;
}

// Special case: user_select (uses typeahead, not web component)
if (fieldType === 'user_select') {
const fieldId = `bulk_${fieldKey}`;
const userInput = fieldWrapper.find(`.js-typeahead-${fieldId}`);
if (userInput.length > 0) {
const selectedUserId = userInput.data('selected-user-id');
if (selectedUserId) {
return `user-${selectedUserId}`;
}
// Fallback: check typeahead instance
const typeaheadSelector = `.js-typeahead-${fieldId}`;
const typeaheadInstance = window.Typeahead?.[typeaheadSelector];
if (
typeaheadInstance &&
typeaheadInstance.items &&
typeaheadInstance.items.length > 0
) {
const selectedItem = typeaheadInstance.items[0];
if (selectedItem && selectedItem.ID) {
return `user-${selectedItem.ID}`;
}
}
}
return null;
}

// Special case: communication_channel (dt-multi-text needs special formatting)
if (fieldType === 'communication_channel') {
const multiTextComponent =
Expand Down Expand Up @@ -1532,7 +1523,8 @@
fieldType === 'connection' ||
fieldType === 'location' ||
fieldType === 'location_meta' ||
fieldType === 'tags'
fieldType === 'tags' ||
fieldType === 'user_select'
) {
return;
}
Expand Down Expand Up @@ -2121,107 +2113,9 @@
console.error('ComponentService initialization error:', e);
}
}

// Initialize field-specific handlers if needed
initializeBulkEditFieldHandlers(fieldKey, fieldType);
});
}

function initializeBulkEditFieldHandlers(fieldKey, fieldType) {
// Special case: user_select uses typeahead (not a web component)
if (fieldType === 'user_select') {
const fieldId = `bulk_${fieldKey}`;
const userInput = $(`.js-typeahead-${fieldId}`);

if (userInput.length) {
// Destroy existing typeahead instance if it exists (for restore scenarios)
const typeaheadSelector = `.js-typeahead-${fieldId}`;
if (window.Typeahead && window.Typeahead[typeaheadSelector]) {
try {
// Try to destroy the existing instance
if (window.Typeahead[typeaheadSelector].destroy) {
window.Typeahead[typeaheadSelector].destroy();
}
delete window.Typeahead[typeaheadSelector];
} catch (e) {
// If destroy fails, just delete the reference
delete window.Typeahead[typeaheadSelector];
}
}

// Initialize typeahead
$.typeahead({
input: `.js-typeahead-${fieldId}`,
minLength: 0,
maxItem: 0,
accent: true,
searchOnFocus: true,
source: window.TYPEAHEADS.typeaheadUserSource(),
templateValue: '{{name}}',
template: function (query, item) {
return `<div class="assigned-to-row" dir="auto">
<span>
<span class="avatar"><img style="vertical-align: text-bottom" src="{{avatar}}"/></span>
${window.SHAREDFUNCTIONS.escapeHTML(item.name)}
</span>
${item.status_color ? `<span class="status-square" style="background-color: ${window.SHAREDFUNCTIONS.escapeHTML(item.status_color)};">&nbsp;</span>` : ''}
${
item.update_needed && item.update_needed > 0
? `<span>
<img style="height: 12px;" src="${window.SHAREDFUNCTIONS.escapeHTML(window.wpApiShare.template_dir)}/dt-assets/images/broken.svg"/>
<span style="font-size: 14px">${window.SHAREDFUNCTIONS.escapeHTML(item.update_needed)}</span>
</span>`
: ''
}
</div>`;
},
dynamic: true,
hint: true,
emptyTemplate: window.SHAREDFUNCTIONS.escapeHTML(
window.wpApiShare.translations.no_records_found,
),
callback: {
onClick: function (node, a, item, event) {
event.preventDefault();
this.hideLayout();
this.resetInput();

// Set the selected user value
const resultContainer = $(`#${fieldId}-result-container`);
resultContainer.html(
`<span class="selected-result">${window.SHAREDFUNCTIONS.escapeHTML(item.name)}</span>`,
);

// Store the selected user ID in data attributes for later collection
userInput.data('selected-user-id', item.ID);
userInput.data('selected-user-name', item.name);
resultContainer.data('selected-user-id', item.ID);
resultContainer.data('selected-user-name', item.name);
},
onResult: function (node, query, result, resultCount) {
const resultContainer = $(`#${fieldId}-result-container`);
if (resultCount > 0) {
resultContainer.html(
`${resultCount} ${window.wpApiShare.translations.user_found || 'user(s) found'}`,
);
} else {
resultContainer.html('');
}
},
onHideLayout: function () {
$(`#${fieldId}-result-container`).html('');
},
},
});
}
return;
}

// For all web components: ComponentService.initialize() handles initialization
// The global dt:get-data listener handles data fetching
// No per-field-type initialization needed
}

/**
* Field Clear/Restore Handlers
*/
Expand Down Expand Up @@ -2361,19 +2255,16 @@
displayHtml += '<em>No option selected</em>';
}
} else if (fieldType === 'user_select') {
// user_select returns "user-{id}" format
if (valuesToRemove) {
const userId = valuesToRemove.replace('user-', '');
// Try to get user name from typeahead data or make a simple display
const fieldId = `bulk_${fieldKey}`;
const userInput = $(`.js-typeahead-${fieldId}`);
let userName = `User ${userId}`;
if (userInput.length > 0) {
const storedName = userInput.data('selected-user-name');
if (storedName) {
userName = storedName;
}
}
const item = Array.isArray(valuesToRemove)
? valuesToRemove[0]
: valuesToRemove;
const userId =
item?.id ||
item?.user_id ||
(typeof item === 'string' ? item.replace('user-', '') : null);
const userName =
item?.label || item?.name || (userId ? `User ${userId}` : null);
if (userName) {
displayHtml += `<span class="label" style="opacity: 0.6; margin-right: 5px; margin-bottom: 5px; display: inline-block;">${window.SHAREDFUNCTIONS.escapeHTML(userName)}</span>`;
} else {
displayHtml += '<em>No user selected</em>';
Expand Down Expand Up @@ -2420,9 +2311,18 @@
if (component && component.value) {
rawValueWithLabels = component.value;
}
} else if (fieldType === 'user_select') {
const usersComponent = fieldWrapper.find('dt-users-connection')[0];
if (usersComponent && usersComponent.value) {
const items = normalizeShareComponentItems(usersComponent.value);
if (items.length > 0) {
rawValueWithLabels = items;
}
}
}

let hasValues = false;
let normalizedUserValueToRemove = null;
if (
currentValue !== null &&
currentValue !== undefined &&
Expand All @@ -2435,18 +2335,25 @@
) {
const values = currentValue?.values || currentValue;
hasValues = Array.isArray(values) && values.length > 0;
} else if (fieldType === 'key_select' || fieldType === 'user_select') {
} else if (fieldType === 'key_select') {
hasValues = true;
} else if (fieldType === 'user_select') {
normalizedUserValueToRemove = normalizeUserSelectValue(currentValue);
hasValues = !!normalizedUserValueToRemove;
}
}

if (supportsSelectiveRemoval && hasValues) {
fieldData.operation = 'remove';
fieldData.valuesToRemove = currentValue;
fieldData.valuesToRemove =
fieldType === 'user_select'
? normalizedUserValueToRemove
: currentValue;
fieldData.rawValueWithLabels = rawValueWithLabels;

const displayValue =
fieldType === 'connection' && rawValueWithLabels
(fieldType === 'connection' || fieldType === 'user_select') &&
rawValueWithLabels
? rawValueWithLabels
: currentValue;
const displayHtml = renderValuesToRemoveDisplay(
Expand Down Expand Up @@ -2483,7 +2390,6 @@
console.error('ComponentService initialization error:', e);
}
}
initializeBulkEditFieldHandlers(fieldKey, fieldType);
});
});
}
Expand Down
24 changes: 1 addition & 23 deletions dt-assets/js/shared-functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -1040,29 +1040,7 @@ window.SHAREDFUNCTIONS = {
}

case 'user_select': {
// user_select uses legacy typeahead (not a web component)
const fieldId = id;
return `<div id="${fieldKey}" class="${fieldId} dt_user_select">
<var id="${fieldId}-result-container" class="result-container ${fieldId}-result-container"></var>
<div id="${fieldId}_t" name="form-${fieldId}" class="scrollable-typeahead">
<div class="typeahead__container" style="margin-bottom: 0">
<div class="typeahead__field">
<span class="typeahead__query">
<input class="js-typeahead-${fieldId} input-height" dir="auto"
name="${fieldId}[query]" placeholder="${window.SHAREDFUNCTIONS.escapeHTML(window.wpApiShare?.translations?.search_users || 'Search Users')}"
data-field_type="user_select"
data-field="${fieldKey}"
autocomplete="off">
</span>
<span class="typeahead__button">
<button type="button" class="search_${fieldKey} typeahead__image_button input-height" data-id="${fieldKey}">
<img src="${window.SHAREDFUNCTIONS.escapeHTML(window.wpApiShare.template_dir)}/dt-assets/images/chevron_down.svg"/>
</button>
</span>
</div>
</div>
</div>
</div>`;
return `<dt-users-connection ${baseAttrs} single></dt-users-connection>`;
}

case 'communication_channel':
Expand Down
1 change: 1 addition & 0 deletions dt-assets/scss/_list.scss
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,7 @@ table.js-list {
dt-datetime label,
dt-number label,
dt-tags label,
dt-users-connection label,
dt-user-select label,
dt-connection label,
dt-location label {
Expand Down
Loading