changes
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
<div class="flex items-center gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
:checked="modelValue.settings.is_accordion"
|
||||
:checked="modelValue?.settings?.is_accordion"
|
||||
@change="updateSettings('is_accordion', $event.target.checked)"
|
||||
class="h-4 w-4 text-primary focus:ring-primary border-layer-line rounded"
|
||||
/>
|
||||
@@ -97,7 +97,7 @@ export default {
|
||||
this.$emit('update:modelValue', { ...this.modelValue, [field]: value });
|
||||
},
|
||||
updateSettings(field, value) {
|
||||
this.update('settings', { ...this.modelValue.settings, [field]: value });
|
||||
this.update('settings', { ...(this.modelValue.settings || {}), [field]: value });
|
||||
},
|
||||
updateTab(index, field, value) {
|
||||
const tabs = [...this.tabs];
|
||||
|
||||
@@ -6,6 +6,43 @@
|
||||
<!-- Flash Messages (shared component) -->
|
||||
<FlashMessages />
|
||||
|
||||
<!-- Deploy Button -->
|
||||
<div v-if="isProduction" class="mb-6 bg-gradient-to-r from-primary/10 to-info/10 border border-primary/20 rounded-lg p-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-10 h-10 rounded-lg bg-primary/20 flex items-center justify-center">
|
||||
<DashboardIcon name="arrow-path" size="5" class="text-primary" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-sm font-semibold text-foreground">Обновление сайта</h3>
|
||||
<p class="text-xs text-muted-foreground-1">Запуск скрипта деплоя и пересборка сервера</p>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
@click="deploySite"
|
||||
:disabled="deploying"
|
||||
class="inline-flex items-center gap-2 px-5 py-2.5 bg-primary text-white text-sm font-medium rounded-lg hover:bg-primary-hover transition-all disabled:opacity-50 disabled:cursor-not-allowed shadow-sm hover:shadow-md"
|
||||
>
|
||||
<svg v-if="deploying" class="animate-spin w-4 h-4" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
<DashboardIcon v-else name="rocket-launch" size="4" />
|
||||
{{ deploying ? 'Обновление...' : 'Обновить сайт' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Deploy Output -->
|
||||
<div v-if="deployOutput" class="mt-4 p-3 bg-surface border border-layer-line rounded-lg">
|
||||
<div class="flex items-start gap-2 mb-2">
|
||||
<DashboardIcon :name="deploySuccess ? 'check-circle' : 'exclamation-circle'" size="4" :class="deploySuccess ? 'text-success' : 'text-rose-500'" />
|
||||
<span class="text-sm font-medium" :class="deploySuccess ? 'text-success' : 'text-rose-500'">{{ deployMessage }}</span>
|
||||
</div>
|
||||
<pre v-if="deployOutput" class="mt-2 p-2 bg-muted/30 rounded text-xs text-foreground overflow-auto max-h-48">{{ deployOutput }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Stats Overview -->
|
||||
<StatsOverview :stats="stats" class="mb-6" />
|
||||
|
||||
@@ -87,6 +124,11 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
deploying: false,
|
||||
deployOutput: null,
|
||||
deploySuccess: false,
|
||||
deployStatus: null,
|
||||
deployPolling: null,
|
||||
domainSections: [
|
||||
{
|
||||
title: 'Контент сайта',
|
||||
@@ -125,7 +167,80 @@ export default {
|
||||
mounted() {
|
||||
this.SET_DOCUMENT_TITLE('Главная');
|
||||
},
|
||||
beforeUnmount() {
|
||||
if (this.deployPolling) {
|
||||
clearInterval(this.deployPolling);
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isProduction() {
|
||||
return this.$page.props.app?.env === 'production';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async deploySite() {
|
||||
if (!confirm('Вы уверены, что хотите обновить сайт? Это запустит скрипт деплоя.')) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.deploying = true;
|
||||
this.deployOutput = null;
|
||||
this.deploySuccess = false;
|
||||
|
||||
try {
|
||||
const response = await fetch(route('dashboard.deploy'), {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
this.deploySuccess = result.success;
|
||||
this.deployOutput = result.message;
|
||||
|
||||
// Если деплой запущен — начинаем polling статуса
|
||||
if (result.success) {
|
||||
this.startDeployPolling();
|
||||
}
|
||||
} catch (error) {
|
||||
this.deploySuccess = false;
|
||||
this.deployOutput = 'Ошибка при выполнении запроса: ' + error.message;
|
||||
} finally {
|
||||
this.deploying = false;
|
||||
}
|
||||
},
|
||||
|
||||
startDeployPolling() {
|
||||
// Проверяем статус каждые 3 секунды
|
||||
this.deployPolling = setInterval(async () => {
|
||||
try {
|
||||
const response = await fetch(route('dashboard.deploy.status'));
|
||||
const status = await response.json();
|
||||
|
||||
this.deployStatus = status;
|
||||
|
||||
if (status.status === 'completed' || status.status === 'failed' || status.status === 'idle') {
|
||||
clearInterval(this.deployPolling);
|
||||
this.deployPolling = null;
|
||||
this.deployOutput = status.message || 'Деплой завершён';
|
||||
this.deploySuccess = status.status === 'completed';
|
||||
|
||||
if (status.log) {
|
||||
this.deployOutput += '\n\n' + status.log;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error polling deploy status:', error);
|
||||
}
|
||||
}, 3000);
|
||||
},
|
||||
get deployMessage() {
|
||||
if (!this.deployOutput) return '';
|
||||
return this.deploySuccess ? 'Сайт успешно обновлён!' : 'Ошибка при обновлении сайта';
|
||||
},
|
||||
getBgClass(color) {
|
||||
const map = {
|
||||
primary: 'bg-primary/10',
|
||||
|
||||
@@ -1,24 +1,47 @@
|
||||
<template>
|
||||
<div class="min-h-screen bg-background-2">
|
||||
<!-- Header -->
|
||||
<div class="border-b border-line-2 bg-layer/50 backdrop-blur-sm sticky top-0 z-10 h-16">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-full">
|
||||
<div class="flex items-center h-full gap-3">
|
||||
<a
|
||||
:href="route('dashboard.pages.index')"
|
||||
class="p-2 text-muted-foreground-1 hover:text-foreground hover:bg-muted-hover rounded-lg transition-all"
|
||||
>
|
||||
<DashboardIcon name="arrow-left" size="5" />
|
||||
</a>
|
||||
<div class="border-b border-line-2 bg-layer/50 backdrop-blur-sm sticky top-0 z-10">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex items-center justify-between h-16">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center">
|
||||
<DashboardIcon name="plus" size="5" class="text-primary" />
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="text-lg font-medium text-foreground">Создание страницы</h1>
|
||||
<p class="text-xs text-muted-foreground-1">Заполните информацию о новой странице</p>
|
||||
<a
|
||||
:href="route('dashboard.pages.index')"
|
||||
class="p-2 text-muted-foreground-1 hover:text-foreground hover:bg-muted-hover rounded-lg transition-all"
|
||||
>
|
||||
<DashboardIcon name="arrow-left" size="5" />
|
||||
</a>
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center">
|
||||
<DashboardIcon name="plus" size="5" class="text-primary" />
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="text-lg font-medium text-foreground">Создание страницы</h1>
|
||||
<p class="text-xs text-muted-foreground-1">Заполните информацию о новой странице</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<a
|
||||
:href="route('dashboard.pages.index')"
|
||||
class="inline-flex items-center gap-2 px-4 py-2 bg-surface border border-layer-line text-foreground text-sm font-medium rounded-lg hover:bg-muted-hover transition-all"
|
||||
>
|
||||
Отмена
|
||||
</a>
|
||||
<button
|
||||
type="button"
|
||||
@click="submit"
|
||||
:disabled="processing"
|
||||
class="inline-flex items-center gap-2 px-4 py-2 bg-primary text-white text-sm font-medium rounded-lg hover:bg-primary-hover transition-all disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
<svg v-if="processing" class="animate-spin h-4 w-4" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" />
|
||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
|
||||
</svg>
|
||||
<DashboardIcon v-else name="check" size="4" />
|
||||
{{ processing ? 'Создание...' : 'Создать страницу' }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -275,28 +298,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<div class="flex items-center justify-end gap-3 mt-8 pt-6 border-t border-line-2">
|
||||
<a
|
||||
:href="route('dashboard.pages.index')"
|
||||
class="inline-flex items-center gap-2 px-4 py-2.5 bg-surface border border-layer-line text-foreground text-sm font-medium rounded-lg hover:bg-muted-hover transition-all"
|
||||
>
|
||||
Отмена
|
||||
</a>
|
||||
<button
|
||||
type="submit"
|
||||
:disabled="processing"
|
||||
class="inline-flex items-center gap-2 px-4 py-2.5 bg-primary text-white text-sm font-medium rounded-lg hover:bg-primary-hover transition-all disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
<svg v-if="processing" class="animate-spin h-4 w-4" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" />
|
||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
|
||||
</svg>
|
||||
<DashboardIcon v-else name="check" size="4" />
|
||||
{{ processing ? 'Сохранение...' : 'Создать страницу' }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,24 +1,47 @@
|
||||
<template>
|
||||
<div class="min-h-screen bg-background-2">
|
||||
<!-- Header -->
|
||||
<div class="border-b border-line-2 bg-layer/50 backdrop-blur-sm sticky top-0 z-10 h-16">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-full">
|
||||
<div class="flex items-center h-full gap-3">
|
||||
<a
|
||||
:href="route('dashboard.pages.index')"
|
||||
class="p-2 text-muted-foreground-1 hover:text-foreground hover:bg-muted-hover rounded-lg transition-all"
|
||||
>
|
||||
<DashboardIcon name="arrow-left" size="5" />
|
||||
</a>
|
||||
<div class="border-b border-line-2 bg-layer/50 backdrop-blur-sm sticky top-0 z-10">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex items-center justify-between h-16">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center">
|
||||
<DashboardIcon name="pencil-square" size="5" class="text-primary" />
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="text-lg font-medium text-foreground">Редактирование страницы</h1>
|
||||
<p class="text-xs text-muted-foreground-1">{{ page.title }}</p>
|
||||
<a
|
||||
:href="route('dashboard.pages.index')"
|
||||
class="p-2 text-muted-foreground-1 hover:text-foreground hover:bg-muted-hover rounded-lg transition-all"
|
||||
>
|
||||
<DashboardIcon name="arrow-left" size="5" />
|
||||
</a>
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center">
|
||||
<DashboardIcon name="pencil-square" size="5" class="text-primary" />
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="text-lg font-medium text-foreground">Редактирование страницы</h1>
|
||||
<p class="text-xs text-muted-foreground-1">{{ page.title }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<a
|
||||
:href="route('dashboard.pages.index')"
|
||||
class="inline-flex items-center gap-2 px-4 py-2 bg-surface border border-layer-line text-foreground text-sm font-medium rounded-lg hover:bg-muted-hover transition-all"
|
||||
>
|
||||
Отмена
|
||||
</a>
|
||||
<button
|
||||
type="button"
|
||||
@click="submit"
|
||||
:disabled="processing"
|
||||
class="inline-flex items-center gap-2 px-4 py-2 bg-primary text-white text-sm font-medium rounded-lg hover:bg-primary-hover transition-all disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
<svg v-if="processing" class="animate-spin h-4 w-4" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" />
|
||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
|
||||
</svg>
|
||||
<DashboardIcon v-else name="check" size="4" />
|
||||
{{ processing ? 'Сохранение...' : 'Сохранить' }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -287,28 +310,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<div class="flex items-center justify-end gap-3 mt-8 pt-6 border-t border-line-2">
|
||||
<a
|
||||
:href="route('dashboard.pages.index')"
|
||||
class="inline-flex items-center gap-2 px-4 py-2.5 bg-surface border border-layer-line text-foreground text-sm font-medium rounded-lg hover:bg-muted-hover transition-all"
|
||||
>
|
||||
Отмена
|
||||
</a>
|
||||
<button
|
||||
type="submit"
|
||||
:disabled="processing"
|
||||
class="inline-flex items-center gap-2 px-4 py-2.5 bg-primary text-white text-sm font-medium rounded-lg hover:bg-primary-hover transition-all disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
<svg v-if="processing" class="animate-spin h-4 w-4" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" />
|
||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
|
||||
</svg>
|
||||
<DashboardIcon v-else name="check" size="4" />
|
||||
{{ processing ? 'Сохранение...' : 'Сохранить' }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user