3.4.2. Пользовательский компонент Выбор и создание записи реестра

Данный пользовательский компонент расширяет функциональность компонента выбор записи реестра, добавив к нему следующие возможности:

  • создание записи реестра;
  • просмотр файла по форме в диалоге;
  • удаление выбранного значения.

На форме компонент отображается следующим образом:

../../_images/form_registry1.png

Пользовательский компонент Выбор и создание записи реестра

Html код компонента содержит следующий код:

<style>
.edit {
    border: 1px solid black;
    float: right;
    background: url('light/images/buttons/dark.gray/edit.png') 50%;
    width: 30px;
    height: 22px;
    background-repeat: no-repeat;
    border-radius: 5px;
    border-color: gray;
}
.edited{
    background-color: #efefef;
}
</style>

//ссылка на документ реестра
<div style="text-decoration:underline; cursor:pointer;width:calc(100% ); color:#06f; margin-bottom:2px"
     innerId="textView" ></div>
//поле ввода для поиска записи реестра
<input type="text" class="asf-textBox" innerId="name" style="width:calc(100% )"/>
//надпись, по клику на которой откроется диалог с формой для заполнения
<div style="color:#606060; text-decoration:underline" class="asf-InlineBlock asf-cursorPointer"
     innerId="add">+Создать</div>
//надпись, по клику по которой открывается диалог выбора записи реестра
<div style="color:#606060; margin-left:10px; text-decoration:underline"
     class="asf-InlineBlock asf-cursorPointer"
     innerId="browse">Выбрать из реестра</div>
//надпись для удаления выбранного значения
<div style="color:#606060; margin-left:10px; text-decoration:underline"
     class="asf-InlineBlock asf-cursorPointer"
     innerId="delete">&#10005; Удалить</div>

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

Способ хранения выбранного значения, как и поведение всего компонента, описывается скриптом в блоке JAVASCRIPT код.

Данные компонента будут храниться в виде:

{
    "id":"custom-zthfcc",
    "type":"custom",
    "value":"Услуга3",
    "key":"c38e83a0-c065-4dec-a334-d32e63fcb0b4"
}

Здесь id - это идентификатор компонента, type - тип, value - значение, key - ключ компонента

За способ хранения данных компонента отвечает следующий кусок кода:

/**
 * метод реализовывает получение данных компонента для хранения
 * @param blockNumber
 * @returns {*}
 */
model.getAsfData = function (blockNumber) {
    return AS.FORMS.ASFDataUtils.getBaseAsfData(model.asfProperty, blockNumber, model.textValue, model.value);
};

Здесь в качестве value передаем параметр model.textValue, который обновляется каждый раз при изменении значения компонента:

/**
 * обновить текстовое представление записи реестра
 */
model.updateTextView = function () {
    if (!model.getValue()) {
        model.textValue = "";
        model.asfDataId = null;
        model.trigger(AS.FORMS.EVENT_TYPE.dataLoad, [model]);
        return;
    }
    AS.FORMS.ApiUtils.getAsfDataUUID(model.getValue(), function (newAsfDataId) {
        model.asfDataId = newAsfDataId;
        if(!registry) return;
        AS.FORMS.ApiUtils.getDocMeaningContent(registry.registryID, newAsfDataId, function (text) {
            if (text === null || text === '') {
                model.textValue = i18n.tr('Документ');
            } else {
                model.textValue = text;
            }
            model.trigger(AS.FORMS.EVENT_TYPE.dataLoad, [model]);
        });
    });
};

Переопределяем метод setAsfData модели, в данном случае в качестве значения выступает key (ид документа выбранной записи).

/**
 * метод реализовывает вставку asfData
 * @param asfData
 */
model.setAsfData = function (asfData) {
    model.setValue(asfData.key);
};

В скрипте компонента на форме необходимо прописать код реестра, записи которого будут выбраны либо созданы. Это указывается следующим образом:

../../_images/form_registry2.png

Скрипт компонента на форме

В результате получим следующий компонент:

../../_images/form_registry3.png

Полный javascript код компонента с комментариями:

