feat(analytics): add site analytics with grouped navigation sections
- Add Analytics container: models, tasks, jobs, controllers, routes, services - Add analytics config with section groups (structure, institute, content, services) - Add database tables: analytics_sessions, analytics_hits, analytics_daily_stats - Add frontend: Analytics page, section detail, chart, overview, navigation components - Add consent banner and JS tracking service (sendBeacon + Inertia listener) - Add permission sync for view_analytics, view_any_analytic - Fix trailing slash URL matching in GetNavigationSectionsTask - Fix event propagation on expand arrows in navigation sections - Fix RecordVisitJob to not depend on dropped analytics_geo_cache table - Replace plain text views/visitors with badge-style icons - Group navigation sections by category with separate blocks - Add config-driven non-CMS sections (faculties, divisions, DPO, journals) - Remove Events, TV, Sveden from analytics sections
This commit is contained in:
@@ -12,7 +12,7 @@ class EducationalGroupFactory extends Factory
|
||||
{
|
||||
return [
|
||||
'title' => $this->faker->words(3, true),
|
||||
'faculty_id' => \App\Containers\InstituteStructure\Models\Faculty::factory(),
|
||||
'faculty_id' => \App\Containers\InstituteStructure\Models\Faculty::inRandomOrder()->first(),
|
||||
'education_form_id' => $this->faker->numberBetween(1, 3),
|
||||
'created_at' => $this->faker->dateTimeBetween('-1 year', 'now'),
|
||||
'updated_at' => $this->faker->dateTimeBetween('-1 year', 'now'),
|
||||
|
||||
@@ -6,23 +6,13 @@ use App\Containers\Event\Models\EventCategory;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Event>
|
||||
*/
|
||||
class EventFactory extends Factory
|
||||
{
|
||||
protected $model = \App\Containers\Event\Models\Event::class;
|
||||
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
$id = $this->faker->numberBetween(1, 1000000);
|
||||
$title = $this->faker->sentence;
|
||||
$slug = Str::slug($title);
|
||||
$content = array_map(function () {
|
||||
return [
|
||||
'type' => $this->faker->randomElement(['heading', 'paragraph']),
|
||||
@@ -32,29 +22,26 @@ class EventFactory extends Factory
|
||||
],
|
||||
];
|
||||
}, range(1, $this->faker->numberBetween(1, 5)));
|
||||
$today = now();
|
||||
$random_days = rand(1, 25); // Генерируем случайное число дней от 1 до 365
|
||||
$event_date_start = date('Y-m-d', strtotime($today->format('Y-m-d') . ' +' . $random_days . ' days'));
|
||||
$event_time_start = $this->faker->time('H:i');
|
||||
$address = $this->faker->address;
|
||||
$is_online = $this->faker->randomElement([true, false]);
|
||||
$category_id = EventCategory::inRandomOrder()->first();
|
||||
$created_at = now();
|
||||
$updated_at = now();
|
||||
|
||||
$eventDateStart = $this->faker->dateTimeBetween('-6 months', 'now');
|
||||
$endDate = date('Y-m-d', strtotime($eventDateStart->format('Y-m-d') . ' +' . rand(1, 30) . ' days'));
|
||||
$eventDateEnd = $this->faker->optional(0.5)->dateTimeBetween(
|
||||
$eventDateStart->format('Y-m-d'),
|
||||
$endDate
|
||||
);
|
||||
|
||||
return [
|
||||
'id' => $id,
|
||||
'title' => $title,
|
||||
'slug' => $slug,
|
||||
'slug' => Str::slug($title),
|
||||
'content' => $content,
|
||||
'event_date_start' => $event_date_start,
|
||||
'event_time_start' => $event_time_start,
|
||||
'address' => $address,
|
||||
'is_online' => $is_online,
|
||||
'category_id' => $category_id,
|
||||
'created_at' => $created_at,
|
||||
'updated_at' => $updated_at,
|
||||
'event_date_start' => $eventDateStart->format('Y-m-d'),
|
||||
'event_date_end' => $eventDateEnd?->format('Y-m-d'),
|
||||
'event_time_start' => $this->faker->time('H:i'),
|
||||
'address' => $this->faker->address,
|
||||
'is_online' => $this->faker->boolean,
|
||||
'category_id' => EventCategory::factory(),
|
||||
'created_at' => $this->faker->dateTimeBetween('-6 months', 'now'),
|
||||
'updated_at' => $this->faker->dateTimeBetween('-6 months', 'now'),
|
||||
];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ class PageFactory extends Factory
|
||||
return [
|
||||
'title' => $title,
|
||||
'slug' => $slug,
|
||||
'path' => $slug,
|
||||
'content' => [['type' => 'paragraph', 'data' => ['content' => $this->faker->paragraph]]],
|
||||
'is_registered' => false,
|
||||
'is_visible' => true,
|
||||
|
||||
@@ -43,12 +43,12 @@ class UserDetailFactory extends Factory
|
||||
'photo' => "images/01J7TKMCR55KY7ARS2DA6VVAHE.jpg",
|
||||
'academicTitle' => $this->faker->word,
|
||||
'AcademicDegree' => $this->faker->word,
|
||||
'education' => $this->faker->sentence,
|
||||
'education' => [['item' => $this->faker->sentence(6)]],
|
||||
'awards' => $awards,
|
||||
'professDisciplines' => $generateItems(),
|
||||
'professionalRetraining' => $generateItems(),
|
||||
'professionalDevelopment' => $generateItems(),
|
||||
'workExperience' => $this->faker->randomDigit(),
|
||||
'workExperience' => $generateItems(),
|
||||
'attendedConferences' => $generateItems(),
|
||||
'publications' => $generateItems(),
|
||||
'contactEmail' => $this->faker->unique()->safeEmail,
|
||||
|
||||
Reference in New Issue
Block a user