if (typeof Settings === "undefined") { Settings = {}; } $.extend(Settings, { DEPRECATED_CLASS: 'deprecated-setting', TRIGGER_CHANGE_CLASS: 'trigger-change', DATA_ROW_CLASS: 'value-row', DATA_COL_CLASS: 'value-col', DATA_CATEGORY_CLASS: 'value-category', ADD_ROW_BUTTON_CLASS: 'add-row', ADD_ROW_SPAN_CLASSES: 'glyphicon glyphicon-plus add-row', DEL_ROW_BUTTON_CLASS: 'del-row', DEL_ROW_SPAN_CLASSES: 'glyphicon glyphicon-remove del-row', ADD_CATEGORY_BUTTON_CLASS: 'add-category', ADD_CATEGORY_SPAN_CLASSES: 'glyphicon glyphicon-plus add-category', TOGGLE_CATEGORY_COLUMN_CLASS: 'toggle-category', TOGGLE_CATEGORY_SPAN_CLASS: 'toggle-category-icon', TOGGLE_CATEGORY_SPAN_CLASSES: 'glyphicon toggle-category-icon', TOGGLE_CATEGORY_EXPANDED_CLASS: 'glyphicon-triangle-bottom', TOGGLE_CATEGORY_CONTRACTED_CLASS: 'glyphicon-triangle-right', DEL_CATEGORY_BUTTON_CLASS: 'del-category', DEL_CATEGORY_SPAN_CLASSES: 'glyphicon glyphicon-remove del-category', MOVE_UP_BUTTON_CLASS: 'move-up', MOVE_UP_SPAN_CLASSES: 'glyphicon glyphicon-chevron-up move-up', MOVE_DOWN_BUTTON_CLASS: 'move-down', MOVE_DOWN_SPAN_CLASSES: 'glyphicon glyphicon-chevron-down move-down', TABLE_BUTTONS_CLASS: 'buttons', ADD_DEL_BUTTONS_CLASS: 'add-del-buttons', ADD_DEL_BUTTONS_CLASSES: 'buttons add-del-buttons', REORDER_BUTTONS_CLASS: 'reorder-buttons', REORDER_BUTTONS_CLASSES: 'buttons reorder-buttons', NEW_ROW_CLASS: 'new-row', CONNECT_ACCOUNT_BTN_ID: 'connect-account-btn', DISCONNECT_ACCOUNT_BTN_ID: 'disconnect-account-btn', CREATE_DOMAIN_ID_BTN_ID: 'create-domain-btn', CHOOSE_DOMAIN_ID_BTN_ID: 'choose-domain-btn', GET_TEMPORARY_NAME_BTN_ID: 'get-temp-name-btn', DOMAIN_ID_SELECTOR: '[name="metaverse.id"]', ACCESS_TOKEN_SELECTOR: '[name="metaverse.access_token"]', PLACES_TABLE_ID: 'places-table', ADD_PLACE_BTN_ID: 'add-place-btn', FORM_ID: 'settings-form', INVALID_ROW_CLASS: 'invalid-input', DATA_ROW_INDEX: 'data-row-index', CONTENT_ARCHIVES_PANEL_ID: 'content_archives', UPLOAD_CONTENT_BACKUP_PANEL_ID: 'upload_content', INSTALLED_CONTENT: 'installed_content' }); var URLs = { // STABLE METAVERSE_URL: https://metaverse.highfidelity.com // STAGING METAVERSE_URL: https://staging.highfidelity.com DEFAULT_METAVERSE_URL: "https://mv.overte.org/server", CDN_URL: 'https://cdn-1.vircadia.com/eu-c-1', PLACE_URL: 'https://xr.place' }; var Strings = { LOADING_SETTINGS_ERROR: "There was a problem loading the domain settings.\nPlease refresh the page to try again.", CHOOSE_DOMAIN_BUTTON: "Choose from my domains", CREATE_DOMAIN_BUTTON: "Create new domain ID", CREATE_DOMAIN_SUCCESS_JUST_CONNECTED: "We connected your Directory Services account and created a new domain ID for this machine.", CREATE_DOMAIN_SUCCESS: "We created a new domain ID for this machine.", // When a place modification fails, they will be brought back to the previous // dialog with new path still set, allowing them to retry immediately, and without // having to type the new path in again. EDIT_PLACE_TITLE: "Modify Viewpoint or Path", EDIT_PLACE_ERROR: "Failed to update Viewpoint or Path for this Place Name. Please try again.", EDIT_PLACE_CONFIRM_BUTTON: "Save", EDIT_PLACE_CONFIRM_BUTTON_PENDING: "Saving...", EDIT_PLACE_CANCEL_BUTTON: "Cancel", REMOVE_PLACE_TITLE: "Are you sure you want to remove {{place}} and its path information?", REMOVE_PLACE_ERROR: "Failed to remove Place Name and its Path information.", REMOVE_PLACE_DELETE_BUTTON: "This action removes your Place Name", REMOVE_PLACE_DELETE_BUTTON_PENDING: "Deleting...", REMOVE_PLACE_CANCEL_BUTTON: "Cancel", ADD_PLACE_TITLE: "Choose a place", ADD_PLACE_MESSAGE: "Choose a Place Name that you own or register a new Place Name.", ADD_PLACE_CONFIRM_BUTTON: "Save", ADD_PLACE_CONFIRM_BUTTON_PENDING: "Saving...", ADD_PLACE_CANCEL_BUTTON: "Cancel", ADD_PLACE_UNKNOWN_ERROR: "There was an error adding this Place Name. Try saving again", ADD_PLACE_NO_PLACES_MESSAGE: "You don't have any Place Names registered. Once you have a Place Name, reopen this window to select it.", ADD_PLACE_NO_PLACES_BUTTON: "Create new place", ADD_PLACE_UNABLE_TO_LOAD_ERROR: "We were unable to load your place names. Please try again later.", ADD_PLACE_LOADING_DIALOG: "Loading your places...", ADD_PLACE_NOT_CONNECTED_TITLE: "Access token required", ADD_PLACE_NOT_CONNECTED_MESSAGE: "You must have an access token to query your Directory Services places.

Please follow the instructions on the settings page to add an access token.", }; var DOMAIN_ID_TYPE_NONE = 0; var DOMAIN_ID_TYPE_TEMP = 1; var DOMAIN_ID_TYPE_FULL = 2; var DOMAIN_ID_TYPE_UNKNOWN = 3; function swalAreYouSure(text, confirmButtonText, callback) { swal({ title: "Are you sure?", text: text, type: "warning", showCancelButton: true, confirmButtonText: confirmButtonText, closeOnConfirm: false }, callback); } function domainIDIsSet() { if (typeof Settings.data.values.metaverse !== 'undefined' && typeof Settings.data.values.metaverse.id !== 'undefined') { return Settings.data.values.metaverse.id.length > 0; } else { return false; } } function getCurrentDomainIDType() { if (!domainIDIsSet()) { return DOMAIN_ID_TYPE_NONE; } if (typeof DomainInfo === 'undefined') { return DOMAIN_ID_TYPE_UNKNOWN; } if (DomainInfo !== null) { // Disabled because detecting as temp domain... and we're not even using temp domains right now. // if (DomainInfo.name !== undefined) { // return DOMAIN_ID_TYPE_TEMP; // } return DOMAIN_ID_TYPE_FULL; } return DOMAIN_ID_TYPE_UNKNOWN; } function isCloudDomain() { if (!domainIDIsSet()) { return false; } if (typeof DomainInfo === 'undefined') { return false; } if (DomainInfo === null) { return false; } if (typeof DomainInfo.cloud_domain !== "boolean") { return false; } return DomainInfo.cloud_domain; } function showLoadingDialog(msg) { var message = '
'; message += ' ' + msg; message += '
'; return bootbox.dialog({ message: message, closeButton: false }); } function sendUpdatePlaceRequest(id, path, domainID, clearDomainID, onSuccess, onError) { var data = { place_id: id, path: path }; if (domainID) { data.domain_id = domainID; } if (clearDomainID) { data.domain_id = null; } $.ajax({ url: '/api/places', type: 'PUT', data: data, success: onSuccess, error: onError }); } var pendingDomainRequest = null; function getDomainFromAPI(callback) { if (pendingDomainRequest !== null) { pendingDomainRequest.success(callback); pendingDomainRequest.error(function() { callback({ status: 'fail' }) }); return pendingDomainRequest; } if (callback === undefined) { callback = function() {}; } if (!domainIDIsSet()) { callback({ status: 'fail' }); return null; } else { var domainID = Settings.data.values.metaverse.id; } pendingDomainRequest = $.ajax({ url: "/api/domains/" + domainID, dataType: 'json', success: function(data) { pendingDomainRequest = null; if (data.status === 'success') { DomainInfo = data.domain; } else { DomainInfo = null; } callback(data); }, error: function() { pendingDomainRequest = null; DomainInfo = null; callback({ status: 'fail' }); } }); return pendingDomainRequest; } function chooseFromMetaversePlaces(accessToken, forcePathTo, onSuccessfullyAdded) { if (accessToken) { getMetaverseUrl(function(metaverse_url) { var loadingDialog = showLoadingDialog(Strings.ADD_PLACE_LOADING_DIALOG); function loadPlaces() { $.ajax("/api/places", { dataType: 'json', jsonp: false, success: function(data) { if (data.status == 'success') { var modal_buttons = { cancel: { label: Strings.ADD_PLACE_CANCEL_BUTTON, className: 'add-place-cancel-button btn-default' } }; var dialog; var modal_body; if (data.data.places.length) { var places_by_id = {}; modal_body = $('
'); modal_body.append($("

Choose a place name that you own or register a new place name

")); var currentDomainIDType = getCurrentDomainIDType(); if (currentDomainIDType === DOMAIN_ID_TYPE_TEMP) { var warning = "
"; warning += "If you choose a place name it will replace your current temporary place name."; warning += "
"; modal_body.append(warning); } // setup a select box for the returned places modal_body.append($("")); place_select = $(""); _.each(data.data.places, function(place) { places_by_id[place.id] = place; place_select.append(""); }) modal_body.append(place_select); modal_body.append($("")); if (forcePathTo === undefined || forcePathTo === null) { var path = "
"; path += ""; path += ""; path += "
"; modal_body.append($(path)); } var place_select = modal_body.find("#place-name-select") place_select.change(function(ev) { var warning = modal_body.find("#place-name-warning"); var place = places_by_id[$(this).val()]; if (place === undefined || place.pointee === null) { warning.hide(); } else { warning.show(); } }); place_select.trigger('change'); modal_buttons["success"] = { label: Strings.ADD_PLACE_CONFIRM_BUTTON, className: 'add-place-confirm-button btn btn-primary', callback: function() { var placeID = $('#place-name-select').val(); // set the place ID on the form $(Settings.place_ID_SELECTOR).val(placeID).change(); if (forcePathTo === undefined || forcePathTo === null) { var placePath = $('#place-path-input').val(); } else { var placePath = forcePathTo; } $('.add-place-confirm-button').attr('disabled', 'disabled'); $('.add-place-confirm-button').html(Strings.ADD_PLACE_CONFIRM_BUTTON_PENDING); $('.add-place-cancel-button').attr('disabled', 'disabled'); function finalizeSaveDomainID(domainID) { var jsonSettings = { metaverse: { id: domainID } } var dialog = showLoadingDialog("Waiting for Domain Server to restart..."); $.ajax('/settings.json', { data: JSON.stringify(jsonSettings), contentType: 'application/json', type: 'POST' }).done(function(data) { if (data.status == "success") { waitForDomainServerRestart(function() { dialog.modal('hide'); if (onSuccessfullyAdded) { onSuccessfullyAdded(places_by_id[placeID].name, domainID); } }); } else { bootbox.alert("Failed to add place"); } }).fail(function() { bootbox.alert("Failed to add place"); }); } // If domainID is not specified, the current domain id will be used. function finishSettingUpPlace(domainID) { sendUpdatePlaceRequest( placeID, placePath, domainID, false, function(data) { dialog.modal('hide') if (domainID) { $(Settings.DOMAIN_ID_SELECTOR).val(domainID).change(); finalizeSaveDomainID(domainID); } else { if (onSuccessfullyAdded) { onSuccessfullyAdded(places_by_id[placeID].name); } } }, function(data) { $('.add-place-confirm-button').removeAttr('disabled'); $('.add-place-confirm-button').html(Strings.ADD_PLACE_CONFIRM_BUTTON); $('.add-place-cancel-button').removeAttr('disabled'); bootbox.alert(Strings.ADD_PLACE_UNKNOWN_ERROR); } ); } function maybeCreateNewDomainID() { console.log("Maybe creating domain id", currentDomainIDType) if (currentDomainIDType === DOMAIN_ID_TYPE_FULL) { finishSettingUpPlace(); } else { sendCreateDomainRequest(function(domainID) { console.log("Created domain", domainID); finishSettingUpPlace(domainID); }, function() { $('.add-place-confirm-button').removeAttr('disabled'); $('.add-place-confirm-button').html(Strings.ADD_PLACE_CONFIRM_BUTTON); $('.add-place-cancel-button').removeAttr('disabled'); bootbox.alert(Strings.ADD_PLACE_UNKNOWN_ERROR); }); } } maybeCreateNewDomainID(); return false; } } } else { modal_buttons["success"] = { label: Strings.ADD_PLACE_NO_PLACES_BUTTON, callback: function() { window.open(metaverse_url + "/user/places", '_blank'); } } modal_body = Strings.ADD_PLACE_NO_PLACES_MESSAGE; } dialog = bootbox.dialog({ title: Strings.ADD_PLACE_TITLE, message: modal_body, closeButton: false, buttons: modal_buttons, onEscape: true }); } else { bootbox.alert(Strings.ADD_PLACE_UNABLE_TO_LOAD_ERROR); } }, error: function() { bootbox.alert(Strings.ADD_PLACE_UNABLE_TO_LOAD_ERROR); }, complete: function() { loadingDialog.modal('hide'); } }); } var domainType = getCurrentDomainIDType(); if (domainType !== DOMAIN_ID_TYPE_UNKNOWN) { loadPlaces(); } else { getDomainFromAPI(function(data) { if (data.status === 'success') { var domainType = getCurrentDomainIDType(); loadPlaces(); } else { loadingDialog.modal('hide'); bootbox.confirm("We were not able to load your domain information from the Directory Services. Would you like to retry?", function(response) { if (response) { chooseFromMetaversePlaces(accessToken, forcePathTo, onSuccessfullyAdded); } }); } }) } }); } else { bootbox.alert({ title: Strings.ADD_PLACE_NOT_CONNECTED_TITLE, message: Strings.ADD_PLACE_NOT_CONNECTED_MESSAGE }) } } function sendCreateDomainRequest(onSuccess, onError) { $.ajax({ url: '/api/domains', dataType: 'json', type: 'POST', data: { label: "" }, success: function(data) { onSuccess(data.domain.id); }, error: onError }); } function waitForDomainServerRestart(callback) { function checkForDomainUp() { $.ajax('', { success: function() { callback(); }, error: function() { setTimeout(checkForDomainUp, 50); } }); } setTimeout(checkForDomainUp, 10); } function prepareAccessTokenPrompt(callback) { swal({ title: "Connect Account", type: "input", text: "Paste your created access token here." + "

If you did not successfully create an access token click cancel below and attempt to connect your account again.

", showCancelButton: true, closeOnConfirm: false, html: true }, function(inputValue){ if (inputValue === false) { return false; } if (inputValue === "") { swal.showInputError("Please paste your access token in the input field.") return false } if (callback) { callback(inputValue); } swal.close(); }); } function createDomainIDPrompt(callback) { swal({ title: 'Finish Registering Domain', type: 'input', text: 'Enter a label for this Domain Server.

This will help you identify which domain ID belongs to which server.

This is a required step for registration.

Acceptable characters are [A-Z][a-z0-9]+-_.