| @@ -1,6 +1,12 @@ | ||
| 1 | 1 | "use strict"; |
| 2 | 2 | |
| 3 | +function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } | |
| 4 | +function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } | |
| 5 | +function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } | |
| 6 | +function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } | |
| 7 | +function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } | |
| 8 | +function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } | |
| 3 | 9 | function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } |
| 4 | 10 | ; |
| 5 | 11 | (function ($, window, document, undefined) { |
| 6 | 12 | 'use strict'; |
| @@ -16,9 +22,18 @@ | ||
| 16 | 22 | $('.merchant-module-page-content').on('change keypress change.merchant', function (e) { |
| 17 | 23 | if ($(e.target).hasClass('merchant-backup-file') || $(e.target).hasClass('merchant-search-field')) { |
| 18 | 24 | return; |
| 19 | 25 | } |
| 20 | - if (!$(this).is('.merchant-module-question-answer-textarea, .merchant-license-code-input')) { | |
| 26 | + | |
| 27 | + // Nothing in the preview is a setting. Its controls are there to be played | |
| 28 | + // with, so a module whose mock-up has working fields cannot dirty the form. | |
| 29 | + if ($(e.target).closest('.merchant-module-page-preview').length) { | |
| 30 | + return; | |
| 31 | + } | |
| 32 | + | |
| 33 | + // The licence key and the module feedback textarea save through their | |
| 34 | + // own handlers, so editing them leaves the save bar alone. | |
| 35 | + if (!$(e.target).is('.merchant-module-question-answer-textarea, .merchant-license-code-input')) { | |
| 21 | 36 | if (!merchant.show_save) { |
| 22 | 37 | $ajaxHeader.addClass('merchant-show'); |
| 23 | 38 | $ajaxHeader.removeClass('merchant-saving'); |
| 24 | 39 | merchant.show_save = true; |
| @@ -483,9 +498,25 @@ | ||
| 483 | 498 | init: function init() { |
| 484 | 499 | this.initiate_datepicker(); |
| 485 | 500 | this.events(); |
| 486 | 501 | }, |
| 502 | + // Date() cannot parse the bare 'H:i' a time-only picker stores, so pin it to today. | |
| 503 | + parseInitialDate: function parseInitialDate(value, fieldOptions) { | |
| 504 | + if (!value) { | |
| 505 | + return []; | |
| 506 | + } | |
| 507 | + if (fieldOptions.onlyTimepicker && /^\d{1,2}:\d{2}$/.test(value)) { | |
| 508 | + var _value$split = value.split(':'), | |
| 509 | + _value$split2 = _slicedToArray(_value$split, 2), | |
| 510 | + hours = _value$split2[0], | |
| 511 | + minutes = _value$split2[1]; | |
| 512 | + return [new Date(new Date().setHours(Number(hours), Number(minutes), 0, 0))]; | |
| 513 | + } | |
| 514 | + var date = new Date(value); | |
| 515 | + return isNaN(date) ? [] : [date]; | |
| 516 | + }, | |
| 487 | 517 | initiate_datepicker: function initiate_datepicker() { |
| 518 | + var self = this; | |
| 488 | 519 | var elements = $('.merchant-module-page-setting-field .merchant-datetime-field'); |
| 489 | 520 | if (elements.length === 0) { |
| 490 | 521 | return; |
| 491 | 522 | } |
| @@ -490,11 +521,12 @@ | ||
| 490 | 521 | return; |
| 491 | 522 | } |
| 492 | 523 | elements.each(function (index) { |
| 493 | 524 | var input = $(this).find('input'), |
| 525 | + fieldOptions = $(this).data('options') || {}, | |
| 494 | 526 | options = { |
| 495 | 527 | locale: JSON.parse(merchant_datepicker_locale), |
| 496 | - selectedDates: input.val() ? [new Date(input.val())] : [], | |
| 528 | + selectedDates: self.parseInitialDate(input.val(), fieldOptions), | |
| 497 | 529 | onSelect: function onSelect(_ref) { |
| 498 | 530 | var date = _ref.date, |
| 499 | 531 | formattedDate = _ref.formattedDate, |
| 500 | 532 | datepicker = _ref.datepicker; |
| @@ -505,23 +537,20 @@ | ||
| 505 | 537 | } |
| 506 | 538 | input.trigger('change.merchant'); |
| 507 | 539 | input.trigger('change.merchant-datepicker', [formattedDate, input, options, index]); |
| 508 | 540 | } |
| 509 | - }, | |
| 510 | - fieldOptions = $(this).data('options'); | |
| 541 | + }; | |
| 511 | 542 | // add buttons to fieldOptions |
| 512 | 543 | fieldOptions.buttons = ['clear']; |
| 513 | - if (fieldOptions) { | |
| 514 | - if (fieldOptions.minDate !== undefined && fieldOptions.minDate === 'today') { | |
| 515 | - fieldOptions.minDate = new Date(); | |
| 516 | - if (fieldOptions.timeZone !== undefined && fieldOptions.timeZone !== '') { | |
| 517 | - fieldOptions.minDate = new Date(fieldOptions.minDate.toLocaleString('en-US', { | |
| 518 | - timeZone: fieldOptions.timeZone | |
| 519 | - })); | |
| 520 | - } | |
| 544 | + if (fieldOptions.minDate !== undefined && fieldOptions.minDate === 'today') { | |
| 545 | + fieldOptions.minDate = new Date(); | |
| 546 | + if (fieldOptions.timeZone !== undefined && fieldOptions.timeZone !== '') { | |
| 547 | + fieldOptions.minDate = new Date(fieldOptions.minDate.toLocaleString('en-US', { | |
| 548 | + timeZone: fieldOptions.timeZone | |
| 549 | + })); | |
| 521 | 550 | } |
| 522 | - options = Object.assign(options, fieldOptions); | |
| 523 | 551 | } |
| 552 | + options = Object.assign(options, fieldOptions); | |
| 524 | 553 | var datepickerObj = new AirDatepicker(input.getPath(), options); |
| 525 | 554 | input.attr('readonly', true); |
| 526 | 555 | $(document).trigger('initiated.merchant-datepicker', [datepickerObj, input, options, index]); |
| 527 | 556 | }); |
| @@ -2139,9 +2168,9 @@ | ||
| 2139 | 2168 | parent.find('.merchant-selected-products-preview ul').append($(this)); |
| 2140 | 2169 | parent.find('.merchant-selections-products-preview').html('').hide(); |
| 2141 | 2170 | parent.find('.merchant-search-field').val('').change(); |
| 2142 | 2171 | if (oldValue === '') { |
| 2143 | - valueField.val($(this).data('id')); | |
| 2172 | + valueField.val($(this).data('id')).change(); | |
| 2144 | 2173 | } else { |
| 2145 | 2174 | if (!multiple) { |
| 2146 | 2175 | valueField.val($(this).data('id')).change(); |
| 2147 | 2176 | } else { |
| @@ -2500,9 +2529,17 @@ | ||
| 2500 | 2529 | }); |
| 2501 | 2530 | $(document).on('dragenter', '.merchant-upload-button-drag-drop', function (e) { |
| 2502 | 2531 | $(this).closest('.merchant-module-page-setting-field-upload').find('.merchant-upload-button').click(); |
| 2503 | 2532 | }); |
| 2504 | - var initSelectAjax = function initSelectAjax($selectAjax) { | |
| 2533 | + | |
| 2534 | + // Callers pass a collection, and reading the source off a collection would give | |
| 2535 | + // every select the first field's source, so each field is set up on its own. | |
| 2536 | + var initSelectAjax = function initSelectAjax($selectAjaxFields) { | |
| 2537 | + $selectAjaxFields.each(function () { | |
| 2538 | + initSelectAjaxField($(this)); | |
| 2539 | + }); | |
| 2540 | + }; | |
| 2541 | + var initSelectAjaxField = function initSelectAjaxField($selectAjax) { | |
| 2505 | 2542 | var $select = $selectAjax.find('select'); |
| 2506 | 2543 | var $source = $select.data('source'); |
| 2507 | 2544 | var $config = window.merchant_admin_options; |
| 2508 | 2545 | var $object = { |
| @@ -2676,8 +2713,92 @@ | ||
| 2676 | 2713 | $moduleAlert.find('.merchant-module-alert-close').on('click', function (e) { |
| 2677 | 2714 | e.preventDefault(); |
| 2678 | 2715 | $moduleAlert.removeClass('merchant-show'); |
| 2679 | 2716 | $(document).off('click.merchant-alert-close'); |
| 2717 | + }); | |
| 2718 | + } | |
| 2719 | + | |
| 2720 | + // AI Prompt Examples Modal | |
| 2721 | + var $aiPromptsModal = $('#merchant-ai-prompts-modal'); | |
| 2722 | + if ($aiPromptsModal.length) { | |
| 2723 | + var $aiPromptsList = $aiPromptsModal.find('.merchant-ai-prompts-modal-list'); | |
| 2724 | + var copyHintText = window.merchant.ai_prompt_copy_hint || 'Click to copy'; | |
| 2725 | + var copiedLabelText = window.merchant.ai_prompt_copied_label || 'Copied!'; | |
| 2726 | + var copyIconSvg = '<svg width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="5" y="5" width="8" height="8" rx="1.5" stroke="currentColor" stroke-width="1.3"/><path d="M3 10V3.5C3 2.67157 3.67157 2 4.5 2H10.5" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>'; | |
| 2727 | + var checkIconSvg = '<svg width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13.5 4.5L6 12L2.5 8.5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg>'; | |
| 2728 | + var copyTextToClipboard = function copyTextToClipboard(text, onCopied) { | |
| 2729 | + if (navigator.clipboard && navigator.clipboard.writeText) { | |
| 2730 | + navigator.clipboard.writeText(text).then(onCopied); | |
| 2731 | + return; | |
| 2732 | + } | |
| 2733 | + var $temp = $('<textarea readonly></textarea>').val(text).css({ | |
| 2734 | + position: 'fixed', | |
| 2735 | + top: '-1000px' | |
| 2736 | + }); | |
| 2737 | + $('body').append($temp); | |
| 2738 | + $temp[0].select(); | |
| 2739 | + document.execCommand('copy'); | |
| 2740 | + $temp.remove(); | |
| 2741 | + onCopied(); | |
| 2742 | + }; | |
| 2743 | + $(document).on('click', '.merchant-ai-badge', function (e) { | |
| 2744 | + e.preventDefault(); | |
| 2745 | + e.stopPropagation(); | |
| 2746 | + var prompts = $(this).data('aiPrompts'); | |
| 2747 | + $aiPromptsModal.find('.merchant-ai-prompts-modal-title-text').text($(this).data('aiTitle') || ''); | |
| 2748 | + $aiPromptsModal.find('.merchant-ai-prompts-modal-blurb').text($(this).data('aiBlurb') || ''); | |
| 2749 | + $aiPromptsList.empty(); | |
| 2750 | + if (Array.isArray(prompts)) { | |
| 2751 | + prompts.forEach(function (prompt) { | |
| 2752 | + var $row = $('<button type="button" class="merchant-ai-prompt-row"></button>').attr('data-prompt', prompt); | |
| 2753 | + $row.append($('<span class="merchant-ai-prompt-text"></span>').text(prompt)); | |
| 2754 | + $row.append($('<span class="merchant-ai-prompt-icon"></span>').html(copyIconSvg)); | |
| 2755 | + $row.attr('aria-label', copyHintText); | |
| 2756 | + $aiPromptsList.append($row); | |
| 2757 | + }); | |
| 2758 | + } | |
| 2759 | + $aiPromptsModal.addClass('merchant-show'); | |
| 2760 | + var $badgeIcon = $aiPromptsModal.find('.merchant-ai-prompts-modal-badge svg'); | |
| 2761 | + $badgeIcon.removeClass('merchant-ai-badge-spin'); | |
| 2762 | + void $badgeIcon[0].offsetWidth; | |
| 2763 | + $badgeIcon.addClass('merchant-ai-badge-spin'); | |
| 2764 | + }); | |
| 2765 | + $(document).on('keydown', '.merchant-ai-badge', function (e) { | |
| 2766 | + if (e.key === 'Enter' || e.key === ' ') { | |
| 2767 | + e.preventDefault(); | |
| 2768 | + $(this).trigger('click'); | |
| 2769 | + } | |
| 2770 | + }); | |
| 2771 | + $aiPromptsList.on('click', '.merchant-ai-prompt-row', function () { | |
| 2772 | + var $row = $(this); | |
| 2773 | + if ($row.hasClass('is-copied')) { | |
| 2774 | + return; | |
| 2775 | + } | |
| 2776 | + copyTextToClipboard($row.attr('data-prompt'), function () { | |
| 2777 | + $row.addClass('is-copied').attr('aria-label', copiedLabelText); | |
| 2778 | + $row.find('.merchant-ai-prompt-icon').html(checkIconSvg); | |
| 2779 | + setTimeout(function () { | |
| 2780 | + $row.removeClass('is-copied').attr('aria-label', copyHintText); | |
| 2781 | + $row.find('.merchant-ai-prompt-icon').html(copyIconSvg); | |
| 2782 | + }, 1600); | |
| 2783 | + }); | |
| 2784 | + }); | |
| 2785 | + var closeAiPromptsModal = function closeAiPromptsModal() { | |
| 2786 | + $aiPromptsModal.removeClass('merchant-show'); | |
| 2787 | + $aiPromptsModal.find('.merchant-ai-prompts-modal-badge svg').removeClass('merchant-ai-badge-spin'); | |
| 2788 | + }; | |
| 2789 | + $(document).on('click', '.merchant-ai-prompts-modal-close', function () { | |
| 2790 | + closeAiPromptsModal(); | |
| 2791 | + }); | |
| 2792 | + $aiPromptsModal.on('click', function (e) { | |
| 2793 | + if ($(e.target).is($aiPromptsModal)) { | |
| 2794 | + closeAiPromptsModal(); | |
| 2795 | + } | |
| 2796 | + }); | |
| 2797 | + $(document).on('keydown', function (e) { | |
| 2798 | + if (e.key === 'Escape' && $aiPromptsModal.hasClass('merchant-show')) { | |
| 2799 | + closeAiPromptsModal(); | |
| 2800 | + } | |
| 2680 | 2801 | }); |
| 2681 | 2802 | } |
| 2682 | 2803 | }); |
| 2683 | 2804 | |