feat: add plan-only space export

Issue: #167
User-Visible: yes
This commit is contained in:
Sergey Matyunin
2026-08-17 12:33:52 +03:00
parent bf2937c1ed
commit 7f397a6875
24 changed files with 859 additions and 84 deletions
+13 -3
View File
@@ -1396,7 +1396,7 @@ class HouseplanCard extends LitElement {
busy: boolean;
} | null = null;
private _backupExportDialog: {
kind: 'full' | 'space'; busy: boolean; error: string;
kind: 'full' | 'space'; planOnly: boolean; busy: boolean; error: string;
} | null = null;
private _backupImportDialog: {
filename: string; size: number; token: string; preview: any;
@@ -13088,7 +13088,7 @@ class HouseplanCard extends LitElement {
private _openBackupExport = (): void => {
this._settingsDialog = null;
this._backupExportDialog = { kind: 'full', busy: false, error: '' };
this._backupExportDialog = { kind: 'full', planOnly: false, busy: false, error: '' };
};
private async _runBackupExport(): Promise<void> {
@@ -13100,6 +13100,7 @@ class HouseplanCard extends LitElement {
type: 'houseplan/export/create',
kind: d.kind,
space_id: d.kind === 'space' ? this._space : undefined,
...(d.kind === 'space' && d.planOnly ? { plan_only: true } : {}),
card_version: CARD_VERSION,
});
const blob = new Blob([JSON.stringify(response.document, null, 2) + '\n'], {
@@ -13285,7 +13286,8 @@ class HouseplanCard extends LitElement {
<div class="body backupbody">
<div class="rhint">${this._t('backup.export_hint')}</div>
<label class="srcrow"><input type="radio" name="backup-kind" value="full"
.checked=${d.kind === 'full'} @change=${() => (this._backupExportDialog = { ...d, kind: 'full' })} />
.checked=${d.kind === 'full'}
@change=${() => (this._backupExportDialog = { ...d, kind: 'full', planOnly: false })} />
<span>${this._t('backup.full')}</span></label>
<label class="srcrow"><input type="radio" name="backup-kind" value="space"
.checked=${d.kind === 'space'} ?disabled=${!currentSpace}
@@ -13293,6 +13295,13 @@ class HouseplanCard extends LitElement {
<span>${currentSpace
? this._t('backup.current_space_title', { title: currentSpace.title || currentSpace.id })
: this._t('backup.no_current_space')}</span></label>
${d.kind === 'space' && currentSpace ? html`<label class="srcrow backupplanonly">
<input type="checkbox" .checked=${d.planOnly}
@change=${(event: Event) => (this._backupExportDialog = {
...d, planOnly: (event.target as HTMLInputElement).checked,
})} />
<span><b>${this._t('backup.plan_only')}</b><small>${this._t('backup.plan_only_hint')}</small></span>
</label>` : nothing}
<div class="backupwarn">${this._t('backup.privacy_warning')}</div>
${d.error ? html`<div class="backuperror" role="alert">${d.error}</div>` : nothing}
</div>
@@ -13320,6 +13329,7 @@ class HouseplanCard extends LitElement {
${p ? html`
<div class="backupsummary">
<b>${this._t(p.kind === 'full' ? 'backup.full' : 'backup.current_space')}</b>
${p.plan_only ? html`<span class="backupplanonlystatus">${this._t('backup.plan_only_preview')}</span>` : nothing}
<span>${this._t(p.source === 'same' ? 'backup.same_source' : 'backup.foreign_source')}</span>
<span>${this._t('backup.created', { value: p.created_at || '—' })}</span>
<span>${this._t('backup.versions', {
+3
View File
@@ -825,6 +825,9 @@
"backup.current_space": "Current space",
"backup.current_space_title": "Current space: {title}",
"backup.no_current_space": "No current space",
"backup.plan_only": "Plan only",
"backup.plan_only_hint": "Keep rooms, walls, openings, decor and room-label positions without devices or Home Assistant bindings.",
"backup.plan_only_preview": "This file contains the plan only",
"backup.privacy_warning": "The archive keeps names, Home Assistant identifiers and exact coordinates. Internal plans and attachments are referenced, not embedded; runtime states and vacuum trails are not included.",
"backup.download": "Download JSON",
"backup.export_done": "Backup downloaded",
+3
View File
@@ -825,6 +825,9 @@
"backup.current_space": "Текущее пространство",
"backup.current_space_title": "Текущее пространство: {title}",
"backup.no_current_space": "Нет текущего пространства",
"backup.plan_only": "Только планировка",
"backup.plan_only_hint": "Сохранить комнаты, стены, проёмы, декор и позиции подписей комнат без устройств и привязок Home Assistant.",
"backup.plan_only_preview": "Файл содержит только планировку",
"backup.privacy_warning": "Архив сохраняет названия, идентификаторы Home Assistant и точные координаты. Внутренние планы и вложения указываются ссылками, но не вкладываются; текущие состояния и маршруты пылесосов не включаются.",
"backup.download": "Скачать JSON",
"backup.export_done": "Резервная копия скачана",
+4
View File
@@ -2867,6 +2867,10 @@ export const cardStyles = css`
.backupupload > .btn { width: 100%; justify-content: center; }
.backupupload input { display: none; }
.backupbody { min-width: 0; }
.backupplanonly { margin-inline-start: var(--sp-4) !important; align-items: flex-start !important; }
.backupplanonly > span:first-of-type { display: grid; gap: 2px; white-space: normal; }
.backupplanonly small { color: var(--secondary-text-color); line-height: 1.35; }
.backupplanonlystatus { color: var(--hp-accent) !important; font-weight: 700; }
.backupfile, .backupsummary, .backupcontent {
display: flex;
flex-direction: column;