feat(hexojs): Add Build & Publish LuCI interface for Gitea workflow
- Add publish_to_www RPCD method to publish static files to /www/blog - Add Build & Publish card in sync.js with configurable publish path - Add generate RPC call for building site - Fix file permissions for all RPCD scripts and init.d scripts - Bump luci-app-hexojs to 1.0.0-r3 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
d6861fe732
commit
0be687b89b
0
package/secubox/luci-app-cyberfeed/root/usr/libexec/rpcd/luci.cyberfeed
Normal file → Executable file
0
package/secubox/luci-app-cyberfeed/root/usr/libexec/rpcd/luci.cyberfeed
Normal file → Executable file
0
package/secubox/luci-app-gitea/root/usr/libexec/rpcd/luci.gitea
Normal file → Executable file
0
package/secubox/luci-app-gitea/root/usr/libexec/rpcd/luci.gitea
Normal file → Executable file
0
package/secubox/luci-app-glances/root/usr/libexec/rpcd/luci.glances
Normal file → Executable file
0
package/secubox/luci-app-glances/root/usr/libexec/rpcd/luci.glances
Normal file → Executable file
0
package/secubox/luci-app-haproxy/root/usr/libexec/rpcd/luci.haproxy
Normal file → Executable file
0
package/secubox/luci-app-haproxy/root/usr/libexec/rpcd/luci.haproxy
Normal file → Executable file
@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
|
|||||||
|
|
||||||
PKG_NAME:=luci-app-hexojs
|
PKG_NAME:=luci-app-hexojs
|
||||||
PKG_VERSION:=1.0.0
|
PKG_VERSION:=1.0.0
|
||||||
PKG_RELEASE:=2
|
PKG_RELEASE:=3
|
||||||
PKG_ARCH:=all
|
PKG_ARCH:=all
|
||||||
|
|
||||||
PKG_LICENSE:=MIT
|
PKG_LICENSE:=MIT
|
||||||
|
|||||||
@ -154,6 +154,13 @@ var callDeployStatus = rpc.declare({
|
|||||||
expect: {}
|
expect: {}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var callPublishToWww = rpc.declare({
|
||||||
|
object: 'luci.hexojs',
|
||||||
|
method: 'publish_to_www',
|
||||||
|
params: ['path'],
|
||||||
|
expect: {}
|
||||||
|
});
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// Preview
|
// Preview
|
||||||
// ============================================
|
// ============================================
|
||||||
@ -478,6 +485,7 @@ return baseclass.extend({
|
|||||||
clean: callClean,
|
clean: callClean,
|
||||||
deploy: callDeploy,
|
deploy: callDeploy,
|
||||||
getDeployStatus: callDeployStatus,
|
getDeployStatus: callDeployStatus,
|
||||||
|
publishToWww: callPublishToWww,
|
||||||
|
|
||||||
// Preview
|
// Preview
|
||||||
previewStart: callPreviewStart,
|
previewStart: callPreviewStart,
|
||||||
|
|||||||
@ -28,6 +28,19 @@ var callGiteaSaveConfig = rpc.declare({
|
|||||||
params: ['enabled', 'gitea_url', 'gitea_user', 'gitea_token', 'content_repo', 'content_branch', 'auto_sync']
|
params: ['enabled', 'gitea_url', 'gitea_user', 'gitea_token', 'content_repo', 'content_branch', 'auto_sync']
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var callBuild = rpc.declare({
|
||||||
|
object: 'luci.hexojs',
|
||||||
|
method: 'generate',
|
||||||
|
expect: {}
|
||||||
|
});
|
||||||
|
|
||||||
|
var callPublishToWww = rpc.declare({
|
||||||
|
object: 'luci.hexojs',
|
||||||
|
method: 'publish_to_www',
|
||||||
|
params: ['path'],
|
||||||
|
expect: {}
|
||||||
|
});
|
||||||
|
|
||||||
return view.extend({
|
return view.extend({
|
||||||
title: _('Content Sync'),
|
title: _('Content Sync'),
|
||||||
wizardStep: 0,
|
wizardStep: 0,
|
||||||
@ -210,6 +223,50 @@ return view.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// Build & Publish Actions
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
handleBuild: function() {
|
||||||
|
ui.showModal(_('Building Site'), [
|
||||||
|
E('p', { 'class': 'spinning' }, _('Generating static files...'))
|
||||||
|
]);
|
||||||
|
|
||||||
|
callBuild().then(function(result) {
|
||||||
|
ui.hideModal();
|
||||||
|
if (result.success) {
|
||||||
|
ui.addNotification(null, E('p', _('Site built successfully!')), 'info');
|
||||||
|
} else {
|
||||||
|
ui.addNotification(null, E('p', result.error || _('Build failed')), 'error');
|
||||||
|
}
|
||||||
|
}).catch(function(err) {
|
||||||
|
ui.hideModal();
|
||||||
|
ui.addNotification(null, E('p', _('Error: %s').format(err.message || err)), 'error');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
handlePublish: function() {
|
||||||
|
var self = this;
|
||||||
|
var path = document.querySelector('#publish-path');
|
||||||
|
var publishPath = path ? path.value : '/www/blog';
|
||||||
|
|
||||||
|
ui.showModal(_('Publishing Site'), [
|
||||||
|
E('p', { 'class': 'spinning' }, _('Building and publishing to %s...').format(publishPath))
|
||||||
|
]);
|
||||||
|
|
||||||
|
callPublishToWww(publishPath).then(function(result) {
|
||||||
|
ui.hideModal();
|
||||||
|
if (result.success) {
|
||||||
|
ui.addNotification(null, E('p', _('Published to %s!').format(result.path || publishPath)), 'info');
|
||||||
|
} else {
|
||||||
|
ui.addNotification(null, E('p', result.error || _('Publish failed')), 'error');
|
||||||
|
}
|
||||||
|
}).catch(function(err) {
|
||||||
|
ui.hideModal();
|
||||||
|
ui.addNotification(null, E('p', _('Error: %s').format(err.message || err)), 'error');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// Gitea Actions
|
// Gitea Actions
|
||||||
// ============================================
|
// ============================================
|
||||||
@ -297,6 +354,49 @@ return view.extend({
|
|||||||
]) : ''
|
]) : ''
|
||||||
]),
|
]),
|
||||||
|
|
||||||
|
// Build & Publish Card
|
||||||
|
E('div', { 'class': 'hexo-card' }, [
|
||||||
|
E('div', { 'class': 'hexo-card-header' }, [
|
||||||
|
E('div', { 'class': 'hexo-card-title' }, [
|
||||||
|
E('span', { 'style': 'margin-right: 8px;' }, '\uD83D\uDE80'),
|
||||||
|
_('Build & Publish')
|
||||||
|
])
|
||||||
|
]),
|
||||||
|
E('p', { 'style': 'margin-bottom: 16px; color: var(--hexo-text-muted);' },
|
||||||
|
_('Build static files and publish to web server.')),
|
||||||
|
E('div', { 'style': 'display: grid; grid-template-columns: 1fr 1fr; gap: 16px;' }, [
|
||||||
|
// Build Section
|
||||||
|
E('div', { 'class': 'hexo-card', 'style': 'background: var(--hexo-bg-input);' }, [
|
||||||
|
E('h4', { 'style': 'margin-bottom: 8px;' }, ['\uD83D\uDD28 ', _('Build')]),
|
||||||
|
E('p', { 'style': 'font-size: 13px; color: var(--hexo-text-muted); margin-bottom: 12px;' },
|
||||||
|
_('Generate static HTML files from your content.')),
|
||||||
|
E('button', {
|
||||||
|
'class': 'hexo-btn hexo-btn-primary',
|
||||||
|
'click': function() { self.handleBuild(); }
|
||||||
|
}, _('Build Site'))
|
||||||
|
]),
|
||||||
|
// Publish Section
|
||||||
|
E('div', { 'class': 'hexo-card', 'style': 'background: var(--hexo-bg-input);' }, [
|
||||||
|
E('h4', { 'style': 'margin-bottom: 8px;' }, ['\uD83C\uDF10 ', _('Publish')]),
|
||||||
|
E('p', { 'style': 'font-size: 13px; color: var(--hexo-text-muted); margin-bottom: 12px;' },
|
||||||
|
_('Copy built files to web server directory.')),
|
||||||
|
E('div', { 'class': 'hexo-form-group', 'style': 'margin-bottom: 8px;' }, [
|
||||||
|
E('input', {
|
||||||
|
'type': 'text',
|
||||||
|
'id': 'publish-path',
|
||||||
|
'class': 'hexo-input',
|
||||||
|
'value': '/www/blog',
|
||||||
|
'placeholder': '/www/blog'
|
||||||
|
})
|
||||||
|
]),
|
||||||
|
E('button', {
|
||||||
|
'class': 'hexo-btn hexo-btn-success',
|
||||||
|
'click': function() { self.handlePublish(); }
|
||||||
|
}, _('Publish to Web'))
|
||||||
|
])
|
||||||
|
])
|
||||||
|
]),
|
||||||
|
|
||||||
// Gitea Integration Card
|
// Gitea Integration Card
|
||||||
E('div', { 'class': 'hexo-card' }, [
|
E('div', { 'class': 'hexo-card' }, [
|
||||||
E('div', { 'class': 'hexo-card-header' }, [
|
E('div', { 'class': 'hexo-card-header' }, [
|
||||||
|
|||||||
43
package/secubox/luci-app-hexojs/root/usr/libexec/rpcd/luci.hexojs
Normal file → Executable file
43
package/secubox/luci-app-hexojs/root/usr/libexec/rpcd/luci.hexojs
Normal file → Executable file
@ -1544,6 +1544,45 @@ gitea_save_config() {
|
|||||||
json_dump
|
json_dump
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Publish to /www (portal)
|
||||||
|
publish_to_www() {
|
||||||
|
read input
|
||||||
|
json_load "$input"
|
||||||
|
json_get_var path path
|
||||||
|
|
||||||
|
json_init
|
||||||
|
|
||||||
|
if ! is_running; then
|
||||||
|
json_add_boolean "success" 0
|
||||||
|
json_add_string "error" "Container not running"
|
||||||
|
json_dump
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Default path is /www/blog
|
||||||
|
[ -z "$path" ] && path="/www/blog"
|
||||||
|
|
||||||
|
# Set portal path in UCI for hexoctl
|
||||||
|
uci set hexojs.portal=hexojs
|
||||||
|
uci set hexojs.portal.path="$path"
|
||||||
|
uci commit hexojs
|
||||||
|
|
||||||
|
# Run publish command
|
||||||
|
local output=$("$HEXOCTL" publish 2>&1)
|
||||||
|
local result=$?
|
||||||
|
|
||||||
|
if [ "$result" -eq 0 ]; then
|
||||||
|
json_add_boolean "success" 1
|
||||||
|
json_add_string "message" "Published to $path"
|
||||||
|
json_add_string "path" "$path"
|
||||||
|
else
|
||||||
|
json_add_boolean "success" 0
|
||||||
|
json_add_string "error" "$output"
|
||||||
|
fi
|
||||||
|
|
||||||
|
json_dump
|
||||||
|
}
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
# Service Control
|
# Service Control
|
||||||
# ============================================
|
# ============================================
|
||||||
@ -1634,7 +1673,8 @@ case "$1" in
|
|||||||
"gitea_setup": {},
|
"gitea_setup": {},
|
||||||
"gitea_clone": {},
|
"gitea_clone": {},
|
||||||
"gitea_sync": {},
|
"gitea_sync": {},
|
||||||
"gitea_save_config": {"enabled": "bool", "gitea_url": "str", "gitea_user": "str", "gitea_token": "str", "content_repo": "str", "content_branch": "str", "auto_sync": "bool"}
|
"gitea_save_config": {"enabled": "bool", "gitea_url": "str", "gitea_user": "str", "gitea_token": "str", "content_repo": "str", "content_branch": "str", "auto_sync": "bool"},
|
||||||
|
"publish_to_www": {"path": "str"}
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
;;
|
;;
|
||||||
@ -1686,6 +1726,7 @@ EOF
|
|||||||
gitea_clone) gitea_clone ;;
|
gitea_clone) gitea_clone ;;
|
||||||
gitea_sync) gitea_sync ;;
|
gitea_sync) gitea_sync ;;
|
||||||
gitea_save_config) gitea_save_config ;;
|
gitea_save_config) gitea_save_config ;;
|
||||||
|
publish_to_www) publish_to_www ;;
|
||||||
*) echo '{"error": "Unknown method"}' ;;
|
*) echo '{"error": "Unknown method"}' ;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
|
|||||||
@ -56,7 +56,8 @@
|
|||||||
"gitea_setup",
|
"gitea_setup",
|
||||||
"gitea_clone",
|
"gitea_clone",
|
||||||
"gitea_sync",
|
"gitea_sync",
|
||||||
"gitea_save_config"
|
"gitea_save_config",
|
||||||
|
"publish_to_www"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"uci": ["hexojs"]
|
"uci": ["hexojs"]
|
||||||
|
|||||||
0
package/secubox/luci-app-localai/root/usr/libexec/rpcd/luci.localai
Normal file → Executable file
0
package/secubox/luci-app-localai/root/usr/libexec/rpcd/luci.localai
Normal file → Executable file
0
package/secubox/luci-app-magicmirror2/root/usr/libexec/rpcd/luci.magicmirror2
Normal file → Executable file
0
package/secubox/luci-app-magicmirror2/root/usr/libexec/rpcd/luci.magicmirror2
Normal file → Executable file
0
package/secubox/luci-app-metabolizer/root/usr/libexec/rpcd/luci.metabolizer
Normal file → Executable file
0
package/secubox/luci-app-metabolizer/root/usr/libexec/rpcd/luci.metabolizer
Normal file → Executable file
0
package/secubox/luci-app-mmpm/root/usr/libexec/rpcd/luci.mmpm
Normal file → Executable file
0
package/secubox/luci-app-mmpm/root/usr/libexec/rpcd/luci.mmpm
Normal file → Executable file
0
package/secubox/luci-app-ollama/root/usr/libexec/rpcd/luci.ollama
Normal file → Executable file
0
package/secubox/luci-app-ollama/root/usr/libexec/rpcd/luci.ollama
Normal file → Executable file
0
package/secubox/luci-app-picobrew/root/usr/libexec/rpcd/luci.picobrew
Normal file → Executable file
0
package/secubox/luci-app-picobrew/root/usr/libexec/rpcd/luci.picobrew
Normal file → Executable file
0
package/secubox/luci-app-streamlit/root/usr/libexec/rpcd/luci.streamlit
Normal file → Executable file
0
package/secubox/luci-app-streamlit/root/usr/libexec/rpcd/luci.streamlit
Normal file → Executable file
0
package/secubox/luci-app-tor-shield/root/usr/libexec/rpcd/luci.tor-shield
Normal file → Executable file
0
package/secubox/luci-app-tor-shield/root/usr/libexec/rpcd/luci.tor-shield
Normal file → Executable file
0
package/secubox/secubox-app-cyberfeed/files/etc/init.d/cyberfeed
Normal file → Executable file
0
package/secubox/secubox-app-cyberfeed/files/etc/init.d/cyberfeed
Normal file → Executable file
0
package/secubox/secubox-app-gitea/files/etc/init.d/gitea
Normal file → Executable file
0
package/secubox/secubox-app-gitea/files/etc/init.d/gitea
Normal file → Executable file
0
package/secubox/secubox-app-glances/files/etc/init.d/glances
Normal file → Executable file
0
package/secubox/secubox-app-glances/files/etc/init.d/glances
Normal file → Executable file
0
package/secubox/secubox-app-haproxy/files/etc/init.d/haproxy
Normal file → Executable file
0
package/secubox/secubox-app-haproxy/files/etc/init.d/haproxy
Normal file → Executable file
0
package/secubox/secubox-app-hexojs/files/etc/init.d/hexojs
Normal file → Executable file
0
package/secubox/secubox-app-hexojs/files/etc/init.d/hexojs
Normal file → Executable file
0
package/secubox/secubox-app-localai/files/etc/init.d/localai
Normal file → Executable file
0
package/secubox/secubox-app-localai/files/etc/init.d/localai
Normal file → Executable file
0
package/secubox/secubox-app-magicmirror2/files/etc/init.d/magicmirror2
Normal file → Executable file
0
package/secubox/secubox-app-magicmirror2/files/etc/init.d/magicmirror2
Normal file → Executable file
0
package/secubox/secubox-app-metabolizer/files/etc/init.d/metabolizer
Normal file → Executable file
0
package/secubox/secubox-app-metabolizer/files/etc/init.d/metabolizer
Normal file → Executable file
0
package/secubox/secubox-app-mmpm/files/etc/init.d/mmpm
Normal file → Executable file
0
package/secubox/secubox-app-mmpm/files/etc/init.d/mmpm
Normal file → Executable file
0
package/secubox/secubox-app-ollama/files/etc/init.d/ollama
Normal file → Executable file
0
package/secubox/secubox-app-ollama/files/etc/init.d/ollama
Normal file → Executable file
0
package/secubox/secubox-app-picobrew/files/etc/init.d/picobrew
Normal file → Executable file
0
package/secubox/secubox-app-picobrew/files/etc/init.d/picobrew
Normal file → Executable file
0
package/secubox/secubox-app-streamlit/files/etc/init.d/streamlit
Normal file → Executable file
0
package/secubox/secubox-app-streamlit/files/etc/init.d/streamlit
Normal file → Executable file
0
package/secubox/secubox-app-tor/files/etc/init.d/tor-shield
Normal file → Executable file
0
package/secubox/secubox-app-tor/files/etc/init.d/tor-shield
Normal file → Executable file
Loading…
Reference in New Issue
Block a user