Update Function MISC_SERVE_SCALAR_UI
This commit is contained in:
@@ -1 +1,612 @@
|
||||
馀鉆琢闳@\由掠@^@
|
||||
SET PATH *LIBL ;
|
||||
|
||||
CREATE OR REPLACE FUNCTION RESTAPI.MISC_SERVE_SCALAR_UI (
|
||||
P_URL VARCHAR(528) DEFAULT NULL ,
|
||||
P_CONTENT CLOB(104857600) DEFAULT NULL ,
|
||||
P_BASESERVERURL VARCHAR(528) DEFAULT NULL ,
|
||||
P_SOURCES CLOB(104857600) DEFAULT NULL ,
|
||||
P_LAYOUT VARCHAR(32) DEFAULT 'modern' ,
|
||||
P_THEME VARCHAR(32) DEFAULT NULL ,
|
||||
P_DARKMODE SMALLINT DEFAULT NULL ,
|
||||
P_FORCEDARKMODESTATE VARCHAR(16) DEFAULT NULL ,
|
||||
P_DOCUMENTDOWNLOADTYPE VARCHAR(32) DEFAULT NULL ,
|
||||
P_FAVICON VARCHAR(528) DEFAULT NULL ,
|
||||
P_WITHDEFAULTFONTS SMALLINT DEFAULT 1 ,
|
||||
P_CUSTOMCSS CLOB(104857600) DEFAULT NULL ,
|
||||
P_AUTHENTICATION CLOB(104857600) DEFAULT NULL ,
|
||||
P_HIDESIDEBAR SMALLINT DEFAULT 0 ,
|
||||
P_SHOWSIDEBAR SMALLINT DEFAULT 1 ,
|
||||
P_HIDESEARCH SMALLINT DEFAULT 0 ,
|
||||
P_HIDECLIENTBUTTON SMALLINT DEFAULT 0 ,
|
||||
P_HIDEDARKMODETOGGLE SMALLINT DEFAULT 0 ,
|
||||
P_HIDETESTREQUESTBUTTON SMALLINT DEFAULT NULL ,
|
||||
P_HIDEMODELS SMALLINT DEFAULT 0 ,
|
||||
P_SHOWOPERATIONID SMALLINT DEFAULT 0 ,
|
||||
P_EXPANDALLRESPONSES SMALLINT DEFAULT NULL ,
|
||||
P_EXPANDALLMODELSECTIONS SMALLINT DEFAULT NULL ,
|
||||
P_DEFAULTOPENALLTAGS SMALLINT DEFAULT NULL ,
|
||||
P_SHOWDEVELOPERTOOLS VARCHAR(16) DEFAULT 'always' ,
|
||||
P_OPERATIONTITLESOURCE VARCHAR(32) DEFAULT NULL ,
|
||||
P_ORDERREQUIREDPROPERTIESFIRST SMALLINT DEFAULT NULL ,
|
||||
P_ORDERSCHEMAPROPERTIESBY VARCHAR(32) DEFAULT NULL ,
|
||||
P_PATHROUTING CLOB(104857600) DEFAULT NULL ,
|
||||
P_PERSISTAUTH SMALLINT DEFAULT NULL ,
|
||||
P_SEARCHHOTKEY VARCHAR(16) DEFAULT NULL ,
|
||||
P_DEFAULTHTTPCLIENT CLOB(104857600) DEFAULT NULL ,
|
||||
P_TAGSSORTER VARCHAR(32) DEFAULT NULL ,
|
||||
P_OPERATIONSSORTER VARCHAR(32) DEFAULT NULL ,
|
||||
P_FETCH CLOB(104857600) DEFAULT NULL ,
|
||||
P_PROXYURL VARCHAR(528) DEFAULT NULL ,
|
||||
P_SERVERS CLOB(104857600) DEFAULT NULL ,
|
||||
P_HIDDENCLIENTS CLOB(104857600) DEFAULT NULL ,
|
||||
P_ONBEFOREREQUEST CLOB(104857600) DEFAULT NULL ,
|
||||
P_ONREQUESTSENT CLOB(104857600) DEFAULT NULL ,
|
||||
P_ONSHOWMORE CLOB(104857600) DEFAULT NULL ,
|
||||
P_ONLOADED CLOB(104857600) DEFAULT NULL ,
|
||||
P_ONSPECUPDATE CLOB(104857600) DEFAULT NULL ,
|
||||
P_ONDOCUMENTSELECT CLOB(104857600) DEFAULT NULL ,
|
||||
P_ONSERVERCHANGE CLOB(104857600) DEFAULT NULL ,
|
||||
P_ONSIDEBARCLICK CLOB(104857600) DEFAULT NULL ,
|
||||
P_METADATA CLOB(104857600) DEFAULT NULL ,
|
||||
P_PLUGINS CLOB(104857600) DEFAULT NULL ,
|
||||
P_REDIRECT VARCHAR(528) DEFAULT NULL ,
|
||||
P_TELEMETRY SMALLINT DEFAULT 0 ,
|
||||
P_GENERATEHEADINGSLUG CLOB(104857600) DEFAULT NULL ,
|
||||
P_GENERATEOPERATIONSLUG CLOB(104857600) DEFAULT NULL ,
|
||||
P_GENERATETAGSLUG CLOB(104857600) DEFAULT NULL ,
|
||||
P_GENERATEWEBHOOKSLUG CLOB(104857600) DEFAULT NULL ,
|
||||
P_GENERATEMODELSLUG CLOB(104857600) DEFAULT NULL ,
|
||||
P_ISLOADING SMALLINT DEFAULT 1 )
|
||||
RETURNS CLOB(2147483647)
|
||||
LANGUAGE SQL
|
||||
SPECIFIC RESTAPI.MISC_SERVE_SCALAR_UI
|
||||
NOT DETERMINISTIC
|
||||
READS SQL DATA
|
||||
CALLED ON NULL INPUT
|
||||
SET OPTION ALWBLK = *ALLREAD ,
|
||||
ALWCPYDTA = *OPTIMIZE ,
|
||||
COMMIT = *NONE ,
|
||||
DECRESULT = (31, 31, 00) ,
|
||||
DYNDFTCOL = *NO ,
|
||||
DYNUSRPRF = *USER ,
|
||||
SRTSEQ = *HEX
|
||||
BEGIN
|
||||
RETURN
|
||||
( '<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Scalar API Reference - Full Config Playground</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap" rel="stylesheet" />
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: "Poppins", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
}
|
||||
#app {
|
||||
min-height: 100vh;
|
||||
transition: filter 0.3s ease-in-out;
|
||||
}
|
||||
#app.modal-blur {
|
||||
filter: blur(8px);
|
||||
}
|
||||
|
||||
#modal-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width:100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: none;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
#modal-dialog {
|
||||
background-color: white;
|
||||
box-shadow: 0 4px 12px rgba(0,0, 0, 0.15);
|
||||
width: 600px;
|
||||
max-width: 90%;
|
||||
padding: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
#modal-dialog h3 {
|
||||
font-size:1.5em;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
color:#333;
|
||||
}
|
||||
#modal-dialog p {
|
||||
font-size: 0.9em;
|
||||
line-height: 1.5;
|
||||
color: #555;
|
||||
margin: 0;
|
||||
}
|
||||
#input-container {
|
||||
position: relative;
|
||||
border: 1px solid #ccc;
|
||||
padding: 12px;
|
||||
min-height: 100px;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
#input-placeholder {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 12px;
|
||||
color: #999;
|
||||
font-size: 1.5em;
|
||||
pointer-events: none;
|
||||
}
|
||||
#api-input {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
border: none;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
resize: none;
|
||||
padding-top: 18px;
|
||||
box-sizing: border-box;
|
||||
color: #333;
|
||||
font-family: monospace;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
#button-container {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
justify-content: flex-end;
|
||||
margin-top: 16px;
|
||||
}
|
||||
.modal-btn {
|
||||
padding: 10px 20px;
|
||||
cursor: pointer;
|
||||
font-size: 0.9em;
|
||||
font-weight: 500;
|
||||
border-radius: 4px;
|
||||
}
|
||||
#cancel-btn {
|
||||
background-color: #f0f0f0;
|
||||
border: 1px solid #ddd;
|
||||
color: #333;
|
||||
}
|
||||
#cancel-btn:hover {
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
#continue-btn {
|
||||
background-color: #010e1c;
|
||||
border: 1px solid #000000;
|
||||
color: white;
|
||||
}
|
||||
#continue-btn:hover {
|
||||
background-color: #021528;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="modal-overlay">
|
||||
<div id="modal-dialog">
|
||||
<h3>Import API</h3>
|
||||
<p>Paste the contents of your OpenAPI document (YAML/JSON) or a link to its location.</p>
|
||||
<div id="input-container">
|
||||
<span id="input-placeholder">OpenAPI Document or Link</span>
|
||||
<textarea id="api-input"></textarea>
|
||||
</div>
|
||||
<div id="button-container">
|
||||
<button id="cancel-btn" class="modal-btn">Cancel</button>
|
||||
<buttonid="continue-btn" class="modal-btn">Continue</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="app"></div>
|
||||
|
||||
<script>
|
||||
(function(){
|
||||
"use strict";
|
||||
const ELEMENTS = {
|
||||
app:"#app",
|
||||
modal: "#modal-overlay",
|
||||
input: "#api-input",
|
||||
placeholder: "#input-placeholder",
|
||||
cancelBtn: "#cancel-btn",
|
||||
continueBtn: "#continue-btn"
|
||||
};
|
||||
const WELCOME_SPEC = {
|
||||
openapi: "3.1.0",
|
||||
info: {
|
||||
title: "Welcome to Scalar",
|
||||
description: "Please import an OpenAPI specification using the dialog above",
|
||||
version: "1.0.0"
|
||||
},
|
||||
paths: {}
|
||||
};
|
||||
const DEFAULT_SCALAR_CONFIG = {
|
||||
layout: ' ||
|
||||
COALESCE ( '''' || P_LAYOUT || '''' , '''modern''' ) || ',
|
||||
theme: ' || COALESCE ( '''' || P_THEME || '''' , 'undefined' )
|
||||
|| ',
|
||||
darkMode: ' || COALESCE (
|
||||
CASE
|
||||
WHEN P_DARKMODE = 1 THEN 'true'
|
||||
WHEN P_DARKMODE = 0 THEN 'false'
|
||||
ELSE NULL
|
||||
END , 'undefined' ) || ',
|
||||
forceDarkModeState: ' ||
|
||||
COALESCE ( '''' || P_FORCEDARKMODESTATE || '''' , 'undefined' ) ||
|
||||
',
|
||||
documentDownloadType: ' ||
|
||||
COALESCE ( '''' || P_DOCUMENTDOWNLOADTYPE || '''' , 'undefined' ) ||
|
||||
',
|
||||
favicon: ' ||
|
||||
COALESCE ( '''' || P_FAVICON || '''' , 'undefined' ) || ',
|
||||
withDefaultFonts: ' || COALESCE (
|
||||
CASE
|
||||
WHEN P_WITHDEFAULTFONTS = 1 THEN 'true'
|
||||
ELSE 'false'
|
||||
END , 'true' ) || ',
|
||||
customCss: ' ||
|
||||
COALESCE ( '''' || P_CUSTOMCSS || '''' , 'undefined' ) || ',
|
||||
authentication: ' ||
|
||||
COALESCE ( P_AUTHENTICATION , 'undefined' ) || ',
|
||||
hideSidebar: '|| COALESCE (
|
||||
CASE
|
||||
WHEN P_HIDESIDEBAR = 1 THEN 'true'
|
||||
ELSE 'false'
|
||||
END , 'false' ) || ',
|
||||
showSidebar: ' || COALESCE (
|
||||
CASE
|
||||
WHEN P_SHOWSIDEBAR = 1 THEN 'true'
|
||||
ELSE 'false'
|
||||
END , 'true' ) || ',
|
||||
hideSearch: ' || COALESCE (
|
||||
CASE
|
||||
WHEN P_HIDESEARCH = 1 THEN 'true'
|
||||
ELSE 'false'
|
||||
END , 'false' ) || ',
|
||||
hideClientButton: ' || COALESCE (
|
||||
CASE
|
||||
WHEN P_HIDECLIENTBUTTON = 1 THEN 'true'
|
||||
ELSE 'false'
|
||||
END , 'false' ) || ',
|
||||
hideDarkModeToggle: ' || COALESCE (
|
||||
CASE
|
||||
WHEN P_HIDEDARKMODETOGGLE = 1 THEN 'true'
|
||||
ELSE 'false'
|
||||
END , 'false' ) || ',
|
||||
hideTestRequestButton: ' || COALESCE (
|
||||
CASE
|
||||
WHEN P_HIDETESTREQUESTBUTTON = 1 THEN 'true'
|
||||
WHEN P_HIDETESTREQUESTBUTTON = 0 THEN 'false'
|
||||
ELSE NULL
|
||||
END , 'undefined' ) || ',
|
||||
hideModels: ' || COALESCE (
|
||||
CASE
|
||||
WHEN P_HIDEMODELS = 1 THEN 'true'
|
||||
ELSE 'false'
|
||||
END , 'false' ) || ',
|
||||
showOperationId: ' || COALESCE (
|
||||
CASE
|
||||
WHEN P_SHOWOPERATIONID = 1 THEN 'true'
|
||||
ELSE 'false'
|
||||
END , 'false' ) || ',
|
||||
expandAllResponses: ' || COALESCE (
|
||||
CASE
|
||||
WHEN P_EXPANDALLRESPONSES = 1 THEN 'true'
|
||||
WHEN P_EXPANDALLRESPONSES = 0 THEN 'false'
|
||||
ELSE NULL
|
||||
END , 'undefined' ) || ',
|
||||
expandAllModelSections: ' || COALESCE(
|
||||
CASE
|
||||
WHEN P_EXPANDALLMODELSECTIONS = 1 THEN 'true'
|
||||
WHEN P_EXPANDALLMODELSECTIONS = 0 THEN 'false'
|
||||
ELSE NULL
|
||||
END , 'undefined' ) || ',
|
||||
defaultOpenAllTags: ' || COALESCE (
|
||||
CASE
|
||||
WHEN P_DEFAULTOPENALLTAGS = 1 THEN 'true'
|
||||
WHEN P_DEFAULTOPENALLTAGS = 0 THEN 'false'
|
||||
ELSE NULL
|
||||
END , 'undefined' ) || ',
|
||||
showDeveloperTools: ' ||
|
||||
COALESCE ( '''' || P_SHOWDEVELOPERTOOLS || '''' , '''always''' ) ||
|
||||
',
|
||||
operationTitleSource: ' ||
|
||||
COALESCE ( '''' || P_OPERATIONTITLESOURCE || '''' , 'undefined' ) ||
|
||||
',
|
||||
orderRequiredPropertiesFirst: ' || COALESCE (
|
||||
CASE
|
||||
WHEN P_ORDERREQUIREDPROPERTIESFIRST = 1 THEN 'true'
|
||||
WHEN P_ORDERREQUIREDPROPERTIESFIRST = 0 THEN 'false'
|
||||
ELSE NULL
|
||||
END , 'undefined' ) || ',
|
||||
orderSchemaPropertiesBy: ' ||
|
||||
COALESCE ( '''' || P_ORDERSCHEMAPROPERTIESBY || '''' , 'undefined' )
|
||||
|| ',
|
||||
pathRouting: ' || COALESCE ( P_PATHROUTING , 'undefined' )||
|
||||
',
|
||||
persistAuth: ' || COALESCE (
|
||||
CASE
|
||||
WHEN P_PERSISTAUTH = 1 THEN 'true'
|
||||
WHEN P_PERSISTAUTH = 0 THEN 'false'
|
||||
ELSE NULL
|
||||
END , 'undefined' ) || ',
|
||||
searchHotKey: ' ||
|
||||
COALESCE ( '''' || P_SEARCHHOTKEY || '''' , 'undefined' ) || ',
|
||||
defaultHttpClient: ' ||
|
||||
COALESCE ( P_DEFAULTHTTPCLIENT , 'undefined' ) || ',
|
||||
tagsSorter:' ||
|
||||
COALESCE ( '''' || P_TAGSSORTER || '''' , 'undefined' ) || ',
|
||||
operationsSorter: ' ||
|
||||
COALESCE ( '''' || P_OPERATIONSSORTER || '''' , 'undefined' ) || ',
|
||||
fetch: ' || COALESCE ( P_FETCH , 'undefined' ) || ',
|
||||
proxyUrl: ' ||
|
||||
COALESCE ( '''' || P_PROXYURL || '''' , 'undefined' ) || ',
|
||||
servers: ' || COALESCE ( P_SERVERS , 'undefined' ) || ',
|
||||
hiddenClients: ' || COALESCE ( P_HIDDENCLIENTS , 'undefined' )
|
||||
|| ',
|
||||
onBeforeRequest: ' ||
|
||||
COALESCE ( P_ONBEFOREREQUEST , 'undefined' ) || ',
|
||||
onRequestSent: ' || COALESCE ( P_ONREQUESTSENT , 'undefined' )
|
||||
|| ',
|
||||
onShowMore: ' || COALESCE ( P_ONSHOWMORE , 'undefined' ) || ',
|
||||
onLoaded: ' || COALESCE ( P_ONLOADED , 'undefined' ) || ',
|
||||
onSpecUpdate: ' || COALESCE ( P_ONSPECUPDATE , 'undefined' ) ||',
|
||||
onDocumentSelect: ' ||
|
||||
COALESCE ( P_ONDOCUMENTSELECT , 'undefined' ) || ',
|
||||
onServerChange: ' ||
|
||||
COALESCE ( P_ONSERVERCHANGE , 'undefined' ) || ',
|
||||
onSidebarClick: ' ||
|
||||
COALESCE ( P_ONSIDEBARCLICK , 'undefined' ) || ',
|
||||
metaData: ' ||COALESCE ( P_METADATA , 'undefined' ) || ',
|
||||
plugins: ' || COALESCE ( P_PLUGINS , 'undefined' ) || ',
|
||||
redirect: ' ||
|
||||
COALESCE ( '''' || P_REDIRECT || '''' , 'undefined' ) || ',
|
||||
telemetry: ' || COALESCE (
|
||||
CASE
|
||||
WHEN P_TELEMETRY = 1 THEN 'true'
|
||||
WHEN P_TELEMETRY = 0 THEN 'false'
|
||||
ELSE NULL
|
||||
END , 'undefined' ) || ',
|
||||
generateHeadingSlug: ' ||
|
||||
COALESCE ( P_GENERATEHEADINGSLUG , 'undefined' ) || ',
|
||||
generateOperationSlug: ' ||
|
||||
COALESCE ( P_GENERATEOPERATIONSLUG , 'undefined' ) || ',
|
||||
generateTagSlug: ' ||
|
||||
COALESCE ( P_GENERATETAGSLUG , 'undefined' ) || ',
|
||||
generateWebhookSlug: ' ||
|
||||
COALESCE ( P_GENERATEWEBHOOKSLUG , 'undefined' ) || ',
|
||||
generateModelSlug: ' ||
|
||||
COALESCE ( P_GENERATEMODELSLUG , 'undefined' ) || ',
|
||||
isLoading:' || COALESCE (
|
||||
CASE
|
||||
WHEN P_ISLOADING = 1 THEN 'true'
|
||||
WHEN P_ISLOADING = 0 THEN 'false'
|
||||
ELSE NULL
|
||||
END , 'undefined' ) || '
|
||||
};
|
||||
function getQueryParameter(paramName) {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const normalizedName = paramName.toLowerCase();
|
||||
for (const [key, value] of params) {
|
||||
if (key.toLowerCase() === normalizedName) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function isValidUrl(input) {
|
||||
try {
|
||||
const url = new URL(input);
|
||||
const isHttpProtocol = url.protocol ==="http:" || url.protocol === "https:";
|
||||
const isNotProtocolRelative = !input.startsWith("//");
|
||||
return isHttpProtocol && isNotProtocolRelative;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function parseOpenApiContent(input) {
|
||||
const trimmedInput = input.trim();
|
||||
if (trimmedInput.startsWith("{") || trimmedInput.startsWith("[")) {
|
||||
return JSON.parse(trimmedInput);
|
||||
}
|
||||
returntrimmedInput;
|
||||
}
|
||||
function hasValue(value) {
|
||||
return value !== null && value !== undefined && value !== "";
|
||||
}
|
||||
const sqlParameters = {
|
||||
url: "",
|
||||
content: null,
|
||||
sources: null,
|
||||
baseServerURL: null
|
||||
};
|
||||
function determineInitialConfiguration() {
|
||||
const config = {};
|
||||
let showModal = false;
|
||||
const specUrlParam = getQueryParameter("specUrl");
|
||||
if (hasValue(specUrlParam)) {
|
||||
config.url = specUrlParam;
|
||||
return { config, showModal };
|
||||
}
|
||||
if (hasValue(sqlParameters.url)) {
|
||||
config.url = sqlParameters.url;
|
||||
return { config, showModal };
|
||||
}
|
||||
if(hasValue(sqlParameters.content) || hasValue(sqlParameters.sources)) {
|
||||
if (hasValue(sqlParameters.content)) {
|
||||
config.content = sqlParameters.content;
|
||||
}
|
||||
if(hasValue(sqlParameters.sources)) {
|
||||
config.sources = sqlParameters.sources;
|
||||
}
|
||||
return { config, showModal };
|
||||
}
|
||||
config.content = WELCOME_SPEC;
|
||||
showModal = true;
|
||||
return { config, showModal };
|
||||
}
|
||||
const ScalarManager = {
|
||||
instance: null,
|
||||
isInitialized: false,
|
||||
render(userConfig = {}) {
|
||||
const finalConfig = { ...userConfig };
|
||||
if(hasValue(sqlParameters.baseServerURL)) {
|
||||
finalConfig.baseServerURL = sqlParameters.baseServerURL;
|
||||
}
|
||||
if (this.instance) {
|
||||
const appElement = document.querySelector(ELEMENTS.app);
|
||||
if (appElement) {
|
||||
appElement.innerHTML = "";
|
||||
}
|
||||
}
|
||||
this.instance = Scalar.createApiReference(ELEMENTS.app, {
|
||||
...DEFAULT_SCALAR_CONFIG,
|
||||
...finalConfig
|
||||
});
|
||||
console.log("Scalar API Reference initialized");
|
||||
},
|
||||
canInitialize() {
|
||||
const isScalarLoaded = typeof Scalar !== "undefined";
|
||||
const isDomReady = document.readyState !== "loading";
|
||||
if (!isScalarLoaded) {
|
||||
console.log("Waiting for Scalar library...");
|
||||
}
|
||||
if (!isDomReady) {
|
||||
console.log("Waiting for DOM...");
|
||||
}
|
||||
return isScalarLoaded && isDomReady;
|
||||
},
|
||||
initialize() {
|
||||
if (this.isInitialized){
|
||||
return;
|
||||
}
|
||||
if (!this.canInitialize()) {
|
||||
return;
|
||||
}
|
||||
this.isInitialized = true;
|
||||
console.log("Initializing Scalar application...");
|
||||
const { config, showModal } = determineInitialConfiguration();
|
||||
if (showModal) {
|
||||
ModalManager.show();
|
||||
} else {
|
||||
ModalManager.hide();
|
||||
}
|
||||
this.render(config);
|
||||
}
|
||||
};
|
||||
const ModalManager = {
|
||||
elements: {},
|
||||
initialize() {
|
||||
this.elements = {
|
||||
modal: document.getElementById("modal-overlay"),
|
||||
input: document.getElementById("api-input"),
|
||||
placeholder: document.getElementById("input-placeholder"),
|
||||
cancelBtn: document.getElementById("cancel-btn"),
|
||||
continueBtn: document.getElementById("continue-btn")
|
||||
};
|
||||
this.attachEventListeners();
|
||||
},
|
||||
attachEventListeners() {
|
||||
this.elements.input.addEventListener("input", () => {
|
||||
this.updatePlaceholder();
|
||||
});
|
||||
this.elements.cancelBtn.addEventListener("click", () => {
|
||||
this.hide();
|
||||
});
|
||||
this.elements.continueBtn.addEventListener("click", () => {
|
||||
this.handleContinue();
|
||||
});
|
||||
},
|
||||
updatePlaceholder() {
|
||||
const hasInput = this.elements.input.value.length > 0;
|
||||
this.elements.placeholder.style.display = hasInput ? "none" : "block";
|
||||
},
|
||||
show() {
|
||||
this.elements.modal.style.display = "flex";
|
||||
const appElement = document.querySelector(ELEMENTS.app);
|
||||
if (appElement) {
|
||||
appElement.classList.add("modal-blur");
|
||||
}
|
||||
},
|
||||
hide() {
|
||||
this.elements.modal.style.display = "none";
|
||||
const appElement = document.querySelector(ELEMENTS.app);
|
||||
if (appElement) {
|
||||
appElement.classList.remove("modal-blur");
|
||||
}
|
||||
},
|
||||
handleContinue() {
|
||||
const userInput = this.elements.input.value.trim();
|
||||
if (!userInput) {
|
||||
alert("Please enter an OpenAPI document or URL");
|
||||
return;
|
||||
}
|
||||
if (isValidUrl(userInput)) {
|
||||
this.loadFromUrl(userInput);
|
||||
return;
|
||||
}
|
||||
this.loadFromContent(userInput);
|
||||
},
|
||||
loadFromUrl(url) {
|
||||
ScalarManager.render({ url });
|
||||
this.hide();
|
||||
},
|
||||
loadFromContent(contentString) {
|
||||
try {
|
||||
const content = parseOpenApiContent(contentString);
|
||||
ScalarManager.render({ content });
|
||||
this.hide();
|
||||
} catch (error) {
|
||||
alert("Error parsing content: " + error.message);
|
||||
}
|
||||
}
|
||||
};
|
||||
const InitializationCoordinator = {
|
||||
state: {
|
||||
domReady: false,
|
||||
scalarLibraryReady: false
|
||||
},
|
||||
tryInitialize() {
|
||||
if(this.state.domReady && this.state.scalarLibraryReady) {
|
||||
ScalarManager.initialize();
|
||||
}
|
||||
},
|
||||
markDomReady() {
|
||||
this.state.domReady = true;
|
||||
this.tryInitialize();
|
||||
},
|
||||
markScalarReady() {
|
||||
this.state.scalarLibraryReady = true;
|
||||
this.tryInitialize();
|
||||
},
|
||||
setup() {
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
this.markDomReady();
|
||||
});
|
||||
window.onScalarLibraryLoaded = () => {
|
||||
this.markScalarReady();
|
||||
};
|
||||
}
|
||||
};
|
||||
ModalManager.initialize();
|
||||
InitializationCoordinator.setup();
|
||||
})();
|
||||
</script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference/dist/browser/standalone.min.js"
|
||||
onload="window.onScalarLibraryLoaded();"></script>
|
||||
|
||||
</body>
|
||||
</html>' ) ;
|
||||
END ;
|
||||
|
||||
GRANT ALTER , EXECUTE
|
||||
ON SPECIFIC FUNCTION RESTAPI.MISC_SERVE_SCALAR_UI
|
||||
TO AMAPICS WITH GRANT OPTION ;
|
||||
|
||||
GRANT EXECUTE
|
||||
ON SPECIFIC FUNCTION RESTAPI.MISC_SERVE_SCALAR_UI
|
||||
TO PUBLIC ;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user