meetups added

This commit is contained in:
Benjamin Takats
2022-12-12 17:44:24 +01:00
parent ad8444b5c5
commit 648bc6395a
41 changed files with 995 additions and 93 deletions

View File

@@ -1,28 +1,33 @@
created:
- database/factories/OrangePillFactory.php
- database/migrations/2022_12_07_095709_create_orange_pills_table.php
- app/Models/OrangePill.php
- app/Nova/OrangePill.php
- database/factories/MeetupFactory.php
- database/factories/MeetupEventFactory.php
- database/migrations/2022_12_12_155928_create_meetups_table.php
- database/migrations/2022_12_12_155929_create_meetup_events_table.php
- app/Models/Meetup.php
- app/Models/MeetupEvent.php
- app/Nova/Meetup.php
- app/Nova/MeetupEvent.php
models:
BookCase: { title: string, latitude: 'float:10', longitude: 'float:10', address: 'text nullable', type: string, open: 'string nullable', comment: 'text nullable', contact: 'text nullable', bcz: 'text nullable', digital: boolean, icontype: string, deactivated: boolean, deactreason: string, entrytype: string, homepage: 'text nullable' }
Category: { name: string, slug: string }
City: { country_id: biginteger, name: string, slug: string, longitude: 'float:10', latitude: 'float:10' }
Country: { name: string, code: string, language_codes: 'json default:[]' }
Course: { lecturer_id: biginteger, name: string, description: 'text nullable' }
CourseEvent: { course_id: biginteger, venue_id: biginteger, '"from"': datetime, '"to"': datetime, link: string }
Episode: { guid: string, podcast_id: biginteger, data: json }
Event: { course_id: biginteger, venue_id: biginteger, '"from"': datetime, '"to"': datetime, link: string }
Lecturer: { team_id: biginteger, name: string, slug: string, active: 'boolean default:1', description: 'text nullable' }
Library: { name: string, is_public: 'boolean default:1', language_codes: 'json default:[]' }
LibraryItem: { lecturer_id: biginteger, episode_id: 'biginteger nullable', order_column: integer, name: string, type: string, language_code: string, value: 'text nullable' }
LoginKey: { k1: string, user_id: biginteger }
Membership: { team_id: biginteger, user_id: biginteger, role: 'string nullable' }
OrangePill: { user_id: biginteger, book_case_id: biginteger, date: datetime, amount: integer }
Participant: { first_name: string, last_name: string }
Podcast: { guid: string, title: string, link: string, language_code: string, data: json }
Registration: { event_id: biginteger, participant_id: biginteger, active: 'boolean default:1' }
Podcast: { guid: string, locked: 'boolean default:1', title: string, link: string, language_code: string, data: 'json nullable' }
Registration: { course_event_id: biginteger, participant_id: biginteger, active: 'boolean default:1' }
Tag: { name: json, slug: json, type: 'string nullable', order_column: 'integer nullable', icon: 'string default:tag' }
Team: { user_id: biginteger, name: string, personal_team: boolean }
TeamInvitation: { team_id: biginteger, email: string, role: 'string nullable' }
User: { name: string, public_key: 'string nullable', email: 'string nullable', email_verified_at: 'datetime nullable', password: 'string nullable', remember_token: 'string:100 nullable', current_team_id: 'biginteger nullable', profile_photo_path: 'string:2048 nullable', is_lecturer: 'boolean default:', two_factor_secret: 'text nullable', two_factor_recovery_codes: 'text nullable', two_factor_confirmed_at: 'datetime nullable', timezone: 'string default:Europe/Berlin' }
Venue: { city_id: biginteger, name: string, slug: string, street: string }
Case: { title: string, lat: double, lon: json, address: text, type: string, open: string, comment: text, contact: text, bcz: text, digital: boolean, icontype: string, deactivated: boolean, deactreason: string, entrytype: string, homepage: string }
BookCase: { title: string, lat: double, lon: json, address: text, type: string, open: string, comment: text, contact: text, bcz: text, digital: boolean, icontype: string, deactivated: boolean, deactreason: string, entrytype: string, homepage: string }
OrangePill: { user_id: foreign, book_case_id: foreign, date: datetime, amount: 'integer unsigned' }
Meetup: { city_id: foreign, name: 'string unique', link: string }
MeetupEvent: { meetup_id: foreign, date: date, start: time, end: time, location: string, description: text, link: string }

View File

