"use strict"; exports.id = 4941; exports.ids = [4941]; exports.modules = { /***/ 9230: /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "Z": () => (/* binding */ CopySlug) /* harmony export */ }); /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(997); /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6689); /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _mui_icons_material_CopyAllTwoTone__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5050); /* harmony import */ var _mui_icons_material_CopyAllTwoTone__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_mui_icons_material_CopyAllTwoTone__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var lucide_react__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2423); /* harmony import */ var lucide_react__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(lucide_react__WEBPACK_IMPORTED_MODULE_3__); // @ts-check /** * Imports * ============================================================================== */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** * Main Component { Functional } * ============================================================================== * @param {{ * slugText: string, * justIcon?: boolean, * title?: string, * outlined?: boolean, * }} props - React component props including { children } */ function CopySlug({ slugText , justIcon , title , outlined }) { return /*#__PURE__*/ (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("div", { className: "button small-text" + (outlined ? " outlined gray bg-white" : " ghost light-gray"), onClick: (e)=>{ navigator.clipboard.writeText(slugText).then(()=>{ alert(`Copied: "${slugText}"`); }); }, style: outlined ? undefined : { padding: 0 }, children: [ /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx(lucide_react__WEBPACK_IMPORTED_MODULE_3__.Copy, { size: outlined ? 15 : 20 }), !justIcon && /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("span", { className: "text-slate-500 dark:text-slate-300", children: title ? title : "Copy Slug" }) ] }); } /***/ }), /***/ 4941: /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "Z": () => (/* binding */ ExtraContentDatabase) /* harmony export */ }); /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(997); /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6689); /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _CopySlug__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9230); /* harmony import */ var _mui_icons_material_CodeRounded__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3849); /* harmony import */ var _mui_icons_material_CodeRounded__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_mui_icons_material_CodeRounded__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _DiskUsageComponent__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6355); /* harmony import */ var _functions_frontend_downloadApiStream__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(7851); /* harmony import */ var _mui_icons_material_SendToMobileTwoTone__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(6500); /* harmony import */ var _mui_icons_material_SendToMobileTwoTone__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_mui_icons_material_SendToMobileTwoTone__WEBPACK_IMPORTED_MODULE_5__); /* harmony import */ var _mui_icons_material_SummarizeTwoTone__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(7428); /* harmony import */ var _mui_icons_material_SummarizeTwoTone__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_mui_icons_material_SummarizeTwoTone__WEBPACK_IMPORTED_MODULE_6__); /* harmony import */ var _mui_icons_material_TipsAndUpdatesTwoTone__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(507); /* harmony import */ var _mui_icons_material_TipsAndUpdatesTwoTone__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(_mui_icons_material_TipsAndUpdatesTwoTone__WEBPACK_IMPORTED_MODULE_7__); /* harmony import */ var _functions_frontend_fetchApi__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(6729); /* harmony import */ var _LoadingBlock__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(5264); /* harmony import */ var lucide_react__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(2423); /* harmony import */ var lucide_react__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(lucide_react__WEBPACK_IMPORTED_MODULE_9__); // @ts-check /** * ============================================================================== * Imports * ============================================================================== */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** * ============================================================================== * Main Component { Functional } * ============================================================================== * @param {Object} props - Server props * @param {import("@/package-shared/types").DSQL_MYSQL_user_databases_Type} props.database * @param {any} [props.query] * @param {any} [props.confirmedDelegetedUser] * @param {import("@/package-shared/types").UserType} props.user */ function ExtraContentDatabase({ database , query , confirmedDelegetedUser , user , }) { /** * Get Contexts * * @abstract { React.useContext } */ //////////////////////////////////////// //////////////////////////////////////// //////////////////////////////////////// /** * Javascript Variables * * @abstract Non hook variables and functions */ const { active_clone , active_clone_parent_db } = database; const isDelegated = confirmedDelegetedUser?.delegated; const isTableEditable = confirmedDelegetedUser?.priviledges?.match(/Edit Tables/i); const isTableDeletable = confirmedDelegetedUser?.priviledges?.match(/Delete Tables/i); //////////////////////////////////////// //////////////////////////////////////// //////////////////////////////////////// /** * React Hooks * * @abstract { useState, useEffect, useRef, etc ... } */ const [links, setLinks] = react__WEBPACK_IMPORTED_MODULE_1___default().useState(null); //////////////////////////////////////// //////////////////////////////////////// //////////////////////////////////////// /** * Function Return * * @abstract Main Function Return */ return /*#__PURE__*/ (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("div", { className: "flex-wrap justify-center gap-4", children: [ /*#__PURE__*/ (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("div", { className: "dropdown-wrapper gap-4", children: [ /*#__PURE__*/ (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("div", { className: "relative", children: [ /*#__PURE__*/ (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("div", { className: "w-8 h-8 relative", children: [ /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("img", { src: database.db_image, alt: "Database Image", width: 20, className: "w-full h-full rounded-full object-cover" }), confirmedDelegetedUser?.delegated && /*#__PURE__*/ (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("div", { className: " absolute -bottom-2 left-5 gap-1", children: [ /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("img", { src: confirmedDelegetedUser.rootUserImage, alt: "Root User Image", className: "w-5 h-5 rounded-full object-cover border-2 border-white dark:border-slate-800 border-solid" }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("span", { className: "text-xs", children: confirmedDelegetedUser.rootUserEmail }) ] }) ] }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("span", { className: "font-semibold text-base" + (confirmedDelegetedUser?.delegated ? " -mt-3" : ""), children: database.db_name }) ] }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx(lucide_react__WEBPACK_IMPORTED_MODULE_9__.ChevronDown, { size: 20 }), /*#__PURE__*/ (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("div", { className: "dropdown p-0", children: [ /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("hr", { className: "m-0" }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("a", { href: `/admin/${user?.id}/databases/${database.db_slug}/edit-database`, className: "button plain-text more-padding normal-weight", children: "Edit Database" }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("hr", { className: "m-0" }), !active_clone && /*#__PURE__*/ (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)((react__WEBPACK_IMPORTED_MODULE_1___default().Fragment), { children: [ /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("a", { href: `/admin/${user?.id}/databases/add-database?duplicate=${database.db_full_name}`, className: "button plain-text more-padding normal-weight", children: "Duplicate Database" }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("hr", { className: "m-0" }) ] }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("a", { href: `/admin/${user?.id}/databases/${database.db_slug}/schema`, className: "button plain-text more-padding normal-weight", children: "Schema" }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("hr", { className: "m-0" }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("a", { href: `/admin/${user?.id}/databases/${database.db_slug}/users`, className: "button plain-text more-padding normal-weight", children: "Database Users" }), !isDelegated && /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx(NonDelegatedSection, { database: database, user: user }) ] }) ] }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("hr", { className: "vertical" }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx(_CopySlug__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z, { slugText: database.db_slug, title: `Copy Database Slug` }), !isDelegated && /*#__PURE__*/ (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)((react__WEBPACK_IMPORTED_MODULE_1___default().Fragment), { children: [ /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("hr", { className: "vertical" }), /*#__PURE__*/ (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("a", { href: `/admin/${user?.id}/databases/${database.db_slug}/shell`, className: "button ghost small-text", style: { height: "30px", padding: 0 }, children: [ /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx(lucide_react__WEBPACK_IMPORTED_MODULE_9__.SquareTerminal, { size: 20 }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("span", { className: "text-sm font-semibold", children: "Shell" }) ] }) ] }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("hr", { className: "vertical" }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx(_DiskUsageComponent__WEBPACK_IMPORTED_MODULE_4__/* ["default"] */ .Z, {}) ] }); //////////////////////////////////////// //////////////////////////////////////// //////////////////////////////////////// } /** ****************************************************************************** */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** * ## Buttons for Database Root Owner * @param {object} props * @param {import("@/package-shared/types").DSQL_MYSQL_user_databases_Type} props.database * @param {import("@/package-shared/types").UserType} props.user */ function NonDelegatedSection({ database , user }) { const [loading, setLoading] = react__WEBPACK_IMPORTED_MODULE_1___default().useState(false); /** @type {React.RefObject} */ // @ts-ignore const uploadSchemaButtonRef = react__WEBPACK_IMPORTED_MODULE_1___default().useRef(); return /*#__PURE__*/ (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)((react__WEBPACK_IMPORTED_MODULE_1___default().Fragment), { children: [ loading && /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx(_LoadingBlock__WEBPACK_IMPORTED_MODULE_8__/* ["default"] */ .Z, { width: "20px" }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("hr", { className: "m-0" }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("a", { href: `/admin/${user?.id}/databases/${database.db_slug}/shell`, className: "button plain-text more-padding normal-weight", children: "Shell" }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("hr", { className: "m-0" }), database?.remote_connected == 1 ? /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx(DisconnectButton, { database: database }) : /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("a", { href: `/admin/${user?.id}/databases/${database.db_slug}/connect`, className: "button plain-text more-padding normal-weight", children: "Connect" }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("hr", { className: "m-0" }), /*#__PURE__*/ (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("button", { className: "button plain-text more-padding normal-weight w-full", onClick: (e)=>{ (0,_functions_frontend_downloadApiStream__WEBPACK_IMPORTED_MODULE_10__/* ["default"] */ .Z)({ url: `/api/exportDatabase?dbName=${database.db_full_name}`, fileName: `${database.db_full_name}.sql` }); }, children: [ /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx((_mui_icons_material_SendToMobileTwoTone__WEBPACK_IMPORTED_MODULE_5___default()), { fontSize: "small", color: "action", className: "opacity-50" }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("span", { children: "Export Database" }) ] }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("input", { type: "file", name: "upload-update-schema", id: "", ref: uploadSchemaButtonRef, className: "hidden" }), /*#__PURE__*/ (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("button", { className: "button green outlined more-padding normal-weight w-full rounded-none -mb-[1px]", onClick: (e)=>{ if (!uploadSchemaButtonRef.current) return; uploadSchemaButtonRef.current.addEventListener("change", (e)=>{ /** * @type {HTMLInputElement} */ // @ts-ignore const inputEl = e.target; const file = inputEl.files?.[0]; if (!file) { alert("No File Selected"); return; } var reader = new FileReader(); reader.onload = function(ev) { var fileContent = ev.target?.result; if (!fileContent) { alert("Invalid File!"); } try { const fileContentString = fileContent?.toString(); if (!fileContentString) { throw new Error("Invalid File!"); } const schemaObject = JSON.parse(fileContentString); if (window.confirm("Are you sure you want to use this schema file for the current database?")) { if (window.confirm("Remember if any existing table doesn't exist in the new schema file that table and all its content will be erased forever. Continue?")) { setLoading(true); (0,_functions_frontend_fetchApi__WEBPACK_IMPORTED_MODULE_11__/* ["default"] */ .Z)("/api/user-schema/replace-database-schema", { method: "POST", body: { schema: schemaObject, dbId: database.id } }, true).then((res)=>{ if (res.success) { window.location.reload(); } }).finally(()=>{ setLoading(false); }); } } } catch (/** @type {any} */ error) { alert("Invalid File. Please enter a valid JSON file"); } }; reader.readAsText(file); // if (window.confirm("Update?")) { // console.log("Updating"); // } }); uploadSchemaButtonRef.current?.click(); }, children: [ /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx((_mui_icons_material_TipsAndUpdatesTwoTone__WEBPACK_IMPORTED_MODULE_7___default()), { fontSize: "small", color: "action", className: "opacity-50 text-inherit" }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("span", { children: "Update From Schema" }) ] }), /*#__PURE__*/ (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("button", { className: "button secondary outlined more-padding normal-weight w-full rounded-none", onClick: (e)=>{ (0,_functions_frontend_downloadApiStream__WEBPACK_IMPORTED_MODULE_10__/* ["default"] */ .Z)({ url: `/api/downloadDatabaseSchema?dbName=${database.db_full_name}`, fileName: `${database.db_full_name}.json` }); // fetchApi(`/api/downloadDatabaseSchema?dbName=${database.db_full_name}`).then((res)=>{ // console.log(res); // }) }, children: [ /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx((_mui_icons_material_SummarizeTwoTone__WEBPACK_IMPORTED_MODULE_6___default()), { fontSize: "small", color: "action", className: "opacity-50 text-inherit" }), /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("span", { children: "Download Schema" }) ] }) ] }); } /** ****************************************************************************** */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** * ### Disconnect Remote Db Button * @param {object} props * @param {import("@/package-shared/types").DSQL_MYSQL_user_databases_Type} props.database */ function DisconnectButton({ database }) { return /*#__PURE__*/ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx("button", { className: "button plain-text more-padding normal-weight w-full", onClick: (e)=>{ if (!window.confirm("Disconnect this Database from the remote host?")) return; (0,_functions_frontend_fetchApi__WEBPACK_IMPORTED_MODULE_11__/* ["default"] */ .Z)(`/api/connect/disconnect`, { method: "POST", body: { dbId: database.id } }, true).then((res)=>{ if (res.success) { window.location.reload(); } else { console.log(res); alert(res.msg || "Remote disconnection failed. Please try again."); } }); }, children: "Disconnect" }); } /***/ }), /***/ 7851: /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "Z": () => (/* binding */ downloadApiStream) /* harmony export */ }); // @ts-check /** * ============================================================================== * Imports * ============================================================================== */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** ****************************************************************************** */ /** * ============================================================================== * Auth user on client side * ============================================================================== * @param {{ * url: string, * fileName: string, * setLoading?: React.Dispatch>, * }} params - params * * @requires search-field name attribute */ function downloadApiStream({ url , fileName , setLoading }) { /** * Check for user in local storage * * @description Preventdefault, declare variables */ if (setLoading) setLoading(true); fetch(url, { method: "GET", // @ts-ignore headers: { "x-csrf-auth": localStorage.getItem("csrf") } }).then((res)=>{ return res.body; }).then((body)=>{ const reader = body?.getReader(); if (reader) { return new ReadableStream({ start (controller) { return pump(); /** @type {() => any} */ function pump() { return reader?.read().then(({ done , value })=>{ // When no more data needs to be consumed, close the stream if (done) { controller.close(); return; } // Enqueue the next data chunk into our target stream controller.enqueue(value); return pump(); }); } } }); } // console.log(body); // const blob = new Blob([body.text], { type: "application/pdf" }); // const url = URL.createObjectURL(blob); // const link = document.createElement("a"); // link.href = blob; // link.download = `${database.db_full_name}.sql`; // link.style.display = "none"; // document.body.appendChild(link); // link.click(); // URL.revokeObjectURL(url); // document.body.removeChild(link); // setTimeout(() => { // setLoading(false); // }, 1000); }).then((stream)=>{ return new Response(stream); }).then((response)=>response.blob()).then((blob)=>URL.createObjectURL(blob)).then((url)=>{ const link = document.createElement("a"); link.href = url; link.download = fileName; link.style.display = "none"; document.body.appendChild(link); link.click(); URL.revokeObjectURL(url); document.body.removeChild(link); setTimeout(()=>{ if (setLoading) setLoading(false); }, 1000); }).catch((error)=>{ console.log(error); setTimeout(()=>{ if (setLoading) setLoading(false); }, 1000); }); } //////////////////////////////////////// //////////////////////////////////////// //////////////////////////////////////// /***/ }) }; ;