Массовое редактирование списков для Админа

Хочу представить вам несколько удобных кнопочек для манипулирования списком и поблагодарить @mr_sharikov за реализацию Silent Mass Update.
Установить сопку:
[SMPL] Mass Update_2023-10-06 14 24 01.sop (11,1 КБ)

Установив сопку у нас появляется в списках такие кнопки:

  1. Include Selected Rows
  2. Exclude Selected Rows
  3. Scripted Query by Field&Value
  4. Copy Value
  5. Silent Mass Update

Include Selected Rows и Exclude Selected Rows соответственно включают или исключают выбранные элементы из списка:

Scripted Query by Field&Value сгенерирует скрипт для этой выборки.
Причем, если до этого вы скопировали значение кнопкой Copy Value оно будет использовано в скрипте. а также подставится колонка, по который вы вызвали кнопку:

Я попытался накидать в скрипт, разных полезностей, которые часто использую в работе, большая часть закомментирована.

Copy Value кнопка копирует значение БД, это удобно для чойс-лайк типов полей, далее это значение используется в смежных кнопках.

и что же, самое вкусное на последок)))

Silent Mass Update - кнопка скрытого массового редактирования (очень спасла меня при миграции большого количества данных)

Долго сомневался, выкладывать ли такое в паблик ))) Ну мы же люди взрослые, админы, не будем портить свои данные,
тем более мы предусмотрели возможность логирования и отката произведенных массовых изменений:

Сохраняем информацию, где было изменение, на каком поле, кем. Сохранен Condition, который применялся для выборки и сами исходные данные.
Данные можно восстановить в исходное состояние кнопкой Restore.

Напомню, данный вид массового редактирования не оставляет следов в системе кроме этого лога, так что пользуйтесь аккуратно.

Всем спасибо!!! Давайте делать SimpleOne лучше!

8 лайков

Пронаблюдал опасный “дефект” что ли,
когда копию дампа забрали на другой инстанс,
масс-апдейт продолжал менять данные на проде, так как инстанс берет юрл из проперти simple.instance.uri
которую конечно никто не поменял.
Думаю можно сделать запрос сам на себя, что бы хотя бы определить на каком мы инстансе, надо бы подумать, как тут обезопаситься.

Добрый день, большое спасибо! Работает отлично!
Заметил багу - не показывает количество изменяемых записей, вместо этого только текст Total.

Немного поправил клиентский скрипт у виджета -
Вместо split(" "), используем split(":"), чтобы разделить текст на две части по двоеточию, и берем вторую часть split(":")[1].

Полный код клиентского скрипта в спойлере

Спойлер
window.s_widget_custom = window.s_widget_custom || {};

s_i18n.getMessage('Silent Mass Update', response => {
    s_modal.setTitle(`Скрытое массовое редактирование`);
});

s_i18n.getMessage('Run', response => {
    s_widget.setFieldValue('btnTitle', response);
});

const storageData = sessionStorage.getItem('virtualClipboard');

if (storageData) {
    document.querySelector(".widget-input-string").parentElement.parentElement.style.margin = "0px";
    s_widget.setFieldValue('inputValue', storageData);
    const message = document.querySelector('.field-msg');
    message.style.visibility = "visible";
    sessionStorage.removeItem('virtualClipboard');
}

const totalItemsElement = document.querySelector('[data-test="table-pagination-total-items"]');
if (totalItemsElement) {
    console.log("Total items text:", totalItemsElement.textContent);
    const totalItems = totalItemsElement.textContent.split(":")[1].trim();
    s_widget.setFieldValue('items', totalItems);
} else {
    console.error("Element not found: [data-test='table-pagination-total-items']");
    s_widget.setFieldValue('items', "0");
}

s_widget.setFieldValue('label', currentCell.value);

s_widget_custom.execute = async () => {
    const parameters = {
        tableName: s_list.getTablesName()[0],
        condition: new URL(window.location.href).searchParams.get("condition") || "()",
        attribute: currentCell.attribute,
        checkedRows: s_list.getCheckedRow(s_list.getTablesName()[0]) || [],
        value: s_widget.getFieldValue('inputValue') || null
    };

    s_widget.setFieldValue('parameters', parameters);
    await s_widget.serverUpdate();
    s_list.refresh(parameters.tableName);
    s_modal.setShow(false);
};

s_widget_custom.hideMessage = async () => {
    const message = document.querySelector('.field-msg');
    message.style.visibility = "hidden";
};