/**
 * обновить текстовое представление записи реестра
 */
model.updateTextView = function () {
    if (!model.getValue()) {
        model.textValue = "";
        model.asfDataId = null;
        model.trigger(AS.FORMS.EVENT_TYPE.dataLoad, [model]);
        return;
    }
    AS.FORMS.ApiUtils.getAsfDataUUID(model.getValue(), function (newAsfDataId) {
        model.asfDataId = newAsfDataId;
        AS.FORMS.ApiUtils.getDocMeaningContent(registry.registryID, newAsfDataId, function (text) {
            if (text === null || text === '') {
                model.textValue = i18n.tr('Документ');
            } else {
                model.textValue = text;
            }
            model.trigger(AS.FORMS.EVENT_TYPE.dataLoad, [model]);
        });
    });
};

/**
 * получить тесктовое представление записи реестра
 * @returns {string|string|*}
 */
model.getTextValue = function () {
    return model.textValue;
};

// подписываемся на событие модели об изменении содержания, чтобы подгрузить дополнительные данные
model.on(AS.FORMS.EVENT_TYPE.valueChange, function () {
    model.updateTextView();
});

/**
 * метод реализовывает вставку asfData
 * @param asfData
 */
model.setAsfData = function (asfData) {
    model.setValue(asfData.key);
};

/**
 * метод реализовывает получение данных компонента для хранения
 * @param blockNumber
 * @returns {*}
 */
model.getAsfData = function (blockNumber) {
    return AS.FORMS.ASFDataUtils.getBaseAsfData(model.asfProperty, blockNumber, model.textValue, model.value);
};


/* инициализация отображения */


/**
 * реестр
 * @type {object}
 */
var registry = null;
/**
 * видимые колонки реестра
 * @type {Array}
 */
var registryColumns = [];


/**
 * поле ввода для поиска записей реестра
 * @type {XMLList|*}
 */
var input = jQuery(view.container).children("[innerId='name']");
/**
 * поле для отображения выбранной записи реестра
 * @type {XMLList|*}
 */
var textView = jQuery(view.container).children("[innerId='textView']");
/**
 * кнопка добавления записи
 * @type {XMLList|*}
 */
var addIcon = jQuery(view.container).children("[innerId='add']");
/**
 * кнопка выбора записи из реестра
 * @type {XMLList|*}
 */
var browseIcon = jQuery(view.container).children("[innerId='browse']");
/**
 * кнопка удаления текущей выбранной записи
 * @type {XMLList|*}
 */
var deleteIcon = jQuery(view.container).children("[innerId='delete']");

// кнопку удаления текущей выбраннйо записи скрываем
deleteIcon.hide();

// по нажатию на кнопку "выбрать из реестра" открываем стандартный диалог выбра записи реестра
browseIcon.click(function () {
    AS.SERVICES.showRegisterLinkDialog(registry, function (documentId) {
        model.setValue(documentId);
    });
});

