@steedos/service-core-objects 3.0.14-beta.9 → 3.0.15-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -87,6 +87,17 @@ fields:
87
87
  label: Enable Tree
88
88
  help:
89
89
  description: Enable a tree structure to display records
90
+ tree_expand:
91
+ label: Tree Default Expand
92
+ help:
93
+ options:
94
+ - label: First node only
95
+ value: first
96
+ - label: Expand all
97
+ value: all
98
+ - label: Collapse all
99
+ value: none
100
+ description: Default expansion behavior of the tree list. Defaults to expanding the first node; can be set to expand all nodes or collapse all.
90
101
  enable_enhanced_lookup:
91
102
  label: Enable Enhanced Lookup
92
103
  help:
@@ -91,6 +91,17 @@ fields:
91
91
  label: 树状结构显示
92
92
  help:
93
93
  description: 以树状格式呈现数据层级结构,方便查看记录的父子关系。
94
+ tree_expand:
95
+ label: 树列表默认展开
96
+ help:
97
+ options:
98
+ - label: 仅展开首个节点
99
+ value: first
100
+ - label: 全部展开
101
+ value: all
102
+ - label: 全部收起
103
+ value: none
104
+ description: 配置开启树状结构显示后,列表加载时的默认展开行为。默认展开第一个节点;可选择默认展开全部节点或全部收起。
94
105
  enable_enhanced_lookup:
95
106
  label: 弹出窗口查找
96
107
  help:
@@ -220,6 +220,22 @@ fields:
220
220
  label: Enable Tree
221
221
  sort_no: 200
222
222
  type: boolean
223
+ tree_expand:
224
+ name: tree_expand
225
+ group: advanced
226
+ hidden: false
227
+ label: Tree Default Expand
228
+ sort_no: 205
229
+ type: select
230
+ defaultValue: first
231
+ options:
232
+ - label: Expand First
233
+ value: first
234
+ - label: Expand All
235
+ value: all
236
+ - label: Collapse All
237
+ value: none
238
+ visible_on: '{{ formData.enable_tree == true }}'
223
239
  enable_workflow:
224
240
  name: enable_workflow
225
241
  defaultValue: true
