var IeBomTreeEditor = (function () { var $root, bomId, storeUrl, moveUrl, updateBase, deleteBase; var applyTemplateUrl, saveTemplateUrl, deleteTemplateUrl, duplicateUrl; var selectedParentId = null, selectedParentName = ''; var selectedLineId = null; var clipboardBranchId = null, clipboardBranchName = ''; var THEME_STORAGE_KEY = 'ie_bom_tree_theme'; var THEME_DEFAULT_KEY = 'ie_bom_tree_theme_default'; var COLLAPSE_STORAGE_KEY = 'ie_bom_tree_collapsed'; var CLIPBOARD_STORAGE_KEY = 'ie_bom_tree_clipboard'; var themeLabels = {}; var defaultThemeId = '18'; function init() { $root = $('#ie_structure_editor'); if (!$root.length) return; bomId = $root.data('bom-id'); storeUrl = $root.data('store-url'); moveUrl = $root.data('move-url'); updateBase = $root.data('update-url'); deleteBase = $root.data('delete-url'); applyTemplateUrl = $root.data('apply-template-url'); saveTemplateUrl = $root.data('save-template-url'); deleteTemplateUrl = $root.data('delete-template-url'); duplicateUrl = $root.data('duplicate-url'); $('#ie_bom_nestable').nestable({ maxDepth: 20, group: 1 }); // Prevent drag when clicking action buttons and toggles $root.on('mousedown click', '.ie-node-actions .btn, .ie-node-actions, .ie-btn-toggle-branch', function (e) { e.stopPropagation(); }); $('#ie_save_tree').on('click', saveTree); $('#ie_add_root_node').on('click', function () { resetForm(null); setTemplateParent(null, ''); }); $('#ie_node_form').on('submit', submitNode); $root.on('click', '.ie-btn-add-child', function () { var id = $(this).data('id'); var name = $(this).data('name') || ''; resetForm(id); setTemplateParent(id, name); }); $root.on('click', '.ie-btn-edit-node', function () { var id = $(this).data('id'); loadNodeForEdit(id); selectedLineId = id; }); $root.on('click', '.ie-btn-delete-node', function () { deleteNode($(this).data('id')); }); $root.on('click', '.ie-btn-select-parent', function () { setTemplateParent($(this).data('id'), $(this).data('name') || ''); selectedLineId = $(this).data('id'); toastr.info('والد الگو: ' + ($(this).data('name') || '')); }); $root.on('click', '.ie-btn-bulk-child', function () { var id = $(this).data('id'); var name = $(this).data('name') || ''; setTemplateParent(id, name); selectedLineId = id; $('#ie_builtin_template').val('air_section_children').trigger('change'); $('html, body').animate({ scrollTop: $('#ie_apply_builtin_template').offset().top - 80 }, 300); }); $('#ie_builtin_template').on('change', function () { var desc = $(this).find(':selected').data('desc') || ''; $('#ie_template_desc').text(desc); }); $('#ie_apply_builtin_template').on('click', function () { var key = $('#ie_builtin_template').val(); if (!key) { toastr.warning('یک الگوی آماده انتخاب کنید'); return; } applyTemplate(key); }); $('#ie_apply_saved_template').on('click', function () { var key = $('#ie_saved_template').val(); if (!key) { toastr.warning('الگوی ذخیره‌شده‌ای انتخاب نشده'); return; } applyTemplate(key); }); $('#ie_delete_saved_template').on('click', deleteSavedTemplate); $('#ie_save_template_btn').on('click', saveTemplate); $root.on('click', '.ie-btn-toggle-branch', function (e) { e.preventDefault(); e.stopPropagation(); toggleBranch($(this).closest('.dd-item'), true); }); $root.on('click', '.ie-btn-copy-branch', function (e) { e.stopPropagation(); copyBranch($(this).data('id'), $(this).data('name') || ''); }); $root.on('click', '.ie-btn-paste-branch', function (e) { e.stopPropagation(); pasteBranch($(this).data('id'), $(this).data('name') || ''); }); $('#ie_expand_all').on('click', function () { setAllBranches(true); }); $('#ie_collapse_all').on('click', function () { setAllBranches(false); }); $('#ie_paste_to_root').on('click', function () { pasteBranch(null, 'ریشه درخت'); }); $('#ie_clear_clipboard').on('click', clearClipboard); loadClipboard(); initBranchCollapse(); initThemePicker(); } function branchStorageKey() { return COLLAPSE_STORAGE_KEY + '_' + (bomId || '0'); } function getCollapsedIds() { try { return JSON.parse(localStorage.getItem(branchStorageKey()) || '[]'); } catch (e) { return []; } } function saveCollapsedIds(ids) { localStorage.setItem(branchStorageKey(), JSON.stringify(ids)); } function initBranchCollapse() { var collapsed = getCollapsedIds(); $('.dd-item[data-has-children="1"]').each(function () { var id = String($(this).data('id')); if (collapsed.indexOf(id) !== -1) { setBranchCollapsed($(this), true, false); } else { setBranchExpanded($(this), false); } }); } function toggleBranch($item, persist) { if ($item.hasClass('ie-branch-collapsed')) { setBranchExpanded($item, persist); } else { setBranchCollapsed($item, true, persist); } } function setBranchCollapsed($item, animate, persist) { var $children = $item.children('.ie-branch-children'); var $btn = $item.find('> .ie-dd-handle .ie-btn-toggle-branch i'); $item.addClass('ie-branch-collapsed'); $btn.removeClass('fa-minus').addClass('fa-plus'); if (animate) { $children.stop(true, true).slideUp(160); } else { $children.hide(); } if (persist) { var ids = getCollapsedIds(); var id = String($item.data('id')); if (ids.indexOf(id) === -1) ids.push(id); saveCollapsedIds(ids); } } function setBranchExpanded($item, persist) { var $children = $item.children('.ie-branch-children'); var $btn = $item.find('> .ie-dd-handle .ie-btn-toggle-branch i'); $item.removeClass('ie-branch-collapsed'); $btn.removeClass('fa-plus').addClass('fa-minus'); $children.stop(true, true).slideDown(160); if (persist) { var ids = getCollapsedIds().filter(function (id) { return id !== String($item.data('id')); }); saveCollapsedIds(ids); } } function setAllBranches(expand) { $('.dd-item[data-has-children="1"]').each(function () { if (expand) { setBranchExpanded($(this), false); } else { setBranchCollapsed($(this), true, false); } }); saveCollapsedIds(expand ? [] : $('.dd-item[data-has-children="1"]').map(function () { return String($(this).data('id')); }).get()); } function loadClipboard() { try { var raw = localStorage.getItem(CLIPBOARD_STORAGE_KEY); if (!raw) return; var data = JSON.parse(raw); if (data && data.bomId == bomId && data.lineId) { clipboardBranchId = data.lineId; clipboardBranchName = data.name || ''; updateClipboardBar(); } } catch (e) { /* ignore */ } } function saveClipboard() { if (!clipboardBranchId) { localStorage.removeItem(CLIPBOARD_STORAGE_KEY); return; } localStorage.setItem(CLIPBOARD_STORAGE_KEY, JSON.stringify({ bomId: bomId, lineId: clipboardBranchId, name: clipboardBranchName })); } function updateClipboardBar() { if (clipboardBranchId) { $('#ie_clipboard_bar').show(); $('#ie_clipboard_label').text(clipboardBranchName || ('#' + clipboardBranchId)); $('.ie-btn-paste-branch').prop('disabled', false); } else { $('#ie_clipboard_bar').hide(); $('.ie-btn-paste-branch').prop('disabled', true); } } function copyBranch(lineId, name) { clipboardBranchId = lineId; clipboardBranchName = name || ''; saveClipboard(); updateClipboardBar(); highlightNode(lineId); if (typeof toastr !== 'undefined') { toastr.info('شاخه کپی شد: ' + (name || lineId)); } } function clearClipboard() { clipboardBranchId = null; clipboardBranchName = ''; saveClipboard(); updateClipboardBar(); } function pasteBranch(targetParentId, targetName) { if (!clipboardBranchId) { toastr.warning('ابتدا یک شاخه را کپی کنید'); return; } if (String(clipboardBranchId) === String(targetParentId)) { toastr.warning('نمی‌توان شاخه را روی خودش پیست کرد'); return; } var msg = 'پیست شاخه «' + (clipboardBranchName || clipboardBranchId) + '» زیر «' + (targetName || 'ریشه درخت') + '»؟'; if (!confirm(msg)) return; $.ajax({ url: duplicateUrl, method: 'POST', data: { _token: $('meta[name="csrf-token"]').attr('content'), source_line_id: clipboardBranchId, target_parent_line_id: targetParentId || null }, success: function (res) { if (res.success) { toastr.success(res.msg); location.reload(); } }, error: function (xhr) { toastr.error(xhr.responseJSON?.msg || xhr.responseJSON?.message || 'خطا در پیست شاخه'); } }); } function initThemePicker() { var $wrapper = $('#ie_tree_wrapper'); var $select = $('#ie_tree_theme_select'); if (!$wrapper.length) return; $('#ie_tree_theme_select option').each(function () { themeLabels[$(this).val()] = $(this).text(); }); defaultThemeId = String(localStorage.getItem(THEME_DEFAULT_KEY) || '18'); var saved = localStorage.getItem(THEME_STORAGE_KEY) || defaultThemeId; applyTheme(saved, false); updateDefaultBadges(); $('.ie-theme-card').on('click', function (e) { if ($(e.target).closest('.ie-theme-pin').length) return; applyTheme($(this).data('theme'), true); $('#ie_tree_theme_picker').collapse('hide'); }); $('.ie-theme-pin').on('click', function (e) { e.preventDefault(); e.stopPropagation(); setDefaultTheme($(this).data('theme')); }); $('#ie_apply_default_theme').on('click', function () { applyTheme(defaultThemeId, true); }); $select.on('change', function () { applyTheme($(this).val(), true); }); } function setDefaultTheme(themeId) { themeId = String(themeId || '2'); defaultThemeId = themeId; localStorage.setItem(THEME_DEFAULT_KEY, themeId); updateDefaultBadges(); if (typeof toastr !== 'undefined') { toastr.success('پیش‌فرض: ' + (themeLabels[themeId] || themeId)); } } function updateDefaultBadges() { $('.ie-theme-card').removeClass('is-default'); $('.ie-theme-pin i').removeClass('fa-star').addClass('fa-star-o'); $('.ie-theme-card[data-theme="' + defaultThemeId + '"]').addClass('is-default'); $('.ie-theme-pin[data-theme="' + defaultThemeId + '"] i').removeClass('fa-star-o').addClass('fa-star'); $('#ie_default_theme_label').text(themeLabels[defaultThemeId] || defaultThemeId); } function applyTheme(themeId, persist) { themeId = String(themeId || defaultThemeId || '18'); var $wrapper = $('#ie_tree_wrapper'); var baseClass = 'ie-tree-indented'; $wrapper.attr('class', baseClass + ' ie-tree-theme-' + themeId); $('.ie-theme-card').removeClass('active'); $('.ie-theme-card[data-theme="' + themeId + '"]').addClass('active'); $('#ie_tree_theme_select').val(themeId); $('#ie_current_theme_label').text(themeLabels[themeId] || themeId); if (persist) { localStorage.setItem(THEME_STORAGE_KEY, themeId); if (typeof toastr !== 'undefined') { toastr.info('دیزاین درخت: ' + (themeLabels[themeId] || themeId)); } } } function setTemplateParent(id, name) { selectedParentId = id || null; selectedParentName = name || ''; $('#ie_template_parent_id').val(id || ''); $('#ie_template_parent_label').val(name || 'ریشه درخت (سطح خط تولید)'); highlightNode(id); } function highlightNode(lineId) { $('.ie-dd-handle').removeClass('ie-node-selected'); if (lineId) { $('.dd-item[data-id="' + lineId + '"] > .ie-dd-handle').addClass('ie-node-selected'); } } function applyTemplate(templateKey) { if (!confirm('اعمال الگو زیر «' + (selectedParentName || 'ریشه درخت') + '»؟')) return; $.ajax({ url: applyTemplateUrl, method: 'POST', data: { _token: $('meta[name="csrf-token"]').attr('content'), parent_line_id: selectedParentId, template_key: templateKey }, success: function (res) { if (res.success) { toastr.success(res.msg); location.reload(); } }, error: function (xhr) { toastr.error(xhr.responseJSON?.msg || xhr.responseJSON?.message || 'خطا در اعمال الگو'); } }); } function saveTemplate() { var lineId = selectedLineId || selectedParentId; var name = $('#ie_save_template_name').val(); if (!lineId) { toastr.warning('ابتدا یک شاخه را انتخاب کنید (دکمه هدف یا ویرایش)'); return; } if (!name) { toastr.warning('نام الگو را وارد کنید'); return; } $.ajax({ url: saveTemplateUrl, method: 'POST', data: { _token: $('meta[name="csrf-token"]').attr('content'), bom_line_id: lineId, name: name }, success: function (res) { if (res.success) { toastr.success(res.msg); location.reload(); } }, error: function (xhr) { toastr.error(xhr.responseJSON?.msg || xhr.responseJSON?.message || 'خطا در ذخیره الگو'); } }); } function deleteSavedTemplate() { var key = $('#ie_saved_template').val(); if (!key || key.indexOf('saved:') !== 0) return; var id = key.replace('saved:', ''); if (!confirm('حذف این الگوی ذخیره‌شده؟')) return; $.ajax({ url: deleteTemplateUrl + '/' + id, method: 'DELETE', data: { _token: $('meta[name="csrf-token"]').attr('content') }, success: function (res) { if (res.success) { toastr.success(res.msg); location.reload(); } }, error: function (xhr) { toastr.error(xhr.responseJSON?.msg || 'خطا در حذف'); } }); } function nestableData() { return $('#ie_bom_nestable').nestable('serialize'); } function saveTree() { $.ajax({ url: moveUrl, method: 'POST', data: { _token: $('meta[name="csrf-token"]').attr('content'), nestable: nestableData() }, success: function (res) { if (res.success) { toastr.success(res.msg); location.reload(); } }, error: function (xhr) { toastr.error(xhr.responseJSON?.msg || xhr.responseJSON?.message || 'خطا در ذخیره درخت'); } }); } function resetForm(parentId) { $('#ie_node_form')[0].reset(); $('#ie_parent_line_id').val(parentId || ''); $('#ie_bom_line_id').val(''); $('#ie_item_name').prop('disabled', false); $('#ie_item_master_id').val('').trigger('change'); $('#ie_panel_title').text(parentId ? 'افزودن زیرمجموعه' : 'افزودن ریشه درخت'); $('#ie_submit_node').html(' افزودن به درخت'); } function submitNode(e) { e.preventDefault(); var lineId = $('#ie_bom_line_id').val(); var data = $('#ie_node_form').serializeArray(); data.push({ name: '_token', value: $('meta[name="csrf-token"]').attr('content') }); var url = storeUrl; var method = 'POST'; if (lineId) { url = updateBase + '/' + lineId; method = 'PUT'; } $.ajax({ url: url, method: method, data: $.param(data), success: function (res) { if (res.success) { toastr.success(res.msg); if (res.integration_messages) { res.integration_messages.forEach(function (m) { if (m.type === 'warning' && typeof toastr.warning === 'function') { toastr.warning(m.text, '', { timeOut: 8000 }); } else if (m.type === 'success' && typeof toastr.info === 'function') { toastr.info(m.text); } }); } location.reload(); } }, error: function (xhr) { toastr.error(xhr.responseJSON?.msg || xhr.responseJSON?.message || 'خطا'); } }); } function loadNodeForEdit(lineId) { var $item = $('.dd-item[data-id="' + lineId + '"]'); if (!$item.length) return; $('#ie_bom_line_id').val(lineId); $('#ie_parent_line_id').val(''); $('#ie_panel_title').text('ویرایش گره'); $('#ie_submit_node').html(' ذخیره تغییرات'); $('#ie_item_name').prop('disabled', true); $('#ie_item_master_id').val($item.data('item-master-id') || '').trigger('change'); $('#ie_item_name').val($item.data('item-name') || ''); $('#ie_item_type').val($item.data('item-type') || 'part'); $('#ie_quantity').val($item.data('quantity') || 1); $('#ie_position_code').val($item.data('position-code') || ''); $('#ie_find_number').val($item.data('find-number') || ''); $('#ie_variation_id').val($item.data('variation-id') || ''); $('#ie_item_code').val(''); $('#ie_search_product').val(''); setTemplateParent(lineId, $item.data('item-name') || ''); } function deleteNode(lineId) { if (!confirm('حذف این گره و تمام زیرمجموعه‌هایش؟')) return; $.ajax({ url: deleteBase + '/' + lineId, method: 'DELETE', data: { _token: $('meta[name="csrf-token"]').attr('content') }, success: function (res) { if (res.success) { toastr.success(res.msg); $('.dd-item[data-id="' + lineId + '"]').remove(); } }, error: function (xhr) { toastr.error(xhr.responseJSON?.msg || xhr.responseJSON?.message || 'خطا در حذف'); } }); } return { init: init }; })();