// по нажатию на кнопку "создать" открываем форму создания записи реестра
addIcon.click(function () {
    if (!registry.rr_create) {
        alert("У вас нет прав на создание записей данного реестра");
        return;
    }

    var createPlayerDiv = jQuery("<div>");
    createPlayerDiv.css("width", "1000px");
    createPlayerDiv.css("height", "700px");

    createPlayerDiv.css("border", "1px solid #afafaf");

    var saveButton = jQuery("<button>", {class: "ns-approveButton ns-basicChooserApplyButton"});
    saveButton.button();
    saveButton.html(i18n.tr("Создать"));
    saveButton.css("margin", "auto");
    saveButton.css("display", "block");
    saveButton.css("margin-top", "10px");
    saveButton.css("margin-bottom", "10px");

    var player = AS.FORMS.createPlayer();

    player.view.setEditable(true);
    player.showFormData(registry.formId);
    player.view.appendTo(createPlayerDiv);

    player.model.on(AS.FORMS.EVENT_TYPE.dataLoad, function () {
        console.log(player.model);
        var registryModel = null;
        if (player.model.formCode === 'crm_form_contact') {
            registryModel = player.model.getModelWithId('crm_form_contact_lead_lead', 'crm_form_contact_lead');
        }
        if (player.model.formCode === 'crm_form_account') {
            registryModel = player.model.getModelWithId('crm_form_account_lead_lead', 'crm_form_account_lead');
        }
        if (player.model.formCode === 'crm_form_dealActivity') {
            registryModel = player.model.getModelWithId('crm_form_dealActivity_main_deal');
        }
        if (player.model.formCode === 'crm_form_leadActivity') {
            registryModel = player.model.getModelWithId('crm_form_leadActivity_main_lead');
        }
        if (registryModel != null) {
            registryModel.setValue(AS.SERVICES.getParameterByName("document_identifier", window.location.href));
        }
    });

    createPlayerDiv.append(saveButton);


    createPlayerDiv.dialog({
        width: 1000,
        height: 700,
        modal: true
    });


    saveButton.click(function () {
        var valid = player.model.isValid();
        if (!valid) {
            alert(i18n.tr("Введите все обязательные поля"));
            return;
        }

        AS.SERVICES.showWaitWindow();
        AS.FORMS.ApiUtils.simpleAsyncGet("rest/api/registry/create_doc?registryID=" + registry.registryID, function (result) {
            if (result.errorCode != 0) {
                AS.SERVICES.hideWaitWindow();
                alert(i18n.tr("Во время сохранения данных по форме произошли ошибки. Обратитесь к администратору"));
                return;
            }
            player.model.asfDataId = result.dataUUID;
            player.saveFormData(function (result) {
                AS.SERVICES.hideWaitWindow();
                if (_.isUndefined(result)) {
                    alert(i18n.tr("Во время сохранения данных по форме произошли ошибки. Обратитесь к администратору"));
                    return;
                };


                createPlayerDiv.dialog("destroy");

                AS.FORMS.ApiUtils.getDocumentIdentifier(result, function (documentID) {
                    /*в качестве значения компонента указываем ид созданного документа*/
                    model.setValue(documentID);
                });

            });
        });

    });


});


// по нажатию на кнопку удалить  - удаляем выбранное значение
deleteIcon.click(function(){
    model.setValue(null);
});


// по нажатию на текстовое отображение  - открываем запись реестра на просмотр
textView.click(function () {
    var createPlayerDiv = jQuery("<div>");
    createPlayerDiv.css("width", "1000px");
    createPlayerDiv.css("height", "700px");

    var editButton = jQuery('<div class="edit"></div>');

    var saveButton = jQuery("<button>", {class: "ns-approveButton ns-basicChooserApplyButton"});
    saveButton.button();
    saveButton.html(i18n.tr("Сохранить"));
    saveButton.css("margin", "auto");
    saveButton.css("display", "block");
    saveButton.css("margin-top", "10px");
    saveButton.css("margin-bottom", "10px");

    if (registry.code == 'crm_registry_leadActivities' || registry.code == 'crm_registry_dealActivities') {
        createPlayerDiv.append(editButton);

        editButton.click(function () {
            if (player.view.editable) {
                player.view.setEditable(false);
                editButton.removeClass('edited');
                saveButton.hide();
            } else {
                player.view.setEditable(true);
                editButton.addClass('edited');
                saveButton.show();
            }
        });
    }

    createPlayerDiv.css("border", "1px solid #afafaf");

    var player = AS.FORMS.createPlayer();

    player.view.setEditable(false);
    player.showFormData(null, null, model.asfDataId, 0);
    player.view.appendTo(createPlayerDiv);
    createPlayerDiv.append(saveButton);
    saveButton.hide();

    createPlayerDiv.dialog({
        width: 1000,
        height: 700,
        modal: true
    });

    saveButton.click(function () {
        var valid = player.model.isValid();
        if (!valid) {
            alert(i18n.tr("Введите все обязательные поля"));
            return;
        }


        AS.SERVICES.showWaitWindow();
        player.saveFormData(function (result) {
            AS.SERVICES.hideWaitWindow();
            if (_.isUndefined(result)) {
                alert(i18n.tr("Во время сохранения данных по форме произошли ошибки. Обратитесь к администратору"));
                return;
            }

            createPlayerDiv.dialog("destroy");

            AS.FORMS.ApiUtils.getDocumentIdentifier(result, function (documentID) {
                model.setValue(documentID);
            });
        });
    });
});

