basic pages functions
parent
667b13c76c
commit
cf18dea146
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Pages;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Pages\Page;
|
||||
use App\Transformers\Pages\PageTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class PagesController extends Controller {
|
||||
protected Page $model;
|
||||
|
||||
public function __construct(Page $model) {
|
||||
$this->model = $model;
|
||||
}
|
||||
|
||||
public function root(Request $request): JsonResponse {
|
||||
return fractal(Page::root(), new PageTransformer())->respond();
|
||||
}
|
||||
|
||||
public function index(Request $request): JsonResponse {
|
||||
$query = $this->model->query();
|
||||
$paginator = $query->paginate(config('app.pagination_limit'));
|
||||
return fractal($paginator, new PageTransformer())->respond();
|
||||
}
|
||||
|
||||
public function show($id): JsonResponse {
|
||||
$model = $this->model->byUuid($id)->firstOrFail();
|
||||
return fractal($model, new PageTransformer())->respond();
|
||||
}
|
||||
|
||||
|
||||
public function store(Request $request): void {
|
||||
}
|
||||
|
||||
|
||||
public function update(Request $request, $uuid): void {
|
||||
}
|
||||
|
||||
public function destroy(Request $request, $uuid): JsonResponse {
|
||||
$model = $this->model->byUuid($uuid)->firstOrFail();
|
||||
$model->delete();
|
||||
return response()->json(null, 204);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models\Pages;
|
||||
|
||||
use App\Support\HasObjectsTrait;
|
||||
use App\Support\RelationValuesTrait;
|
||||
use App\Support\UuidScopeTrait;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class Page extends Model {
|
||||
use UuidScopeTrait, SoftDeletes, HasObjectsTrait, RelationValuesTrait;
|
||||
|
||||
protected $dates = [
|
||||
];
|
||||
|
||||
protected $fillable = [
|
||||
'uuid',
|
||||
'parent_id',
|
||||
'slug',
|
||||
'type',
|
||||
'name',
|
||||
'title',
|
||||
'h1',
|
||||
'ord'
|
||||
];
|
||||
|
||||
protected $hidden = [
|
||||
'id'
|
||||
];
|
||||
|
||||
|
||||
public function parent(): BelongsTo {
|
||||
return $this->belongsTo(Page::class, 'parent_id');
|
||||
}
|
||||
|
||||
public function children(): HasMany {
|
||||
return $this->hasMany(Page::class, 'parent_id');
|
||||
}
|
||||
|
||||
public function sections(): MorphToMany {
|
||||
return $this->objects()->whereHas('type.parent', function($query) {
|
||||
$query->where(['name' => 'page-section']);
|
||||
});
|
||||
}
|
||||
|
||||
public function sidebar(): Model {
|
||||
return $this->getObject('page-sidebar');
|
||||
}
|
||||
public function sidebars(): MorphToMany {
|
||||
return $this->objects()->whereHas('type', function($query) {
|
||||
$query->where(['name' => 'page-sidebar']);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public function getLinkAttribute(): string {
|
||||
return $this->parents->reverse()->push($this)->pluck('slug')->implode('/');
|
||||
}
|
||||
|
||||
public function getParentsAttribute(): Collection {
|
||||
$page = $this;
|
||||
$result = collect([]);
|
||||
while($page = $page->parent) $result->push($page);
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getParsedTypeAttribute(): array {
|
||||
return ['name' => $this->type, 'title' => PageType::TITLES[$this->type] ?? null];
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function addSection($typeName, $ord) {
|
||||
$this->createObject($typeName, $ord);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static function root() {
|
||||
return self::query()->where(['parent_id' => 0])->get();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models\Pages;
|
||||
|
||||
class PageType {
|
||||
public const CONTENT = 'content';
|
||||
|
||||
public const TITLES = [
|
||||
self::CONTENT => 'Контентная страница'
|
||||
];
|
||||
}
|
||||
|
|
@ -2,47 +2,18 @@
|
|||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Models\Advisories\Advisory;
|
||||
use App\Models\Advisories\AdvisoryMember;
|
||||
use App\Models\Advisories\AdvisorySession;
|
||||
use App\Models\Advisories\SessionInvitation;
|
||||
use App\Models\Applications\Application;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Catalog\Category;
|
||||
use App\Models\Classification\Classifier;
|
||||
use App\Models\Classification\Code;
|
||||
use App\Models\Companies\Address;
|
||||
use App\Models\Companies\BankDetails;
|
||||
use App\Models\Companies\Company;
|
||||
use App\Models\Companies\CompanyMember;
|
||||
use App\Models\Companies\Contact;
|
||||
use App\Models\Companies\Department;
|
||||
use App\Models\Correspondence\Letter;
|
||||
use App\Models\Dictionaries\Dictionary;
|
||||
use App\Models\Dictionaries\DictionaryItem;
|
||||
use App\Models\Normatives\Development\Development;
|
||||
use App\Models\Normatives\Development\DevelopmentStage;
|
||||
use App\Models\Normatives\Normative;
|
||||
use App\Models\Normatives\Plans\Plan;
|
||||
use App\Models\Notes\Note;
|
||||
use App\Models\Objects\Field;
|
||||
use App\Models\Objects\FieldsGroup;
|
||||
use App\Models\Objects\NirObject;
|
||||
use App\Models\Objects\ObjectType;
|
||||
use App\Models\Pages\Page;
|
||||
use App\Models\Permission;
|
||||
use App\Models\Polls\Poll;
|
||||
use App\Models\Polls\PollInvitation;
|
||||
use App\Models\Processes\Demand;
|
||||
use App\Models\Processes\Participant;
|
||||
use App\Models\Processes\Performer;
|
||||
use App\Models\Processes\Process;
|
||||
use App\Models\Processes\Scenario;
|
||||
use App\Models\Processes\Stage;
|
||||
use App\Models\Processes\Task;
|
||||
use App\Models\Role;
|
||||
use App\Models\SocialProvider;
|
||||
use App\Models\User;
|
||||
use App\Models\UserKey;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
|
@ -82,7 +53,9 @@ class AppServiceProvider extends ServiceProvider
|
|||
'object-field' => Field::class,
|
||||
'fields-group' => FieldsGroup::class,
|
||||
'object' => NirObject::class,
|
||||
'object-type' => ObjectType::class
|
||||
'object-type' => ObjectType::class,
|
||||
|
||||
'page' => Page::class
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
|||
|
||||
trait HasObjectsTrait {
|
||||
public function objects(): MorphToMany {
|
||||
return $this->morphToMany(NirObject::class, 'objectable')->withTimestamps();
|
||||
return $this->morphToMany(NirObject::class, 'objectable')->orderByPivot('ord')->withTimestamps();
|
||||
}
|
||||
|
||||
public function getObjectAttribute() {
|
||||
|
|
@ -21,8 +21,13 @@ trait HasObjectsTrait {
|
|||
return ($type = ObjectType::query()->where(['name' => $typeName])->first()) ? $this->objects()->firstOrCreate(['type_id' => $type->id]) : null;
|
||||
}
|
||||
|
||||
public function createObject($typeName): ?Model {
|
||||
return ($type = ObjectType::query()->where(['name' => $typeName])->first()) ? $this->objects()->create(['type_id' => $type->id]) : null;
|
||||
public function createObject($typeName, $ord = null): ?Model {
|
||||
if (($type = ObjectType::query()->where(['name' => $typeName])->first()) && ($object = NirObject::create(['type_id' => $type->id]))) {
|
||||
if ($ord !== null) $ord = ($res = $this->objects()->where(['type_id' => $type->id])->withPivot('ord')->reorder()->orderByPivot('ord', 'desc')->first()) ? ($res->pivot->ord + 1) : 0;
|
||||
$this->objects()->attach($object->id, ['ord' => $ord]);
|
||||
return $object;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getValue($fieldName) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
namespace App\Transformers\Pages;
|
||||
|
||||
use App\Models\Pages\Page;
|
||||
use App\Services\PermissionsService;
|
||||
use App\Transformers\Objects\ObjectTransformer;
|
||||
use League\Fractal\Resource\Collection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Resource\Primitive;
|
||||
use League\Fractal\TransformerAbstract;
|
||||
|
||||
class PageTransformer extends TransformerAbstract {
|
||||
protected array $defaultIncludes = [
|
||||
|
||||
];
|
||||
|
||||
protected array $availableIncludes = [
|
||||
'children', 'parent', 'sections', 'sidebars', 'permissions'
|
||||
];
|
||||
|
||||
public function transform(Page $model): array {
|
||||
return [
|
||||
'id' => $model->uuid,
|
||||
'slug' => $model->slug,
|
||||
'link' => $model->link,
|
||||
'type' => $model->parsedType,
|
||||
'name' => $model->name,
|
||||
'title' => $model->title,
|
||||
'h1' => $model->h1,
|
||||
'created_at' => $model->created_at ? $model->created_at->toIso8601String() : null,
|
||||
'updated_at' => $model->updated_at ? $model->updated_at->toIso8601String() : null
|
||||
];
|
||||
}
|
||||
|
||||
public function includeChildren(Page $model): Collection {
|
||||
return $this->collection($model->children, new PageTransformer());
|
||||
}
|
||||
|
||||
public function includeParent(Page $model): ?Item {
|
||||
return $model->parent ? $this->item($model->parent, new PageTransformer()) : null;
|
||||
}
|
||||
|
||||
public function includeSections(Page $model): Collection {
|
||||
return $this->collection($model->sections, new ObjectTransformer());
|
||||
}
|
||||
|
||||
public function includeSidebars(Page $model): Collection {
|
||||
return $this->collection($model->sidebars, new ObjectTransformer());
|
||||
}
|
||||
|
||||
public function includePermissions(Page $model): Primitive {
|
||||
return $this->primitive((new PermissionsService($model))->get());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ class CreateObjectablesTable extends Migration
|
|||
$table->id();
|
||||
$table->integer('nir_object_id')->index()->nullable();
|
||||
$table->nullableMorphs('objectable');
|
||||
$table->integer('ord')->index()->default(0);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreatePagesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('pages', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->char('uuid', 36)->index()->unique();
|
||||
$table->integer('parent_id')->index()->default(0);
|
||||
$table->string('slug')->index()->nullable();
|
||||
$table->string('type')->index()->nullable();
|
||||
$table->string('name')->index()->nullable();
|
||||
$table->string('title')->index()->nullable();
|
||||
$table->string('h1')->index()->nullable();
|
||||
$table->integer('ord')->index()->default(0);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('pages');
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ namespace Database\Seeders;
|
|||
|
||||
use Database\Seeders\Dictionaries\DictionariesTablesSeeder;
|
||||
use Database\Seeders\Objects\ObjectsTablesSeeder;
|
||||
use Database\Seeders\Pages\PagesTableSeeder;
|
||||
use Database\Seeders\Users\RoleTableSeeder;
|
||||
use Database\Seeders\Users\UsersTableSeeder;
|
||||
|
||||
|
|
@ -15,5 +16,6 @@ class DatabaseSeeder extends Seeder {
|
|||
$this->call(UsersTableSeeder::class);
|
||||
$this->call(ObjectsTablesSeeder::class);
|
||||
$this->call(DictionariesTablesSeeder::class);
|
||||
$this->call(PagesTableSeeder::class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@ use Illuminate\Database\Seeder;
|
|||
|
||||
class DictionariesTableSeeder extends Seeder {
|
||||
public array $dictionaries = [
|
||||
'list-types' => [
|
||||
'title' => 'Виды списка',
|
||||
'items' => ['marked' => 'Маркированный', 'numeric' => 'Нумерованный']
|
||||
]
|
||||
];
|
||||
|
||||
public function run() {
|
||||
|
|
|
|||
|
|
@ -2,12 +2,78 @@
|
|||
|
||||
namespace Database\Seeders\Objects;
|
||||
|
||||
use App\Models\Dictionaries\DictionaryItem;
|
||||
use App\Models\Objects\Field;
|
||||
use App\Models\Objects\FieldType;
|
||||
use App\Transformers\Dictionaries\DictionaryItemTransformer;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class FieldsTableSeeder extends Seeder {
|
||||
public array $fields = [
|
||||
'header' => [
|
||||
'title' => 'Текст заголовка',
|
||||
'type' => FieldType::TEXT
|
||||
],
|
||||
'header-required' => [
|
||||
'title' => 'Текст заголовка',
|
||||
'type' => FieldType::TEXT,
|
||||
'required' => true
|
||||
],
|
||||
|
||||
'subheader' => [
|
||||
'title' => 'Текст подзаголовка',
|
||||
'type' => FieldType::TEXT
|
||||
],
|
||||
'subheader-required' => [
|
||||
'title' => 'Текст подзаголовка',
|
||||
'type' => FieldType::TEXT,
|
||||
'required' => true
|
||||
],
|
||||
|
||||
'documents' => [
|
||||
'title' => 'Документы',
|
||||
'type' => FieldType::DOCUMENT,
|
||||
'multiple' => true
|
||||
],
|
||||
'documents-required' => [
|
||||
'title' => 'Документы',
|
||||
'type' => FieldType::DOCUMENT,
|
||||
'multiple' => true,
|
||||
'required' => true
|
||||
],
|
||||
|
||||
'text' => [
|
||||
'title' => 'Содержимое текстового блока',
|
||||
'type' => FieldType::TEXT
|
||||
],
|
||||
'text-required' => [
|
||||
'title' => 'Содержимое текстового блока',
|
||||
'type' => FieldType::TEXT,
|
||||
'required' => true
|
||||
],
|
||||
|
||||
'list-type' => [
|
||||
'title' => 'Вид списка',
|
||||
'type' => FieldType::RELATION,
|
||||
'required' => true,
|
||||
'params' => [
|
||||
'related' => DictionaryItem::class, 'transformer' => DictionaryItemTransformer::class,
|
||||
'options' => ['show' => true, 'whereHas' => ['dictionary' => ['name' => 'list-types']]]
|
||||
]
|
||||
],
|
||||
'list-items' => [
|
||||
'title' => 'Элементы списка',
|
||||
'type' => FieldType::TEXT,
|
||||
'multiple' => true,
|
||||
'required' => true
|
||||
],
|
||||
|
||||
'images' => [
|
||||
'title' => 'Изображения',
|
||||
'type' => FieldType::IMAGE,
|
||||
'multiple' => true,
|
||||
'required' => true
|
||||
]
|
||||
];
|
||||
|
||||
public function run() {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,41 @@ use Illuminate\Database\Seeder;
|
|||
|
||||
class ObjectTypeFieldsTableSeeder extends Seeder {
|
||||
public array $objectTypeFields = [
|
||||
'page-sidebar' => [
|
||||
'common' => [
|
||||
'fields' => ['header', 'subheader', 'documents']
|
||||
]
|
||||
],
|
||||
'page-section-header' => [
|
||||
'common' => [
|
||||
'fields' => ['header-required']
|
||||
]
|
||||
],
|
||||
'page-section-subheader' => [
|
||||
'common' => [
|
||||
'fields' => ['subheader-required']
|
||||
]
|
||||
],
|
||||
'page-section-text' => [
|
||||
'common' => [
|
||||
'fields' => ['text-required']
|
||||
]
|
||||
],
|
||||
'page-section-list' => [
|
||||
'common' => [
|
||||
'fields' => ['list-type', 'list-items']
|
||||
]
|
||||
],
|
||||
'page-section-images' => [
|
||||
'common' => [
|
||||
'fields' => ['images']
|
||||
]
|
||||
],
|
||||
'page-section-videos' => [
|
||||
'common' => [
|
||||
'fields' => []
|
||||
]
|
||||
]
|
||||
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,32 @@ use Illuminate\Database\Seeder;
|
|||
|
||||
class ObjectTypesTableSeeder extends Seeder {
|
||||
public array $types = [
|
||||
|
||||
'page-sidebar' => [
|
||||
'title' => 'Сторонний блок контентной страницы'
|
||||
],
|
||||
'page-section' => [
|
||||
'title' => 'Секция контентной страницы',
|
||||
'children' => [
|
||||
'page-section-header' => [
|
||||
'title' => 'Заголовок'
|
||||
],
|
||||
'page-section-subheader' => [
|
||||
'title' => 'Подзаголовок'
|
||||
],
|
||||
'page-section-text' => [
|
||||
'title' => 'Текст'
|
||||
],
|
||||
'page-section-list' => [
|
||||
'title' => 'Список'
|
||||
],
|
||||
'page-section-images' => [
|
||||
'title' => 'Изображения'
|
||||
],
|
||||
'page-section-videos' => [
|
||||
'title' => 'Видео'
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
public function run() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders\Pages;
|
||||
|
||||
use App\Models\Pages\Page;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class PagesTableSeeder extends Seeder {
|
||||
public array $pages = [
|
||||
'О центре' => [
|
||||
'children' => [
|
||||
'Руководство' => [
|
||||
|
||||
],
|
||||
'Документы' => [
|
||||
'children' => [
|
||||
'Документы об учреждении' => [],
|
||||
'Закупки' => [],
|
||||
'Бухгалтерская отчетность' => [],
|
||||
'Государственное задание' => [],
|
||||
'Нормативные правовые акты' => [],
|
||||
'Антимонопольное законодательство' => [],
|
||||
'Специальная оценка условий труда' => []
|
||||
]
|
||||
],
|
||||
'Структура' => [
|
||||
|
||||
],
|
||||
'Наблюдательный совет' => [
|
||||
'children' => [
|
||||
'Структура' => [],
|
||||
'Документы' => [],
|
||||
'Решения' => []
|
||||
]
|
||||
],
|
||||
'Закупки' => [
|
||||
|
||||
],
|
||||
'Противодействие коррупции' => [
|
||||
'children' => [
|
||||
'ФЗ, указы, постановления' => [],
|
||||
'Ведомственные нормативные правовые акты' => [],
|
||||
'Внутренние нормативные документы' => [],
|
||||
'Антикоррупционная экспертиза' => [],
|
||||
'Методические материалы' => [],
|
||||
'Формы документов для заполнения' => [],
|
||||
'Финансовые сведения' => [],
|
||||
'Aттестационная комиссия' => [],
|
||||
'Обратная связь' => [],
|
||||
'Остальные документы' => []
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
'Деятельность' => [
|
||||
|
||||
],
|
||||
'Коммерческие услуги' => [
|
||||
|
||||
],
|
||||
'Пресс-центр' => [
|
||||
|
||||
],
|
||||
'Контакты' => [
|
||||
|
||||
]
|
||||
];
|
||||
|
||||
public function run() {
|
||||
$ord = 0;
|
||||
collect($this->pages)->each(function($data, $name) use(&$ord) {
|
||||
$data['ord'] = $ord++;
|
||||
$this->importPage($name, $data);
|
||||
});
|
||||
}
|
||||
|
||||
public function importPage($name, $data, ?Page $parent = null) {
|
||||
$slug = Str::slug(Str::transliterate($name));
|
||||
$page = Page::firstOrCreate(['parent_id' => $parent->id ?? 0, 'slug' => $slug]);
|
||||
$page->update(['name' => $name]);
|
||||
if ($v = collect($data)->except('children')->all()) $page->update($v);
|
||||
$ord = 0;
|
||||
collect($data['children'] ?? [])->each(function($data, $name) use($page, &$ord) {
|
||||
$data['ord'] = $ord++;
|
||||
$this->importPage($name, $data, $page);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders\Pages;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class PagesTablesSeeder extends Seeder {
|
||||
public function run() {
|
||||
$this->call(PagesTableSeeder::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,10 @@ Route::put('passwords/reset', 'Api\Auth\PasswordsController@update');
|
|||
|
||||
Route::get('/check-email', 'Api\Auth\RegisterController@checkEmail');
|
||||
|
||||
Route::get('pages', 'Api\Pages\PagesController@index');
|
||||
Route::get('pages/root', 'Api\Pages\PagesController@root');
|
||||
Route::get('pages/{id}', 'Api\Pages\PagesController@show');
|
||||
|
||||
Route::group(['middleware' => ['auth:api']], function() {
|
||||
Route::apiResource('users', 'Api\Users\UsersController');
|
||||
Route::apiResource('roles', 'Api\Users\RolesController');
|
||||
|
|
|
|||
Loading…
Reference in New Issue