Viewing File: /usr/local/cpanel/base/frontend/jupiter/domains/views/listDomains.js
// Copyright 2025 WebPros International, LLC
// All rights reserved.
// copyright@cpanel.net http://cpanel.net
// This code is subject to the cPanel license. Unauthorized copying is prohibited.
/* global define */
/** @namespace cpanel.domains.views.listDomains */
define(
[
"angular",
"cjt/util/locale",
"app/services/domains",
"app/directives/domainSearchModalDirective",
"app/directives/tldPriorityInputDirective",
"cjt/services/cpanel/componentSettingSaverService",
],
function(angular, LOCALE) {
"use strict";
var app = angular.module("cpanel.domains");
/**
* View Controller for Domain Listing
*
* @module listDomains
*
* @param {Object} $scope angular scope
* @param {Object} $local angular location Object
* @param {Array} domains array of domains to display
* @param {Object} ITEM_LISTER_CONSTANTS event constants for table actions
*
*/
var COMPONENT_NAME = "listDomainsView";
var controller = app.controller(
"listDomains",
["$scope", "$location", "$filter", "componentSettingSaverService", "currentDomains", "ITEM_LISTER_CONSTANTS", "PAGE", "domains", "alertService", "DOMAIN_TYPE_CONSTANTS", "domainSearchModalService", "$document", "$timeout",
function($scope, $location, $filter, $CSSS, initialDomains, ITEM_LISTER_CONSTANTS, PAGE, $domainsService, $alertService, DOMAIN_TYPE_CONSTANTS, domainSearchModalService, $document, $timeout) {
var _tableConfigurationOptions = [];
var LIST_DOMAIN_EVENTS = {
HIDE_ASSOCIATED: "hideAssociatedSubdomains",
SHOW_ASSOCIATED: "showAssociatedSubdomains",
};
// ---- Dialog focus-trap / scroll-lock helpers ----------
var _triggerElement = null;
var _dialogKeydownHandler = null;
var _focusTimeoutPromise = null;
var _FOCUSABLE_SELECTOR = [
"a[href]",
"button:not([disabled])",
"input:not([disabled])",
"select:not([disabled])",
"textarea:not([disabled])",
"[tabindex]:not([tabindex='-1'])",
].join(", ");
function _getFocusableInDialog() {
var dialog = $document[0].querySelector(".domain-chooser");
if (!dialog) {
return [];
}
// offsetParent is null for elements inside position:fixed containers
// in some browsers, so check visibility via getComputedStyle instead.
var view = $document[0].defaultView;
return Array.prototype.filter.call(
dialog.querySelectorAll(_FOCUSABLE_SELECTOR),
function(el) {
if (!view) {
return true;
}
var style = view.getComputedStyle(el);
return style.display !== "none" && style.visibility !== "hidden";
}
);
}
function _teardownDialogTrap() {
$document[0].body.classList.remove("domain-chooser-open");
if (_dialogKeydownHandler) {
$document[0].removeEventListener("keydown", _dialogKeydownHandler);
_dialogKeydownHandler = null;
}
if (_focusTimeoutPromise) {
$timeout.cancel(_focusTimeoutPromise);
_focusTimeoutPromise = null;
}
}
var associatedDomainsExist = initialDomains.some(function(domainObject) {
if (domainObject.associatedAddonDomain) {
return true;
}
return false;
});
/**
* Navigate to the Manage screen for a specific domain
*
* @method manageDomain
*
* @param {String} domain domain to manage
*
*/
function _manageDomain(domain) {
$location.path("manage").search("domain", domain);
}
function _itemChangeRequested(event, parameters) {
switch (parameters.actionType) {
case "manage":
_manageDomain(parameters.item.domain);
break;
}
}
function _itemListerUpdated(event, parameters) {
$scope.itemListerMeta = parameters.meta;
$scope.currentSearchFilterValue = $scope.itemListerMeta.filterValue;
}
/**
* On updating of the show associated addon domains checkbox, refilter domains
*
* @method onUpdateShowAssociated
*
*/
function _filterAssociatedDomains(domain) {
if ($scope.showAssociatedSubdomains) {
return true;
}
if (!domain.associatedAddonDomain) {
return true;
}
return false;
}
var lastFiltered = true;
function _updateFiltered() {
var filteredDomains = $filter("filter")(initialDomains, _filterAssociatedDomains);
lastFiltered = $scope.showAssociatedSubdomains;
// Need to do this without destroying the original array
$scope.filteredDomains = filteredDomains;
}
function toggleShowAssociatedSubdomains() {
$scope.showAssociatedSubdomains = !$scope.showAssociatedSubdomains;
$CSSS.set(COMPONENT_NAME, { showAssociatedSubdomains: $scope.showAssociatedSubdomains });
_updateFiltered();
_updateTableConfigurationOptions();
}
function getFilteredDomains() {
if (lastFiltered !== $scope.showAssociatedSubdomains) {
_updateFiltered();
}
return $scope.filteredDomains;
}
function _updateTableConfigurationOptions() {
_tableConfigurationOptions.splice(0);
if (!associatedDomainsExist) {
return;
}
if ($scope.showAssociatedSubdomains) {
_tableConfigurationOptions.push({
label: LOCALE.maketext("Hide Associated Subdomains"),
event: LIST_DOMAIN_EVENTS.HIDE_ASSOCIATED,
});
} else {
_tableConfigurationOptions.push({
label: LOCALE.maketext("Show Associated Subdomains"),
event: LIST_DOMAIN_EVENTS.SHOW_ASSOCIATED,
});
}
}
$scope.$on(ITEM_LISTER_CONSTANTS.TABLE_ITEM_BUTTON_EVENT, _itemChangeRequested);
$scope.$on(ITEM_LISTER_CONSTANTS.ITEM_LISTER_UPDATED_EVENT, _itemListerUpdated);
$scope.$on(LIST_DOMAIN_EVENTS.SHOW_ASSOCIATED, toggleShowAssociatedSubdomains);
$scope.$on(LIST_DOMAIN_EVENTS.HIDE_ASSOCIATED, toggleShowAssociatedSubdomains);
$scope.domains = initialDomains;
$scope.filteredDomains = initialDomains;
$scope.showAssociatedSubdomains = false;
$scope.temporaryDomainBannerText = LOCALE.maketext("You cannot create an email account for a temporary domain.");
$scope.hasTemporaryDomainInList = !PAGE.isDisabledTempDomains && initialDomains.some(function(domain) {
return domain.is_temporary;
});
$scope.tableHeaderItems = [];
$scope.tableHeaderItems.push({ field: "batchSelect", sortable: false, label: null });
$scope.tableHeaderItems.push({ field: "domain", sortable: true, label: LOCALE.maketext("Domain") });
if (PAGE.hasWebServerRole) {
$scope.tableHeaderItems.push({ field: "documentRoot", sortable: true, label: LOCALE.maketext("Document Root"), hiddenInSmall: true });
$scope.tableHeaderItems.push({ field: "redirectsTo", sortable: true, label: LOCALE.maketext("Redirects To"), hiddenInSmall: true });
$scope.tableHeaderItems.push({ field: "HTTPSRedirect", sortable: true, label: LOCALE.maketext("Force HTTPS Redirect"), hiddenInSmall: true });
}
$scope.tableHeaderItems.push({ field: "actions", label: LOCALE.maketext("Actions"), hiddenInSmall: true });
_updateTableConfigurationOptions();
// Domain chooser modal logic
var domainRecommendationsEnabled = !!(PAGE.features && PAGE.features.domain_recommendation);
var canCreateAlias = !!(PAGE.features && PAGE.features.alias);
var mainDomain = $domainsService.getMainDomain() || {};
var mainDomainDocRoot = mainDomain.documentRoot || "/home/user/public_html";
var mainDomainName = mainDomain.domain || "";
function openDomainChooser() {
if ($scope.showDomainChooser) {
return;
}
_triggerElement = $document[0].activeElement || null;
$scope.showDomainChooser = true;
$scope.selectedDomainOption = null;
$document[0].body.classList.add("domain-chooser-open");
_dialogKeydownHandler = function($event) {
if ($event.key === "Escape") {
$scope.$apply(function() {
if (!$scope.creatingDomain) {
closeDomainChooser();
}
});
return;
}
if ($event.key !== "Tab") {
return;
}
var focusable = _getFocusableInDialog();
if (!focusable.length) {
$event.preventDefault();
return;
}
var first = focusable[0];
var last = focusable[focusable.length - 1];
var dialog = $document[0].querySelector(".domain-chooser");
var focusIsInDialog = dialog && dialog.contains($document[0].activeElement);
if (!focusIsInDialog) {
// Focus escaped the dialog (or never landed): pull it back.
$event.preventDefault();
if ($event.shiftKey) {
last.focus();
} else {
first.focus();
}
} else if ($event.shiftKey) {
if ($document[0].activeElement === first) {
$event.preventDefault();
last.focus();
}
} else {
if ($document[0].activeElement === last) {
$event.preventDefault();
first.focus();
}
}
};
$document[0].addEventListener("keydown", _dialogKeydownHandler);
_focusTimeoutPromise = $timeout(function() {
_focusTimeoutPromise = null;
var focusable = _getFocusableInDialog();
if (focusable.length) {
focusable[0].focus();
}
});
}
// Monotonic token guarding the async purchase-search launch.
// Bumped on every launch and on cancel/close so a saved-TLD
// read that resolves late cannot open a stale or duplicate
// modal (CPANEL-53293).
var _purchaseLaunchToken = 0;
function _invalidatePurchaseLaunch() {
_purchaseLaunchToken++;
}
function closeDomainChooser() {
_invalidatePurchaseLaunch();
$scope.showDomainChooser = false;
$scope.selectedDomainOption = null;
$scope.registeredForm.domainName = "";
$scope.registeredForm.shareDocRoot = canCreateAlias;
$scope.registeredForm.documentRootPath = "";
_resetPurchaseForm();
_teardownDialogTrap();
if (_triggerElement && typeof _triggerElement.focus === "function") {
_triggerElement.focus();
_triggerElement = null;
}
}
function _resetPurchaseForm() {
$scope.purchaseForm.searchQuery = "";
$scope.purchaseForm.showSearchOptions = false;
$scope.purchaseForm.tldFilters = [];
}
// Pre-populate the prioritised TLDs from the user's saved
// NVData preference so a prioritisation set in a previous
// session carries over into the create-domain chooser and
// is forwarded to the search modal (CPANEL-53293). Runs
// after _resetPurchaseForm(); only applies the saved value
// when the (freshly reset) list is still empty so it never
// clobbers in-progress edits.
// Tracks the in-flight saved-TLD read so a purchase search
// can wait for it before seeding the modal (see
// _launchPurchaseSearch).
var _savedTldFiltersLoad = null;
function _loadSavedTldFilters() {
_savedTldFiltersLoad = $domainsService.getPrioritizedTlds().then(function(savedTlds) {
if (savedTlds && savedTlds.length && !$scope.purchaseForm.tldFilters.length) {
$scope.purchaseForm.tldFilters = savedTlds;
}
});
return _savedTldFiltersLoad;
}
function selectDomainOption(option) {
$scope.selectedDomainOption = option;
if (option === "registered") {
$scope.registeredForm.domainName = "";
$scope.registeredForm.shareDocRoot = canCreateAlias;
$scope.registeredForm.documentRootPath = "";
$scope.registeredForm.subdomain = "";
$scope.registeredForm.rootDomain = "";
$scope.registeredForm.domainType = "";
} else if (option === "purchase") {
_resetPurchaseForm();
_ensureSupportedTldsLoaded();
_loadSavedTldFilters();
}
}
function cancelDomainOption() {
_invalidatePurchaseLaunch();
$scope.selectedDomainOption = null;
$scope.registeredForm.domainName = "";
$scope.registeredForm.shareDocRoot = canCreateAlias;
$scope.registeredForm.documentRootPath = "";
$scope.registeredForm.subdomain = "";
$scope.registeredForm.rootDomain = "";
$scope.registeredForm.domainType = "";
_resetPurchaseForm();
}
// ----- Purchase chooser: TLD priority helpers ----------
// null = not yet loaded; [] = loaded but empty/unavailable.
$scope.supportedTlds = null;
var _supportedTldsRequested = false;
function _ensureSupportedTldsLoaded() {
if (_supportedTldsRequested) {
return;
}
_supportedTldsRequested = true;
$domainsService.fetchSupportedTlds()
.then(function(tlds) {
$scope.supportedTlds = tlds;
})
.catch(function() {
$scope.supportedTlds = [];
});
}
function togglePurchaseSearchOptions() {
$scope.purchaseForm.showSearchOptions = !$scope.purchaseForm.showSearchOptions;
}
function handlePurchaseSearchKeyup($event) {
if ($event.key !== "Enter") {
return;
}
if (!$scope.purchaseForm.searchQuery || $scope.creatingDomain) {
return;
}
// Handling on keyup (not keydown) lets the Enter event
// chain finish on the still-focused input before we
// mutate the DOM. This prevents the browser from
// dispatching a synthetic click on whatever button
// gains focus next (e.g. the "Create A New Domain"
// trigger), which would re-open the chooser overlay
// on top of the search modal.
$event.preventDefault();
$event.stopPropagation();
confirmDomainOption();
}
function onUpdateRegisteredDomainName() {
// Clear derived fields on each update so previous suggestions invalidate
$scope.registeredForm.documentRootPath = "";
$scope.registeredForm.subdomain = "";
$scope.registeredForm.rootDomain = "";
$scope.registeredForm.domainType = "";
if (!$scope.registeredForm.domainName) {
return;
}
// The backend doesn't accept uppercase letters in domain names
$scope.registeredForm.domainName = $scope.registeredForm.domainName.toLowerCase();
var domainName = $scope.registeredForm.domainName;
// Determine domain type from name
var domainType = "";
var rootDomain = "";
if ($scope.registeredForm.shareDocRoot && canCreateAlias) {
domainType = DOMAIN_TYPE_CONSTANTS.ALIAS;
} else {
var domainParts = domainName.split(".");
if (domainParts.length > 2) {
for (var i = 1; i < domainParts.length; i++) {
var suffix = domainParts.slice(i).join(".");
if ($domainsService.findDomainByName(suffix)) {
domainType = DOMAIN_TYPE_CONSTANTS.SUBDOMAIN;
rootDomain = suffix;
break;
}
}
}
if (!domainType) {
domainType = DOMAIN_TYPE_CONSTANTS.ADDON;
rootDomain = mainDomainName;
}
}
$scope.registeredForm.domainType = domainType;
$scope.registeredForm.rootDomain = rootDomain;
// Auto-populate document root
if (!$scope.registeredForm.shareDocRoot) {
$scope.registeredForm.documentRootPath = domainName.replace("*", "_wildcard_");
}
// Auto-populate subdomain
$scope.registeredForm.subdomain = domainName;
}
function onToggleShareDocRoot() {
if (!$scope.registeredForm.domainName) {
return;
}
// Update domain type based on the new checkbox state
if ($scope.registeredForm.shareDocRoot && canCreateAlias) {
$scope.registeredForm.domainType = DOMAIN_TYPE_CONSTANTS.ALIAS;
$scope.registeredForm.documentRootPath = mainDomainDocRoot.replace(mainDomain.homedir + "/", "");
} else {
// Re-derive from domain name when unchecked
onUpdateRegisteredDomainName();
}
}
function confirmDomainOption() {
var option = $scope.selectedDomainOption;
if (!option) {
return;
}
if (option === "purchase") {
_launchPurchaseSearch();
return;
}
if (option === "temporary") {
_createTemporaryDomain();
return;
}
if (option === "registered") {
_createRegisteredDomain();
return;
}
$scope.showDomainChooser = false;
$scope.selectedDomainOption = null;
$location.path("/create").search("mode", option);
}
function _createTemporaryDomain() {
$scope.creatingDomain = true;
var domainObject = {
domainType: DOMAIN_TYPE_CONSTANTS.ADDON,
createTemporaryDomain: "1",
newDomainName: null,
documentRoot: null,
subdomain: null,
domain: null,
fullDocumentRoot: null,
};
$domainsService.add(domainObject).then(function(result) {
var domainName = result.domain;
var msg;
if (PAGE.hasWebServerRole) {
msg = LOCALE.maketext("You have successfully created the new “[_1]” domain with the document root of “[_2]”.", domainName, _.escape(result.documentRoot));
} else {
msg = LOCALE.maketext("You have successfully created the new “[_1]” domain.", domainName);
}
$alertService.add({
type: "success",
message: msg,
autoClose: 10000,
});
_updateFiltered();
$scope.hasTemporaryDomainInList = true;
}).finally(function() {
$scope.creatingDomain = false;
closeDomainChooser();
});
}
function _createRegisteredDomain() {
var domainName = ($scope.registeredForm.domainName || "").trim().toLowerCase();
if (!domainName) {
return;
}
$scope.creatingDomain = true;
// Use pre-computed domain type from auto-populate, or detect now
var domainType = $scope.registeredForm.domainType;
var rootDomain = $scope.registeredForm.rootDomain;
if (!domainType) {
if ($scope.registeredForm.shareDocRoot && canCreateAlias) {
domainType = DOMAIN_TYPE_CONSTANTS.ALIAS;
} else {
var domainParts = domainName.split(".");
if (domainParts.length > 2) {
for (var i = 1; i < domainParts.length; i++) {
var suffix = domainParts.slice(i).join(".");
if ($domainsService.findDomainByName(suffix)) {
domainType = DOMAIN_TYPE_CONSTANTS.SUBDOMAIN;
rootDomain = suffix;
break;
}
}
}
if (!domainType) {
domainType = DOMAIN_TYPE_CONSTANTS.ADDON;
rootDomain = $domainsService.getMainDomain().domain;
}
}
}
// No webserver role forces alias type
if (!PAGE.hasWebServerRole) {
domainType = DOMAIN_TYPE_CONSTANTS.ALIAS;
}
// Build document root paths — alias domains share the main domain's docroot
var relativeDocRoot, fullDocRoot;
if (domainType === DOMAIN_TYPE_CONSTANTS.ALIAS) {
fullDocRoot = mainDomainDocRoot;
relativeDocRoot = mainDomainDocRoot.replace(mainDomain.homedir + "/", "");
} else {
relativeDocRoot = $scope.registeredForm.documentRootPath || domainName.replace("*", "_wildcard_");
fullDocRoot = $domainsService.generateFullDocumentRoot(relativeDocRoot);
}
var subdomain = $scope.registeredForm.subdomain || domainName;
var domainObject = {
domainType: domainType,
newDomainName: domainName,
subdomain: subdomain,
domain: rootDomain,
documentRoot: relativeDocRoot,
fullDocumentRoot: fullDocRoot,
inheritDocumentRoot: $scope.registeredForm.shareDocRoot,
};
$domainsService.add(domainObject).then(function(result) {
var createdDomain = result.domain || domainName;
var msg;
if (PAGE.hasWebServerRole) {
msg = LOCALE.maketext("You have successfully created the new “[_1]” domain with the document root of “[_2]”.", _.escape(createdDomain), _.escape(result.documentRoot));
} else {
msg = LOCALE.maketext("You have successfully created the new “[_1]” domain.", _.escape(createdDomain));
}
$alertService.add({
type: "success",
message: msg,
autoClose: 10000,
});
_updateFiltered();
closeDomainChooser();
}).finally(function() {
$scope.creatingDomain = false;
});
}
function _launchPurchaseSearch() {
var query = ($scope.purchaseForm.searchQuery || "").trim();
if (!query) {
return;
}
// Claim this launch. A later launch or a cancel/close
// bumps the token, so a stale or duplicate callback is
// ignored below.
var token = ++_purchaseLaunchToken;
function _openModal() {
// Ignore if a repeated submit or a cancel superseded
// this launch while the saved-TLD read was in flight.
if (token !== _purchaseLaunchToken) {
return;
}
var initialTldFilters = $scope.purchaseForm.tldFilters.slice();
closeDomainChooser();
domainSearchModalService.open({
initialQuery: query,
initialTldFilters: initialTldFilters,
autoSearch: true,
source: "create",
onAddDomain: _addPurchasedDomain,
});
}
// Wait for any in-flight saved-TLD read to settle before
// seeding the modal. Without this, a fast user (select
// purchase → type → Continue) could open the modal with an
// empty initialTldFilters before the NVData read resolves;
// the modal treats the presence of that property as an
// explicit empty seed, skips its own load, and then
// persists the empty list on auto-search — clearing the
// saved preference (CPANEL-53293).
if (_savedTldFiltersLoad && typeof _savedTldFiltersLoad.finally === "function") {
_savedTldFiltersLoad.finally(_openModal);
} else {
_openModal();
}
}
// Callback handed to the domain-search modal: after the
// user purchases a domain in the store, re-open the
// create-domain chooser on its "Registered Domain" step
// with the just-purchased name prefilled, so they can add
// it to cPanel without retyping it.
// Deferred a tick so the search modal finishes tearing
// down — and releases focus — before the chooser dialog
// opens and claims it. selectDomainOption("registered")
// resets the form, so the name is set afterwards and the
// derived fields (type, document root, subdomain) are
// computed via onUpdateRegisteredDomainName().
function _addPurchasedDomain(domain) {
if (!domain) {
return;
}
$timeout(function() {
openDomainChooser();
selectDomainOption("registered");
$scope.registeredForm.domainName = domain;
onUpdateRegisteredDomainName();
});
}
$scope.$on("openDomainChooser", openDomainChooser);
angular.extend($scope, {
getFilteredDomains: getFilteredDomains,
showAssociatedSubdomains: false,
toggleShowAssociatedSubdomains: toggleShowAssociatedSubdomains,
tableConfigurationOptions: _tableConfigurationOptions,
showDomainChooser: false,
selectedDomainOption: null,
creatingDomain: false,
registeredForm: {
domainName: "",
shareDocRoot: canCreateAlias,
documentRootPath: "",
subdomain: "",
rootDomain: "",
domainType: "",
},
purchaseForm: {
searchQuery: "",
showSearchOptions: false,
tldFilters: [],
},
togglePurchaseSearchOptions: togglePurchaseSearchOptions,
handlePurchaseSearchKeyup: handlePurchaseSearchKeyup,
canCreateAlias: canCreateAlias,
domainRecommendationsEnabled: domainRecommendationsEnabled,
documentRootPattern: $domainsService.getDocumentRootPattern(),
DOMAIN_TYPE_CONSTANTS: DOMAIN_TYPE_CONSTANTS,
openDomainChooser: openDomainChooser,
closeDomainChooser: closeDomainChooser,
selectDomainOption: selectDomainOption,
cancelDomainOption: cancelDomainOption,
confirmDomainOption: confirmDomainOption,
onUpdateRegisteredDomainName: onUpdateRegisteredDomainName,
onToggleShareDocRoot: onToggleShareDocRoot,
domainChooserStrings: {
dialogLabel: LOCALE.maketext("Choose Domain Type"),
closeLabel: LOCALE.maketext("Close"),
heading: LOCALE.maketext("What kind of domain do you want to use?"),
temporaryAlt: LOCALE.maketext("Temporary domain illustration."),
temporarySubtitle: LOCALE.maketext("Find a domain later."),
temporaryHeading: LOCALE.maketext("Temporary Domain"),
registeredAlt: LOCALE.maketext("Registered domain illustration."),
registeredSubtitle: LOCALE.maketext("Use a domain you own."),
registeredHeading: LOCALE.maketext("Registered Domain"),
purchaseAlt: LOCALE.maketext("Purchase a domain illustration."),
purchaseSubtitle: LOCALE.maketext("Search for a new domain."),
purchaseHeading: LOCALE.maketext("Purchase a Domain"),
cancelLabel: LOCALE.maketext("Cancel"),
continueLabel: LOCALE.maketext("Continue"),
creatingLabel: LOCALE.maketext("Creating …"),
registeredFormLabel: LOCALE.maketext("Registered Domain"),
registeredFormDescription: LOCALE.maketext("Add a domain that is already registered. You can also create a subdomain for an existing domain."),
shareDocRootLabel: LOCALE.maketext("Share document root ([_1]) with “[_2]”?", mainDomainDocRoot, mainDomainName),
shareDocRootHelp: LOCALE.maketext("If the document root is shared, the new domain will serve the same content as “[_1]”. [output,strong,You cannot change this setting once you create the domain].", mainDomainName),
docRootHeading: LOCALE.maketext("Document Root (File System Location)"),
docRootDescription: LOCALE.maketext("Specify the directory where you want the files for this domain to exist."),
domainRequired: LOCALE.maketext("The Domain field is required."),
domainNotUnique: LOCALE.maketext("This domain already exists on this account."),
docRootPatternError: LOCALE.maketext("Directory paths cannot be empty, contain spaces, or contain the following characters: [output,chr,92] ? % * : | [output,quot] [output,gt] [output,lt]"),
subdomainHeading: LOCALE.maketext("Subdomain"),
subdomainDescription: LOCALE.maketext("An addon domain requires a subdomain in order to use a separate document root."),
subdomainRequired: LOCALE.maketext("A subdomain is required."),
purchaseFormLabel: LOCALE.maketext("Search for a domain"),
purchaseFormDescription: "",
searchLabel: LOCALE.maketext("Search"),
showOptions: LOCALE.maketext("Show Options"),
hideOptions: LOCALE.maketext("Hide Options"),
purchaseSearchPlaceholder: LOCALE.maketext("Use exact terms or let our AI find unique suggestions based on your input."),
},
});
// When the user arrives from the Manage screen's
// "Explore Domains → Purchase → Add Domain" flow, the
// purchased domain is handed over through the domains
// service. Consume it (one-shot) and open the chooser on
// its "Registered Domain" step prefilled.
var _pendingAddDomain = $domainsService.consumePendingAddDomain();
if (_pendingAddDomain) {
_addPurchasedDomain(_pendingAddDomain);
}
var registerSuccess = $CSSS.register(COMPONENT_NAME);
if ( registerSuccess ) {
registerSuccess.then(function _savedStateLoaded(result) {
if (result && $scope.showAssociatedSubdomains !== result.showAssociatedSubdomains) {
$scope.showAssociatedSubdomains = result.showAssociatedSubdomains;
_updateFiltered();
_updateTableConfigurationOptions();
}
});
}
$scope.$on("$destroy", function() {
$CSSS.unregister(COMPONENT_NAME);
_teardownDialogTrap();
});
},
]
);
return controller;
}
);
Back to Directory