| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- @extends('layouts.app')
- @section('content')
- <div class="row mb-3 page-header-row">
- <div class="col-12 col-md-6 page-header-title">
- <h3>Документация</h3>
- </div>
- @if($canCreateRoot)
- <div class="col-12 col-md-6 text-md-end page-header-actions">
- <button class="btn btn-sm btn-primary" type="button" data-bs-toggle="collapse" data-bs-target="#createRootFolder">
- <i class="bi bi-folder-plus"></i> Корневая папка
- </button>
- </div>
- @endif
- </div>
- @if($canCreateRoot)
- <div class="collapse mb-3" id="createRootFolder">
- <div class="card card-body">
- <form action="{{ route('documents.folders.store') }}" method="POST" class="row g-2 align-items-end">
- @csrf
- <div class="col-md-8">
- <label class="form-label" for="root-folder-name">Название корневой папки</label>
- <input class="form-control" id="root-folder-name" name="name" maxlength="255" required>
- </div>
- <div class="col-md-4">
- <button class="btn btn-primary w-100" type="submit">Создать</button>
- </div>
- </form>
- </div>
- </div>
- @endif
- <div class="row g-3">
- <div class="col-12 col-lg-3">
- <div class="card h-100">
- <div class="card-header fw-semibold">Папки</div>
- <div class="card-body p-2">
- @include('documents._folder_tree', [
- 'parentId' => 0,
- 'foldersByParent' => $foldersByParent,
- 'selectedFolder' => $selectedFolder,
- ])
- @if($folders->isEmpty())
- <div class="text-muted small p-2">
- {{ $canCreateRoot ? 'Создайте первую корневую папку.' : 'Доступных папок пока нет.' }}
- </div>
- @endif
- </div>
- </div>
- </div>
- <div class="col-12 col-lg-9">
- @if($selectedFolder)
- <div class="d-flex flex-wrap justify-content-between align-items-start gap-2 mb-3">
- <div>
- <h4 class="mb-1"><i class="bi bi-folder2-open"></i> {{ $selectedFolder->name }}</h4>
- <div class="small text-muted">
- @if($selectedFolder->parent_id && $selectedFolder->inherits_permissions)
- Права наследуются от родительской папки
- @else
- Для папки настроены собственные права
- @endif
- </div>
- </div>
- @if($canWrite)
- <div class="d-flex flex-wrap gap-1">
- <button class="btn btn-sm btn-outline-primary" type="button" data-bs-toggle="collapse" data-bs-target="#folderSettings">
- <i class="bi bi-pencil"></i> Папка
- </button>
- <button class="btn btn-sm btn-primary" type="button" data-bs-toggle="collapse" data-bs-target="#uploadDocument">
- <i class="bi bi-file-earmark-arrow-up"></i> Загрузить документ
- </button>
- </div>
- @endif
- </div>
- @if($canWrite)
- <div class="collapse mb-3" id="folderSettings">
- <div class="card card-body">
- <div class="row g-3">
- <div class="col-md-6">
- <h6>Переименовать папку</h6>
- <form action="{{ route('documents.folders.update', $selectedFolder) }}" method="POST" class="d-flex gap-2">
- @csrf
- @method('PUT')
- <input class="form-control" name="name" value="{{ $selectedFolder->name }}" maxlength="255" required>
- <button class="btn btn-outline-primary" type="submit">Сохранить</button>
- </form>
- </div>
- <div class="col-md-6">
- <h6>Создать подпапку</h6>
- <form action="{{ route('documents.folders.store') }}" method="POST" class="d-flex gap-2">
- @csrf
- <input type="hidden" name="parent_id" value="{{ $selectedFolder->id }}">
- <input class="form-control" name="name" placeholder="Название подпапки" maxlength="255" required>
- <button class="btn btn-outline-primary" type="submit">Создать</button>
- </form>
- </div>
- </div>
- <hr>
- <form action="{{ route('documents.folders.destroy', $selectedFolder) }}" method="POST"
- onsubmit="return confirm('Удалить папку, все вложенные папки, документы и версии?')">
- @csrf
- @method('DELETE')
- <button class="btn btn-sm btn-outline-danger" type="submit">
- <i class="bi bi-trash"></i> Удалить папку со всем содержимым
- </button>
- </form>
- </div>
- </div>
- <div class="collapse mb-3" id="uploadDocument">
- <div class="card card-body">
- <h6>Новый документ</h6>
- <form action="{{ route('documents.store', $selectedFolder) }}" method="POST" enctype="multipart/form-data" class="row g-2 align-items-end">
- @csrf
- <div class="col-md-5">
- <label class="form-label" for="document-name">Название</label>
- <input class="form-control" id="document-name" name="name" maxlength="255" placeholder="По умолчанию — имя файла">
- </div>
- <div class="col-md-5">
- <label class="form-label" for="document-file">Файл, до 20 МБ</label>
- <input class="form-control" id="document-file" type="file" name="file" required>
- </div>
- <div class="col-md-2">
- <button class="btn btn-primary w-100" type="submit">Загрузить</button>
- </div>
- </form>
- </div>
- </div>
- @endif
- @if($canManagePermissions)
- <div class="card mb-3">
- <div class="card-header p-0">
- <button class="btn w-100 text-start px-3 py-2" type="button" data-bs-toggle="collapse" data-bs-target="#folderPermissions">
- <i class="bi bi-shield-lock"></i> Права доступа
- </button>
- </div>
- <div class="collapse" id="folderPermissions">
- <div class="card-body">
- <form action="{{ route('documents.folders.permissions.update', $selectedFolder) }}" method="POST">
- @csrf
- @method('PUT')
- @if($selectedFolder->parent_id)
- <div class="form-check mb-3">
- <input class="form-check-input" type="checkbox" value="1" name="inherit_permissions" id="inherit-permissions"
- @checked($selectedFolder->inherits_permissions)>
- <label class="form-check-label" for="inherit-permissions">
- Наследовать права родительской папки
- </label>
- </div>
- @endif
- <div class="row g-3">
- <div class="col-12">
- <div class="d-flex gap-4">
- <div class="form-check">
- <input class="form-check-input" type="checkbox" value="1" name="all_read" id="all-read"
- @checked($permissionValues['all_read'])>
- <label class="form-check-label" for="all-read">Все: чтение</label>
- </div>
- <div class="form-check">
- <input class="form-check-input" type="checkbox" value="1" name="all_write" id="all-write"
- @checked($permissionValues['all_write'])>
- <label class="form-check-label" for="all-write">Все: запись</label>
- </div>
- </div>
- </div>
- <div class="col-md-6">
- <label class="form-label" for="role-read">Роли: чтение</label>
- <select class="form-select" id="role-read" name="role_read_ids[]" multiple size="5">
- @foreach($roles as $role)
- <option value="{{ $role->id }}" @selected(in_array($role->id, $permissionValues['role_read_ids'], true))>{{ $role->name }}</option>
- @endforeach
- </select>
- </div>
- <div class="col-md-6">
- <label class="form-label" for="role-write">Роли: запись</label>
- <select class="form-select" id="role-write" name="role_write_ids[]" multiple size="5">
- @foreach($roles as $role)
- <option value="{{ $role->id }}" @selected(in_array($role->id, $permissionValues['role_write_ids'], true))>{{ $role->name }}</option>
- @endforeach
- </select>
- </div>
- <div class="col-md-6">
- <label class="form-label" for="user-read">Пользователи: чтение</label>
- <select class="form-select" id="user-read" name="user_read_ids[]" multiple size="7">
- @foreach($users as $user)
- <option value="{{ $user->id }}" @selected(in_array($user->id, $permissionValues['user_read_ids'], true))>
- {{ $user->name }} ({{ $user->email }})
- </option>
- @endforeach
- </select>
- </div>
- <div class="col-md-6">
- <label class="form-label" for="user-write">Пользователи: запись</label>
- <select class="form-select" id="user-write" name="user_write_ids[]" multiple size="7">
- @foreach($users as $user)
- <option value="{{ $user->id }}" @selected(in_array($user->id, $permissionValues['user_write_ids'], true))>
- {{ $user->name }} ({{ $user->email }})
- </option>
- @endforeach
- </select>
- </div>
- </div>
- <p class="small text-muted mt-3 mb-2">Право записи автоматически включает чтение. При включённом наследовании собственные правила удаляются.</p>
- <button class="btn btn-primary" type="submit">Сохранить права</button>
- </form>
- </div>
- </div>
- </div>
- @endif
- <form action="{{ route('documents.index') }}" method="GET" class="row g-2 mb-3">
- <input type="hidden" name="folder" value="{{ $selectedFolder->id }}">
- <div class="col-md-10">
- <input class="form-control" name="search" value="{{ $search }}" placeholder="Поиск документа по названию">
- </div>
- <div class="col-md-2">
- <button class="btn btn-outline-primary w-100" type="submit"><i class="bi bi-search"></i> Найти</button>
- </div>
- </form>
- <div class="card">
- <div class="table-responsive">
- <table class="table table-hover align-middle mb-0">
- <thead>
- <tr>
- <th>Документ</th>
- <th>Текущая версия</th>
- <th>Обновлён</th>
- <th>Автор</th>
- <th class="text-end">Действия</th>
- </tr>
- </thead>
- <tbody>
- @forelse($documents as $document)
- @php($currentVersion = $document->currentVersion)
- <tr>
- <td class="text-break">
- @if($currentVersion?->isImage())
- <a href="{{ route('documents.versions.preview', $currentVersion) }}" target="_blank" rel="noopener"
- class="text-body text-decoration-none" title="Открыть изображение">
- <i class="{{ $currentVersion->iconClass() }} me-1"></i>{{ $document->name }}
- </a>
- @else
- <i class="{{ $currentVersion?->iconClass() ?? 'bi bi-file-earmark' }} me-1"></i>{{ $document->name }}
- @endif
- <details class="mt-2">
- <summary class="small text-primary" style="cursor: pointer">Все версии ({{ $document->versions->count() }})</summary>
- <div class="mt-2">
- @foreach($document->versions as $version)
- <div class="d-flex flex-wrap align-items-center gap-2 border-top py-2 small">
- <span class="badge text-bg-secondary">v{{ $version->version }}</span>
- @if($version->isImage())
- <a href="{{ route('documents.versions.preview', $version) }}" target="_blank" rel="noopener"
- class="text-body text-decoration-none" title="Открыть изображение">
- <i class="{{ $version->iconClass() }}"></i> {{ $version->file?->original_name }}
- </a>
- @else
- <span><i class="{{ $version->iconClass() }}"></i> {{ $version->file?->original_name }}</span>
- @endif
- <span class="text-muted">{{ number_format($version->file_size / 1024, 1, ',', ' ') }} КБ</span>
- <span class="text-muted">{{ $version->created_at?->format('d.m.Y H:i') }}</span>
- <a class="btn btn-sm btn-outline-primary" href="{{ route('documents.versions.download', $version) }}">Скачать</a>
- @if($canWrite)
- <form action="{{ route('documents.versions.destroy', $version) }}" method="POST"
- onsubmit="return confirm('Полностью удалить эту версию?')">
- @csrf
- @method('DELETE')
- <button class="btn btn-sm btn-outline-danger" type="submit">Удалить</button>
- </form>
- @endif
- </div>
- @endforeach
- </div>
- </details>
- </td>
- <td>v{{ $currentVersion?->version }}</td>
- <td>{{ $currentVersion?->created_at?->format('d.m.Y H:i') }}</td>
- <td>{{ $currentVersion?->creator?->name }}</td>
- <td class="text-end">
- @if($currentVersion)
- <a class="btn btn-sm btn-outline-primary mb-1" href="{{ route('documents.versions.download', $currentVersion) }}">
- <i class="bi bi-download"></i>
- </a>
- @endif
- @if($canWrite)
- <button class="btn btn-sm btn-outline-secondary mb-1" type="button" data-bs-toggle="collapse"
- data-bs-target="#document-actions-{{ $document->id }}">
- <i class="bi bi-pencil"></i>
- </button>
- @endif
- </td>
- </tr>
- @if($canWrite)
- <tr class="collapse" id="document-actions-{{ $document->id }}">
- <td colspan="5" class="bg-light">
- <div class="row g-3">
- <div class="col-lg-6">
- <form action="{{ route('documents.update', $document) }}" method="POST" class="d-flex gap-2">
- @csrf
- @method('PUT')
- <input class="form-control form-control-sm" name="name" value="{{ $document->name }}" maxlength="255" required>
- <button class="btn btn-sm btn-outline-primary" type="submit">Переименовать</button>
- </form>
- </div>
- <div class="col-lg-6">
- <form action="{{ route('documents.versions.store', $document) }}" method="POST" enctype="multipart/form-data" class="d-flex gap-2">
- @csrf
- <input class="form-control form-control-sm" type="file" name="file" required>
- <button class="btn btn-sm btn-outline-primary" type="submit">Новая версия</button>
- </form>
- </div>
- <div class="col-12">
- <form action="{{ route('documents.destroy', $document) }}" method="POST"
- onsubmit="return confirm('Полностью удалить документ и все версии?')">
- @csrf
- @method('DELETE')
- <button class="btn btn-sm btn-outline-danger" type="submit">Удалить документ</button>
- </form>
- </div>
- </div>
- </td>
- </tr>
- @endif
- @empty
- <tr>
- <td colspan="5" class="text-center text-muted py-4">
- {{ $search !== '' ? 'Документы по запросу не найдены.' : 'В папке пока нет документов.' }}
- </td>
- </tr>
- @endforelse
- </tbody>
- </table>
- </div>
- </div>
- @if($documents->hasPages())
- <div class="mt-3">
- {{ $documents->links() }}
- </div>
- @endif
- @else
- <div class="card card-body text-center text-muted py-5">
- <i class="bi bi-folder2-open fs-1"></i>
- <p class="mb-0 mt-2">Выберите доступную папку или создайте новую.</p>
- </div>
- @endif
- </div>
- </div>
- @endsection
|