@@ -0,0 +1,15 @@
<?php
namespace App\Http\Livewire\Meetup;
use App\Models\Country;
use Livewire\Component;
class MeetupEventTable extends Component
{
public Country $country;
public function render()
{
return view('livewire.meetup.meetup-event-table');
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace App\Http\Livewire\Meetup;
use App\Models\Country;
use Livewire\Component;
class MeetupTable extends Component
{
public Country $country;
public function render()
{
return view('livewire.meetup.meetup-table');
}
}

View File

@@ -3,7 +3,7 @@
namespace App\Http\Livewire\Tables;
use App\Models\Category;
use App\Models\Event;
use App\Models\CourseEvent;
use App\Models\Lecturer;
use Illuminate\Database\Eloquent\Builder;
use Rappasoft\LaravelLivewireTables\DataTableComponent;
@@ -17,7 +17,7 @@ class EventTable extends DataTableComponent
public string $country;
public bool $viewingModal = false;
public $currentModal;
protected $model = Event::class;
protected $model = CourseEvent::class;
public function configure(): void
{
@@ -157,7 +157,7 @@ class EventTable extends DataTableComponent
public function builder(): Builder
{
return Event::query()
return CourseEvent::query()
->withCount([
'registrations',
])
@@ -168,7 +168,7 @@ class EventTable extends DataTableComponent
public function viewHistoryModal($modelId): void
{
$this->viewingModal = true;
$this->currentModal = Event::findOrFail($modelId);
$this->currentModal = CourseEvent::findOrFail($modelId);
}
public function resetModal(): void

View File

@@ -0,0 +1,35 @@
<?php
namespace App\Http\Livewire\Tables;
use Rappasoft\LaravelLivewireTables\DataTableComponent;
use Rappasoft\LaravelLivewireTables\Views\Column;
use App\Models\MeetupEvent;
class MeetupEventTable extends DataTableComponent
{
public string $country;
protected $model = MeetupEvent::class;
public function configure(): void
{
$this->setPrimaryKey('id');
}
public function columns(): array
{
return [
Column::make(__('Location'), 'location')
->sortable(),
Column::make(__('Start'), 'start')
->sortable(),
Column::make(__('Link'), 'link')
->sortable(),
Column::make("Created at", "created_at")
->sortable(),
Column::make("Updated at", "updated_at")
->sortable(),
];
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace App\Http\Livewire\Tables;
use App\Models\Meetup;
use Rappasoft\LaravelLivewireTables\DataTableComponent;
use Rappasoft\LaravelLivewireTables\Views\Column;
class MeetupTable extends DataTableComponent
{
public string $country;
protected $model = Meetup::class;
public function configure(): void
{
$this->setPrimaryKey('id');
}
public function columns(): array
{
return [
Column::make(__('Name'), 'name')
->sortable(),
Column::make(__('Link'), 'link')
->sortable(),
];
}
}

View File

@@ -52,6 +52,6 @@ class City extends Model
function events()
{
return $this->hasManyThrough(Event::class, Venue::class);
return $this->hasManyThrough(CourseEvent::class, Venue::class);
}
}

View File

@@ -66,6 +66,6 @@ class Course extends Model implements HasMedia
public function events(): \Illuminate\Database\Eloquent\Relations\HasMany
{
return $this->hasMany(Event::class);
return $this->hasMany(CourseEvent::class);
}
}

View File

@@ -5,7 +5,7 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Event extends Model
class CourseEvent extends Model
{
use HasFactory;

33
app/Models/Meetup.php Normal file
View File

@@ -0,0 +1,33 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Meetup extends Model
{
use HasFactory;
/**
* The attributes that aren't mass assignable.
*
* @var array
*/
protected $guarded = [];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'id' => 'integer',
'city_id' => 'integer',
];
public function city(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(City::class);
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class MeetupEvent extends Model
{
use HasFactory;
/**
* The attributes that aren't mass assignable.
*
* @var array
*/
protected $guarded = [];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'id' => 'integer',
'meetup_id' => 'integer',
'start' => 'datetime',
];
public function meetup(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Meetup::class);
}
}

View File

@@ -30,7 +30,7 @@ class Registration extends Model
public function event(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Event::class);
return $this->belongsTo(CourseEvent::class);
}
public function participant(): \Illuminate\Database\Eloquent\Relations\BelongsTo

View File

@@ -75,11 +75,11 @@ class Venue extends Model implements HasMedia
public function courses()
{
return $this->hasManyDeepFromRelations($this->events(), (new Event())->course());
return $this->hasManyDeepFromRelations($this->events(), (new CourseEvent())->course());
}
public function events(): \Illuminate\Database\Eloquent\Relations\HasMany
{
return $this->hasMany(Event::class);
return $this->hasMany(CourseEvent::class);
}
}

View File

@@ -11,13 +11,13 @@ use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\URL;
use Laravel\Nova\Http\Requests\NovaRequest;
class Event extends Resource
class CourseEvent extends Resource
{
/**
* The model the resource corresponds to.
* @var string
*/
public static $model = \App\Models\Event::class;
public static $model = \App\Models\CourseEvent::class;
/**
* The columns that should be searched.
* @var array

101
app/Nova/Meetup.php Normal file
View File

@@ -0,0 +1,101 @@
<?php
namespace App\Nova;
use Laravel\Nova\Fields\ID;
use Illuminate\Http\Request;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Fields\BelongsTo;
class Meetup extends Resource
{
/**
* The model the resource corresponds to.
*
* @var string
*/
public static $model = \App\Models\Meetup::class;
/**
* The single value that should be used to represent the resource when being displayed.
*
* @var string
*/
public static $title = 'name';
/**
* The columns that should be searched.
*
* @var array
*/
public static $search = [
'id',
'name',
];
/**
* Get the fields displayed by the resource.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function fields(Request $request)
{
return [
ID::make()->sortable(),
Text::make('Name')
->rules('required', 'string', 'unique:meetups,name'),
Text::make('Link')
->rules('required', 'string'),
BelongsTo::make('City')->searchable(),
];
}
/**
* Get the cards available for the request.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function cards(Request $request)
{
return [];
}
/**
* Get the filters available for the resource.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function filters(Request $request)
{
return [];
}
/**
* Get the lenses available for the resource.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function lenses(Request $request)
{
return [];
}
/**
* Get the actions available for the resource.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function actions(Request $request)
{
return [];
}
}

111
app/Nova/MeetupEvent.php Normal file
View File

@@ -0,0 +1,111 @@
<?php
namespace App\Nova;
use Illuminate\Http\Request;
use Laravel\Nova\Fields\BelongsTo;
use Laravel\Nova\Fields\DateTime;
use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Text;
class MeetupEvent extends Resource
{
/**
* The model the resource corresponds to.
* @var string
*/
public static $model = \App\Models\MeetupEvent::class;
/**
* The single value that should be used to represent the resource when being displayed.
* @var string
*/
public static $title = 'id';
/**
* The columns that should be searched.
* @var array
*/
public static $search = [
'id',
];
/**
* Get the fields displayed by the resource.
*
* @param \Illuminate\Http\Request $request
*
* @return array
*/
public function fields(Request $request)
{
return [
ID::make()
->sortable(),
DateTime::make(__('Start'), 'start'),
Text::make('Location')
->rules('required', 'string'),
Text::make('Description')
->rules('required', 'string')
->hideFromIndex(),
Text::make('Link')
->rules('required', 'string'),
BelongsTo::make('Meetup')
->searchable(),
];
}
/**
* Get the cards available for the request.
*
* @param \Illuminate\Http\Request $request
*
* @return array
*/
public function cards(Request $request)
{
return [];
}
/**
* Get the filters available for the resource.
*
* @param \Illuminate\Http\Request $request
*
* @return array
*/
public function filters(Request $request)
{
return [];
}
/**
* Get the lenses available for the resource.
*
* @param \Illuminate\Http\Request $request
*
* @return array
*/
public function lenses(Request $request)
{
return [];
}
/**
* Get the actions available for the resource.
*
* @param \Illuminate\Http\Request $request
*
* @return array
*/
public function actions(Request $request)
{
return [];
}
}

View File

@@ -46,10 +46,9 @@ class Registration extends Resource
Boolean::make('Active')
->rules('required'),
BelongsTo::make('Event'),
BelongsTo::make('Course Event'),
BelongsTo::make('Participant'),
];
}