@@ -4,9 +4,15 @@
4
4
  "body": [
5
5
  {
6
6
  "type": "liquid",
7
- "template": "<style>\n .steedos-launcher {\n font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', sans-serif;\n -webkit-font-smoothing: antialiased;\n -webkit-user-select: none;\n user-select: none;\n }\n\n .no-scrollbar::-webkit-scrollbar { display: none; }\n .no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }\n\n .app-icon-box {\n transition: transform 0.18s ease, box-shadow 0.18s ease;\n will-change: transform;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .app-item:not(.static-item):hover .app-icon-box {\n transform: scale(1.06);\n box-shadow: 0 8px 24px -4px rgba(0,0,0,0.12);\n }\n\n .app-item:not(.static-item):active .app-icon-box {\n transform: scale(0.97);\n box-shadow: 0 2px 8px rgba(0,0,0,0.08);\n }\n\n .app-item.static-item:hover .app-icon-box {\n background-color: rgba(0,0,0,0.04);\n }\n\n .sortable-drag .app-icon-box {\n transform: scale(1.1) !important;\n box-shadow: 0 20px 40px -8px rgba(0,0,0,0.18);\n cursor: grabbing;\n }\n\n .sortable-ghost { opacity: 0; }\n\n .loading-skeleton {\n animation: sk-pulse 1.6s ease-in-out infinite;\n background-color: rgba(0,0,0,0.06);\n border-radius: 1.25rem;\n }\n\n @keyframes sk-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.4; }\n }\n</style>\n\n<div id=\"launcher-container\" class=\"steedos-launcher relative w-full h-screen bg-neutral-100 text-neutral-800 overflow-hidden\">\n <div class=\"relative z-10 w-full h-full flex flex-col items-center pt-24 pb-10 px-6 overflow-y-auto no-scrollbar\" id=\"main-scroll-area\">\n <div id=\"vibrant-grid\"\n class=\"grid grid-cols-3 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-6 xl:grid-cols-8 gap-x-5 gap-y-8 w-full max-w-5xl px-2 pb-20\">\n </div>\n </div>\n</div>\n\n<script>\n window.handleAppStoreClick = function() {\n window.location.href = \"/app/admin/page/app_store\";\n };\n\n window.handleAddAppClick = function() {\n data._scoped.doAction([{\n actionType: 'click',\n componentId: 'buttonAddApp',\n }])\n };\n\n var STORE_KEY = 'steedos_launcher_order';\n var COLOR_MAP = {\n 'red': 'bg-red-500',\n 'orange': 'bg-orange-500',\n 'yellow': 'bg-amber-500',\n 'green': 'bg-emerald-500',\n 'teal': 'bg-teal-500',\n 'cyan': 'bg-cyan-500',\n 'sky': 'bg-sky-500',\n 'blue': 'bg-blue-500',\n 'purple': 'bg-violet-500',\n 'pink': 'bg-pink-500',\n 'gray': 'bg-neutral-500',\n 'default':'bg-sky-500'\n };\n\n function saveAppOrder(orderArray) {\n var cleanOrder = orderArray.filter(function(id) { return id !== 'add'; });\n localStorage.setItem(STORE_KEY, JSON.stringify(cleanOrder));\n }\n\n function createAppHtml(app) {\n var colorKey = app.color;\n if (!colorKey) colorKey = 'sky';\n if (app.id === 'admin' && !app.color) colorKey = 'gray';\n var bgClass = COLOR_MAP[colorKey] || COLOR_MAP['sky'];\n\n var iconName = app.icon || 'account';\n var iconPath = '/assets/icons/standard-sprite/svg/symbols.svg#' + iconName;\n\n return `\n <div class=\"app-item group flex flex-col items-center select-none\"\n data-id=\"\\${app.id}\"\n onclick=\"window.location.href='\\${app.path}'\">\n <div class=\"app-icon-box relative w-16 h-16 md:w-[72px] md:h-[72px] rounded-2xl \\${bgClass} text-white shadow-sm\">\n <svg class=\"w-9 h-9 md:w-10 md:h-10\" aria-hidden=\"true\" fill=\"currentColor\">\n <use xlink:href=\"\\${iconPath}\"></use>\n </svg>\n </div>\n <span class=\"mt-2 text-[11px] md:text-xs text-neutral-500 group-hover:text-neutral-800 transition-colors text-center leading-tight line-clamp-2 w-16 md:w-[72px]\">\\${app.name}</span>\n </div>\n `;\n }\n\n function createAddBtnHtml() {\n return `\n <div class=\"app-item group flex flex-col items-center select-none static-item\" data-id=\"add\" onclick=\"handleAddAppClick()\">\n <div class=\"app-icon-box relative w-16 h-16 md:w-[72px] md:h-[72px] rounded-2xl border border-dashed border-neutral-300 text-neutral-300\">\n <svg class=\"w-8 h-8 md:w-9 md:h-9\" aria-hidden=\"true\" fill=\"currentColor\">\n <use xlink:href=\"/assets/icons/utility-sprite/svg/symbols.svg#add\"></use>\n </svg>\n </div>\n <span class=\"mt-2 text-[11px] md:text-xs text-neutral-400\">添加应用</span>\n </div>\n `;\n }\n\n (async function initLauncher() {\n var gridElement = document.getElementById('vibrant-grid');\n var skeletonHtml = '';\n for(var i=0; i<8; i++) { skeletonHtml += '<div class=\"w-16 h-16 md:w-[72px] md:h-[72px] loading-skeleton mx-auto\"></div>'; }\n gridElement.innerHTML = skeletonHtml;\n\n try {\n var response = await fetch('/service/api/apps/menus?mobile=false');\n if (!response.ok) throw new Error('Failed to fetch apps');\n var appsData = (await response.json()).filter(function(a) { return a.id !== 'desktop'; });\n\n var savedOrderStr = localStorage.getItem(STORE_KEY);\n var finalApps = [];\n\n if (savedOrderStr) {\n var savedOrderIds = JSON.parse(savedOrderStr);\n savedOrderIds.forEach(function(id) {\n var app = appsData.find(function(a) { return a.id === id; });\n if (app) finalApps.push(app);\n });\n appsData.forEach(function(app) {\n if (savedOrderIds.indexOf(app.id) === -1) finalApps.push(app);\n });\n } else {\n finalApps = appsData;\n }\n\n var htmlContent = finalApps.map(function(app) { return createAppHtml(app); }).join('');\n htmlContent += createAddBtnHtml();\n gridElement.innerHTML = htmlContent;\n\n if (typeof Sortable !== 'undefined') {\n new Sortable(gridElement, {\n animation: 300,\n easing: \"ease\",\n delay: 0,\n delayOnTouchOnly: true,\n ghostClass: 'sortable-ghost',\n dragClass: 'sortable-drag',\n filter: \".static-item\",\n onMove: function (evt) { return evt.related.className.indexOf('static-item') === -1; },\n onEnd: function (evt) {\n var newOrder = [];\n var currentItems = gridElement.querySelectorAll('.app-item');\n currentItems.forEach(function(item) {\n var id = item.getAttribute('data-id');\n if (id && id !== 'add') newOrder.push(id);\n });\n saveAppOrder(newOrder);\n }\n });\n }\n } catch (error) {\n console.error(\"Launcher Error:\", error);\n gridElement.innerHTML = '<div class=\"col-span-full text-center text-neutral-400 py-20\">加载失败<br><span class=\"text-xs opacity-60\">' + error.message + '</span></div>';\n }\n })();\n</script>",
7
+ "template": "<style>\n .steedos-launcher {\n font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', sans-serif;\n -webkit-font-smoothing: antialiased;\n -webkit-user-select: none;\n user-select: none;\n }\n\n .no-scrollbar::-webkit-scrollbar { display: none; }\n .no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }\n\n .app-icon-box {\n transition: transform 0.18s ease, box-shadow 0.18s ease;\n will-change: transform;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .app-item:not(.static-item):hover .app-icon-box {\n transform: scale(1.06);\n box-shadow: 0 8px 24px -4px rgba(0,0,0,0.12);\n }\n\n .app-item:not(.static-item):active .app-icon-box {\n transform: scale(0.97);\n box-shadow: 0 2px 8px rgba(0,0,0,0.08);\n }\n\n .app-item.static-item:hover .app-icon-box {\n background-color: rgba(0,0,0,0.04);\n }\n\n .sortable-drag .app-icon-box {\n transform: scale(1.1) !important;\n box-shadow: 0 20px 40px -8px rgba(0,0,0,0.18);\n cursor: grabbing;\n }\n\n .sortable-ghost { opacity: 0; }\n\n .loading-skeleton {\n animation: sk-pulse 1.6s ease-in-out infinite;\n background-color: rgba(0,0,0,0.06);\n border-radius: 1.25rem;\n }\n\n @keyframes sk-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.4; }\n }\n</style>\n\n<div id=\"launcher-container\" class=\"steedos-launcher relative w-full text-neutral-800\">\n <div class=\"relative z-10 w-full flex flex-col items-center pt-6 pb-4 px-4 no-scrollbar\" id=\"main-scroll-area\">\n <div id=\"vibrant-grid\"\n class=\"bg-white rounded-xl shadow-sm grid grid-cols-3 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-6 xl:grid-cols-8 gap-x-5 gap-y-6 w-full max-w-4xl mx-auto py-6 px-8\">\n </div>\n </div>\n</div>\n\n<script>\n window.navigateTo = function(path) {\n if (!path) return;\n if (path.startsWith('/') || path.startsWith(window.location.origin)) {\n try {\n var url = new URL(path, window.location.origin);\n window.navigate(url.pathname + url.search + url.hash);\n } catch(e) {\n window.navigate(path);\n }\n } else {\n window.location.href = path;\n }\n };\n\n window.handleAppStoreClick = function() {\n window.navigateTo(\"/app/admin/page/app_store\");\n };\n\n window.handleAddAppClick = function() {\n data._scoped.doAction([{\n actionType: 'click',\n componentId: 'buttonAddApp',\n }])\n };\n\n var STORE_KEY = 'steedos_launcher_order';\n var COLOR_MAP = {\n 'red': 'bg-red-500',\n 'orange': 'bg-orange-500',\n 'yellow': 'bg-amber-500',\n 'green': 'bg-emerald-500',\n 'teal': 'bg-teal-500',\n 'cyan': 'bg-cyan-500',\n 'sky': 'bg-sky-500',\n 'blue': 'bg-blue-500',\n 'purple': 'bg-violet-500',\n 'pink': 'bg-pink-500',\n 'gray': 'bg-neutral-500',\n 'default':'bg-sky-500'\n };\n\n function saveAppOrder(orderArray) {\n var cleanOrder = orderArray.filter(function(id) { return id !== 'add'; });\n localStorage.setItem(STORE_KEY, JSON.stringify(cleanOrder));\n }\n\n function createAppHtml(app) {\n var colorKey = app.color;\n if (!colorKey) colorKey = 'sky';\n if (app.id === 'admin' && !app.color) colorKey = 'gray';\n var bgClass = COLOR_MAP[colorKey] || COLOR_MAP['sky'];\n\n var iconName = app.icon || 'account';\n var iconPath = '/assets/icons/standard-sprite/svg/symbols.svg#' + iconName;\n\n return `\n <div class=\"app-item group flex flex-col items-center select-none\"\n data-id=\"\\${app.id}\"\n onclick=\"window.navigateTo('\\${app.path}')\">\n <div class=\"app-icon-box relative w-16 h-16 md:w-[72px] md:h-[72px] rounded-2xl \\${bgClass} text-white shadow-sm\">\n <svg class=\"w-9 h-9 md:w-10 md:h-10\" aria-hidden=\"true\" fill=\"currentColor\">\n <use xlink:href=\"\\${iconPath}\"></use>\n </svg>\n </div>\n <span class=\"mt-2 text-[11px] md:text-xs text-neutral-500 group-hover:text-neutral-800 transition-colors text-center leading-tight line-clamp-2 w-16 md:w-[72px]\">\\${app.name}</span>\n </div>\n `;\n }\n\n function createAddBtnHtml() {\n return `\n <div class=\"app-item group flex flex-col items-center select-none static-item\" data-id=\"add\" onclick=\"handleAddAppClick()\">\n <div class=\"app-icon-box relative w-16 h-16 md:w-[72px] md:h-[72px] rounded-2xl border border-dashed border-neutral-300 text-neutral-300\">\n <svg class=\"w-8 h-8 md:w-9 md:h-9\" aria-hidden=\"true\" fill=\"currentColor\">\n <use xlink:href=\"/assets/icons/utility-sprite/svg/symbols.svg#add\"></use>\n </svg>\n </div>\n <span class=\"mt-2 text-[11px] md:text-xs text-neutral-400\">添加应用</span>\n </div>\n `;\n }\n\n (async function initLauncher() {\n var gridElement = document.getElementById('vibrant-grid');\n var skeletonHtml = '';\n for(var i=0; i<8; i++) { skeletonHtml += '<div class=\"w-16 h-16 md:w-[72px] md:h-[72px] loading-skeleton mx-auto\"></div>'; }\n gridElement.innerHTML = skeletonHtml;\n\n try {\n var isMobile = window.innerWidth < 768;\n var response = await fetch('/service/api/apps/menus?mobile=' + isMobile);\n if (!response.ok) throw new Error('Failed to fetch apps');\n var appsData = (await response.json()).filter(function(a) { return a.id !== 'desktop'; });\n\n var savedOrderStr = localStorage.getItem(STORE_KEY);\n var finalApps = [];\n\n if (savedOrderStr) {\n var savedOrderIds = JSON.parse(savedOrderStr);\n savedOrderIds.forEach(function(id) {\n var app = appsData.find(function(a) { return a.id === id; });\n if (app) finalApps.push(app);\n });\n appsData.forEach(function(app) {\n if (savedOrderIds.indexOf(app.id) === -1) finalApps.push(app);\n });\n } else {\n finalApps = appsData;\n }\n\n var htmlContent = finalApps.map(function(app) { return createAppHtml(app); }).join('');\n htmlContent += createAddBtnHtml();\n gridElement.innerHTML = htmlContent;\n\n if (typeof Sortable !== 'undefined') {\n new Sortable(gridElement, {\n animation: 300,\n easing: \"ease\",\n delay: 0,\n delayOnTouchOnly: true,\n ghostClass: 'sortable-ghost',\n dragClass: 'sortable-drag',\n filter: \".static-item\",\n onMove: function (evt) { return evt.related.className.indexOf('static-item') === -1; },\n onEnd: function (evt) {\n var newOrder = [];\n var currentItems = gridElement.querySelectorAll('.app-item');\n currentItems.forEach(function(item) {\n var id = item.getAttribute('data-id');\n if (id && id !== 'add') newOrder.push(id);\n });\n saveAppOrder(newOrder);\n }\n });\n }\n } catch (error) {\n console.error(\"Launcher Error:\", error);\n gridElement.innerHTML = '<div class=\"col-span-full text-center text-neutral-400 py-20\">加载失败<br><span class=\"text-xs opacity-60\">' + error.message + '</span></div>';\n }\n })();\n</script>",
8
8
  "id": "u:04103f69c7d4"
9
9
  },
10
+ {
11
+ "type": "service",
12
+ "schemaApi": "get:/service/api/@steedos/service-pages/page/app_launcher/widget_schema",
13
+ "id": "u:app_launcher_widgets",
14
+ "className": "w-full max-w-4xl mx-auto p-0 m-0"
15
+ },
10
16
  {
11
17
  "type": "button",
12
18
  "label": "按钮",
@@ -3,7 +3,6 @@
3
3
  <script src="/unpkg.com/@steedos-builder/fiddle@0.0.5/dist/builder-fiddle.umd.js"></script>
4
4
  <script src="/unpkg.com/axios@0.26.1/dist/axios.min.js"></script>
5
5
  <script src="https://unpkg.steedos.cn/flowbite@2.3.0/dist/flowbite.min.js"></script>
6
- <script src="https://cdn.tailwindcss.com"></script>
7
6
  <link href="/toast/toastr.min.css" rel="stylesheet" />
8
7
  <script src="/jquery.min.js" ></script>
9
8
  <script src="/toast/toastr.min.js"></script>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steedos/service-core-objects",
3
- "version": "3.0.14-beta.9",
3
+ "version": "3.0.15-beta.1",
4
4
  "main": "package.service.js",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -9,7 +9,7 @@
9
9
  "steedos"
10
10
  ],
11
11
  "dependencies": {
12
- "@steedos/service-package-loader": "3.0.14-beta.9",
12
+ "@steedos/service-package-loader": "3.0.15-beta.1",
13
13
  "bcryptjs": "^3.0.3",
14
14
  "json2xls": "^0.1.2",
15
15
  "lodash": "^4.17.21"
@@ -17,5 +17,5 @@
17
17
  "description": "steedos package",
18
18
  "repository": {},
19
19
  "license": "MIT",
20
- "gitHead": "87f62a32df2ab475171cd9be1c664acd15448f85"
20
+ "gitHead": "ff62e2bc9d8c85b48d928e042f7882f0ef77cbe1"
21
21
  }