', { class: 'copy-commentary-actions' });
$actionsWrapper.append($submitButton, $tagScriptWrapper);
$addCommentaryDialog.append($copyCommentaryDetails);
$copyCommentaryDetails.append($('
', { text: 'Copy Commentary' }));
$copyCommentaryDetails.append(
$queryWrapper,
$resultsTable,
$actionsWrapper,
);
const fetchPosts = async () => {
try {
$resultsTbody.empty();
updateSelectAllState();
const tags = $queryInput.val()?.trim();
if (!tags) {
return;
}
$fetchButton.prop('disabled', true);
const posts = await $.getJSON('/posts.json', {
tags,
only: 'id',
limit: 200,
});
fillTable(posts.map(post => post.id));
}
finally {
$fetchButton.prop('disabled', false);
updateSelectAllState();
}
};
const fillTable = (post_ids) => {
for (const post_id of post_ids) {
const $checkbox = $('', {
'type': 'checkbox',
'data-post-id': post_id,
'checked': true,
});
$checkbox.on('change', updateSelectAllState);
const $row = $('');
const $statusCell = $('| ', { class: 'copy-commentary-cell-status' });
const $tagScriptStatusCell = $(' | ', { class: 'copy-commentary-cell-tag-script-status' });
setStatus($statusCell, 'pending');
setStatus($tagScriptStatusCell, 'pending');
$row.append(
$(' | ', { class: 'copy-commentary-cell-select' }).append($checkbox),
$(' | ', { class: 'copy-commentary-cell-id' }).append(
$('', {
href: `/posts/${post_id}`,
text: `post #${post_id}`,
class: 'dtext-link dtext-id-link dtext-post-id-link',
}),
),
$statusCell,
$tagScriptStatusCell,
);
$resultsTbody.append($row);
}
};
const submitCommentary = async () => {
$submitButton.prop('disabled', true);
const $checkedRows = $resultsTbody.find('input[type="checkbox"]:checked');
const $form = $('#edit-commentary');
const formData = new FormData($form.get(0));
const payload = Object.fromEntries(formData.entries());
for (const checkbox of $checkedRows) {
const $checkbox = $(checkbox);
const $row = $checkbox.closest('tr');
const postId = $checkbox.data('post-id');
const $statusCell = $row.find('.copy-commentary-cell-status');
setStatus($statusCell, 'processing');
try {
await $.post(`/posts/${postId}/artist_commentary/create_or_update.json`, payload);
setStatus($statusCell, 'success');
uncheckRow($row, $checkbox);
}
catch (error) {
console.error('Failed to submit commentary', postId, error);
setStatus($statusCell, 'error');
}
}
updateSelectAllState();
$submitButton.prop('disabled', false);
};
const submitTagScript = async () => {
const tagString = $tagScriptInput.val()?.trim();
if (!tagString) {
return;
}
$tagScriptSubmitButton.prop('disabled', true);
const $checkedRows = $resultsTbody.find('input[type="checkbox"]:checked');
try {
for (const checkbox of $checkedRows) {
const $checkbox = $(checkbox);
const $row = $checkbox.closest('tr');
const postId = $checkbox.data('post-id');
const $statusCell = $row.find('.copy-commentary-cell-tag-script-status');
setStatus($statusCell, 'processing');
try {
await $.ajax({
type: 'PUT',
url: `/posts/${postId}.json`,
data: {
post: {
old_tag_string: '',
tag_string: tagString,
},
},
});
setStatus($statusCell, 'success');
uncheckRow($row, $checkbox);
}
catch (error) {
console.error('Failed to submit tag script', postId, error);
setStatus($statusCell, 'error');
}
}
}
finally {
updateSelectAllState();
$tagScriptSubmitButton.prop('disabled', false);
}
};
const updateSelectAllState = () => {
const $checkboxes = $resultsTbody.find('input[type="checkbox"]');
const total = $checkboxes.length;
const checked = $checkboxes.filter(':checked').length;
if (total === 0) {
$selectAllCheckbox.prop('checked', false).prop('indeterminate', false);
}
else if (checked === total) {
$selectAllCheckbox.prop('checked', true).prop('indeterminate', false);
}
else if (checked === 0) {
$selectAllCheckbox.prop('checked', false).prop('indeterminate', false);
}
else {
$selectAllCheckbox.prop('checked', false).prop('indeterminate', true);
}
};
const setStatus = ($cell, status) => {
$cell
.removeClass(
(_, className) => className
.split(' ')
.filter(cls => cls.startsWith('copy-commentary-status-'))
.join(' '),
)
.addClass(`copy-commentary-status-${status}`)
.text(status);
};
const uncheckRow = ($row, $checkbox) => {
const commentaryStatus = $row.find('.copy-commentary-cell-status').text().trim().toLowerCase();
const tagScriptStatus = $row.find('.copy-commentary-cell-tag-script-status').text().trim().toLowerCase();
if (commentaryStatus === 'success' && tagScriptStatus === 'success') {
$checkbox.prop('checked', false).trigger('change');
}
};
const onClickShortcut = (ev, tag) => {
ev.preventDefault();
$queryInput.val(tag);
fetchPosts();
};
const onClickTagScriptShortcut = (ev, tag) => {
ev.preventDefault();
const tokens = $tagScriptInput.val().match(/\S+/g) || [];
const hasTag = tokens.some(token => token.toLowerCase() === tag.toLowerCase());
if (hasTag) {
$tagScriptInput.val($tagScriptInput.val().replace(new RegExp(`(?<=^|\\s)${RegExp.escape(tag)}(?=$|\\s)`, 'gi'), ''));
}
else {
$tagScriptInput.val(`${$tagScriptInput.val().trim()} ${tag}`.trim());
}
};
}, 0);
|