feat(photoprism): Add configurable originals_path via UCI/LuCI
- Add originals_path option to UCI config (default: /srv/photoprism/originals) - Add set_config RPC method to update originals_path from LuCI - Add Storage Settings section to LuCI dashboard - Update LXC config to use configurable ORIGINALS_PATH - Update get_stats to scan originals_path instead of data_path/originals - Lyrion media_path already configurable via Settings page Both services now support external mount points: - PhotoPrism: /mnt/PHOTO for photos - Lyrion: /mnt/MUSIC for music Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
7bcd09b81d
commit
363e2af9d6
@ -59,6 +59,19 @@ var callEmancipate = rpc.declare({
|
||||
expect: {}
|
||||
});
|
||||
|
||||
var callGetConfig = rpc.declare({
|
||||
object: 'luci.photoprism',
|
||||
method: 'get_config',
|
||||
expect: {}
|
||||
});
|
||||
|
||||
var callSetConfig = rpc.declare({
|
||||
object: 'luci.photoprism',
|
||||
method: 'set_config',
|
||||
params: ['originals_path'],
|
||||
expect: {}
|
||||
});
|
||||
|
||||
return view.extend({
|
||||
css: `
|
||||
:root {
|
||||
@ -225,11 +238,13 @@ return view.extend({
|
||||
|
||||
status: null,
|
||||
stats: null,
|
||||
config: null,
|
||||
|
||||
load: function() {
|
||||
return Promise.all([
|
||||
callStatus(),
|
||||
callGetStats()
|
||||
callGetStats(),
|
||||
callGetConfig()
|
||||
]);
|
||||
},
|
||||
|
||||
@ -237,6 +252,7 @@ return view.extend({
|
||||
var self = this;
|
||||
this.status = data[0] || {};
|
||||
this.stats = data[1] || {};
|
||||
this.config = data[2] || {};
|
||||
|
||||
var container = E('div', { 'class': 'kiss-container' }, [
|
||||
E('style', {}, this.css),
|
||||
@ -245,9 +261,10 @@ return view.extend({
|
||||
]);
|
||||
|
||||
poll.add(function() {
|
||||
return Promise.all([callStatus(), callGetStats()]).then(function(results) {
|
||||
return Promise.all([callStatus(), callGetStats(), callGetConfig()]).then(function(results) {
|
||||
self.status = results[0] || {};
|
||||
self.stats = results[1] || {};
|
||||
self.config = results[2] || {};
|
||||
self.updateView();
|
||||
});
|
||||
}, 10);
|
||||
@ -376,6 +393,41 @@ return view.extend({
|
||||
])
|
||||
]),
|
||||
|
||||
// Settings
|
||||
E('div', { 'class': 'kiss-section' }, [
|
||||
E('h3', {}, 'Storage Settings'),
|
||||
E('div', { 'class': 'kiss-input-group' }, [
|
||||
E('label', { 'style': 'color: var(--kiss-muted); margin-right: 10px;' }, 'Photos Path:'),
|
||||
E('input', {
|
||||
'class': 'kiss-input',
|
||||
'type': 'text',
|
||||
'id': 'originals-path',
|
||||
'value': self.config.originals_path || '/srv/photoprism/originals',
|
||||
'placeholder': '/mnt/PHOTO'
|
||||
}),
|
||||
E('button', {
|
||||
'class': 'kiss-btn kiss-btn-secondary',
|
||||
'click': function() {
|
||||
var path = document.getElementById('originals-path').value;
|
||||
if (!path) {
|
||||
ui.addNotification(null, E('p', {}, 'Please enter a path'), 'warning');
|
||||
return;
|
||||
}
|
||||
this.disabled = true;
|
||||
this.textContent = 'Saving...';
|
||||
var btn = this;
|
||||
callSetConfig(path).then(function(res) {
|
||||
if (res.success) {
|
||||
ui.addNotification(null, E('p', {}, 'Path updated. Restart PhotoPrism to apply.'), 'success');
|
||||
}
|
||||
btn.disabled = false;
|
||||
btn.textContent = 'Save';
|
||||
});
|
||||
}
|
||||
}, 'Save')
|
||||
])
|
||||
]),
|
||||
|
||||
// Emancipate
|
||||
E('div', { 'class': 'kiss-section' }, [
|
||||
E('h3', {}, 'Public Exposure'),
|
||||
|
||||
@ -17,6 +17,7 @@ method_get_config() {
|
||||
|
||||
json_add_boolean "enabled" "$([ "$(uci -q get ${CONFIG}.main.enabled)" = "1" ] && echo true || echo false)"
|
||||
json_add_string "data_path" "$(uci -q get ${CONFIG}.main.data_path || echo '/srv/photoprism')"
|
||||
json_add_string "originals_path" "$(uci -q get ${CONFIG}.main.originals_path || echo '/srv/photoprism/originals')"
|
||||
json_add_string "http_port" "$(uci -q get ${CONFIG}.main.http_port || echo '2342')"
|
||||
json_add_string "memory_limit" "$(uci -q get ${CONFIG}.main.memory_limit || echo '2G')"
|
||||
json_add_string "admin_user" "$(uci -q get ${CONFIG}.admin.username || echo 'admin')"
|
||||
@ -28,18 +29,33 @@ method_get_config() {
|
||||
json_dump
|
||||
}
|
||||
|
||||
# Method: set_config
|
||||
method_set_config() {
|
||||
local originals_path="$1"
|
||||
|
||||
if [ -n "$originals_path" ]; then
|
||||
uci set ${CONFIG}.main.originals_path="$originals_path"
|
||||
uci commit ${CONFIG}
|
||||
fi
|
||||
|
||||
json_init
|
||||
json_add_boolean "success" true
|
||||
json_dump
|
||||
}
|
||||
|
||||
# Method: get_stats
|
||||
method_get_stats() {
|
||||
local data_path=$(uci -q get ${CONFIG}.main.data_path || echo '/srv/photoprism')
|
||||
local originals_path=$(uci -q get ${CONFIG}.main.originals_path || echo '/srv/photoprism/originals')
|
||||
local originals_size="0"
|
||||
local storage_size="0"
|
||||
local photo_count=0
|
||||
local video_count=0
|
||||
|
||||
if [ -d "${data_path}/originals" ]; then
|
||||
originals_size=$(du -sh "${data_path}/originals" 2>/dev/null | cut -f1 || echo "0")
|
||||
photo_count=$(find "${data_path}/originals" -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.heic" -o -iname "*.raw" -o -iname "*.dng" \) 2>/dev/null | wc -l || echo 0)
|
||||
video_count=$(find "${data_path}/originals" -type f \( -iname "*.mp4" -o -iname "*.mov" -o -iname "*.avi" -o -iname "*.mkv" \) 2>/dev/null | wc -l || echo 0)
|
||||
if [ -d "${originals_path}" ]; then
|
||||
originals_size=$(du -sh "${originals_path}" 2>/dev/null | cut -f1 || echo "0")
|
||||
photo_count=$(find "${originals_path}" -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.heic" -o -iname "*.raw" -o -iname "*.dng" \) 2>/dev/null | wc -l || echo 0)
|
||||
video_count=$(find "${originals_path}" -type f \( -iname "*.mp4" -o -iname "*.mov" -o -iname "*.avi" -o -iname "*.mkv" \) 2>/dev/null | wc -l || echo 0)
|
||||
fi
|
||||
|
||||
if [ -d "${data_path}/storage" ]; then
|
||||
@ -162,6 +178,7 @@ case "$1" in
|
||||
echo '{
|
||||
"status": {},
|
||||
"get_config": {},
|
||||
"set_config": {"originals_path": "string"},
|
||||
"get_stats": {},
|
||||
"start": {},
|
||||
"stop": {},
|
||||
@ -178,6 +195,11 @@ case "$1" in
|
||||
case "$2" in
|
||||
status) method_status ;;
|
||||
get_config) method_get_config ;;
|
||||
set_config)
|
||||
read -r input
|
||||
originals_path=$(echo "$input" | jsonfilter -e '@.originals_path' 2>/dev/null)
|
||||
method_set_config "$originals_path"
|
||||
;;
|
||||
get_stats) method_get_stats ;;
|
||||
start) method_start ;;
|
||||
stop) method_stop ;;
|
||||
|
||||
@ -22,7 +22,8 @@
|
||||
"uninstall",
|
||||
"index",
|
||||
"import",
|
||||
"emancipate"
|
||||
"emancipate",
|
||||
"set_config"
|
||||
]
|
||||
},
|
||||
"uci": ["photoprism"]
|
||||
|
||||
@ -36,6 +36,7 @@ uci_set() { uci set "${CONFIG}.$1=$2" && uci commit "$CONFIG"; }
|
||||
defaults() {
|
||||
ENABLED=$(uci_get main.enabled 0)
|
||||
DATA_PATH=$(uci_get main.data_path /srv/photoprism)
|
||||
ORIGINALS_PATH=$(uci_get main.originals_path /srv/photoprism/originals)
|
||||
HTTP_PORT=$(uci_get main.http_port 2342)
|
||||
MEMORY_LIMIT=$(uci_get main.memory_limit 2G)
|
||||
TIMEZONE=$(uci_get main.timezone Europe/Paris)
|
||||
@ -123,7 +124,7 @@ lxc.net.0.type = none
|
||||
lxc.mount.auto = proc:mixed sys:ro
|
||||
|
||||
# Bind mounts for data persistence
|
||||
lxc.mount.entry = ${DATA_PATH}/originals opt/photoprism/originals none bind,create=dir 0 0
|
||||
lxc.mount.entry = ${ORIGINALS_PATH} opt/photoprism/originals none bind,create=dir 0 0
|
||||
lxc.mount.entry = ${DATA_PATH}/storage opt/photoprism/storage none bind,create=dir 0 0
|
||||
lxc.mount.entry = ${DATA_PATH}/import opt/photoprism/import none bind,create=dir 0 0
|
||||
|
||||
@ -439,6 +440,7 @@ cmd_status() {
|
||||
"videos": $videos,
|
||||
"storage_used": "$storage_used",
|
||||
"data_path": "$DATA_PATH",
|
||||
"originals_path": "$ORIGINALS_PATH",
|
||||
"domain": "$DOMAIN",
|
||||
"admin_user": "$ADMIN_USER",
|
||||
"face_recognition": $([ "$FACE_RECOGNITION" = "1" ] && echo "true" || echo "false"),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user