Changes
@@ -0,0 +1,491 @@
|
||||
<template>
|
||||
<div class="max-w-6xl mx-auto p-6 mt-10">
|
||||
|
||||
<!-- БЛОК 1: Форма загрузки (смешанные файлы) -->
|
||||
<div class="bg-white rounded-lg shadow-md p-8">
|
||||
<h2 class="text-2xl font-bold mb-6 text-gray-800 border-b pb-4">Загрузка файлов</h2>
|
||||
|
||||
<!-- Уведомление об успехе -->
|
||||
<div v-if="$page.props.flash?.success" class="mb-6 p-4 bg-green-50 border-l-4 border-green-500 text-green-700 rounded-r-md">
|
||||
{{ $page.props.flash.success }}
|
||||
</div>
|
||||
|
||||
<!-- Уведомление об ошибке -->
|
||||
<div v-if="$page.props.flash?.error" class="mb-6 p-4 bg-red-50 border-l-4 border-red-500 text-red-700 rounded-r-md">
|
||||
{{ $page.props.flash.error }}
|
||||
</div>
|
||||
|
||||
<!-- Информация о созданном посте -->
|
||||
<div v-if="$page.props.flash?.created_post" class="mb-6 p-4 bg-indigo-50 border-l-4 border-indigo-500 rounded-r-md">
|
||||
<h4 class="font-semibold text-indigo-800 mb-2">Создана новость:</h4>
|
||||
<div class="text-sm text-indigo-700 space-y-1">
|
||||
<p><strong>Заголовок:</strong> {{ $page.props.flash.created_post.title }}</p>
|
||||
<p><strong>Статус:</strong> {{ $page.props.flash.created_post.status }}</p>
|
||||
<p><strong>Категория:</strong> {{ $page.props.flash.created_post.category?.title || 'Не указана' }}</p>
|
||||
|
||||
<!-- Превью изображения -->
|
||||
<div v-if="$page.props.flash.created_post.preview" class="mt-2">
|
||||
<img
|
||||
:src="`/storage/${$page.props.flash.created_post.preview}`"
|
||||
alt="Preview"
|
||||
class="h-24 w-auto rounded border border-indigo-200"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 flex gap-2">
|
||||
<a
|
||||
:href="`/admin/posts/${$page.props.flash.created_post.id}/edit`"
|
||||
class="inline-flex items-center px-3 py-1.5 bg-indigo-600 text-white text-sm font-medium rounded hover:bg-indigo-700 transition"
|
||||
>
|
||||
Редактировать в админке
|
||||
</a>
|
||||
<button
|
||||
@click.prevent="openPostModal($page.props.flash.created_post)"
|
||||
class="inline-flex items-center px-3 py-1.5 bg-white text-indigo-600 border border-indigo-600 text-sm font-medium rounded hover:bg-indigo-50 transition"
|
||||
>
|
||||
Быстрый просмотр
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form @submit.prevent="submitForm" class="space-y-6">
|
||||
|
||||
<!-- Поле для загрузки всех файлов -->
|
||||
<div>
|
||||
<label class="block text-sm font-semibold text-gray-700 mb-2">
|
||||
Файлы <span class="text-gray-400 font-normal">(DOCX для текста новости + изображения, PDF, приложения)</span>
|
||||
</label>
|
||||
|
||||
<!-- Зона Drag & Drop -->
|
||||
<div
|
||||
@dragover.prevent="isDragging = true"
|
||||
@dragleave.prevent="isDragging = false"
|
||||
@drop.prevent="handleDrop"
|
||||
@click="triggerFileInput"
|
||||
:class="[
|
||||
'mt-1 flex justify-center px-6 pt-8 pb-8 border-2 border-dashed rounded-lg cursor-pointer transition-all duration-200',
|
||||
isDragging ? 'border-indigo-500 bg-indigo-50 scale-[1.01]' : 'border-gray-300 hover:border-indigo-400 hover:bg-gray-50'
|
||||
]"
|
||||
>
|
||||
<div class="space-y-2 text-center">
|
||||
<svg class="mx-auto h-12 w-12 text-gray-400" stroke="currentColor" fill="none" viewBox="0 0 48 48">
|
||||
<path d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
<div class="flex text-sm text-gray-600 justify-center">
|
||||
<span class="relative cursor-pointer bg-transparent rounded-md font-medium text-indigo-600 hover:text-indigo-500 focus-within:outline-none">
|
||||
Выберите файлы
|
||||
</span>
|
||||
<p class="pl-1">или перетащите их сюда</p>
|
||||
</div>
|
||||
<p class="text-xs text-gray-500">
|
||||
DOCX, PDF, XLSX, JPG, PNG, WEBP (до 20MB каждый)
|
||||
</p>
|
||||
<p class="text-xs text-indigo-600 font-medium">
|
||||
Система автоматически определит файл с текстом новости по названию или содержанию
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Скрытый системный инпут -->
|
||||
<input
|
||||
type="file"
|
||||
id="filesInput"
|
||||
multiple
|
||||
ref="filesInput"
|
||||
class="hidden"
|
||||
@change="handleFileInput"
|
||||
accept=".doc,.docx,.pdf,.xls,.xlsx,.jpg,.jpeg,.png,.webp,.gif"
|
||||
/>
|
||||
|
||||
<!-- Ошибки валидации -->
|
||||
<div v-if="hasFileErrors" class="mt-2 text-sm text-red-600 font-medium">
|
||||
<p v-if="form.errors.files">{{ form.errors.files }}</p>
|
||||
<ul class="list-disc pl-5 mt-1">
|
||||
<li v-for="(error, key) in fileSpecificErrors" :key="key">
|
||||
{{ error }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Список выбранных файлов (Превью) -->
|
||||
<ul v-if="form.files.length > 0" class="mt-4 divide-y divide-gray-100 border border-gray-200 rounded-lg bg-gray-50 shadow-sm">
|
||||
<li v-for="(file, index) in form.files" :key="index" class="pl-4 pr-4 py-3 flex items-center justify-between text-sm transition hover:bg-white">
|
||||
<div class="w-0 flex-1 flex items-center">
|
||||
<svg class="flex-shrink-0 h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M8 4a3 3 0 00-3 3v4a5 5 0 0010 0V7a1 1 0 112 0v4a7 7 0 11-14 0V7a5 5 0 0110 0v4a3 3 0 11-6 0V7a1 1 0 012 0v4a1 1 0 102 0V7a3 3 0 00-3-3z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
<span class="ml-2 flex-1 w-0 truncate text-gray-700 font-medium">
|
||||
{{ file.name }}
|
||||
<span class="text-gray-400 text-xs ml-1 font-normal">({{ (file.size / 1024 / 1024).toFixed(2) }} MB)</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="ml-4 flex-shrink-0">
|
||||
<button type="button" @click.prevent="removeFile(index)" class="font-medium text-red-500 hover:text-red-700 bg-red-50 px-2 py-1 rounded transition">
|
||||
Удалить
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Прогресс-бар загрузки -->
|
||||
<div v-if="form.progress" class="w-full bg-gray-200 rounded-full h-2.5 overflow-hidden">
|
||||
<div class="bg-indigo-600 h-2.5 rounded-full transition-all duration-300 ease-out" :style="{ width: form.progress.percentage + '%' }"></div>
|
||||
</div>
|
||||
|
||||
<!-- Кнопка сабмита -->
|
||||
<button
|
||||
type="submit"
|
||||
:disabled="form.processing || form.files.length === 0"
|
||||
class="w-full flex justify-center py-3 px-4 border border-transparent rounded-lg shadow-sm text-base font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
<span v-if="form.processing">
|
||||
Обработка и загрузка файлов ({{ form.progress ? form.progress.percentage : 0 }}%)...
|
||||
</span>
|
||||
<span v-else>Отправить файлы на сервер</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- БЛОК 0: Список черновиков -->
|
||||
<div v-if="draftPosts && draftPosts.length > 0" class="bg-white rounded-lg shadow-md p-8">
|
||||
<h2 class="text-2xl font-bold mb-6 text-gray-800 border-b pb-4">
|
||||
Черновики (без publish_at)
|
||||
<span class="text-sm font-normal text-gray-500 ml-2">{{ draftPosts.length }} шт.</span>
|
||||
</h2>
|
||||
|
||||
<div class="grid gap-4">
|
||||
<div
|
||||
v-for="post in draftPosts"
|
||||
:key="post.id"
|
||||
class="border border-gray-200 rounded-lg p-4 hover:shadow-md transition cursor-pointer"
|
||||
@click="openPostModal(post)"
|
||||
>
|
||||
<div class="flex items-start justify-between">
|
||||
<div class="flex-1">
|
||||
<h3 class="text-lg font-semibold text-gray-800 mb-2">{{ post.title }}</h3>
|
||||
<div class="flex flex-wrap gap-2 text-sm text-gray-600">
|
||||
<span class="bg-gray-100 px-2 py-1 rounded">ID: {{ post.id }}</span>
|
||||
<span v-if="post.category" class="bg-indigo-50 text-indigo-700 px-2 py-1 rounded">
|
||||
{{ post.category.title }}
|
||||
</span>
|
||||
<span v-if="post.authors" class="bg-gray-100 px-2 py-1 rounded">
|
||||
Автор: {{ Array.isArray(post.authors) ? post.authors.join(', ') : post.authors }}
|
||||
</span>
|
||||
</div>
|
||||
<p v-if="post.preview_text" class="mt-3 text-sm text-gray-600 line-clamp-2">
|
||||
{{ post.preview_text }}
|
||||
</p>
|
||||
<div class="mt-3 flex items-center gap-4 text-xs text-gray-500">
|
||||
<span>Создано: {{ new Date(post.created_at).toLocaleDateString('ru-RU') }}</span>
|
||||
<span>Обновлено: {{ new Date(post.updated_at).toLocaleDateString('ru-RU') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ml-4 flex flex-col gap-2">
|
||||
<button
|
||||
@click.stop="publishPost(post)"
|
||||
:disabled="publishProcessing"
|
||||
class="px-3 py-1.5 bg-green-600 text-white text-sm font-medium rounded hover:bg-green-700 transition disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
Опубликовать
|
||||
</button>
|
||||
<span class="text-indigo-600 hover:text-indigo-800 text-xs font-medium text-center">
|
||||
Подробнее →
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Модальное окно просмотра новости -->
|
||||
<div
|
||||
v-if="selectedPost"
|
||||
class="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4"
|
||||
@click.self="closePostModal"
|
||||
>
|
||||
<div class="bg-white rounded-lg shadow-xl max-w-4xl w-full max-h-[90vh] overflow-y-auto">
|
||||
<div class="sticky top-0 bg-white border-b border-gray-200 px-6 py-4 flex items-center justify-between rounded-t-lg">
|
||||
<h3 class="text-xl font-bold text-gray-800">{{ selectedPost.title }}</h3>
|
||||
<button
|
||||
@click="closePostModal"
|
||||
class="text-gray-400 hover:text-gray-600 transition"
|
||||
>
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="p-6">
|
||||
<!-- Мета информация -->
|
||||
<div class="flex flex-wrap gap-2 mb-4 text-sm">
|
||||
<span class="bg-gray-100 px-3 py-1 rounded-full">ID: {{ selectedPost.id }}</span>
|
||||
<span v-if="selectedPost.category" class="bg-indigo-50 text-indigo-700 px-3 py-1 rounded-full">
|
||||
{{ selectedPost.category.title }}
|
||||
</span>
|
||||
<span v-if="selectedPost.status" class="bg-green-50 text-green-700 px-3 py-1 rounded-full">
|
||||
{{ selectedPost.status }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Главное изображение (Preview) -->
|
||||
<div v-if="selectedPost.preview" class="mb-6">
|
||||
<p class="text-sm font-semibold text-gray-700 mb-2">Главное изображение:</p>
|
||||
<div class="rounded-lg overflow-hidden border border-gray-200">
|
||||
<img
|
||||
:src="`/storage/${selectedPost.preview}`"
|
||||
alt="Preview"
|
||||
class="w-full h-auto max-h-96 object-cover"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Галерея изображений -->
|
||||
<div v-if="selectedPost.images && selectedPost.images.length > 0" class="mb-6">
|
||||
<p class="text-sm font-semibold text-gray-700 mb-2">Галерея ({{ selectedPost.images.length }}):</p>
|
||||
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-3">
|
||||
<div
|
||||
v-for="(image, index) in selectedPost.images"
|
||||
:key="index"
|
||||
class="rounded-lg overflow-hidden border border-gray-200 aspect-square"
|
||||
>
|
||||
<img
|
||||
:src="`/storage/${image}`"
|
||||
alt="Gallery image {{ index + 1 }}"
|
||||
class="w-full h-full object-cover cursor-pointer hover:opacity-80 transition"
|
||||
@click="viewImage(image)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Авторы -->
|
||||
<div v-if="selectedPost.authors" class="mb-4 p-4 bg-gray-50 rounded-lg">
|
||||
<p class="text-sm font-semibold text-gray-700 mb-2">Автор(ы):</p>
|
||||
<p class="text-sm text-gray-600">
|
||||
{{ Array.isArray(selectedPost.authors) ? selectedPost.authors.join(', ') : selectedPost.authors }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Превью -->
|
||||
<div v-if="selectedPost.preview_text" class="mb-6">
|
||||
<p class="text-sm font-semibold text-gray-700 mb-2">Превью:</p>
|
||||
<p class="text-gray-600">{{ selectedPost.preview_text }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Полный контент -->
|
||||
<div class="mb-6">
|
||||
<p class="text-sm font-semibold text-gray-700 mb-2">Полный текст:</p>
|
||||
<div class="prose max-w-none bg-gray-50 p-4 rounded-lg border border-gray-200">
|
||||
<div v-html="renderContent(selectedPost.content)"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Дополнительная информация -->
|
||||
<div class="border-t pt-4 text-xs text-gray-500">
|
||||
<div class="flex justify-between">
|
||||
<span>Создано: {{ new Date(selectedPost.created_at).toLocaleString('ru-RU') }}</span>
|
||||
<span>Обновлено: {{ new Date(selectedPost.updated_at).toLocaleString('ru-RU') }}</span>
|
||||
</div>
|
||||
<div v-if="selectedPost.reading_time" class="mt-1">
|
||||
Время чтения: {{ selectedPost.reading_time }} мин.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Кнопки действий -->
|
||||
<div class="sticky bottom-0 bg-gray-50 border-t border-gray-200 px-6 py-4 flex justify-between items-center rounded-b-lg">
|
||||
<div class="flex gap-3">
|
||||
<!-- Кнопка "Опубликовать" (только для черновиков) -->
|
||||
<button
|
||||
v-if="!selectedPost.publish_at"
|
||||
@click="publishPost(selectedPost)"
|
||||
:disabled="publishProcessing"
|
||||
class="inline-flex items-center px-4 py-2 bg-green-600 text-white text-sm font-medium rounded-lg hover:bg-green-700 transition disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
<span v-if="publishProcessing">
|
||||
Публикация...
|
||||
</span>
|
||||
<span v-else>
|
||||
Опубликовать
|
||||
</span>
|
||||
</button>
|
||||
<!-- Кнопка "Редактировать в админке" -->
|
||||
<a
|
||||
:href="`/admin/posts/${selectedPost.id}/edit`"
|
||||
class="inline-flex items-center px-4 py-2 bg-indigo-600 text-white text-sm font-medium rounded-lg hover:bg-indigo-700 transition"
|
||||
>
|
||||
Редактировать
|
||||
</a>
|
||||
</div>
|
||||
<button
|
||||
@click="closePostModal"
|
||||
class="px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 transition"
|
||||
>
|
||||
Закрыть
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { useForm, usePage, router } from '@inertiajs/vue3';
|
||||
|
||||
// Сохраняем имя компонента
|
||||
defineOptions({
|
||||
name: "Main",
|
||||
});
|
||||
|
||||
// Получаем данные из Inertia
|
||||
const page = usePage();
|
||||
const draftPosts = computed(() => page.props.draftPosts || []);
|
||||
|
||||
// Состояние для модального окна
|
||||
const selectedPost = ref(null);
|
||||
|
||||
// Состояние для процесса публикации
|
||||
const publishProcessing = ref(false);
|
||||
|
||||
// Открытие модального окна
|
||||
const openPostModal = (post) => {
|
||||
selectedPost.value = post;
|
||||
};
|
||||
|
||||
// Закрытие модального окна
|
||||
const closePostModal = () => {
|
||||
selectedPost.value = null;
|
||||
};
|
||||
|
||||
// Публикация поста
|
||||
const publishPost = (post) => {
|
||||
if (!confirm(`Опубликовать новость "${post.title}"?`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
publishProcessing.value = true;
|
||||
|
||||
router.post(route('dashboard.posts.publish', post.id), {}, {
|
||||
preserveScroll: true,
|
||||
onSuccess: () => {
|
||||
publishProcessing.value = false;
|
||||
// Закрываем модальное окно, если оно открыто
|
||||
if (selectedPost.value?.id === post.id) {
|
||||
closePostModal();
|
||||
}
|
||||
},
|
||||
onError: () => {
|
||||
publishProcessing.value = false;
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// Рендеринг контента (массив блоков или строка)
|
||||
const renderContent = (content) => {
|
||||
if (!content) return '';
|
||||
|
||||
// Если контент - массив блоков (например, редактор)
|
||||
if (Array.isArray(content)) {
|
||||
return content.map(block => {
|
||||
if (typeof block === 'string') return block;
|
||||
if (block.type === 'paragraph' && block.data?.content) {
|
||||
return block.data.content;
|
||||
}
|
||||
if (block.type === 'heading' && block.data?.content) {
|
||||
return `<h2>${block.data.content}</h2>`;
|
||||
}
|
||||
if (block.data?.content) {
|
||||
return block.data.content;
|
||||
}
|
||||
return '';
|
||||
}).join('');
|
||||
}
|
||||
|
||||
// Если контент - строка
|
||||
return content;
|
||||
};
|
||||
|
||||
// Просмотр изображения
|
||||
const viewImage = (imagePath) => {
|
||||
window.open(`/storage/${imagePath}`, '_blank');
|
||||
};
|
||||
|
||||
// Инициализация формы Inertia
|
||||
const form = useForm({
|
||||
files: [], // Массив для всех файлов
|
||||
});
|
||||
|
||||
// Состояния для кастомного Dropzone
|
||||
const isDragging = ref(false);
|
||||
const filesInput = ref(null);
|
||||
|
||||
// Имитация клика по скрытому input type="file"
|
||||
const triggerFileInput = () => {
|
||||
filesInput.value.click();
|
||||
};
|
||||
|
||||
// Обработка перетаскивания файлов (Drag & Drop)
|
||||
const handleDrop = (e) => {
|
||||
isDragging.value = false;
|
||||
const files = Array.from(e.dataTransfer.files);
|
||||
addFilesToForm(files);
|
||||
};
|
||||
|
||||
// Обработка выбора файлов через стандартное окно браузера
|
||||
const handleFileInput = (e) => {
|
||||
const files = Array.from(e.target.files);
|
||||
addFilesToForm(files);
|
||||
// Сбрасываем value, чтобы можно было удалить файл из списка и выбрать его снова
|
||||
e.target.value = '';
|
||||
};
|
||||
|
||||
// Функция добавления файлов в массив с защитой от дублей
|
||||
const addFilesToForm = (files) => {
|
||||
files.forEach(file => {
|
||||
// Проверяем, нет ли уже файла с таким именем и размером
|
||||
const exists = form.files.some(f => f.name === file.name && f.size === file.size);
|
||||
if (!exists) {
|
||||
form.files.push(file);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Удаление конкретного файла из массива
|
||||
const removeFile = (index) => {
|
||||
form.files.splice(index, 1);
|
||||
};
|
||||
|
||||
// Отправка формы
|
||||
const submitForm = () => {
|
||||
form.post(route('dashboard.files.store'), {
|
||||
preserveScroll: true,
|
||||
onSuccess: () => {
|
||||
// Очищаем данные в стейте useForm
|
||||
form.reset();
|
||||
// Очищаем визуальный input
|
||||
const filesInputElement = document.getElementById('filesInput');
|
||||
if (filesInputElement) filesInputElement.value = '';
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// Вычисляемые свойства для удобного отображения ошибок валидации массива files
|
||||
const hasFileErrors = computed(() => {
|
||||
return Object.keys(form.errors).some(key => key.startsWith('files'));
|
||||
});
|
||||
|
||||
const fileSpecificErrors = computed(() => {
|
||||
const errors = {};
|
||||
Object.keys(form.errors).forEach(key => {
|
||||
if (key.startsWith('files.')) {
|
||||
errors[key] = form.errors[key];
|
||||
}
|
||||
});
|
||||
return errors;
|
||||
});
|
||||
</script>
|
||||
|
Before Width: | Height: | Size: 683 B After Width: | Height: | Size: 683 B |
|
Before Width: | Height: | Size: 610 B After Width: | Height: | Size: 610 B |
|
Before Width: | Height: | Size: 429 B After Width: | Height: | Size: 429 B |
|
Before Width: | Height: | Size: 428 B After Width: | Height: | Size: 428 B |
|
Before Width: | Height: | Size: 491 B After Width: | Height: | Size: 491 B |
|
Before Width: | Height: | Size: 536 B After Width: | Height: | Size: 536 B |
|
Before Width: | Height: | Size: 474 B After Width: | Height: | Size: 474 B |
|
Before Width: | Height: | Size: 286 B After Width: | Height: | Size: 286 B |
|
Before Width: | Height: | Size: 258 B After Width: | Height: | Size: 258 B |
|
Before Width: | Height: | Size: 482 B After Width: | Height: | Size: 482 B |
|
Before Width: | Height: | Size: 371 B After Width: | Height: | Size: 371 B |
|
Before Width: | Height: | Size: 255 B After Width: | Height: | Size: 255 B |
|
Before Width: | Height: | Size: 327 B After Width: | Height: | Size: 327 B |
|
Before Width: | Height: | Size: 255 B After Width: | Height: | Size: 255 B |
|
Before Width: | Height: | Size: 285 B After Width: | Height: | Size: 285 B |
|
Before Width: | Height: | Size: 372 B After Width: | Height: | Size: 372 B |
|
Before Width: | Height: | Size: 372 B After Width: | Height: | Size: 372 B |
|
Before Width: | Height: | Size: 368 B After Width: | Height: | Size: 368 B |
|
Before Width: | Height: | Size: 254 B After Width: | Height: | Size: 254 B |
|
Before Width: | Height: | Size: 259 B After Width: | Height: | Size: 259 B |
|
Before Width: | Height: | Size: 257 B After Width: | Height: | Size: 257 B |
|
Before Width: | Height: | Size: 258 B After Width: | Height: | Size: 258 B |
|
Before Width: | Height: | Size: 256 B After Width: | Height: | Size: 256 B |
|
Before Width: | Height: | Size: 546 B After Width: | Height: | Size: 546 B |
|
Before Width: | Height: | Size: 386 B After Width: | Height: | Size: 386 B |
|
Before Width: | Height: | Size: 286 B After Width: | Height: | Size: 286 B |
|
Before Width: | Height: | Size: 369 B After Width: | Height: | Size: 369 B |
|
Before Width: | Height: | Size: 365 B After Width: | Height: | Size: 365 B |
|
Before Width: | Height: | Size: 365 B After Width: | Height: | Size: 365 B |
|
Before Width: | Height: | Size: 254 B After Width: | Height: | Size: 254 B |
|
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 262 B |
|
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 262 B |
|
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 262 B |
|
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 262 B |
|
Before Width: | Height: | Size: 351 B After Width: | Height: | Size: 351 B |
|
Before Width: | Height: | Size: 328 B After Width: | Height: | Size: 328 B |
|
Before Width: | Height: | Size: 323 B After Width: | Height: | Size: 323 B |
|
Before Width: | Height: | Size: 273 B After Width: | Height: | Size: 273 B |
|
Before Width: | Height: | Size: 273 B After Width: | Height: | Size: 273 B |
|
Before Width: | Height: | Size: 275 B After Width: | Height: | Size: 275 B |
|
Before Width: | Height: | Size: 275 B After Width: | Height: | Size: 275 B |
|
Before Width: | Height: | Size: 275 B After Width: | Height: | Size: 275 B |
|
Before Width: | Height: | Size: 276 B After Width: | Height: | Size: 276 B |
|
Before Width: | Height: | Size: 273 B After Width: | Height: | Size: 273 B |
|
Before Width: | Height: | Size: 273 B After Width: | Height: | Size: 273 B |
|
Before Width: | Height: | Size: 285 B After Width: | Height: | Size: 285 B |
|
Before Width: | Height: | Size: 259 B After Width: | Height: | Size: 259 B |
|
Before Width: | Height: | Size: 482 B After Width: | Height: | Size: 482 B |
|
Before Width: | Height: | Size: 367 B After Width: | Height: | Size: 367 B |
|
Before Width: | Height: | Size: 257 B After Width: | Height: | Size: 257 B |
|
Before Width: | Height: | Size: 325 B After Width: | Height: | Size: 325 B |
|
Before Width: | Height: | Size: 253 B After Width: | Height: | Size: 253 B |
|
Before Width: | Height: | Size: 260 B After Width: | Height: | Size: 260 B |
|
Before Width: | Height: | Size: 261 B After Width: | Height: | Size: 261 B |
|
Before Width: | Height: | Size: 260 B After Width: | Height: | Size: 260 B |
|
Before Width: | Height: | Size: 261 B After Width: | Height: | Size: 261 B |
|
Before Width: | Height: | Size: 352 B After Width: | Height: | Size: 352 B |
|
Before Width: | Height: | Size: 368 B After Width: | Height: | Size: 368 B |
|
Before Width: | Height: | Size: 293 B After Width: | Height: | Size: 293 B |
|
Before Width: | Height: | Size: 292 B After Width: | Height: | Size: 292 B |
|
Before Width: | Height: | Size: 342 B After Width: | Height: | Size: 342 B |
|
Before Width: | Height: | Size: 467 B After Width: | Height: | Size: 467 B |