feat(luci-hexojs): Add Gitea integration to sync page
- Add gitea_status, gitea_sync, gitea_clone, gitea_save_config RPCD methods - Add Gitea section to sync.js with config form and sync buttons - Update ACL for new Gitea methods - Fix luci-app-metabolizer install section for RPCD executable Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
70358370f6
commit
170f4a90e2
@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-hexojs
|
||||
PKG_VERSION:=1.0.0
|
||||
PKG_RELEASE:=1
|
||||
PKG_RELEASE:=2
|
||||
PKG_ARCH:=all
|
||||
|
||||
PKG_LICENSE:=MIT
|
||||
|
||||
@ -1,14 +1,42 @@
|
||||
'use strict';
|
||||
'require view';
|
||||
'require ui';
|
||||
'require rpc';
|
||||
'require hexojs/api as api';
|
||||
|
||||
var callGiteaStatus = rpc.declare({
|
||||
object: 'luci.hexojs',
|
||||
method: 'gitea_status',
|
||||
expect: {}
|
||||
});
|
||||
|
||||
var callGiteaSync = rpc.declare({
|
||||
object: 'luci.hexojs',
|
||||
method: 'gitea_sync',
|
||||
expect: {}
|
||||
});
|
||||
|
||||
var callGiteaClone = rpc.declare({
|
||||
object: 'luci.hexojs',
|
||||
method: 'gitea_clone',
|
||||
expect: {}
|
||||
});
|
||||
|
||||
var callGiteaSaveConfig = rpc.declare({
|
||||
object: 'luci.hexojs',
|
||||
method: 'gitea_save_config',
|
||||
params: ['enabled', 'gitea_url', 'gitea_user', 'gitea_token', 'content_repo', 'content_branch', 'auto_sync']
|
||||
});
|
||||
|
||||
return view.extend({
|
||||
title: _('GitHub Sync'),
|
||||
title: _('Content Sync'),
|
||||
wizardStep: 0,
|
||||
|
||||
load: function() {
|
||||
return api.getGitSyncData();
|
||||
return Promise.all([
|
||||
api.getGitSyncData(),
|
||||
callGiteaStatus()
|
||||
]);
|
||||
},
|
||||
|
||||
// ============================================
|
||||
@ -182,15 +210,76 @@ return view.extend({
|
||||
});
|
||||
},
|
||||
|
||||
// ============================================
|
||||
// Gitea Actions
|
||||
// ============================================
|
||||
|
||||
handleGiteaSync: function() {
|
||||
ui.showModal(_('Syncing from Gitea'), [
|
||||
E('p', { 'class': 'spinning' }, _('Pulling content from Gitea...'))
|
||||
]);
|
||||
|
||||
callGiteaSync().then(function(result) {
|
||||
ui.hideModal();
|
||||
if (result.success) {
|
||||
ui.addNotification(null, E('p', _('Content synced from Gitea!')), 'info');
|
||||
location.reload();
|
||||
} else {
|
||||
ui.addNotification(null, E('p', result.error || _('Sync failed')), 'error');
|
||||
}
|
||||
}).catch(function(err) {
|
||||
ui.hideModal();
|
||||
ui.addNotification(null, E('p', _('Error: %s').format(err.message || err)), 'error');
|
||||
});
|
||||
},
|
||||
|
||||
handleGiteaClone: function() {
|
||||
ui.showModal(_('Cloning from Gitea'), [
|
||||
E('p', { 'class': 'spinning' }, _('Cloning content repository from Gitea...'))
|
||||
]);
|
||||
|
||||
callGiteaClone().then(function(result) {
|
||||
ui.hideModal();
|
||||
if (result.success) {
|
||||
ui.addNotification(null, E('p', _('Content cloned from Gitea!')), 'info');
|
||||
location.reload();
|
||||
} else {
|
||||
ui.addNotification(null, E('p', result.error || _('Clone failed')), 'error');
|
||||
}
|
||||
}).catch(function(err) {
|
||||
ui.hideModal();
|
||||
ui.addNotification(null, E('p', _('Error: %s').format(err.message || err)), 'error');
|
||||
});
|
||||
},
|
||||
|
||||
handleGiteaSaveConfig: function() {
|
||||
var enabled = document.querySelector('#gitea-enabled').checked ? '1' : '0';
|
||||
var url = document.querySelector('#gitea-url').value;
|
||||
var user = document.querySelector('#gitea-user').value;
|
||||
var token = document.querySelector('#gitea-token').value;
|
||||
var repo = document.querySelector('#gitea-repo').value;
|
||||
var branch = document.querySelector('#gitea-branch').value || 'main';
|
||||
|
||||
callGiteaSaveConfig(enabled, url, user, token, repo, branch, '0').then(function(result) {
|
||||
if (result.success) {
|
||||
ui.addNotification(null, E('p', _('Gitea configuration saved!')), 'info');
|
||||
} else {
|
||||
ui.addNotification(null, E('p', result.error || _('Save failed')), 'error');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// ============================================
|
||||
// Render
|
||||
// ============================================
|
||||
|
||||
render: function(data) {
|
||||
var self = this;
|
||||
var status = data.status || {};
|
||||
var credentials = data.credentials || {};
|
||||
var commits = data.commits || [];
|
||||
var gitData = data[0] || {};
|
||||
var giteaStatus = data[1] || {};
|
||||
var status = gitData.status || {};
|
||||
var credentials = gitData.credentials || {};
|
||||
var commits = gitData.commits || [];
|
||||
var isRepo = status.is_repo;
|
||||
|
||||
return E('div', { 'class': 'hexo-dashboard' }, [
|
||||
@ -200,7 +289,7 @@ return view.extend({
|
||||
E('div', { 'class': 'hexo-header' }, [
|
||||
E('div', { 'class': 'hexo-card-title' }, [
|
||||
E('span', { 'class': 'hexo-card-title-icon' }, '\uD83D\uDD04'),
|
||||
_('GitHub Sync')
|
||||
_('Content Sync')
|
||||
]),
|
||||
isRepo ? E('div', { 'class': 'hexo-status-badge ' + (status.ahead > 0 ? 'warning' : 'running') }, [
|
||||
E('span', { 'class': 'hexo-status-dot' }),
|
||||
@ -208,6 +297,138 @@ return view.extend({
|
||||
]) : ''
|
||||
]),
|
||||
|
||||
// Gitea Integration Card
|
||||
E('div', { 'class': 'hexo-card' }, [
|
||||
E('div', { 'class': 'hexo-card-header' }, [
|
||||
E('div', { 'class': 'hexo-card-title' }, [
|
||||
E('span', { 'style': 'margin-right: 8px;' }, '\uD83E\uDD8A'),
|
||||
_('Gitea Content Sync')
|
||||
]),
|
||||
giteaStatus.enabled ? E('div', { 'class': 'hexo-status-badge running' }, [
|
||||
E('span', { 'class': 'hexo-status-dot' }),
|
||||
_('Enabled')
|
||||
]) : E('div', { 'class': 'hexo-status-badge stopped' }, [
|
||||
E('span', { 'class': 'hexo-status-dot' }),
|
||||
_('Disabled')
|
||||
])
|
||||
]),
|
||||
E('p', { 'style': 'margin-bottom: 16px; color: var(--hexo-text-muted);' },
|
||||
_('Sync blog content from your local Gitea server.')),
|
||||
|
||||
// Gitea Status
|
||||
giteaStatus.has_local_repo ? E('div', { 'style': 'background: var(--hexo-bg-input); padding: 12px; border-radius: 8px; margin-bottom: 16px;' }, [
|
||||
E('div', { 'style': 'display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px;' }, [
|
||||
E('div', {}, [
|
||||
E('div', { 'style': 'font-size: 11px; color: var(--hexo-text-muted); text-transform: uppercase;' }, _('Repository')),
|
||||
E('div', { 'style': 'font-size: 14px;' }, giteaStatus.content_repo || '-')
|
||||
]),
|
||||
E('div', {}, [
|
||||
E('div', { 'style': 'font-size: 11px; color: var(--hexo-text-muted); text-transform: uppercase;' }, _('Branch')),
|
||||
E('div', { 'style': 'font-size: 14px;' }, giteaStatus.local_branch || '-')
|
||||
]),
|
||||
E('div', {}, [
|
||||
E('div', { 'style': 'font-size: 11px; color: var(--hexo-text-muted); text-transform: uppercase;' }, _('Last Commit')),
|
||||
E('div', { 'style': 'font-size: 13px;' }, giteaStatus.last_commit || '-')
|
||||
])
|
||||
])
|
||||
]) : '',
|
||||
|
||||
// Gitea Actions
|
||||
E('div', { 'style': 'display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 16px;' }, [
|
||||
giteaStatus.has_local_repo ?
|
||||
E('button', {
|
||||
'class': 'hexo-btn hexo-btn-primary',
|
||||
'click': function() { self.handleGiteaSync(); },
|
||||
'disabled': !giteaStatus.enabled
|
||||
}, ['\uD83D\uDD04 ', _('Sync from Gitea')]) :
|
||||
E('button', {
|
||||
'class': 'hexo-btn hexo-btn-success',
|
||||
'click': function() { self.handleGiteaClone(); },
|
||||
'disabled': !giteaStatus.enabled
|
||||
}, ['\uD83D\uDCE5 ', _('Clone from Gitea')])
|
||||
]),
|
||||
|
||||
// Gitea Config Form
|
||||
E('details', { 'style': 'margin-top: 8px;' }, [
|
||||
E('summary', { 'style': 'cursor: pointer; color: var(--hexo-primary);' }, _('Configure Gitea Connection')),
|
||||
E('div', { 'style': 'margin-top: 12px; display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px;' }, [
|
||||
E('div', { 'class': 'hexo-form-group', 'style': 'margin: 0;' }, [
|
||||
E('label', { 'style': 'display: flex; align-items: center; gap: 8px;' }, [
|
||||
E('input', {
|
||||
'type': 'checkbox',
|
||||
'id': 'gitea-enabled',
|
||||
'checked': giteaStatus.enabled
|
||||
}),
|
||||
_('Enable Gitea Sync')
|
||||
])
|
||||
]),
|
||||
E('div', { 'class': 'hexo-form-group', 'style': 'margin: 0;' }, [
|
||||
E('label', { 'class': 'hexo-form-label' }, _('Gitea URL')),
|
||||
E('input', {
|
||||
'type': 'text',
|
||||
'id': 'gitea-url',
|
||||
'class': 'hexo-input',
|
||||
'value': giteaStatus.gitea_url || '',
|
||||
'placeholder': 'http://192.168.255.1:3000'
|
||||
})
|
||||
]),
|
||||
E('div', { 'class': 'hexo-form-group', 'style': 'margin: 0;' }, [
|
||||
E('label', { 'class': 'hexo-form-label' }, _('Username')),
|
||||
E('input', {
|
||||
'type': 'text',
|
||||
'id': 'gitea-user',
|
||||
'class': 'hexo-input',
|
||||
'value': giteaStatus.gitea_user || '',
|
||||
'placeholder': 'admin'
|
||||
})
|
||||
]),
|
||||
E('div', { 'class': 'hexo-form-group', 'style': 'margin: 0;' }, [
|
||||
E('label', { 'class': 'hexo-form-label' }, _('Access Token')),
|
||||
E('input', {
|
||||
'type': 'password',
|
||||
'id': 'gitea-token',
|
||||
'class': 'hexo-input',
|
||||
'placeholder': _('Gitea access token')
|
||||
})
|
||||
]),
|
||||
E('div', { 'class': 'hexo-form-group', 'style': 'margin: 0;' }, [
|
||||
E('label', { 'class': 'hexo-form-label' }, _('Content Repository')),
|
||||
E('input', {
|
||||
'type': 'text',
|
||||
'id': 'gitea-repo',
|
||||
'class': 'hexo-input',
|
||||
'value': giteaStatus.content_repo || '',
|
||||
'placeholder': 'blog-content'
|
||||
})
|
||||
]),
|
||||
E('div', { 'class': 'hexo-form-group', 'style': 'margin: 0;' }, [
|
||||
E('label', { 'class': 'hexo-form-label' }, _('Branch')),
|
||||
E('input', {
|
||||
'type': 'text',
|
||||
'id': 'gitea-branch',
|
||||
'class': 'hexo-input',
|
||||
'value': giteaStatus.content_branch || 'main',
|
||||
'placeholder': 'main'
|
||||
})
|
||||
])
|
||||
]),
|
||||
E('button', {
|
||||
'class': 'hexo-btn hexo-btn-secondary',
|
||||
'style': 'margin-top: 12px;',
|
||||
'click': function() { self.handleGiteaSaveConfig(); }
|
||||
}, _('Save Gitea Config'))
|
||||
])
|
||||
]),
|
||||
|
||||
// Divider
|
||||
E('div', { 'style': 'border-top: 1px solid var(--hexo-border); margin: 24px 0;' }),
|
||||
|
||||
// GitHub Sync Header
|
||||
E('div', { 'class': 'hexo-card-title', 'style': 'margin-bottom: 16px;' }, [
|
||||
E('span', { 'class': 'hexo-card-title-icon' }, '\uD83D\uDC19'),
|
||||
_('GitHub / Git Sync')
|
||||
]),
|
||||
|
||||
// Setup Wizard (shown if not a repo)
|
||||
!isRepo ? E('div', { 'class': 'hexo-card' }, [
|
||||
E('div', { 'class': 'hexo-card-header' }, [
|
||||
|
||||
@ -1423,6 +1423,127 @@ git_get_credentials() {
|
||||
json_dump
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# Gitea Integration Methods
|
||||
# ============================================
|
||||
|
||||
gitea_status() {
|
||||
json_init
|
||||
|
||||
local enabled=$(uci -q get hexojs.gitea.enabled) || enabled="0"
|
||||
local gitea_url=$(uci -q get hexojs.gitea.url) || gitea_url=""
|
||||
local gitea_user=$(uci -q get hexojs.gitea.user) || gitea_user=""
|
||||
local content_repo=$(uci -q get hexojs.gitea.content_repo) || content_repo=""
|
||||
local content_branch=$(uci -q get hexojs.gitea.content_branch) || content_branch="main"
|
||||
local auto_sync=$(uci -q get hexojs.gitea.auto_sync) || auto_sync="0"
|
||||
|
||||
local data_path=$(uci_get main.data_path) || data_path="$DATA_PATH"
|
||||
local content_path="$data_path/content"
|
||||
local has_repo="false"
|
||||
local last_commit=""
|
||||
local branch=""
|
||||
|
||||
if [ -d "$content_path/.git" ]; then
|
||||
has_repo="true"
|
||||
cd "$content_path"
|
||||
last_commit=$(git log -1 --format="%h %s" 2>/dev/null || echo "unknown")
|
||||
branch=$(git branch --show-current 2>/dev/null || echo "unknown")
|
||||
fi
|
||||
|
||||
json_add_boolean "enabled" "$enabled"
|
||||
json_add_string "gitea_url" "$gitea_url"
|
||||
json_add_string "gitea_user" "$gitea_user"
|
||||
json_add_string "content_repo" "$content_repo"
|
||||
json_add_string "content_branch" "$content_branch"
|
||||
json_add_boolean "auto_sync" "$auto_sync"
|
||||
json_add_boolean "has_local_repo" "$([ "$has_repo" = "true" ] && echo 1 || echo 0)"
|
||||
json_add_string "local_branch" "$branch"
|
||||
json_add_string "last_commit" "$last_commit"
|
||||
|
||||
json_dump
|
||||
}
|
||||
|
||||
gitea_setup() {
|
||||
json_init
|
||||
|
||||
local output=$("$HEXOCTL" gitea setup 2>&1)
|
||||
local result=$?
|
||||
|
||||
if [ "$result" -eq 0 ]; then
|
||||
json_add_boolean "success" 1
|
||||
json_add_string "message" "Git credentials configured"
|
||||
else
|
||||
json_add_boolean "success" 0
|
||||
json_add_string "error" "$output"
|
||||
fi
|
||||
|
||||
json_dump
|
||||
}
|
||||
|
||||
gitea_clone() {
|
||||
json_init
|
||||
|
||||
local output=$("$HEXOCTL" gitea clone 2>&1)
|
||||
local result=$?
|
||||
|
||||
if [ "$result" -eq 0 ]; then
|
||||
json_add_boolean "success" 1
|
||||
json_add_string "message" "Content cloned from Gitea"
|
||||
else
|
||||
json_add_boolean "success" 0
|
||||
json_add_string "error" "$output"
|
||||
fi
|
||||
|
||||
json_dump
|
||||
}
|
||||
|
||||
gitea_sync() {
|
||||
json_init
|
||||
|
||||
local output=$("$HEXOCTL" gitea sync 2>&1)
|
||||
local result=$?
|
||||
|
||||
if [ "$result" -eq 0 ]; then
|
||||
json_add_boolean "success" 1
|
||||
json_add_string "message" "Content synced from Gitea"
|
||||
else
|
||||
json_add_boolean "success" 0
|
||||
json_add_string "error" "$output"
|
||||
fi
|
||||
|
||||
json_dump
|
||||
}
|
||||
|
||||
gitea_save_config() {
|
||||
read input
|
||||
json_load "$input"
|
||||
|
||||
json_get_var enabled enabled
|
||||
json_get_var gitea_url gitea_url
|
||||
json_get_var gitea_user gitea_user
|
||||
json_get_var gitea_token gitea_token
|
||||
json_get_var content_repo content_repo
|
||||
json_get_var content_branch content_branch
|
||||
json_get_var auto_sync auto_sync
|
||||
|
||||
json_init
|
||||
|
||||
[ -n "$enabled" ] && uci set hexojs.gitea.enabled="$enabled"
|
||||
[ -n "$gitea_url" ] && uci set hexojs.gitea.url="$gitea_url"
|
||||
[ -n "$gitea_user" ] && uci set hexojs.gitea.user="$gitea_user"
|
||||
[ -n "$gitea_token" ] && uci set hexojs.gitea.token="$gitea_token"
|
||||
[ -n "$content_repo" ] && uci set hexojs.gitea.content_repo="$content_repo"
|
||||
[ -n "$content_branch" ] && uci set hexojs.gitea.content_branch="$content_branch"
|
||||
[ -n "$auto_sync" ] && uci set hexojs.gitea.auto_sync="$auto_sync"
|
||||
|
||||
uci commit hexojs
|
||||
|
||||
json_add_boolean "success" 1
|
||||
json_add_string "message" "Gitea configuration saved"
|
||||
|
||||
json_dump
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# Service Control
|
||||
# ============================================
|
||||
@ -1508,7 +1629,12 @@ case "$1" in
|
||||
"git_log": {},
|
||||
"git_reset": {"hard": "bool"},
|
||||
"git_set_credentials": {"name": "str", "email": "str"},
|
||||
"git_get_credentials": {}
|
||||
"git_get_credentials": {},
|
||||
"gitea_status": {},
|
||||
"gitea_setup": {},
|
||||
"gitea_clone": {},
|
||||
"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"}
|
||||
}
|
||||
EOF
|
||||
;;
|
||||
@ -1555,6 +1681,11 @@ EOF
|
||||
git_reset) git_reset ;;
|
||||
git_set_credentials) git_set_credentials ;;
|
||||
git_get_credentials) git_get_credentials ;;
|
||||
gitea_status) gitea_status ;;
|
||||
gitea_setup) gitea_setup ;;
|
||||
gitea_clone) gitea_clone ;;
|
||||
gitea_sync) gitea_sync ;;
|
||||
gitea_save_config) gitea_save_config ;;
|
||||
*) echo '{"error": "Unknown method"}' ;;
|
||||
esac
|
||||
;;
|
||||
|
||||
@ -21,7 +21,8 @@
|
||||
"list_presets",
|
||||
"git_status",
|
||||
"git_log",
|
||||
"git_get_credentials"
|
||||
"git_get_credentials",
|
||||
"gitea_status"
|
||||
]
|
||||
},
|
||||
"uci": ["hexojs"]
|
||||
@ -51,7 +52,11 @@
|
||||
"git_push",
|
||||
"git_fetch",
|
||||
"git_reset",
|
||||
"git_set_credentials"
|
||||
"git_set_credentials",
|
||||
"gitea_setup",
|
||||
"gitea_clone",
|
||||
"gitea_sync",
|
||||
"gitea_save_config"
|
||||
]
|
||||
},
|
||||
"uci": ["hexojs"]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user