// скрываем или отображаем поля ввода в зависимости от того режим чтения это или редактирования
if (!editable) {
    input.hide();
    addIcon.hide();
    browseIcon.hide();
    deleteIcon.hide();
}
addIcon.text('+' + i18n.tr('Создать'));
browseIcon.text(i18n.tr('Выбрать из реестра'));
deleteIcon.html('<div style="color:#606060; margin-left:10px; text-decoration:underline" ' +
    'class="asf-InlineBlock asf-cursorPointer" innerId="delete">&#10005;' + i18n.tr('Удалить') + '</div>');

// реализовываем метод обновления отображения согласно изменившимся данным модели
view.updateValueFromModel = function () {
    input.val("");
    if (model.getValue()) {
        textView.css("display", "");
        input.hide();
        textView.html(model.getTextValue());
        input.hide();
        if (editable) {
            deleteIcon.css("display", "");
        } else {
            input.hide();
            addIcon.hide();
            browseIcon.hide();
            deleteIcon.hide();
        }
    } else {

        if (editable) {
            input.css("display", "");
        } else {
            input.hide();
            addIcon.hide();
            browseIcon.hide();
            deleteIcon.hide();
        }

        textView.html("");
        input.text("");
        deleteIcon.hide();
    }
};

// подписываем на событие подгрузки дополнительных данных значения
model.on(AS.FORMS.EVENT_TYPE.dataLoad, function () {
    view.updateValueFromModel();
});


/**
 * если нет прав создания записи реестра, то кнопки создать не должно быть видно
 */
function validateIconsState() {
    addIcon.hide();
    if (registry.rr_create && editable) {
        addIcon.css("display", "");
    }
}

/**
 * инициализируем компонент (получаем реестр, колонки)
 */
function initComponent() {
    AS.FORMS.ApiUtils.simpleAsyncGet('rest/api/registry/info?code=' + model.code, function (reg) {
        registry = reg;

        registry.registryID = reg.registryID;

        registryColumns = [];
        registry.columns.forEach(function (col) {
            if (col.visible != 1) {
                return;
            }
            registryColumns.push(col);
        });

        registryColumns = registryColumns.sort(function (item1, item2) {
            var number1 = item1.order;
            var number2 = item2.order;
            if (number1 === number2) {
                if (item1.name < item2.name) {
                    return -1;
                } else if (item1.name > item2.name) {
                    return 1;
                }
            } else {
                if (number1 === 0) {
                    return 1;
                } else if (number2 === 0) {
                    return -1;
                } else if (number1 < number2) {
                    return -1;
                } else {
                    return 1;
                }
            }
            return 0;
        });
        model.updateTextView();
        view.updateValueFromModel();
        validateIconsState();
    });

}

// при вводе пользователя отображаем первые 10 результатов поиска
input.on("input", function () {
    var search = input.val();
    if (search.length === 0 || !registry) {
        AS.SERVICES.showDropDown([]);
        return;
    }

    AS.FORMS.ApiUtils.getRegistryData(registry.registryID, 0, 10, search, null, null, function (foundData) {
        var values = [];
        foundData.result.forEach(function (record) {
            var value = {value: record.documentID};
            var label = "";

            registryColumns.forEach(function (column) {
                if (record.fieldValue[column.columnID] !== undefined) {
                    label += record.fieldValue[column.columnID] + " - ";
                }
            });

            value.title = label;
            values.push(value);
        });

        AS.SERVICES.showDropDown(values, input, null, function (selectedValue) {
            model.setValue(selectedValue);
            view.updateValueFromModel();
        });

    });

});

setTimeout(function () {
    initComponent();
}, 0);

AS.SERVICES.getParameterByName = function(name, url) {
    if (!url) {
        url = window.location.href;
    }
    name = name.replace(/[\[\]]/g, "\\$&");
    var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
        results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, " "));
};