View File

@@ -2,18 +2,18 @@
namespace App\Observers;
use App\Models\Event;
use App\Models\CourseEvent;
class EventObserver
{
/**
* Handle the Event "created" event.
*
* @param \App\Models\Event $event
* @param \App\Models\CourseEvent $event
*
* @return void
*/
public function created(Event $event)
public function created(CourseEvent $event)
{
//
}
@@ -21,11 +21,11 @@ class EventObserver
/**
* Handle the Event "updated" event.
*
* @param \App\Models\Event $event
* @param \App\Models\CourseEvent $event
*
* @return void
*/
public function updated(Event $event)
public function updated(CourseEvent $event)
{
//
}
@@ -33,11 +33,11 @@ class EventObserver
/**
* Handle the Event "deleted" event.
*
* @param \App\Models\Event $event
* @param \App\Models\CourseEvent $event
*
* @return void
*/
public function deleted(Event $event)
public function deleted(CourseEvent $event)
{
//
}
@@ -45,11 +45,11 @@ class EventObserver
/**
* Handle the Event "restored" event.
*
* @param \App\Models\Event $event
* @param \App\Models\CourseEvent $event
*
* @return void
*/
public function restored(Event $event)
public function restored(CourseEvent $event)
{
//
}
@@ -57,11 +57,11 @@ class EventObserver
/**
* Handle the Event "force deleted" event.
*
* @param \App\Models\Event $event
* @param \App\Models\CourseEvent $event
*
* @return void
*/
public function forceDeleted(Event $event)
public function forceDeleted(CourseEvent $event)
{
//
}

View File

@@ -2,11 +2,11 @@
namespace App\Policies;
use App\Models\Event;
use App\Models\CourseEvent;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class EventPolicy extends BasePolicy
class CourseEventPolicy extends BasePolicy
{
use HandlesAuthorization;
@@ -25,10 +25,11 @@ class EventPolicy extends BasePolicy
* Determine whether the user can view the model.
*
* @param \App\Models\User $user
* @param \App\Models\Event $event
* @param \App\Models\CourseEvent $courseEvent
*
* @return \Illuminate\Auth\Access\Response|bool
*/
public function view(User $user, Event $event)
public function view(User $user, CourseEvent $courseEvent)
{
return $user->is_lecturer;
}
@@ -48,22 +49,24 @@ class EventPolicy extends BasePolicy
* Determine whether the user can update the model.
*
* @param \App\Models\User $user
* @param \App\Models\Event $event
* @param \App\Models\CourseEvent $courseEvent
*
* @return \Illuminate\Auth\Access\Response|bool
*/
public function update(User $user, Event $event)
public function update(User $user, CourseEvent $courseEvent)
{
return $user->belongsToTeam($event->course->lecturer->team);
return $user->belongsToTeam($courseEvent->course->lecturer->team);
}
/**
* Determine whether the user can delete the model.
*
* @param \App\Models\User $user
* @param \App\Models\Event $event
* @param \App\Models\CourseEvent $courseEvent
*
* @return \Illuminate\Auth\Access\Response|bool
*/
public function delete(User $user, Event $event)
public function delete(User $user, CourseEvent $courseEvent)
{
//
}
@@ -72,10 +75,11 @@ class EventPolicy extends BasePolicy
* Determine whether the user can restore the model.
*
* @param \App\Models\User $user
* @param \App\Models\Event $event
* @param \App\Models\CourseEvent $courseEvent
*
* @return \Illuminate\Auth\Access\Response|bool
*/
public function restore(User $user, Event $event)
public function restore(User $user, CourseEvent $courseEvent)
{
//
}
@@ -84,10 +88,11 @@ class EventPolicy extends BasePolicy
* Determine whether the user can permanently delete the model.
*
* @param \App\Models\User $user
* @param \App\Models\Event $event
* @param \App\Models\CourseEvent $courseEvent
*
* @return \Illuminate\Auth\Access\Response|bool
*/
public function forceDelete(User $user, Event $event)
public function forceDelete(User $user, CourseEvent $courseEvent)
{
//
}

View File

@@ -0,0 +1,94 @@
<?php
namespace App\Policies;
use App\Models\MeetupEvent;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class MeetupEventPolicy extends BasePolicy
{
use HandlesAuthorization;
/**
* Determine whether the user can view any models.
*
* @param \App\Models\User $user
* @return \Illuminate\Auth\Access\Response|bool
*/
public function viewAny(User $user)
{
return true;
}
/**
* Determine whether the user can view the model.
*
* @param \App\Models\User $user
* @param \App\Models\MeetupEvent $meetupEvent
* @return \Illuminate\Auth\Access\Response|bool
*/
public function view(User $user, MeetupEvent $meetupEvent)
{
return true;
}
/**
* Determine whether the user can create models.
*
* @param \App\Models\User $user
* @return \Illuminate\Auth\Access\Response|bool
*/
public function create(User $user)
{
return true;
}
/**
* Determine whether the user can update the model.
*
* @param \App\Models\User $user
* @param \App\Models\MeetupEvent $meetupEvent
* @return \Illuminate\Auth\Access\Response|bool
*/
public function update(User $user, MeetupEvent $meetupEvent)
{
return false;
}
/**
* Determine whether the user can delete the model.
*
* @param \App\Models\User $user
* @param \App\Models\MeetupEvent $meetupEvent
* @return \Illuminate\Auth\Access\Response|bool
*/
public function delete(User $user, MeetupEvent $meetupEvent)
{
return false;
}
/**
* Determine whether the user can restore the model.
*
* @param \App\Models\User $user
* @param \App\Models\MeetupEvent $meetupEvent
* @return \Illuminate\Auth\Access\Response|bool
*/
public function restore(User $user, MeetupEvent $meetupEvent)
{
return false;
}
/**
* Determine whether the user can permanently delete the model.
*
* @param \App\Models\User $user
* @param \App\Models\MeetupEvent $meetupEvent
* @return \Illuminate\Auth\Access\Response|bool
*/
public function forceDelete(User $user, MeetupEvent $meetupEvent)
{
return false;
}
}

View File

@@ -0,0 +1,101 @@
<?php
namespace App\Policies;
use App\Models\Meetup;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class MeetupPolicy extends BasePolicy
{
use HandlesAuthorization;
/**
* Determine whether the user can view any models.
*
* @param \App\Models\User $user
*
* @return \Illuminate\Auth\Access\Response|bool
*/
public function viewAny(User $user)
{
return true;
}
/**
* Determine whether the user can view the model.
*
* @param \App\Models\User $user
* @param \App\Models\Meetup $meetup
*
* @return \Illuminate\Auth\Access\Response|bool
*/
public function view(User $user, Meetup $meetup)
{
return true;
}
/**
* Determine whether the user can create models.
*
* @param \App\Models\User $user
*
* @return \Illuminate\Auth\Access\Response|bool
*/
public function create(User $user)
{
return true;
}
/**
* Determine whether the user can update the model.
*
* @param \App\Models\User $user
* @param \App\Models\Meetup $meetup
*
* @return \Illuminate\Auth\Access\Response|bool
*/
public function update(User $user, Meetup $meetup)
{
return false;
}
/**
* Determine whether the user can delete the model.
*
* @param \App\Models\User $user
* @param \App\Models\Meetup $meetup
*
* @return \Illuminate\Auth\Access\Response|bool
*/
public function delete(User $user, Meetup $meetup)
{
return false;
}
/**
* Determine whether the user can restore the model.
*
* @param \App\Models\User $user
* @param \App\Models\Meetup $meetup
*
* @return \Illuminate\Auth\Access\Response|bool
*/
public function restore(User $user, Meetup $meetup)
{
return false;
}
/**
* Determine whether the user can permanently delete the model.
*
* @param \App\Models\User $user
* @param \App\Models\Meetup $meetup
*
* @return \Illuminate\Auth\Access\Response|bool
*/
public function forceDelete(User $user, Meetup $meetup)
{
return false;
}
}

View File

@@ -10,10 +10,12 @@ use App\Nova\Country;
use App\Nova\Course;
use App\Nova\Dashboards\Main;
use App\Nova\Episode;
use App\Nova\Event;
use App\Nova\CourseEvent;
use App\Nova\Lecturer;
use App\Nova\Library;
use App\Nova\LibraryItem;
use App\Nova\Meetup;
use App\Nova\MeetupEvent;
use App\Nova\OrangePill;
use App\Nova\Participant;
use App\Nova\Podcast;
@@ -45,12 +47,19 @@ class NovaServiceProvider extends NovaApplicationServiceProvider
MenuSection::dashboard(Main::class)
->icon('lightning-bolt'),
MenuSection::make('Meetups', [
MenuItem::resource(Meetup::class),
MenuItem::resource(MeetupEvent::class),
])
->icon('calendar')
->collapsable(),
MenuSection::make('Schule', [
MenuItem::resource(City::class),
MenuItem::resource(Venue::class),
MenuItem::resource(Lecturer::class),
MenuItem::resource(Course::class),
MenuItem::resource(Event::class),
MenuItem::resource(CourseEvent::class),
MenuItem::resource(Participant::class),
MenuItem::resource(Registration::class),
])
@@ -71,7 +80,7 @@ class NovaServiceProvider extends NovaApplicationServiceProvider
->icon('microphone')
->collapsable(),
MenuSection::make('Books', [
MenuSection::make('Book-Cases', [
MenuItem::resource(BookCase::class),
MenuItem::resource(OrangePill::class),
])

View File

@@ -24,6 +24,7 @@
"laravel/tinker": "^2.7",
"livewire/livewire": "^2.5",
"nova/start": "*",
"oneduo/nova-time-field": "^1.0",
"podcastindex/podcastindex-php": "^1.0",
"rappasoft/laravel-livewire-tables": "^2.8",
"sentry/sentry-laravel": "^3.1",

64
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "8289fc02dc91d846d7179784df552d42",
"content-hash": "f361449843e880ec16cbc06c10871928",
"packages": [
{
"name": "akuechler/laravel-geoly",
@@ -4631,6 +4631,68 @@
],
"time": "2022-06-22T07:13:36+00:00"
},
{
"name": "oneduo/nova-time-field",
"version": "v1.0.0",
"source": {
"type": "git",
"url": "https://github.com/oneduo/nova-time-field.git",
"reference": "4c353e41b55b73d13eeb80b61898d284a26d66cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/oneduo/nova-time-field/zipball/4c353e41b55b73d13eeb80b61898d284a26d66cf",
"reference": "4c353e41b55b73d13eeb80b61898d284a26d66cf",
"shasum": ""
},
"require": {
"laravel/nova": "^4.0",
"php": "^8.0"
},
"require-dev": {
"guzzlehttp/guzzle": "^7.0.1",
"laravel/pint": "^1.2",
"mockery/mockery": "^1.5",
"orchestra/testbench": "^6.24|^7.6",
"pestphp/pest": "^1.21",
"pestphp/pest-plugin-laravel": "^1.2",
"pestphp/pest-plugin-mock": "^1.0",
"spatie/laravel-ray": "^1.29"
},
"type": "library",
"autoload": {
"psr-4": {
"Oneduo\\NovaTimeField\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mikaël Popowicz",
"email": "mikael@popowicz.fr"
},
{
"name": "Charaf Rezrazi",
"email": "charaf@rezrazi.fr"
}
],
"description": "A Laravel Nova time field",
"homepage": "https://github.com/oneduo/nova-time-field",
"keywords": [
"field",
"laravel",
"nova",
"time"
],
"support": {
"issues": "https://github.com/oneduo/nova-time-field/issues",
"source": "https://github.com/oneduo/nova-time-field/tree/v1.0.0"
},
"time": "2022-11-18T17:20:22+00:00"
},
{
"name": "openspout/openspout",
"version": "v3.7.4",

View File

@@ -5,7 +5,7 @@ namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
use App\Models\Course;
use App\Models\Event;
use App\Models\CourseEvent;
use App\Models\Venue;
class EventFactory extends Factory
@@ -15,7 +15,7 @@ class EventFactory extends Factory
*
* @var string
*/
protected $model = Event::class;
protected $model = CourseEvent::class;
/**
* Define the model's default state.

View File

@@ -0,0 +1,36 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
use App\Models\Meetup;
use App\Models\MeetupEvent;
class MeetupEventFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = MeetupEvent::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition(): array
{
return [
'meetup_id' => Meetup::factory(),
'date' => $this->faker->date(),
'start' => $this->faker->time(),
'end' => $this->faker->time(),
'location' => $this->faker->word,
'description' => $this->faker->text,
'link' => $this->faker->word,
];
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
use App\Models\City;
use App\Models\Meetup;
class MeetupFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Meetup::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition(): array
{
return [
'city_id' => City::factory(),
'name' => $this->faker->name,
'link' => $this->faker->word,
];
}
}

View File

@@ -4,7 +4,7 @@ namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
use App\Models\Event;
use App\Models\CourseEvent;
use App\Models\Participant;
use App\Models\Registration;
@@ -25,7 +25,7 @@ class RegistrationFactory extends Factory
public function definition(): array
{
return [
'event_id' => Event::factory(),
'event_id' => CourseEvent::factory(),
'participant_id' => Participant::factory(),
'active' => $this->faker->boolean,
];

View File

@@ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateEventsTable extends Migration
class CreateCourseEventsTable extends Migration
{
/**
* Run the migrations.
@@ -15,7 +15,7 @@ class CreateEventsTable extends Migration
{
Schema::disableForeignKeyConstraints();
Schema::create('events', function (Blueprint $table) {
Schema::create('course_events', function (Blueprint $table) {
$table->id();
$table->foreignId('course_id')->constrained()->cascadeOnDelete()->cascadeOnUpdate();
$table->foreignId('venue_id')->constrained()->cascadeOnDelete()->cascadeOnUpdate();
@@ -34,6 +34,6 @@ class CreateEventsTable extends Migration
*/
public function down(): void
{
Schema::dropIfExists('events');
Schema::dropIfExists('course_events');
}
}

View File

@@ -17,7 +17,7 @@ class CreateRegistrationsTable extends Migration
Schema::create('registrations', function (Blueprint $table) {
$table->id();
$table->foreignId('event_id')->constrained()->cascadeOnDelete()->cascadeOnUpdate()->primary();
$table->foreignId('course_event_id')->constrained()->cascadeOnDelete()->cascadeOnUpdate()->primary();
$table->foreignId('participant_id')->constrained()->cascadeOnDelete()->cascadeOnUpdate()->primary();
$table->boolean('active')->default(true);
$table->timestamps();

View File

@@ -11,7 +11,7 @@ return new class extends Migration {
*/
public function up()
{
Schema::table('events', function (Blueprint $table) {
Schema::table('course_events', function (Blueprint $table) {
$table->string('link');
});
}
@@ -22,7 +22,7 @@ return new class extends Migration {
*/
public function down()
{
Schema::table('events', function (Blueprint $table) {
Schema::table('course_events', function (Blueprint $table) {
//
});
}

View File

@@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateMeetupsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up(): void
{
Schema::disableForeignKeyConstraints();
Schema::create('meetups', function (Blueprint $table) {
$table->id();
$table->foreignId('city_id')->constrained()->cascadeOnDelete()->cascadeOnUpdate();
$table->string('name')->unique();
$table->string('link');
$table->timestamps();
});
Schema::enableForeignKeyConstraints();
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down(): void
{
Schema::dropIfExists('meetups');
}
}

View File

@@ -0,0 +1,44 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateMeetupEventsTable extends Migration
{
/**
* Run the migrations.
* @return void
*/
public function up(): void
{
Schema::disableForeignKeyConstraints();
Schema::create('meetup_events', function (Blueprint $table) {
$table->id();
$table->foreignId('meetup_id')
->constrained()
->cascadeOnDelete()
->cascadeOnUpdate();
$table->dateTime('start');
$table->string('location')
->nullable();
$table->text('description')
->nullable();
$table->string('link')
->nullable();
$table->timestamps();
});
Schema::enableForeignKeyConstraints();
}
/**
* Reverse the migrations.
* @return void
*/
public function down(): void
{
Schema::dropIfExists('meetup_events');
}
}

View File

@@ -10,10 +10,12 @@ use App\Models\Category;
use App\Models\City;
use App\Models\Country;
use App\Models\Course;
use App\Models\Event;
use App\Models\CourseEvent;
use App\Models\Lecturer;
use App\Models\Library;
use App\Models\LibraryItem;
use App\Models\Meetup;
use App\Models\MeetupEvent;
use App\Models\Participant;
use App\Models\Registration;
use App\Models\Team;
@@ -170,7 +172,7 @@ class DatabaseSeeder extends Seeder
'first_name' => 'Roman',
'last_name' => 'Reher',
]);
Event::create([
CourseEvent::create([
'course_id' => 2,
'venue_id' => 1,
'link' => 'https://einundzwanzig.space',
@@ -182,7 +184,7 @@ class DatabaseSeeder extends Seeder
->startOfDay()
->addHour(),
]);
Event::create([
CourseEvent::create([
'course_id' => 1,
'venue_id' => 2,
'link' => 'https://einundzwanzig.space',
@@ -194,7 +196,7 @@ class DatabaseSeeder extends Seeder
->startOfDay()
->addHour(),
]);
Event::create([
CourseEvent::create([
'course_id' => 1,
'venue_id' => 3,
'link' => 'https://einundzwanzig.space',
@@ -206,7 +208,7 @@ class DatabaseSeeder extends Seeder
->startOfDay()
->addHour(),
]);
Event::create([
CourseEvent::create([
'course_id' => 3,
'venue_id' => 3,
'link' => 'https://einundzwanzig.space',
@@ -219,7 +221,7 @@ class DatabaseSeeder extends Seeder
->addHour(),
]);
Registration::create([
'event_id' => 1,
'course_event_id' => 1,
'participant_id' => 1,
]);
$library = Library::create([
@@ -281,5 +283,20 @@ class DatabaseSeeder extends Seeder
->attach($libraryItem);
Artisan::call(ReadAndSyncEinundzwanzigPodcastFeed::class);
Artisan::call(SyncOpenBooks::class);
Meetup::create([
'city_id' => 1,
'name' => 'Einundzwanzig Kempten',
'link' => 'https://t.me/EinundzwanzigKempten',
]);
MeetupEvent::create([
'meetup_id' => 1,
'start' => now()
->addDays(2)
->startOfDay()
->addHours(20),
'location' => 'Einundzwanzig Kempten',
'description' => fake()->text(),
'link' => 'https://t.me/EinundzwanzigKempten',
]);
}
}

View File

@@ -0,0 +1,13 @@
models:
Meetup:
city_id: foreign
name: string:unique
link: string
MeetupEvent:
meetup_id: foreign
date: date
start: time
end: time:nullable
location: string:nullable
description: text:nullable
link: string:nullable

View File

@@ -56,6 +56,16 @@
Bücher-Schränke
</a>
@endif
@if(str(request()->route()->getName())->contains('meetup.'))
<a href="{{ route('meetup.table.meetup', ['country' => $c]) }}"
class="{{ request()->routeIs('meetup.table.meetup') ? 'text-amber-500 underline' : 'text-gray-400' }} mr-5 font-medium leading-6 hover:text-gray-300">
Meetups
</a>
<a href="{{ route('meetup.table.meetupEvent', ['country' => $c]) }}"
class="{{ request()->routeIs('meetup.table.meetupEvent') ? 'text-amber-500 underline' : 'text-gray-400' }} mr-5 font-medium leading-6 hover:text-gray-300">
Meetup-Termine
</a>
@endif
</nav>
</div>
@@ -117,6 +127,17 @@
</div>
@endif
@if(str(request()->route()->getName())->contains('meetup.'))
<div>
<h1 class="mb-6 text-5xl font-extrabold leading-none max-w-5xl mx-auto tracking-normal text-gray-200 sm:text-6xl md:text-6xl lg:text-7xl md:tracking-tight">
Bitcoiner <span
class="w-full text-transparent bg-clip-text bg-gradient-to-r from-amber-400 via-amber-500 to-amber-200 lg:inline">Meetups</span><br class="lg:block hidden">
Plebs together strong 💪
</h1>
<p class="px-0 mb-6 text-lg text-gray-600 md:text-xl lg:px-24"> Finde Bitcoiner in deiner Stadt und lerne sie auf einem der Meetups kennen. </p>
</div>
@endif
</div>
</div>
</section>

View File

@@ -14,7 +14,7 @@
</div>
<div class="grid w-full grid-cols-1 gap-8 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4">
<div class="row-span-2 col-span-full sm:col-span-1 md:col-start-1 sm:row-start-2 md:row-start-3">
<a href="#"
<a href="{{ route('meetup.table.meetup', ['country' => 'de']) }}"
class="relative flex flex-col items-start justify-end w-full h-full overflow-hidden bg-black shadow-lg rounded-xl group"
style="aspect-ratio: 1/1;">
<div class="absolute inset-0 w-full h-full">
@@ -98,7 +98,7 @@
</div>
<div
class="row-span-2 col-span-full sm:col-span-1 md:col-start-3 xl:col-start-3 sm:row-start-3 md:row-start-1 xl:row-start-3">
<a href="{{ route('library.table.libraryItems', ['country' => 'de']) }}"
<a href="{{ route('bookCases.table.bookcases', ['country' => 'de']) }}"
class="relative flex flex-col items-start justify-end w-full h-full overflow-hidden bg-black shadow-lg rounded-xl group"
style="aspect-ratio: 1/1;">
<div class="absolute inset-0 w-full h-full">
@@ -106,18 +106,18 @@
class="absolute bottom-0 left-0 z-10 w-full h-full opacity-30 bg-gradient-to-b from-transparent to-gray-900"></div>
<img
class="absolute inset-0 object-cover object-center w-full h-full transition duration-500 lg:opacity-80 group-hover:opacity-100 group-hover:scale-110"
src="{{ asset('img/einundzwanzig_podcast_niko_jilch.jpg') }}" alt="">
src="{{ asset('img/aprycot-media-bitcoin-21-lektionen-01.webp') }}" alt="">
</div>
<div class="relative z-10 flex flex-col items-start justify-start w-full px-6 py-7">
<span
class="px-2 py-1 mb-3 text-xs font-semibold tracking-tight text-white uppercase bg-amber-500 rounded-md">Listening</span>
class="px-2 py-1 mb-3 text-xs font-semibold tracking-tight text-white uppercase bg-amber-500 rounded-md">Reading</span>
<h4 class="text-4xl font-bold tracking-tight text-gray-100 sm:text-3xl md:text-2xl lg:text-3xl">
Podcasts
Bücher-Schränke
</h4>
</div>
</a>
</div>
<div
{{--<div
class="row-span-2 col-span-full sm:col-span-1 md:col-start-3 xl:col-start-4 sm:row-start-5 md:row-start-3 xl:row-start-2">
<a href="{{ route('bookCases.table.bookcases', ['country' => 'de']) }}"
class="relative flex flex-col items-start justify-end w-full h-full overflow-hidden bg-black shadow-lg rounded-xl group"
@@ -137,7 +137,7 @@
</h4>
</div>
</a>
</div>
</div>--}}
</div>
</div>
</section>

View File

@@ -0,0 +1,12 @@
<div class="bg-21gray flex flex-col h-screen justify-between">
{{-- HEADER --}}
<livewire:frontend.header :country="$country"/>
{{-- MAIN --}}
<section class="w-full mb-12">
<div class="max-w-screen-2xl mx-auto px-2 sm:px-10 space-y-4" id="table">
<livewire:tables.meetup-event-table :country="$country->code"/>
</div>
</section>
{{-- FOOTER --}}
<livewire:frontend.footer/>
</div>

View File

@@ -0,0 +1,12 @@
<div class="bg-21gray flex flex-col h-screen justify-between">
{{-- HEADER --}}
<livewire:frontend.header :country="$country"/>
{{-- MAIN --}}
<section class="w-full mb-12">
<div class="max-w-screen-2xl mx-auto px-2 sm:px-10 space-y-4" id="table">
<livewire:tables.meetup-table :country="$country->code"/>
</div>
</section>
{{-- FOOTER --}}
<livewire:frontend.footer/>
</div>

View File

@@ -12,6 +12,17 @@
<!-- Navigation Links -->
<div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
@if(str(request()->route()->getName())->contains('meetup.'))
<x-jet-nav-link href="/nova/resources/meetups" target="_blank">
{{ __('Meetup eintragen') }}
</x-jet-nav-link>
<x-jet-nav-link href="/nova/resources/meetup-events" target="_blank">
{{ __('Meetup-Termin eintragen') }}
</x-jet-nav-link>
@endif
@if(str(request()->route()->getName())->contains('school.'))
<x-jet-nav-link href="/nova/resources/lecturers" target="_blank">
{{ __('Dozent eintragen') }}
</x-jet-nav-link>
@@ -21,12 +32,20 @@
<x-jet-nav-link href="/nova/resources/events" target="_blank">
{{ __('Kurs-Termin eintragen') }}
</x-jet-nav-link>
@endif
@if(str(request()->route()->getName())->contains('library.'))
<x-jet-nav-link href="/nova/resources/library-items" target="_blank">
{{ __('Inhalte eintragen') }}
</x-jet-nav-link>
@endif
@if(str(request()->route()->getName())->contains('bookCases.'))
<x-jet-nav-link href="/nova/resources/book-cases" target="_blank">
{{ __('Bücher-Schränke verwalten') }}
</x-jet-nav-link>
@endif
<x-jet-nav-link href="{{ route('profile.show') }}" :active="request()->routeIs('profile.show')">
{{ __('Mein Profil') }}
</x-jet-nav-link>

View File

@@ -67,6 +67,15 @@ Route::middleware([])
/*
* Meetups
* */
Route::middleware([])
->as('meetup.')
->prefix('meetup')
->group(function () {
Route::get('/{country:code}/table/meetup', \App\Http\Livewire\Meetup\MeetupTable::class)
->name('table.meetup');
Route::get('/{country:code}/table/meetup-events', \App\Http\Livewire\Meetup\MeetupEventTable::class)
->name('table.meetupEvent');
});
/*
* Authenticated