// ==UserScript== // @name Oracle APEX Shared Components Menu // @run-at document-idle // @namespace https://github.com/lufcmattylad // @version 26.1.1 // @description Converts the Shared Components button in the APEX 26.1 builder toolbar into a drop-down menu with direct links to every Shared Components section. // @author Matt Mulvaney - @Matt_Mulvaney // @match *://*/ords/* // @match *://*/pls/* // @tag orclapex // @grant none // @downloadURL https://raw.githubusercontent.com/lufcmattylad/oracle-apex-userscripts/refs/heads/main/scripts/oracle-apex-shared-components-menu/script.js // ==/UserScript== (function () { 'use strict'; /** * DISCLAIMER: * This code is unofficial and is not supported by Oracle APEX. * It is provided "as is" without warranty of any kind, either express or implied. * Use of this code is at your own risk. The authors and distributors accept no responsibility * for any consequences arising from its use. */ function isApexBuilderValid() { if (typeof apex === 'undefined') return false; const appId = parseInt(apex.env.APP_ID, 10); if (appId < 3000 || appId > 8999) return false; const version = apex.env.APEX_VERSION || ''; const major = parseInt(version.split('.')[0], 10); const minor = parseInt(version.split('.')[1], 10); return major > 26 || (major === 26 && minor >= 1); } const MENU_ID = 'apex-scm-menu'; function buildUrl(path, params) { const base = location.origin + '/ords/r/apex/app-builder/' + path; return base + '?' + (params ? params + '&' : '') + 'session=' + encodeURIComponent(apex.env.APP_SESSION); } // Attempt to discover the ID of the application being edited in Page Designer. // Used for the two app-scoped pages (Security Attributes, Globalization Attributes). function getEditedFlowId() { if (typeof gFlowId !== 'undefined' && gFlowId) return String(gFlowId); const params = new URLSearchParams(location.search); const fromParams = params.get('fb_flow_id') || params.get('app_id'); if (fromParams) return fromParams; const el = document.querySelector('input[name="pFlowId"]'); if (el && el.value) return el.value; return ''; } function buildMenuItems() { const fid = getEditedFlowId(); const fidPfx = fid ? 'fb_flow_id=' + fid + '&' : ''; return [ { type: 'action', label: 'Open Shared Components', href: buildUrl('shared-components'), icon: 'icon-shared-components' }, { type: 'separator' }, { type: 'action', label: 'Application Logic', disabled: true, icon: 'icon-sc-logic' }, { type: 'action', label: 'Application Definition', href: buildUrl('edit-application-definition') }, { type: 'action', label: 'Application Items', href: buildUrl('application-items') }, { type: 'action', label: 'Application Processes', href: buildUrl('application-processes') }, { type: 'action', label: 'Application Computations', href: buildUrl('application-computations') }, { type: 'action', label: 'Application Settings', href: buildUrl('application-settings') }, { type: 'action', label: 'Build Options', href: buildUrl('build-options') }, { type: 'separator' }, { type: 'action', label: 'Security', disabled: true, icon: 'icon-util-security-profiles' }, { type: 'action', label: 'Security Attributes', href: buildUrl('edit-security-attributes', fidPfx + (fid ? '509_fb_upd_id=' + fid + '&' : '') + 'clear=509') }, { type: 'action', label: 'Authentication Schemes', href: buildUrl('authentication-schemes') }, { type: 'action', label: 'Authorization Schemes', href: buildUrl('authorization-schemes') }, { type: 'action', label: 'Application Access Control', href: buildUrl('application-access-control', 'clear=RP,2300') }, { type: 'action', label: 'Session State Protection', href: buildUrl('session-state-protection') }, { type: 'separator' }, { type: 'action', label: 'Other Components', disabled: true, icon: 'icon-util-shared-components' }, { type: 'action', label: 'Lists of Values', href: buildUrl('lists-of-values') }, { type: 'action', label: 'Plug-ins', href: buildUrl('plug-ins', 'clear=RP') }, { type: 'action', label: 'Component Settings', href: buildUrl('component-settings', 'clear=RP') }, { type: 'action', label: 'Shortcuts', href: buildUrl('shortcuts') }, { type: 'action', label: 'Component Groups', href: buildUrl('component-groups') }, { type: 'action', label: 'Data Load Definitions', href: buildUrl('data-load-definitions') }, { type: 'separator' }, { type: 'action', label: 'Navigation and Search', disabled: true, icon: 'icon-sc-nav' }, { type: 'action', label: 'Lists', href: buildUrl('lists', 'clear=RIR') }, { type: 'action', label: 'Navigation Menu', href: buildUrl('lists', 'ir_is_navmenu=1&clear=RIR') }, { type: 'action', label: 'Breadcrumbs', href: buildUrl('breadcrumbs') }, { type: 'action', label: 'Navigation Bar List', href: buildUrl('lists', 'ir_is_navbar=1&clear=RIR') }, { type: 'action', label: 'Search Configurations', href: buildUrl('search-configuration') }, { type: 'separator' }, { type: 'action', label: 'User Interface', disabled: true, icon: 'icon-sc-ui' }, { type: 'action', label: 'User Interface Attributes', href: buildUrl('edit-user-interface') }, { type: 'action', label: 'Progressive Web App', href: buildUrl('edit-progressive-web-app') }, { type: 'action', label: 'Themes', href: buildUrl('themes') }, { type: 'action', label: 'Templates', href: buildUrl('templates') }, { type: 'action', label: 'Email Templates', href: buildUrl('email-templates') }, { type: 'action', label: 'Map Backgrounds', href: buildUrl('map-backgrounds') }, { type: 'separator' }, { type: 'action', label: 'Files and Reports', disabled: true, icon: 'icon-sc-files' }, { type: 'action', label: 'Static Application Files', href: buildUrl('static-application-files') }, { type: 'action', label: 'Static Workspace Files', href: buildUrl('static-workspace-files', 'clear=RP') }, { type: 'action', label: 'Report Layouts', href: buildUrl('report-layouts') }, { type: 'action', label: 'Report Queries', href: buildUrl('report-queries') }, { type: 'separator' }, { type: 'action', label: 'Data Sources', disabled: true, icon: 'icon-util-webservice' }, { type: 'action', label: 'REST Data Sources', href: buildUrl('rest-data-sources') }, { type: 'action', label: 'JSON Duality Views', href: buildUrl('document-sources', 'p7100_source_type=DUALITY_VIEW&clear=7100') }, { type: 'action', label: 'JSON Sources', href: buildUrl('document-sources', 'p7100_source_type=JSON_TABLE&clear=7100') }, { type: 'separator' }, { type: 'action', label: 'Workflows and Automations', disabled: true, icon: 'icon-sc-tree' }, { type: 'action', label: 'Task Definitions', href: buildUrl('task-definitions') }, { type: 'action', label: 'Automations', href: buildUrl('automations') }, { type: 'action', label: 'Workflows', href: buildUrl('workflows') }, { type: 'separator' }, { type: 'action', label: 'Globalization', disabled: true, icon: 'icon-sc-globalization' }, { type: 'action', label: 'Globalization Attributes', href: buildUrl('edit-globalization-attributes', fidPfx + 'clear=506') }, { type: 'action', label: 'Text Messages', href: buildUrl('text-messages') }, { type: 'action', label: 'Application Translations', href: buildUrl('translate-application') }, { type: 'separator' }, { type: 'action', label: 'Generative AI', disabled: true, icon: 'icon-sc-ai' }, { type: 'action', label: 'AI Attributes', href: buildUrl('edit-ai') }, { type: 'action', label: 'AI Agents', href: buildUrl('gen-ai-agents') }, { type: 'action', label: 'AI Services', href: buildUrl('generative-ai-services') }, ]; } function ensureMenu($) { let $menu = $('#' + MENU_ID); if ($menu.length && $menu.data('apex-menu')) return $menu; if ($menu.length) $menu.remove(); $menu = $('