(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@beanbag/spina'), require('@beanbag/ink'), require('babel-plugin-dedent')) :
    typeof define === 'function' && define.amd ? define(['exports', '@beanbag/spina', '@beanbag/ink', 'babel-plugin-dedent'], factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.RB = global.RB || {}, global.Spina, global.Ink));
})(this, (function (exports, spina, ink) { 'use strict';

    /**
     * Error for license action calls.
     *
     * Version Added:
     *     8.0
     */

    /**
     * Options for CallLicenseActionError.
     *
     * Version Added:
     *     8.0
     */

    /**
     * Error for license action calls.
     *
     * This can be thrown whenever a license action call fails, allowing the
     * handler to convey the error from the client or server and introspect any
     * API results.
     *
     * Version Added:
     *     8.0
     */
    class CallLicenseActionError extends Error {
      /**********************
       * Instance variables *
       **********************/

      /** The action that was called. */

      /** The target for the action. */

      /** The HTTP response from the request, if any. */

      /**
       * Construct a new instance.
       *
       * This will store the information from the options and set either the
       * provided or a default error message.
       *
       * Args:
       *     options (CallLicenseActionErrorOptions):
       *         Options for the error.
       */
      constructor(options) {
        const action = options.action;
        super(options.message || `Error performing license action "${action}"`);
        this.action = action;
        this.actionTarget = options.actionTarget;
        this.response = options.response || null;
      }
    }

    var _dec$1, _class$3;
    /**
     * The current status of a license.
     *
     * Version Added:
     *     8.0
     */
    let LicenseStatus = /*#__PURE__*/function (LicenseStatus) {
      /** No license is currently active. */
      LicenseStatus["UNLICENSED"] = "unlicensed";
      /** A valid license is active. */
      LicenseStatus["LICENSED"] = "licensed";
      /** The license has expired but is in a grace period. */
      LicenseStatus["EXPIRED_GRACE_PERIOD"] = "expired-grace-period";
      /** The license has expired with no grace period remaining. */
      LicenseStatus["HARD_EXPIRED"] = "hard-expired";
      return LicenseStatus;
    }({});

    /**
     * The status of a license check operation.
     *
     * Version Added:
     *     8.0
     */
    let LicenseCheckStatus = /*#__PURE__*/function (LicenseCheckStatus) {
      /** Checking for an updated license. */
      LicenseCheckStatus["CHECKING"] = "checking";
      /** The latest license has already been applied. */
      LicenseCheckStatus["HAS_LATEST"] = "has-latest";
      /** Applying a new license. */
      LicenseCheckStatus["APPLYING"] = "applying";
      /** A new license has been applied. */
      LicenseCheckStatus["APPLIED"] = "applied";
      /** There is no accessible license. */
      LicenseCheckStatus["NO_LICENSE"] = "no-license";
      /** There was an error checking for a new license. */
      LicenseCheckStatus["ERROR_CHECKING"] = "error-checking";
      /** There was an error applying a new license. */
      LicenseCheckStatus["ERROR_APPLYING"] = "error-applying";
      return LicenseCheckStatus;
    }({});

    /**
     * Response payload from checking for license updates.
     *
     * This is returned by Review Board.
     *
     * Version Added:
     *     8.0
     */

    /**
     * Options for calling an action on the license provider.
     *
     * Version Added:
     *     8.0
     */

    /**
     * A displayed action that can be taken on a license.
     *
     * Version Added:
     *     8.0
     */

    /**
     * A displayed line item for the license.
     *
     * Version Added:
     *     8.0
     */

    /**
     * Attributes for a license.
     *
     * Version Added:
     *     8.0
     */

    /**
     * Options for a license.
     *
     * Version Added:
     *     8.0
     */

    /**
     * Model for managing a Review Board license.
     *
     * This model handles license status tracking, updates, and management
     * operations.
     *
     * Version Added:
     *     8.0
     */
    let License = (_dec$1 = spina.spina({
      prototypeAttrs: ['actionBuilders']
    }), _dec$1(_class$3 = class License extends spina.BaseModel {
      static idAttribute = 'licenseID';
      static defaults = {
        actionTarget: null,
        actions: null,
        autoRenew: false,
        canUploadLicense: false,
        checkStatus: LicenseCheckStatus.HAS_LATEST,
        expiresDate: null,
        expiresSoon: false,
        gracePeriodDaysRemaining: null,
        hardExpiresDate: null,
        isTrial: false,
        licenseID: null,
        licensedTo: null,
        lineItems: null,
        manageURL: null,
        noticeHTML: null,
        planID: null,
        planName: null,
        productName: null,
        status: LicenseStatus.UNLICENSED,
        summary: null,
        warningHTML: null
      };

      /**********************
       * Instance variables *
       **********************/

      /** CSRF token for any actions performed on this license. */

      /**
       * Initialize the license.
       *
       * Args:
       *     attrs (LicenseAttrs):
       *         The initial attributes for the license.
       *
       *     options (LicenseOptions):
       *         Options for the license.
       */
      initialize(attributes, options) {
        this.actionCSRFToken = options?.actionCSRFToken;
      }

      /**
       * Upload a new set of license data to the license provider.
       *
       * Args:
       *     contents (Blob):
       *         The binary contents of the file to upload.
       *
       * Returns:
       *     Promise:
       *     The promise for the upload request.
       */
      async uploadLicenseFile(contents) {
        await this.callAction({
          action: 'upload-license',
          uploads: {
            license_data: contents
          }
        });
      }

      /**
       * Call an action in the license provider backend.
       *
       * Args:
       *     options (CallActionOptions):
       *         Options for the action call.
       *
       * Returns:
       *     Promise:
       *     The promise for the action call.
       */
      async callAction(options) {
        /*
         * For this, we're going to use $.ajax instead of RB.apiCall, so
         * that we don't have to worry about turning things off like the
         * activity indicator or dealing with anything specific to the
         * Review Board API.
         *
         * Also, let any errors bubble up.
         */
        const action = options.action;
        const actionTarget = this.get('actionTarget');
        const formData = new FormData();
        formData.append('action', action);
        formData.append('action_target', actionTarget);
        formData.append('csrfmiddlewaretoken', this.actionCSRFToken);
        if (options.args) {
          formData.append('action_data', JSON.stringify(options.args));
        }
        if (options.uploads) {
          for (const [key, value] of Object.entries(options.uploads)) {
            formData.append(key, value);
          }
        }
        let response = null;
        let rsp;
        try {
          response = await fetch('.', {
            body: formData,
            method: 'POST'
          });
          rsp = await response.json();
        } catch (err) {
          /* Fall through and handle this below. */
        }
        if (!rsp || !response.ok) {
          throw new CallLicenseActionError({
            action: action,
            actionTarget: actionTarget,
            message: rsp?.error,
            response: response
          });
        }
        return rsp;
      }

      /**
       * Check for license updates.
       *
       * This will start by fetching request data from the license provider's
       * configured endpoint, passing in the data needed for the request. If
       * successful, the data will be processed by the license provider backend
       * in Review Board, returning new attributes .
       *
       * The status will be updated throughout the process to reflect the current
       * state. Listeners can monitor the ``checkStatus`` attribute for changes.
       * Upon completion, the ``licenseUpdates`` event will be triggered.
       */
      async checkForUpdates() {
        this.set('checkStatus', LicenseCheckStatus.CHECKING);

        /* Fetch a license check request payload. */
        let checkRsp;
        try {
          checkRsp = await this.callAction({
            action: 'license-update-check'
          });
        } catch (xhr) {
          this.set('checkStatus', LicenseCheckStatus.ERROR_CHECKING);
          return;
        }
        if (!checkRsp.canCheck) {
          /* There's nothing to do. */
          this.set('checkStatus', LicenseCheckStatus.HAS_LATEST);
          return;
        }
        const checkStatusURL = checkRsp.checkStatusURL;
        const requestData = checkRsp.data;
        const sessionToken = checkRsp.sessionToken || null;
        let data = null;
        if (typeof requestData === 'string') {
          data = requestData;
        } else if (requestData) {
          data = new FormData();
          for (const [key, value] of Object.entries(requestData)) {
            data.append(key, value);
          }
        }

        /* Send it to the configured endpoint. */
        let response = null;
        let licenseRsp;
        try {
          const request = {
            body: data,
            method: 'POST'
          };
          if (checkRsp.credentials) {
            request.credentials = checkRsp.credentials;
          }
          if (checkRsp.headers) {
            request.headers = checkRsp.headers;
          }
          response = await fetch(checkStatusURL, request);
          const contentType = response.headers.get('content-type').toLowerCase();
          if (contentType.startsWith('application/json') || contentType.endsWith('+json')) {
            licenseRsp = await response.json();
          } else {
            licenseRsp = await response.text();
          }
        } catch (err) {
          /* Fall through and handle this below. */
          console.error('Error performing license check: %s', err);
          licenseRsp = null;
        }
        if (!licenseRsp || !response.ok) {
          this.onCheckForUpdatesHTTPError(response);
          return;
        }
        this.#processCheckForUpdatesResponse(licenseRsp, requestData, sessionToken);
      }

      /**
       * Handle HTTP errors when checking for updates.
       *
       * This will update the status of the license check depending on the error
       * code we get back.
       *
       * Subclasses can override this to provide custom error handling.
       *
       * By default, this will set the following values for ``checkStatus``:
       *
       * * :js:attr:`LicenseCheckStatus.NO_LICENSE` if the server returns a 403.
       * * :js:attr:`LicenseCheckStatus.ERROR_CHECKING` for any other error.
       *
       * Args:
       *     rsp (Response):
       *         The fetch response object.
       */
      onCheckForUpdatesHTTPError(response) {
        if (response.status === 403) {
          /*
           * A 403 response from a license server indicates that there's
           * no accessible license.
           */
          this.set('checkStatus', LicenseCheckStatus.NO_LICENSE);
        } else {
          console.error('Error checking for license %o: response=%o', this, response);
          this.set('checkStatus', LicenseCheckStatus.ERROR_CHECKING);
        }
      }

      /**
       * Process the response from checking for updates.
       *
       * This will pass the request and response payloads to the license
       * provider on the server, allowing it to handle the data as needed.
       * The result will be a new set of attributes to set on the license.
       *
       * Args:
       *     checkLicenseData (object):
       *         The license data received from the server.
       *
       *     options (CheckForUpdatesOptions):
       *         The options used for checking for updates.
       */
      async #processCheckForUpdatesResponse(checkLicenseData, requestData, sessionToken) {
        this.set('checkStatus', LicenseCheckStatus.APPLYING);
        let rsp;
        try {
          rsp = await this.callAction({
            action: 'process-license-update',
            args: {
              check_request_data: requestData,
              check_response_data: checkLicenseData,
              session_token: sessionToken
            }
          });
        } catch (xhr) {
          const responseText = xhr.responseText;
          console.error('Error processing license %o response %o: rsp=%o, ' + 'textStatus=%o', this, checkLicenseData, responseText, xhr.statusText);
          this.set('checkStatus', LicenseCheckStatus.ERROR_APPLYING);
          return;
        }

        /* The call succeeded. Notify the UI and listeners. */
        if (rsp.license_infos) {
          /*
           * There's new license information. We'll set this on all affected
           * licenses, set the status, and notify listeners of updates.
           *
           * This should be the common case.
           */
          const collection = this.collection;
          collection.updateLicenses(rsp.license_infos, {
            checkStatus: rsp.status
          });
        } else {
          /*
           * There's no license data. We'll set the status on this license
           * and notify if this is marked as applied.
           */
          this.set('checkStatus', rsp.status);
          if (rsp.status === LicenseCheckStatus.APPLIED) {
            this.trigger('licenseUpdated');
          }
        }
      }
    }) || _class$3);

    var _class$2;

    /**
     * Options for updating licenses.
     *
     * Version Added:
     *     8.0
     */

    /**
     * A collection of licenses.
     *
     * This manages a collection of licenses from the same License Provider, and
     * is used for updating batches of licenses or triggering sequential update
     * checks.
     *
     * Version Added:
     *     8.0
     */
    let LicenseCollection = spina.spina(_class$2 = class LicenseCollection extends spina.BaseCollection {
      static model = License;

      /**
       * Check for updates to each license in the collection.
       *
       * License checks will be handled one-by-one. All errors will be handled
       * gracefully.
       */
      async checkForUpdates() {
        for (const license of this) {
          try {
            await license.checkForUpdates();
          } catch (err) {
            console.error('Update check for license "%s" failed: %s', license.id, err);
          }
        }
      }

      /**
       * Update attributes for a batch of licenses in the collection.
       *
       * Any licenses found in ``licenseInfos`` that are not present in the
       * collection will be added. Any that exist will be updated. If any
       * are set to ``null``, they will be removed from the collection.
       *
       * This will trigger ``licenseUpdated`` events on any added or updated
       * licenses, and ``remove`` events on any removed licenses.
       *
       * Args:
       *     licenseInfos (object):
       *         A mapping of license IDs to either parsable license information
       *         or ``null``.
       *
       *     options (UpdateLicenseOptions, optional):
       *         Options to control the license updates.
       */
      updateLicenses(licenseInfos, options = {}) {
        const checkStatus = options?.checkStatus;

        /* Gather all licenses we want to add, update, or remove. */
        const toRemove = [];
        const toSet = [];
        for (const [licenseID, licenseInfo] of Object.entries(licenseInfos)) {
          if (licenseInfo === null) {
            toRemove.push(licenseID);
          } else {
            toSet.push(licenseInfo);
          }
        }

        /*
         * Remove any removed licenses.
         *
         * This will trigger ``remove`` signals for these licenses.
         */
        if (toRemove.length > 0) {
          this.remove(toRemove);
        }

        /* Add or update any applicable licenses. */
        if (toSet.length > 0) {
          this.set(toSet, {
            parse: true,
            remove: false
          });
        }

        /* Notify all signal handlers. */
        for (const licenseID of Object.keys(licenseInfos)) {
          const license = this.get(licenseID);
          if (license) {
            if (checkStatus) {
              license.set('checkStatus', checkStatus);
            }
            license.trigger('licenseUpdated');
          }
        }
      }
    }) || _class$2;

    var _class$1;

    /**
     * The base page view class for admin UI pages.
     */
    let BaseAdminPageView = spina.spina(_class$1 = class BaseAdminPageView extends RB.PageView {}) || _class$1;

    var _dec, _class;

    /**
     * A mapping of license check statuses to localized description strings.
     *
     * Version Added:
     *     8.0
     */
    const CHECK_STATUS_TEXT = {
      [LicenseCheckStatus.NO_LICENSE]: gettext("The product is not licensed."),
      [LicenseCheckStatus.CHECKING]: gettext("Checking for updates..."),
      [LicenseCheckStatus.HAS_LATEST]: gettext("Your license is up-to-date."),
      [LicenseCheckStatus.APPLYING]: gettext("Applying license update..."),
      [LicenseCheckStatus.APPLIED]: gettext("Your license has been automatically updated."),
      [LicenseCheckStatus.ERROR_CHECKING]: gettext("An error occurred when trying to check for license updates. Please contact support."),
      [LicenseCheckStatus.ERROR_APPLYING]: gettext("An error occurred when trying to apply a new license. Please contact support.")
    };

    /**
     * Options for adding a detail item for a license.
     *
     * Version Added:
     *     8.0
     */

    /**
     * Options passed to a license action handler.
     *
     * Version Added:
     *     8.0
     */

    /**
     * A view managing the display, state, and actions for a license.
     *
     * This shows the state of the license, whether it's active, expired, or
     * expiring soon. It lists the product, line items, and any specific
     * detail line items provided by a subclass.
     *
     * License views contain buttons that can be used to perform actions on a
     * license, such as managing a license or uploading new license data.
     *
     * Version Added:
     *     8.0
     */
    let LicenseView = (_dec = spina.spina({
      prototypeAttrs: ['actionBuilders']
    }), _dec(_class = class LicenseView extends ink.BaseComponentView {
      static className = 'rb-c-license';
      static modelEvents = {
        'change:checkStatus': '_onCheckStatusChanged',
        'licenseUpdated': 'render',
        'remove': 'remove'
      };

      /**
       * A mapping of action IDs to builder functions for action rendering.
       *
       * Subclasses can override this to provide special rendering and
       * handling for actions.
       */
      static actionBuilders = {
        'upload-license': '_buildUploadLicenseActionButton'
      };
      /**********************
       * Instance variables *
       **********************/

      /** The element storing additional details for the license. */
      #detailsEl;

      /** The element showing license state. */
      #stateEl;

      /**
       * Add a row of details to the license.
       *
       * The content and display of the details is up to the caller.
       *
       * Args:
       *     item (string or Node or Ink.CraftedComponent or Array):
       *         The item or items to use for the contents of the details row.
       *
       *     options (AddLicenseDetailOptions, optional):
       *         Options for the item.
       */
      addLicenseDetail(item, options = {}) {
        const attrs = options.attrs || {};
        const className = options.className;
        const iconName = options.iconName || '';
        attrs.class = 'rb-c-license__detail';
        if (className) {
          attrs.class += ` ${className}`;
        }
        ink.renderInto(this.#detailsEl, ink.paintComponent("li", attrs, ink.paintComponent("span", {
          "class": "rb-c-license__detail-icon " + iconName
        }), ink.paintComponent("div", {
          "class": "rb-c-license__detail-content"
        }, item)));
      }

      /**
       * Handle rendering of the license.
       *
       * This will replace the entire contents of the license with a new
       * render, showing the current state and details for the license along
       * with any actions.
       */
      onRender() {
        const model = this.model;
        const actions = model.get('actions') || [];
        const autoRenew = model.get('autoRenew');
        const expiresDate = model.get('expiresDate');
        const licenseStatus = model.get('status');
        const lineItems = model.get('lineItems') || [];
        const noticeHTML = model.get('noticeHTML');
        const summary = model.get('summary');
        const warningHTML = model.get('warningHTML');

        /* Begin building the license details. */
        const detailsNodes = ink.paintComponent("ul", {
          "class": "rb-c-license__details"
        });
        this.#detailsEl = detailsNodes;

        /* Build the information on the license expiration. */
        if (licenseStatus !== LicenseStatus.UNLICENSED && expiresDate) {
          const expiresMoment = moment(expiresDate);
          const expirationTimestamp = expiresMoment.format();
          const expirationDate = expiresMoment.format('MMM. D, YYYY, h:mm A');
          let expiresHTML;
          let expiresIcon;
          const datetimeHTML = `<time class="timesince"
dateTime="${expirationTimestamp}"></time>`;
          if (licenseStatus === LicenseStatus.LICENSED) {
            expiresIcon = 'ink-i-info';
            if (autoRenew) {
              /*
               * The license server has reported that this license
               * will renew automatically. Frame the date as a
               * renewal rather than an expiration so admins don't
               * see this as something they need to act on.
               */
              expiresHTML = interpolate(gettext("Renews %(datetimeHTML)s on %(expirationDate)s"), {
                "datetimeHTML": datetimeHTML,
                "expirationDate": expirationDate
              }, true);
            } else {
              expiresHTML = interpolate(gettext("Expires %(datetimeHTML)s on %(expirationDate)s"), {
                "datetimeHTML": datetimeHTML,
                "expirationDate": expirationDate
              }, true);
            }
          } else if (licenseStatus === LicenseStatus.HARD_EXPIRED) {
            expiresIcon = 'ink-i-warning';
            expiresHTML = interpolate(gettext("Expired %(datetimeHTML)s on %(expirationDate)s"), {
              "datetimeHTML": datetimeHTML,
              "expirationDate": expirationDate
            }, true);
          } else if (licenseStatus === LicenseStatus.EXPIRED_GRACE_PERIOD) {
            const gracePeriodDaysRemaining = model.get('gracePeriodDaysRemaining');
            expiresIcon = 'ink-i-warning';
            expiresHTML = interpolate(gettext("Expired %(datetimeHTML)s on %(expirationDate)s. There are %(gracePeriodDaysRemaining)s days left on your grace period."), {
              "datetimeHTML": datetimeHTML,
              "expirationDate": expirationDate,
              "gracePeriodDaysRemaining": gracePeriodDaysRemaining
            }, true);
          } else {
            expiresIcon = 'ink-i-warning';
            expiresHTML = gettext("Unknown expiration status. Please report this.");
          }
          this.addLicenseDetail(ink.paint([expiresHTML]), {
            iconName: expiresIcon
          });
        }
        for (const lineItem of lineItems) {
          this.addLicenseDetail(lineItem.contentIsHTML ? ink.paint([lineItem.content]) : lineItem.content, {
            iconName: lineItem.icon
          });
        }

        /* Begin rendering the view. */
        const el = this.el;
        el.setAttribute('data-status', licenseStatus);
        if (warningHTML) {
          el.classList.add('-has-warning');
        }
        const stateEl = ink.paintComponent("div", {
          "class": "rb-c-license__state"
        });
        this.#stateEl = stateEl;
        this._onCheckStatusChanged();
        const buildActionButton = this.#buildActionButton.bind(this);
        const actionBuilders = this.actionBuilders;
        const actionEls = actions.map(actionInfo => {
          const builderFuncName = actionBuilders[actionInfo.actionID];
          const builderFunc = builderFuncName ? this[builderFuncName] : buildActionButton;
          return builderFunc.call(this, actionInfo);
        });
        ink.renderInto(el, ink.paintComponent("div", {
          "class": "rb-c-license__header"
        }, ink.paintComponent("h3", {
          "class": "rb-c-license__summary"
        }, summary), warningHTML && ink.paintComponent("div", {
          "class": "rb-c-license__warning"
        }, ink.paint([warningHTML])), noticeHTML && ink.paintComponent("div", {
          "class": "rb-c-license__notice"
        }, ink.paint([noticeHTML])), stateEl, ink.paintComponent("div", {
          "class": "rb-c-license__actions"
        }, actionEls), detailsNodes), {
          empty: true
        });
        this.$('.timesince').timesince();
      }

      /**
       * Handle a license action.
       *
       * Subclasses can override it to provide handling of any custom actions.
       *
       * By default, actions will result in action calls to the License
       * Provider. These can return a ``license_infos`` with a list of license
       * changes, and can return a ``redirect_url`` with a URL to navigate to.
       *
       * Args:
       *     options (LicenseActionHandlerOptions):
       *         Options for the action invocation.
       */
      async onAction(options) {
        try {
          const rsp = await this.model.callAction({
            action: options.actionID,
            args: options.actionInfo.callArgs
          });
        } catch (err) {
          console.error('Unexpected error performing license action: %s', err);

          /* Show the error to the user. */
          alert(`There was an error performing this action: ${err.message}`);
          return;
        }
        if (rsp.license_infos) {
          const collection = this.collection;
          collection.updateLicenses(rsp.license_infos);
        }
        if (rsp.redirect_url) {
          RB.navigateTo(rsp.redirect_url);
        }
      }

      /**
       * Build an action button.
       *
       * Args:
       *     actionInfo (LicenseAction):
       *         Information for the action.
       *
       * Returns:
       *     Ink.ButtonView:
       *     The resulting action button.
       */
      #buildActionButton(actionInfo) {
        const attrs = {};
        if (actionInfo.url) {
          attrs.tagName = 'a';
          attrs.href = actionInfo.url;
        } else {
          attrs.onClick = evt => this.onAction({
            actionID: actionInfo.actionID,
            actionInfo: actionInfo,
            button: actionButton,
            event: evt
          });
        }
        if (actionInfo.primary) {
          attrs.type = ink.ButtonType.PRIMARY;
        }
        const actionButton = ink.craftComponent("Ink.Button", attrs, actionInfo.label);
        return actionButton;
      }

      /**
       * Build the Upload License action elements.
       *
       * This will build the action and upload field, and handle all
       * interactions and UI updates for the upload process.
       *
       * Args:
       *     actionInfo (LicenseAction):
       *         Information for the action.
       *
       * Returns:
       *     HTMLElement[]:
       *     The resulting action elements.
       */
      _buildUploadLicenseActionButton(actionInfo) {
        const buttonLabel = actionInfo.label;
        const fileFieldID = `license-upload-form-field-${this.cid}`;
        function resetButton() {
          button.busy = false;
          button.label = buttonLabel;
        }
        function onClick() {
          button.busy = true;
          button.label = gettext("Selecting license file...");
          fileFieldEl.click();
        }
        const button = ink.craftComponent("Ink.Button", {
          onClick: onClick
        }, buttonLabel);
        const fileFieldEl = ink.paintComponent("input", {
          id: fileFieldID,
          name: "license_data",
          type: "file",
          style: "display: none"
        });
        fileFieldEl.addEventListener('cancel', () => resetButton());
        fileFieldEl.addEventListener('change', async () => {
          /* Handle the file upload. */
          const file = fileFieldEl.files[0];

          /*
           * Just a quick sanity-check before we start uploading content.
           */
          console.assert(file.size < 1000000);
          button.label = gettext("Uploading license file...");
          try {
            await this.model.uploadLicenseFile(file);
          } catch (err) {
            alert(err.message);
          }
          resetButton();
        });
        return [fileFieldEl, ink.paintComponent("label", {
          htmlFor: fileFieldID
        }, button)];
      }

      /**
       * Handle changes to the license status.
       *
       * This will update the display of the license and the status text to
       * reflect the current status.
       */
      _onCheckStatusChanged() {
        const checkStatus = this.model.get('checkStatus') || LicenseCheckStatus.HAS_LATEST;
        this.el.setAttribute('data-check-status', checkStatus);
        this.#stateEl.innerText = CHECK_STATUS_TEXT[checkStatus] || '';
      }
    }) || _class);

    const Admin = {
      PageView: BaseAdminPageView
    };

    exports.Admin = Admin;
    exports.BaseAdminPageView = BaseAdminPageView;
    exports.CallLicenseActionError = CallLicenseActionError;
    exports.License = License;
    exports.LicenseCheckStatus = LicenseCheckStatus;
    exports.LicenseCollection = LicenseCollection;
    exports.LicenseStatus = LicenseStatus;
    exports.LicenseView = LicenseView;

    Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });

}));
//# sourceMappingURL=index.js.map
