mirror of
https://github.com/Einundzwanzig-Podcast/einundzwanzig-portal.git
synced 2025-12-11 06:46:47 +00:00
cleanup and start with nostr
This commit is contained in:
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Export;
|
||||
|
||||
use App\Exports\MeetupEventAttendeesExport;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\MeetupEvent;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class MeetupEventAttendeesExportController extends Controller
|
||||
{
|
||||
/**
|
||||
* Handle the incoming request.
|
||||
*/
|
||||
public function __invoke(Request $request, MeetupEvent $meetupEvent)
|
||||
{
|
||||
return (new MeetupEventAttendeesExport($meetupEvent))->download($meetupEvent->start->toDateString().'_'.$meetupEvent->meetup->slug.'.xlsx');
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Auth;
|
||||
|
||||
use Livewire\Component;
|
||||
use SimpleSoftwareIO\QrCode\Facades\QrCode;
|
||||
|
||||
class Auth47Component extends Component
|
||||
{
|
||||
public ?string $k1 = null;
|
||||
|
||||
protected ?string $url = null;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->k1 = bin2hex(str()->random(32));
|
||||
$this->url = 'auth47://'.$this->k1.'?c=https://einundzwanzig.eu-1.sharedwithexpose.com/auth/auth47-callback&r=https://einundzwanzig.eu-1.sharedwithexpose.com/auth/auth47-callback';
|
||||
$this->qrCode = base64_encode(QrCode::format('png')
|
||||
->size(600)
|
||||
->errorCorrection('L')
|
||||
->generate($this->url));
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.auth.auth47-component')->layout('layouts.guest');
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Auth;
|
||||
|
||||
use App\Models\LoginKey;
|
||||
use App\Models\User;
|
||||
use App\Notifications\ModelCreatedNotification;
|
||||
use eza\lnurl;
|
||||
use Livewire\Component;
|
||||
use SimpleSoftwareIO\QrCode\Facades\QrCode;
|
||||
|
||||
class LNUrlAuth extends Component
|
||||
{
|
||||
public ?string $k1 = null;
|
||||
|
||||
protected ?string $url = null;
|
||||
|
||||
protected ?string $lnurl = null;
|
||||
|
||||
protected ?string $qrCode = null;
|
||||
|
||||
public function switchToEmailLogin()
|
||||
{
|
||||
return to_route('login');
|
||||
}
|
||||
|
||||
public function switchToEmailSignup()
|
||||
{
|
||||
return to_route('register');
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->k1 = bin2hex(str()->random(32));
|
||||
if (app()->environment('local')) {
|
||||
$this->url = 'https://einundzwanzig.eu-1.sharedwithexpose.com/api/lnurl-auth-callback?tag=login&k1='.$this->k1.'&action=login';
|
||||
} else {
|
||||
$this->url = url('/api/lnurl-auth-callback?tag=login&k1='.$this->k1.'&action=login');
|
||||
}
|
||||
$this->lnurl = lnurl\encodeUrl($this->url);
|
||||
$this->qrCode = base64_encode(QrCode::format('png')
|
||||
->size(300)
|
||||
->merge('/public/android-chrome-192x192.png', .3)
|
||||
->errorCorrection('H')
|
||||
->generate($this->lnurl));
|
||||
}
|
||||
|
||||
public function checkAuth()
|
||||
{
|
||||
$loginKey = LoginKey::query()
|
||||
->where('k1', $this->k1)
|
||||
->whereDate('created_at', '>=', now()->subMinutes(5))
|
||||
->first();
|
||||
// you should also restrict this 👆🏻 by time, and find only the $k1 that were created in the last 5 minutes
|
||||
|
||||
if ($loginKey) {
|
||||
$user = User::find($loginKey->user_id);
|
||||
|
||||
\App\Models\User::find(1)
|
||||
->notify(new ModelCreatedNotification($user, 'users'));
|
||||
auth()->login($user);
|
||||
|
||||
return to_route('welcome');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.auth.ln-url-auth')->layout('layouts.guest');
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Auth;
|
||||
|
||||
use App\Models\Team;
|
||||
use App\Models\User;
|
||||
use Livewire\Component;
|
||||
|
||||
class Login extends Component
|
||||
{
|
||||
public array $userProfile = [];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'userProfile.npub' => 'required|string',
|
||||
'userProfile.pubkey' => 'required|string',
|
||||
|
||||
'userProfile.banner' => 'required|string',
|
||||
'userProfile.image' => 'required|string',
|
||||
|
||||
'userProfile.name' => 'required|string',
|
||||
'userProfile.username' => 'required|string',
|
||||
'userProfile.website' => 'required|string',
|
||||
'userProfile.about' => 'required|string',
|
||||
'userProfile.displayName' => 'required|string',
|
||||
'userProfile.lud16' => 'required|string',
|
||||
'userProfile.nip05' => 'required|string',
|
||||
];
|
||||
}
|
||||
|
||||
public function login($value)
|
||||
{
|
||||
if ($value) {
|
||||
$firstUser = User::query()->where('nostr', $value)->first();
|
||||
if ($firstUser) {
|
||||
auth()->login($firstUser, true);
|
||||
|
||||
return to_route('welcome');
|
||||
} else {
|
||||
$fakeName = str()->random(10);
|
||||
// create User
|
||||
$user = User::create([
|
||||
'is_lecturer' => true,
|
||||
'name' => $fakeName,
|
||||
'email' => str($fakeName)->slug() . '@portal.einundzwanzig.space',
|
||||
'email_verified_at' => now(),
|
||||
'lnbits' => [
|
||||
'read_key' => null,
|
||||
'url' => null,
|
||||
'wallet_id' => null,
|
||||
],
|
||||
'nostr' => $value,
|
||||
]);
|
||||
$user->ownedTeams()
|
||||
->save(Team::forceCreate([
|
||||
'user_id' => $user->id,
|
||||
'name' => $fakeName . "'s Team",
|
||||
'personal_team' => true,
|
||||
]));
|
||||
auth()->login($user, true);
|
||||
|
||||
return to_route('welcome');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.auth.login')->layout('layouts.guest');
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Auth;
|
||||
|
||||
use App\Models\User;
|
||||
use Livewire\Component;
|
||||
|
||||
class LoginWithNDK extends Component
|
||||
{
|
||||
public $existingAccount = false;
|
||||
|
||||
public array $userProfile = [];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'userProfile.npub' => 'required|string',
|
||||
'userProfile.pubkey' => 'required|string',
|
||||
|
||||
'userProfile.banner' => 'required|string',
|
||||
'userProfile.image' => 'required|string',
|
||||
|
||||
'userProfile.name' => 'required|string',
|
||||
'userProfile.username' => 'required|string',
|
||||
'userProfile.website' => 'required|string',
|
||||
'userProfile.about' => 'required|string',
|
||||
'userProfile.displayName' => 'required|string',
|
||||
'userProfile.lud16' => 'required|string',
|
||||
'userProfile.nip05' => 'required|string',
|
||||
];
|
||||
}
|
||||
|
||||
public function updatedUserProfile($value)
|
||||
{
|
||||
if (User::query()->where('nostr', $value['npub'])->exists()) {
|
||||
$this->existingAccount = true;
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.auth.login-with-n-d-k')->layout('layouts.guest');
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Banner;
|
||||
|
||||
use App\Console\Commands\MempoolSpace\CacheRecommendedFees;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Livewire\Component;
|
||||
|
||||
class MempoolWeather extends Component
|
||||
{
|
||||
public $weather;
|
||||
public $changed;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
/*if (cache()->has('mempool-weather')) {
|
||||
$this->weather = cache()->get('mempool-weather');
|
||||
} else {
|
||||
Artisan::call(CacheRecommendedFees::class);
|
||||
$this->weather = cache()->get('mempool-weather');
|
||||
}
|
||||
$this->changed = cache()->get('mempool-weather-changed');*/
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.banner.mempool-weather');
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\BitcoinEvent;
|
||||
|
||||
use App\Models\BitcoinEvent;
|
||||
use App\Models\Country;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class BitcoinEventTable extends Component
|
||||
{
|
||||
public Country $country;
|
||||
|
||||
public ?int $year = null;
|
||||
|
||||
protected $queryString = ['year'];
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (! $this->year) {
|
||||
$this->year = now()->year;
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.bitcoin-event.bitcoin-event-table', [
|
||||
'markers' => BitcoinEvent::query()
|
||||
->with([
|
||||
'venue.city.country',
|
||||
])
|
||||
->where('bitcoin_events.from', '>=', now())
|
||||
->where(fn ($query) => $query
|
||||
->whereHas('venue.city.country',
|
||||
fn ($query) => $query->where('countries.code', $this->country->code))
|
||||
->orWhere('show_worldwide', true)
|
||||
)
|
||||
->get()
|
||||
->map(fn ($event) => [
|
||||
'id' => $event->id,
|
||||
'name' => $event->title,
|
||||
'coords' => [$event->venue->city->latitude, $event->venue->city->longitude],
|
||||
]),
|
||||
'events' => BitcoinEvent::query()
|
||||
->where('bitcoin_events.from', '>=', now())
|
||||
->where(fn ($query) => $query
|
||||
->whereHas('venue.city.country',
|
||||
fn ($query) => $query->where('countries.code', $this->country->code))
|
||||
->orWhere('show_worldwide', true)
|
||||
)
|
||||
->get()
|
||||
->map(fn ($event) => [
|
||||
'id' => $event->id,
|
||||
'startDate' => $event->from,
|
||||
'endDate' => $event->to,
|
||||
'location' => $event->title,
|
||||
'description' => $event->description,
|
||||
]),
|
||||
])->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('Bitcoin Events'),
|
||||
description: __('Search out a Bitcoin Event'),
|
||||
image: asset('img/screenshot.png')
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
public function filterByMarker($id)
|
||||
{
|
||||
return to_route('bitcoinEvent.table.bitcoinEvent', [
|
||||
'#table',
|
||||
'country' => $this->country->code,
|
||||
'year' => $this->year,
|
||||
'bitcoin_events' => [
|
||||
'filters' => [
|
||||
'byid' => $id,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function popover($content, $ids)
|
||||
{
|
||||
return to_route('bitcoinEvent.table.bitcoinEvent', [
|
||||
'#table',
|
||||
'country' => $this->country->code,
|
||||
'year' => $this->year,
|
||||
'bitcoin_events' => [
|
||||
'filters' => [
|
||||
'byid' => $ids,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\BitcoinEvent\Form;
|
||||
|
||||
use App\Models\BitcoinEvent;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
use WireUi\Traits\Actions;
|
||||
|
||||
class BitcoinEventForm extends Component
|
||||
{
|
||||
use WithFileUploads;
|
||||
use Actions;
|
||||
|
||||
public string $country;
|
||||
|
||||
public ?BitcoinEvent $bitcoinEvent = null;
|
||||
|
||||
public $image;
|
||||
|
||||
public ?string $fromUrl = '';
|
||||
|
||||
protected $queryString = [
|
||||
'fromUrl' => [
|
||||
'except' => null,
|
||||
],
|
||||
];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'image' => [Rule::requiredIf(!$this->bitcoinEvent->id), 'nullable', 'mimes:jpeg,png,jpg,gif', 'max:10240'],
|
||||
|
||||
'bitcoinEvent.venue_id' => 'required',
|
||||
'bitcoinEvent.from' => 'required',
|
||||
'bitcoinEvent.to' => 'required',
|
||||
'bitcoinEvent.title' => 'required',
|
||||
'bitcoinEvent.description' => 'required',
|
||||
'bitcoinEvent.link' => 'required|url',
|
||||
'bitcoinEvent.show_worldwide' => 'bool',
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (!$this->bitcoinEvent) {
|
||||
$this->bitcoinEvent = new BitcoinEvent(
|
||||
[
|
||||
'description' => '',
|
||||
'show_worldwide' => true,
|
||||
]
|
||||
);
|
||||
} elseif (!auth()
|
||||
->user()
|
||||
->can('update', $this->bitcoinEvent)) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
if (!$this->fromUrl) {
|
||||
$this->fromUrl = url()->previous();
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteMe()
|
||||
{
|
||||
$this->bitcoinEvent->delete();
|
||||
|
||||
return redirect($this->fromUrl);
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
$this->validate();
|
||||
$this->bitcoinEvent->save();
|
||||
|
||||
if ($this->image) {
|
||||
$this->bitcoinEvent->addMedia($this->image)
|
||||
->usingFileName(md5($this->image->getClientOriginalName()).'.'.$this->image->getClientOriginalExtension())
|
||||
->toMediaCollection('logo');
|
||||
}
|
||||
|
||||
return redirect($this->fromUrl);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.bitcoin-event.form.bitcoin-event-form');
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\BookCase;
|
||||
|
||||
use App\Models\BookCase;
|
||||
use App\Models\Country;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class BookCaseTable extends Component
|
||||
{
|
||||
public ?Country $country = null;
|
||||
|
||||
public string $c = 'de';
|
||||
|
||||
public array $bookcases = [];
|
||||
|
||||
protected $queryString = ['bookcases'];
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.book-case.book-case-table', [
|
||||
'markers' => ! isset($this->table['filters']['byids']) ? []
|
||||
: BookCase::query()
|
||||
->whereIn('id', str($this->table['filters']['byids'] ?? '')->explode(','))
|
||||
->get()
|
||||
->map(fn ($b) => [
|
||||
'title' => $b->title,
|
||||
'lat' => $b->latitude,
|
||||
'lng' => $b->longitude,
|
||||
'url' => route('bookCases.comment.bookcase', ['country' => $this->country, 'bookCase' => $b]),
|
||||
'icon' => asset('img/btc-logo-6219386_1280.png'),
|
||||
'icon_size' => [42, 42],
|
||||
])
|
||||
->toArray(),
|
||||
'bookCases' => BookCase::query()->active()->get(),
|
||||
'countries' => Country::query()
|
||||
->select(['code', 'name'])
|
||||
->get(),
|
||||
])->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('Bookcases'),
|
||||
description: __('Search out a public bookcase'),
|
||||
image: asset('img/screenshot.png')
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\BookCase;
|
||||
|
||||
use App\Models\Country;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class CityTable extends Component
|
||||
{
|
||||
public Country $country;
|
||||
|
||||
public bool $manage = false;
|
||||
|
||||
protected $queryString = [
|
||||
'manage' => [
|
||||
'except' => false,
|
||||
],
|
||||
];
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.book-case.city-table')->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('Bookcases'),
|
||||
description: __('Search out a public bookcase'),
|
||||
image: asset('img/screenshot.png')
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\BookCase;
|
||||
|
||||
use App\Models\BookCase;
|
||||
use App\Models\Country;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
||||
|
||||
class CommentBookCase extends Component
|
||||
{
|
||||
use WithFileUploads;
|
||||
|
||||
public Country $country;
|
||||
|
||||
public $photo;
|
||||
|
||||
public string $c = 'de';
|
||||
|
||||
public BookCase $bookCase;
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->validate([
|
||||
'photo' => 'image|max:4096', // 4MB Max
|
||||
]);
|
||||
|
||||
$this->bookCase
|
||||
->addMedia($this->photo)
|
||||
->usingFileName(md5($this->photo->getClientOriginalName()).'.'.$this->photo->getClientOriginalExtension())
|
||||
->toMediaCollection('images');
|
||||
|
||||
return to_route('bookCases.comment.bookcase', ['country' => $this->country, 'bookCase' => $this->bookCase->id]);
|
||||
}
|
||||
|
||||
public function deletePhoto($id)
|
||||
{
|
||||
Media::find($id)
|
||||
->delete();
|
||||
|
||||
return to_route('bookCases.comment.bookcase', ['country' => $this->country, 'bookCase' => $this->bookCase->id]);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.book-case.comment-book-case')
|
||||
->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: $this->bookCase->title,
|
||||
description: $this->bookCase->address,
|
||||
image: $this->bookCase->getFirstMediaUrl('images', 'seo') ?? asset('img/bookcase.jpg'),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
protected function url_to_absolute($url)
|
||||
{
|
||||
if (str($url)->contains('http')) {
|
||||
return $url;
|
||||
}
|
||||
if (!str($url)->contains('http')) {
|
||||
return str($url)->prepend('https://');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\BookCase\Form;
|
||||
|
||||
use App\Gamify\Points\BookCaseOrangePilled;
|
||||
use App\Models\BookCase;
|
||||
use App\Models\Country;
|
||||
use App\Models\OrangePill;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
|
||||
class OrangePillForm extends Component
|
||||
{
|
||||
use WithFileUploads;
|
||||
|
||||
public Country $country;
|
||||
|
||||
public BookCase $bookCase;
|
||||
|
||||
public ?OrangePill $orangePill = null;
|
||||
|
||||
public $image;
|
||||
|
||||
public string $fromUrl = '';
|
||||
|
||||
protected $queryString = ['fromUrl' => ['except' => '']];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'orangePill.book_case_id' => ['required'],
|
||||
'orangePill.user_id' => ['required'],
|
||||
'orangePill.amount' => ['required', 'numeric'],
|
||||
'orangePill.date' => ['required', 'date'],
|
||||
'orangePill.comment' => ['required', 'string'],
|
||||
|
||||
'image' => ['max:8192', Rule::requiredIf(!$this->orangePill->id), 'image', 'nullable'], // 8MB Max
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (!$this->orangePill) {
|
||||
$this->orangePill = new OrangePill([
|
||||
'user_id' => auth()->id(),
|
||||
'book_case_id' => $this->bookCase->id,
|
||||
'date' => now(),
|
||||
'amount' => 1,
|
||||
]);
|
||||
} elseif ($this->orangePill->user_id !== auth()->id()) {
|
||||
abort(403);
|
||||
}
|
||||
if (!$this->fromUrl) {
|
||||
$this->fromUrl = url()->previous();
|
||||
}
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
if (!auth()->check()) {
|
||||
return to_route('auth.login');
|
||||
}
|
||||
$this->validate();
|
||||
$this->orangePill->save();
|
||||
|
||||
if ($this->image) {
|
||||
$this->orangePill
|
||||
->addMedia($this->image)
|
||||
->usingFileName(md5($this->image->getClientOriginalName()).'.'.$this->image->getClientOriginalExtension())
|
||||
->toMediaCollection('images');
|
||||
}
|
||||
|
||||
return redirect($this->fromUrl);
|
||||
}
|
||||
|
||||
public function deleteMe()
|
||||
{
|
||||
$this->orangePill->delete();
|
||||
auth()
|
||||
->user()
|
||||
->undoPoint(new BookCaseOrangePilled($this->orangePill));
|
||||
|
||||
return redirect($this->fromUrl);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.book-case.form.orange-pill-form');
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\BookCase;
|
||||
|
||||
use App\Models\BookCase;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class Heatmap extends Component
|
||||
{
|
||||
public string $country;
|
||||
|
||||
public function render()
|
||||
{
|
||||
$data = BookCase::query()
|
||||
->active()
|
||||
->whereHas('orangePills')
|
||||
->get()
|
||||
->map(fn ($bookCase) => [
|
||||
'lat' => $bookCase->latitude,
|
||||
'lng' => $bookCase->longitude,
|
||||
]);
|
||||
|
||||
return view('livewire.book-case.heatmap', [
|
||||
'heatmap_data' => $data->toArray(),
|
||||
])->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('Heatmap of Bookcases'),
|
||||
description: __('On this map you can see the success and spread of the Bitcoin books.'),
|
||||
image: asset('img/heatmap_bookcases.png'),
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\BookCase;
|
||||
|
||||
use App\Models\Country;
|
||||
use App\Models\User;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class HighscoreTable extends Component
|
||||
{
|
||||
public Country $country;
|
||||
|
||||
public bool $viewingModal = false;
|
||||
|
||||
public ?User $modal = null;
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.book-case.highscore-table', [
|
||||
'plebs' => User::query()
|
||||
->with([
|
||||
'reputations',
|
||||
])
|
||||
->withCount([
|
||||
'orangePills',
|
||||
])
|
||||
->where('reputation', '>', 0)
|
||||
->orderByDesc('reputation')
|
||||
->get(),
|
||||
])->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('Highscore Table'),
|
||||
description: __('Hall of fame of our honorable plebs'),
|
||||
image: asset('img/highscore_table_screenshot.png'),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
public function toggleChat()
|
||||
{
|
||||
$this->emit('toggleHighscoreChat');
|
||||
}
|
||||
|
||||
public function openModal($id)
|
||||
{
|
||||
$this->modal = User::query()
|
||||
->with([
|
||||
'orangePills',
|
||||
'reputations',
|
||||
])
|
||||
->where('id', $id)
|
||||
->first();
|
||||
|
||||
$this->viewingModal = true;
|
||||
}
|
||||
|
||||
public function resetModal()
|
||||
{
|
||||
$this->modal = null;
|
||||
$this->viewingModal = false;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\BookCase;
|
||||
|
||||
use App\Models\OrangePill;
|
||||
use App\Models\User;
|
||||
use Livewire\Component;
|
||||
|
||||
class Stats extends Component
|
||||
{
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.book-case.stats', [
|
||||
'orangePills' => OrangePill::query()->count(),
|
||||
'plebs' => User::query()->whereHas('orangePills')->count(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\BookCase;
|
||||
|
||||
use App\Models\BookCase;
|
||||
use App\Models\Country;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class WorldMap extends Component
|
||||
{
|
||||
public Country $country;
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.book-case.world-map', [
|
||||
'mapData' => BookCase::query()
|
||||
->select(['id', 'latitude', 'longitude'])
|
||||
->withCount('orangePills')
|
||||
->active()
|
||||
->get()
|
||||
->map(fn ($bookCase) => [
|
||||
'lat' => $bookCase->latitude,
|
||||
'lng' => $bookCase->longitude,
|
||||
'url' => url()->route('bookCases.comment.bookcase',
|
||||
[
|
||||
'country' => $this->country,
|
||||
'bookCase' => $bookCase,
|
||||
]),
|
||||
'op' => $bookCase->orange_pills_count,
|
||||
])
|
||||
->toArray(),
|
||||
])->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('World Map of Bookcases'),
|
||||
description: __('On this map you can see bookcases that have been orange pilled. You can also click on a marker to go to the search result.'),
|
||||
image: asset('img/world_map_bookcases.png')
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Chat;
|
||||
|
||||
use App\Events\ChatMessageSentEvent;
|
||||
use Livewire\Component;
|
||||
|
||||
class HighscoreChat extends Component
|
||||
{
|
||||
public bool $open = false;
|
||||
|
||||
public array $messages = [];
|
||||
|
||||
public string $myNewMessage = '';
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'myNewMessage' => 'required|min:1|max:255',
|
||||
];
|
||||
}
|
||||
|
||||
public function getListeners()
|
||||
{
|
||||
return [
|
||||
'toggleHighscoreChat' => 'toggle',
|
||||
'echo:plebchannel,.App\Events\ChatMessageSentEvent' => 'chatMessageSent',
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->messages = cache()->get('highscore_chat_messages', []);
|
||||
}
|
||||
|
||||
public function toggle()
|
||||
{
|
||||
$this->open = ! $this->open;
|
||||
}
|
||||
|
||||
public function chatMessageSent()
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$this->messages = cache()->get('highscore_chat_messages', []);
|
||||
$this->dispatchBrowserEvent('chat-updated');
|
||||
}
|
||||
}
|
||||
|
||||
public function sendMessage()
|
||||
{
|
||||
$this->validate();
|
||||
$newMessages = collect(cache()->get('highscore_chat_messages', []))
|
||||
->push([
|
||||
'fromId' => auth()->id(),
|
||||
'fromName' => str(auth()->user()->name)->limit(2),
|
||||
'userImg' => str(auth()->user()->profile_photo_url)->replace('background=EBF4FF', 'background=F7931A'),
|
||||
'message' => $this->myNewMessage,
|
||||
'time' => now()->asDateTime(),
|
||||
])
|
||||
->take(-21)
|
||||
->toArray();
|
||||
cache()->set('highscore_chat_messages', $newMessages);
|
||||
event(new ChatMessageSentEvent());
|
||||
$this->messages = $newMessages;
|
||||
$this->myNewMessage = '';
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.chat.highscore-chat');
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\City\Form;
|
||||
|
||||
use App\Models\City;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Livewire\Component;
|
||||
|
||||
class CityForm extends Component
|
||||
{
|
||||
public ?City $city = null;
|
||||
|
||||
public string $fromUrl = '';
|
||||
|
||||
protected $queryString = [
|
||||
'fromUrl' => [
|
||||
'except' => null,
|
||||
],
|
||||
];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'city.country_id' => 'required',
|
||||
'city.name' => [
|
||||
'required',
|
||||
Rule::unique('cities', 'name')
|
||||
->ignore($this->city),
|
||||
],
|
||||
'city.longitude' => 'required',
|
||||
'city.latitude' => 'required',
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (!$this->city) {
|
||||
$this->city = new City();
|
||||
}
|
||||
if (!$this->fromUrl) {
|
||||
$this->fromUrl = url()->previous();
|
||||
}
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->validate();
|
||||
$this->city->longitude = str($this->city->longitude)
|
||||
->replace(',', '.')
|
||||
->toFloat();
|
||||
$this->city->latitude = str($this->city->latitude)
|
||||
->replace(',', '.')
|
||||
->toFloat();
|
||||
$this->city->save();
|
||||
|
||||
return redirect($this->fromUrl ?? url()->route('welcome'));
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.city.form.city-form');
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\ContentCreator\Form;
|
||||
|
||||
use App\Models\Lecturer;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
|
||||
class ContentCreatorForm extends Component
|
||||
{
|
||||
use WithFileUploads;
|
||||
|
||||
public ?Lecturer $lecturer = null;
|
||||
|
||||
public $image;
|
||||
|
||||
public ?string $fromUrl = '';
|
||||
|
||||
protected $queryString = ['fromUrl' => ['except' => '']];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'image' => [Rule::requiredIf(!$this->lecturer->id), 'nullable', 'mimes:jpeg,png,jpg,gif', 'max:10240'],
|
||||
|
||||
'lecturer.name' => [
|
||||
'required',
|
||||
Rule::unique('lecturers', 'name')
|
||||
->ignore($this->lecturer),
|
||||
],
|
||||
'lecturer.active' => 'boolean',
|
||||
'lecturer.subtitle' => 'nullable|string',
|
||||
'lecturer.intro' => 'nullable|string',
|
||||
'lecturer.paynym' => 'nullable|string',
|
||||
'lecturer.nostr' => 'nullable|string',
|
||||
'lecturer.twitter_username' => 'nullable|string',
|
||||
'lecturer.website' => 'nullable|url',
|
||||
'lecturer.lightning_address' => 'nullable|string',
|
||||
'lecturer.lnurl' => 'nullable|string',
|
||||
'lecturer.node_id' => 'nullable|string',
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (!$this->lecturer) {
|
||||
$this->lecturer = new Lecturer([
|
||||
'intro' => '',
|
||||
'active' => true,
|
||||
]);
|
||||
}
|
||||
if (!$this->fromUrl) {
|
||||
$this->fromUrl = url()->previous();
|
||||
}
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->validate();
|
||||
$this->lecturer->save();
|
||||
|
||||
if ($this->image) {
|
||||
$this->lecturer->addMedia($this->image)
|
||||
->usingFileName(md5($this->image->getClientOriginalName()).'.'.$this->image->getClientOriginalExtension())
|
||||
->toMediaCollection('avatar');
|
||||
}
|
||||
|
||||
return redirect($this->fromUrl);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.content-creator.form.content-creator-form');
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Frontend;
|
||||
|
||||
use Illuminate\Support\Facades\Cookie;
|
||||
use JoeDixon\Translation\Language;
|
||||
use JoeDixon\Translation\Translation;
|
||||
use Livewire\Component;
|
||||
|
||||
class Footer extends Component
|
||||
{
|
||||
public function render()
|
||||
{
|
||||
$l = Cookie::get('lang', config('app.locale'));
|
||||
$language = Language::query()
|
||||
->where('language', $l)
|
||||
->first();
|
||||
if (!$language || str($l)->contains('ey')) {
|
||||
$language = Language::query()
|
||||
->where('language', config('app.locale'))
|
||||
->first();
|
||||
}
|
||||
$translated = $language->translations()
|
||||
->whereNotNull('value')
|
||||
->where('value', '<>', '')
|
||||
->count();
|
||||
$toTranslate = Translation::query()
|
||||
->where('language_id', $language->id)
|
||||
->count();
|
||||
$toTranslate = $toTranslate > 0 ? $toTranslate : 1;
|
||||
|
||||
return view('livewire.frontend.footer', [
|
||||
'percentTranslated' => $l === 'en' ? 100 : round(($translated / $toTranslate) * 100),
|
||||
'language' => $language,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Frontend;
|
||||
|
||||
use App\Models\BitcoinEvent;
|
||||
use App\Models\City;
|
||||
use App\Models\Country;
|
||||
use App\Models\CourseEvent;
|
||||
use App\Models\LibraryItem;
|
||||
use App\Models\MeetupEvent;
|
||||
use App\Models\OrangePill;
|
||||
use App\Models\ProjectProposal;
|
||||
use Illuminate\Support\Facades\Cookie;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Livewire\Component;
|
||||
|
||||
class Header extends Component
|
||||
{
|
||||
public ?Country $country = null;
|
||||
|
||||
public $currentRouteName;
|
||||
|
||||
public string $c = 'de';
|
||||
|
||||
public string $l = 'de';
|
||||
|
||||
public string $timezone;
|
||||
|
||||
public $bgColor = 'bg-21gray';
|
||||
|
||||
protected $queryString = ['l'];
|
||||
|
||||
protected $listeners = ['refresh' => '$refresh'];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'c' => 'required',
|
||||
'l' => 'required',
|
||||
'timezone' => 'required',
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->timezone = config('app.user-timezone');
|
||||
$this->l = Cookie::get('lang') ?: config('app.locale');
|
||||
$this->c = Cookie::get('country') ?: config('app.country');
|
||||
if (!$this->country) {
|
||||
$this->country = Country::query()
|
||||
->where('code', $this->c)
|
||||
->first();
|
||||
}
|
||||
$this->currentRouteName = Route::currentRouteName();
|
||||
}
|
||||
|
||||
public function updatedTimezone($value)
|
||||
{
|
||||
auth()
|
||||
->user()
|
||||
->update(['timezone' => $value]);
|
||||
|
||||
return redirect(request()->header('Referer'));
|
||||
}
|
||||
|
||||
public function updatedC($value)
|
||||
{
|
||||
Cookie::queue('country', $value, 60 * 24 * 365);
|
||||
$url = str(request()->header('Referer'))->explode('/');
|
||||
$url[3] = $value;
|
||||
|
||||
return redirect($url->implode('/'));
|
||||
}
|
||||
|
||||
public function updatedL($value)
|
||||
{
|
||||
Cookie::queue('lang', $value, 60 * 24 * 365);
|
||||
|
||||
return redirect(request()->header('Referer'));
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.frontend.header', [
|
||||
'news' => LibraryItem::query()
|
||||
->with([
|
||||
'createdBy.roles',
|
||||
'lecturer',
|
||||
'tags',
|
||||
])
|
||||
->where('type', 'markdown_article')
|
||||
->where('approved', true)
|
||||
->where('news', true)
|
||||
->orderByDesc('created_at')
|
||||
->take(2)
|
||||
->get(),
|
||||
'meetups' => MeetupEvent::query()
|
||||
->with([
|
||||
'meetup.users',
|
||||
'meetup.city.country',
|
||||
])
|
||||
->where('start', '>', now())
|
||||
->orderBy('start')
|
||||
->take(2)
|
||||
->get(),
|
||||
'courseEvents' => CourseEvent::query()
|
||||
->with([
|
||||
'venue.city.country',
|
||||
'course.lecturer',
|
||||
])
|
||||
->where('from', '>', now())
|
||||
->orderBy('from')
|
||||
->take(2)
|
||||
->get(),
|
||||
'libraryItems' => LibraryItem::query()
|
||||
->with([
|
||||
'lecturer',
|
||||
])
|
||||
->where('type', '<>', 'markdown_article')
|
||||
->orderByDesc('created_at')
|
||||
->take(2)
|
||||
->get(),
|
||||
'bitcoinEvents' => BitcoinEvent::query()
|
||||
->with([
|
||||
'venue',
|
||||
])
|
||||
->where('from', '>', now())
|
||||
->orderBy('from')
|
||||
->take(2)
|
||||
->get(),
|
||||
'orangePills' => OrangePill::query()
|
||||
->with([
|
||||
'user',
|
||||
'bookCase',
|
||||
])
|
||||
->orderByDesc('date')
|
||||
->take(2)
|
||||
->get(),
|
||||
'projectProposals' => ProjectProposal::query()
|
||||
->with([
|
||||
'votes',
|
||||
'user',
|
||||
])
|
||||
->take(2)
|
||||
->get(),
|
||||
'cities' => City::query()
|
||||
->select(['latitude', 'longitude'])
|
||||
->get(),
|
||||
'countries' => Country::query()
|
||||
->select('id', 'name', 'code')
|
||||
->orderBy('name')
|
||||
->get()
|
||||
->map(function (Country $country) {
|
||||
$country->name = config('countries.emoji_flags')[str($country->code)
|
||||
->upper()
|
||||
->toString()].' '.$country->name;
|
||||
|
||||
return $country;
|
||||
}),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Frontend;
|
||||
|
||||
use Livewire\Component;
|
||||
|
||||
class SearchTabs extends Component
|
||||
{
|
||||
public string $country;
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.frontend.search-tabs');
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Frontend;
|
||||
|
||||
use App\Models\Country;
|
||||
use Illuminate\Support\Facades\Cookie;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class Welcome extends Component
|
||||
{
|
||||
public string $c = 'de';
|
||||
|
||||
public string $l = 'de';
|
||||
|
||||
protected $queryString = ['c', 'l'];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'c' => 'required',
|
||||
'l' => 'required',
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->l = Cookie::get('lang') ?: config('app.locale');
|
||||
$this->c = Cookie::get('country') ?: config('app.country');
|
||||
Cookie::queue('lang', $this->l, 60 * 24 * 365);
|
||||
Cookie::queue('country', $this->c, 60 * 24 * 365);
|
||||
}
|
||||
|
||||
public function updated($property, $value)
|
||||
{
|
||||
$this->validate();
|
||||
if ($property === 'c') {
|
||||
$c = $value;
|
||||
} else {
|
||||
$c = $this->c;
|
||||
}
|
||||
if ($property === 'l') {
|
||||
$l = $value;
|
||||
} else {
|
||||
$l = $this->l;
|
||||
}
|
||||
|
||||
Cookie::queue('lang', $this->l, 60 * 24 * 365);
|
||||
Cookie::queue('country', $this->c, 60 * 24 * 365);
|
||||
|
||||
return to_route('welcome', ['c' => $c, 'l' => $l]);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.frontend.welcome', [
|
||||
'countries' => Country::query()
|
||||
->select('id', 'name', 'code')
|
||||
->orderBy('name')
|
||||
->get()
|
||||
->map(function (Country $country) {
|
||||
$country->name = config('countries.emoji_flags')[str($country->code)
|
||||
->upper()
|
||||
->toString()].' '.$country->name;
|
||||
|
||||
return $country;
|
||||
}),
|
||||
])->layout('layouts.guest', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('Welcome'),
|
||||
description: __('Welcome to the portal of the Einundzwanzig Community.'),
|
||||
image: url()->route('imgPublic', ['path' => 'img/screenshot.png', 'h' => 630, 'w' => 1200, 'fit' => 'crop'])
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Guest;
|
||||
|
||||
use Livewire\Component;
|
||||
|
||||
class Welcome extends Component
|
||||
{
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.guest.welcome')->layout('layouts.guest');
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
|
||||
use App\Events\PaidMessageEvent;
|
||||
use App\Traits\LNBitsTrait;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Livewire\Component;
|
||||
use SimpleSoftwareIO\QrCode\Facades\QrCode;
|
||||
use WireUi\Traits\Actions;
|
||||
|
||||
class Hello extends Component
|
||||
{
|
||||
use Actions;
|
||||
use LNBitsTrait;
|
||||
|
||||
public $message = '';
|
||||
public $qrCode = '';
|
||||
public $invoice = '';
|
||||
public $paymentHash = '';
|
||||
public $checkid = null;
|
||||
public bool $invoicePaid = false;
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'message' => 'required|string|max:1000',
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
try {
|
||||
// {"url":"","wallet_id":"","read_key":""}
|
||||
$invoice = $this->createInvoice(
|
||||
sats: 21,
|
||||
memo: 'Payment for: Bitcoin im Ländle 2023 - Code is Speech',
|
||||
lnbits: [
|
||||
'url' => config('services.lnbits.url'),
|
||||
'wallet_id' => config('services.lnbits.wallet_id'),
|
||||
'read_key' => config('services.lnbits.read_key'),
|
||||
],
|
||||
);
|
||||
} catch (\Exception $e) {
|
||||
$this->notification()
|
||||
->error('LNBits error: '.$e->getMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->paymentHash = $invoice['payment_hash'];
|
||||
$this->qrCode = base64_encode(QrCode::format('png')
|
||||
->size(300)
|
||||
->merge('/public/img/markus_turm.png', .3)
|
||||
->errorCorrection('H')
|
||||
->generate($invoice['payment_request']));
|
||||
$this->invoice = $invoice['payment_request'];
|
||||
$this->checkid = $invoice['checking_id'];
|
||||
}
|
||||
|
||||
public function checkPaymentHash()
|
||||
{
|
||||
try {
|
||||
$invoice = $this->check($this->checkid, [
|
||||
'url' => config('services.lnbits.url'),
|
||||
'wallet_id' => config('services.lnbits.wallet_id'),
|
||||
'read_key' => config('services.lnbits.read_key'),
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
$this->notification()
|
||||
->error('LNBits error: '.$e->getMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
if (isset($invoice['paid']) && $invoice['paid']) {
|
||||
$this->invoicePaid = true;
|
||||
event(new PaidMessageEvent($this->message, $this->checkid));
|
||||
} else {
|
||||
Log::error(json_encode($invoice, JSON_THROW_ON_ERROR));
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.hello')->layout('layouts.guest');
|
||||
}
|
||||
}
|
||||
@@ -1,198 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Library\Form;
|
||||
|
||||
use App\Enums\LibraryItemType;
|
||||
use App\Models\Country;
|
||||
use App\Models\Library;
|
||||
use App\Models\LibraryItem;
|
||||
use App\Traits\HasTagsTrait;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
use Spatie\LaravelOptions\Options;
|
||||
|
||||
class LibraryItemForm extends Component
|
||||
{
|
||||
use HasTagsTrait;
|
||||
use WithFileUploads;
|
||||
|
||||
public Country $country;
|
||||
|
||||
public ?LibraryItem $libraryItem = null;
|
||||
|
||||
public $library;
|
||||
|
||||
public $image;
|
||||
|
||||
public $file;
|
||||
|
||||
public bool $lecturer = false;
|
||||
|
||||
public bool $isBindle = false;
|
||||
|
||||
public ?string $fromUrl = '';
|
||||
|
||||
protected $queryString = [
|
||||
'fromUrl' => ['except' => ''],
|
||||
'lecturer' => ['except' => false],
|
||||
'isBindle' => ['except' => false],
|
||||
];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'image' => [Rule::requiredIf(!$this->libraryItem->id), 'nullable', 'mimes:jpeg,png,jpg,gif', 'max:10240'],
|
||||
|
||||
'library' => 'required',
|
||||
|
||||
'selectedTags' => 'array|min:1',
|
||||
|
||||
'libraryItem.lecturer_id' => 'required',
|
||||
'libraryItem.name' => 'required',
|
||||
'libraryItem.type' => 'required',
|
||||
'libraryItem.language_code' => 'required',
|
||||
'libraryItem.value' => [
|
||||
Rule::when($this->libraryItem->type !== LibraryItemType::DownloadableFile(), 'required'),
|
||||
Rule::when(
|
||||
$this->libraryItem->type !== LibraryItemType::MarkdownArticle()
|
||||
&& $this->libraryItem->type !== LibraryItemType::MarkdownArticleExtern(), ['url']
|
||||
),
|
||||
],
|
||||
'libraryItem.subtitle' =>
|
||||
[
|
||||
Rule::when(
|
||||
$this->libraryItem->type !== 'bindle',
|
||||
'required',
|
||||
)
|
||||
],
|
||||
'libraryItem.excerpt' =>
|
||||
[
|
||||
Rule::when(
|
||||
$this->libraryItem->type !== 'bindle',
|
||||
'required',
|
||||
)
|
||||
],
|
||||
'libraryItem.main_image_caption' =>
|
||||
[
|
||||
Rule::when(
|
||||
$this->libraryItem->type !== 'bindle',
|
||||
'required',
|
||||
)
|
||||
],
|
||||
'libraryItem.read_time' =>
|
||||
[
|
||||
Rule::when(
|
||||
$this->libraryItem->type !== 'bindle',
|
||||
'required',
|
||||
)
|
||||
],
|
||||
'libraryItem.approved' =>
|
||||
[
|
||||
Rule::when(
|
||||
$this->libraryItem->type !== 'bindle',
|
||||
'required',
|
||||
)
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (!$this->libraryItem) {
|
||||
$this->libraryItem = new LibraryItem([
|
||||
'approved' => true,
|
||||
'read_time' => 1,
|
||||
'value' => ''
|
||||
]);
|
||||
if ($this->lecturer) {
|
||||
$this->library = Library::query()
|
||||
->firstWhere('name', '=', 'Dozentenmaterial')?->id;
|
||||
}
|
||||
} else {
|
||||
$this->selectedTags = $this->libraryItem->tags()
|
||||
->where('type', 'library_item')
|
||||
->get()
|
||||
->map(fn($tag) => $tag->name)
|
||||
->toArray();
|
||||
$this->library = $this->libraryItem->libraries()
|
||||
->first()
|
||||
->id;
|
||||
}
|
||||
if (!$this->fromUrl) {
|
||||
$this->fromUrl = url()->previous();
|
||||
}
|
||||
if ($this->isBindle) {
|
||||
$this->library = 21;
|
||||
$this->libraryItem->lecturer_id = 125;
|
||||
$this->libraryItem->type = 'bindle';
|
||||
$this->libraryItem->language_code = 'de';
|
||||
$this->selectedTags = ['Bindle'];
|
||||
}
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->validate();
|
||||
$this->libraryItem->save();
|
||||
$this->libraryItem->setStatus('published');
|
||||
|
||||
$this->libraryItem->syncTagsWithType(
|
||||
$this->selectedTags,
|
||||
'library_item'
|
||||
);
|
||||
|
||||
if ($this->image) {
|
||||
$this->libraryItem->addMedia($this->image)
|
||||
->usingFileName(md5($this->image->getClientOriginalName()) . '.' . $this->image->getClientOriginalExtension())
|
||||
->toMediaCollection('main');
|
||||
}
|
||||
|
||||
if ($this->file) {
|
||||
$this->libraryItem->addMedia($this->file)
|
||||
->usingFileName(md5($this->file->getClientOriginalName()) . '.' . $this->file->getClientOriginalExtension())
|
||||
->toMediaCollection('single_file');
|
||||
}
|
||||
|
||||
$this->libraryItem->libraries()
|
||||
->syncWithoutDetaching([(int)$this->library]);
|
||||
|
||||
if ($this->libraryItem->type === 'bindle') {
|
||||
return to_route('bindles');
|
||||
}
|
||||
|
||||
return to_route('library.table.libraryItems', ['country' => $this->country]);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
$types = Options::forEnum(LibraryItemType::class)
|
||||
->filter(
|
||||
fn($type) => $type !== LibraryItemType::PodcastEpisode
|
||||
&& $type !== LibraryItemType::MarkdownArticle
|
||||
)
|
||||
->toArray();
|
||||
$libaries = Library::query()
|
||||
->when(auth()->id() != config('portal.bonus.fiat-tracker-user-id'),
|
||||
fn($query) => $query->where('name', '!=', 'Bindle')
|
||||
)
|
||||
->get()
|
||||
->map(fn($library) => [
|
||||
'id' => $library->id,
|
||||
'name' => $library->name,
|
||||
])
|
||||
->toArray();
|
||||
|
||||
if (auth()->id() == config('portal.bonus.fiat-tracker-user-id')) {
|
||||
$types = collect($types)->prepend([
|
||||
'label' => 'Bindle',
|
||||
'value' => 'bindle',
|
||||
]);
|
||||
}
|
||||
|
||||
return view('livewire.library.form.library-item-form', [
|
||||
'types' => $types,
|
||||
'libraries' => $libaries,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Library;
|
||||
|
||||
use App\Models\Country;
|
||||
use App\Models\Library;
|
||||
use App\Models\LibraryItem;
|
||||
use App\Models\Tag;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class LibraryTable extends Component
|
||||
{
|
||||
public Country $country;
|
||||
|
||||
public array $filters = [];
|
||||
|
||||
public bool $isLecturerPage = false;
|
||||
|
||||
public string $search = '';
|
||||
|
||||
public $perPage = 9;
|
||||
|
||||
public $currentTab = '*';
|
||||
|
||||
protected $queryString = [
|
||||
'currentTab' => ['except' => '*'],
|
||||
'filters' => ['except' => ''],
|
||||
'search' => ['except' => ''],
|
||||
];
|
||||
|
||||
public function loadMore()
|
||||
{
|
||||
$this->perPage += 9;
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (str(request()
|
||||
->route()
|
||||
->getName())->contains(['.lecturer'])) {
|
||||
$this->isLecturerPage = true;
|
||||
}
|
||||
}
|
||||
|
||||
public function resetFiltering($isLecturerPage = false)
|
||||
{
|
||||
if ($isLecturerPage) {
|
||||
return to_route('library.table.lecturer', ['country' => $this->country, 'currentTab' => '*']);
|
||||
} else {
|
||||
return to_route('library.table.libraryItems', ['country' => $this->country, 'currentTab' => '*']);
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
$shouldBePublic = !$this->isLecturerPage;
|
||||
$libraries = \App\Models\Library::query()
|
||||
->where('name', '!=', 'Bindle')
|
||||
->whereNull('parent_id')
|
||||
->where('is_public', $shouldBePublic)
|
||||
->orderBy('name')
|
||||
->get();
|
||||
$tabs = collect([
|
||||
[
|
||||
'name' => '*',
|
||||
],
|
||||
]);
|
||||
foreach ($libraries as $library) {
|
||||
$tabs->push([
|
||||
'name' => $library->name,
|
||||
]);
|
||||
}
|
||||
|
||||
if ($this->currentTab !== '*') {
|
||||
$parentLibrary = Library::query()
|
||||
->where('name', $this->currentTab)
|
||||
->first();
|
||||
}
|
||||
$searchTags = [];
|
||||
if ($this->search) {
|
||||
$searchTags = Tag::where('name', 'ilike', '%' . $this->search . '%')
|
||||
->pluck('id')
|
||||
->toArray();
|
||||
}
|
||||
|
||||
return view('livewire.library.library-table', [
|
||||
'libraries' => $tabs,
|
||||
'libraryItems' => LibraryItem::query()
|
||||
->with([
|
||||
'lecturer',
|
||||
'tags',
|
||||
])
|
||||
->where('type', '!=', 'bindle')
|
||||
->when($this->search, fn($query) => $query
|
||||
->where('name', 'ilike', '%' . $this->search . '%')
|
||||
->orWhere(fn($query) => $query
|
||||
->when(count($searchTags) > 0 && count($this->filters) < 1,
|
||||
fn($query) => $query->whereHas('tags',
|
||||
fn($query) => $query->whereIn('tags.id', $searchTags)))
|
||||
)
|
||||
)
|
||||
->when($this->currentTab !== '*', fn($query) => $query
|
||||
->whereHas('libraries',
|
||||
fn($query) => $query
|
||||
->where('libraries.name', $this->currentTab)
|
||||
)
|
||||
)
|
||||
->when(isset($this->filters['lecturer_id']),
|
||||
fn($query) => $query->where('library_items.lecturer_id',
|
||||
$this->filters['lecturer_id'])
|
||||
)
|
||||
->when(isset($this->filters['tag']), fn($query) => $query->whereHas('tags',
|
||||
fn($query) => $query->whereIn('tags.id', $this->filters['tag'])))
|
||||
->when(isset($this->filters['language']),
|
||||
fn($query) => $query->whereIn('language_code', $this->filters['language']))
|
||||
->whereHas('libraries',
|
||||
fn($query) => $query->where('libraries.is_public', $shouldBePublic))
|
||||
->orderByDesc('library_items.created_at')
|
||||
->paginate($this->perPage),
|
||||
])->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('Library'),
|
||||
description: __('Here you can find all content that are available in the library.'),
|
||||
image: asset('img/screenshot.png')
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Library;
|
||||
|
||||
use App\Models\Country;
|
||||
use App\Models\Episode;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class PodcastEpisodesTable extends Component
|
||||
{
|
||||
public Country $country;
|
||||
|
||||
public array $filters = [];
|
||||
|
||||
public string $search = '';
|
||||
|
||||
public $perPage = 9;
|
||||
|
||||
public $currentTab = '*';
|
||||
|
||||
protected $queryString = [
|
||||
'filters' => ['except' => ''],
|
||||
'search' => ['except' => ''],
|
||||
];
|
||||
|
||||
public function loadMore()
|
||||
{
|
||||
$this->perPage += 9;
|
||||
}
|
||||
|
||||
public function resetFiltering($isLecturerPage = false)
|
||||
{
|
||||
return to_route('library.table.podcastsEpisodes', ['country' => $this->country]);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.library.podcast-episodes-table', [
|
||||
'episodes' => Episode::query()
|
||||
->with(['podcast'])
|
||||
->whereNot('data->link', '=', '')
|
||||
->when($this->search,
|
||||
fn($query, $search) => $query
|
||||
->where('data->title', 'ilike', "%{$search}%")
|
||||
->orWhere('data->description', 'ilike', "%{$search}%")
|
||||
->orWhereHas('podcast',
|
||||
fn($query) => $query->where('data->title', 'ilike', "%{$search}%"))
|
||||
)
|
||||
->orderByDesc('data->datePublished')
|
||||
->paginate($this->perPage),
|
||||
])->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('Podcast Episodes'),
|
||||
description: __('Search and find Bitcoin Podcast episodes.'),
|
||||
image: asset('img/Screenshot_Podcast_Episodes.png')
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Library;
|
||||
|
||||
use App\Models\LibraryItem;
|
||||
use App\Models\Tag;
|
||||
use Livewire\Component;
|
||||
|
||||
class SearchByTagComponent extends Component
|
||||
{
|
||||
public string $country = 'de';
|
||||
|
||||
public array $filters = [];
|
||||
|
||||
protected $queryString = [
|
||||
'filters' => ['except' => ''],
|
||||
];
|
||||
|
||||
public function render()
|
||||
{
|
||||
$shouldBePublic = request()
|
||||
->route()
|
||||
->getName() !== 'library.table.lecturer';
|
||||
|
||||
return view('livewire.library.search-by-tag-component', [
|
||||
'languages' => LibraryItem::query()
|
||||
->pluck('language_code')
|
||||
->unique()
|
||||
->sort()
|
||||
->map(fn ($item) => str($item)
|
||||
->before('_')
|
||||
->toString())
|
||||
->values()
|
||||
->toArray(),
|
||||
'tags' => Tag::query()
|
||||
->with([
|
||||
'libraryItems.libraries',
|
||||
'libraryItems.lecturer',
|
||||
])
|
||||
->withCount([
|
||||
'libraryItems',
|
||||
])
|
||||
->where('type', 'library_item')
|
||||
->whereHas('libraryItems.libraries',
|
||||
fn ($query) => $query->where('is_public', $shouldBePublic))
|
||||
->orderByDesc('library_items_count')
|
||||
->orderBy('tags.id')
|
||||
->get(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Meetup\Embed;
|
||||
|
||||
use App\Models\Country;
|
||||
use App\Models\Meetup;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class CountryMap extends Component
|
||||
{
|
||||
public Country $country;
|
||||
|
||||
public bool $darkMode = false;
|
||||
|
||||
protected $queryString = ['darkMode' => ['except' => false]];
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.meetup.embed.country-map', [
|
||||
'markers' => Meetup::query()
|
||||
->with([
|
||||
'city.country',
|
||||
])
|
||||
->whereHas('city.country',
|
||||
fn($query) => $query->where('countries.code', $this->country->code))
|
||||
->get()
|
||||
->map(fn($meetup) => [
|
||||
'id' => $meetup->id,
|
||||
'name' => $meetup->name,
|
||||
'coords' => [$meetup->city->latitude, $meetup->city->longitude],
|
||||
'url' => url()->route('meetup.landing', [
|
||||
'country' => $meetup->city->country->code,
|
||||
'meetup' => $meetup,
|
||||
]),
|
||||
]),
|
||||
])->layout('layouts.app', [
|
||||
'darkModeDisabled' => !$this->darkMode,
|
||||
'SEOData' => new SEOData(
|
||||
title: __('Meetups'),
|
||||
description: __('Bitcoiner Meetups are a great way to meet other Bitcoiners in your area. You can learn from each other, share ideas, and have fun!'),
|
||||
image: asset('img/screenshot.png')
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Meetup\Form;
|
||||
|
||||
use App\Models\MeetupEvent;
|
||||
use App\Support\Carbon;
|
||||
use Livewire\Component;
|
||||
use WireUi\Traits\Actions;
|
||||
|
||||
class MeetupEventForm extends Component
|
||||
{
|
||||
use Actions;
|
||||
|
||||
public string $country;
|
||||
|
||||
public ?MeetupEvent $meetupEvent = null;
|
||||
|
||||
public bool $recurring = false;
|
||||
|
||||
public int $repetitions = 12;
|
||||
|
||||
public array $series = [];
|
||||
|
||||
public ?string $fromUrl = '';
|
||||
|
||||
protected $queryString = ['fromUrl' => ['except' => '']];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'meetupEvent.meetup_id' => 'required',
|
||||
'meetupEvent.start' => 'required',
|
||||
'meetupEvent.location' => 'string|max:255|nullable',
|
||||
'meetupEvent.description' => 'string|nullable',
|
||||
'meetupEvent.link' => 'url|max:255|nullable',
|
||||
|
||||
'series' => 'array',
|
||||
'series.*.start' => 'required',
|
||||
|
||||
'recurring' => 'bool',
|
||||
'repetitions' => 'numeric|min:1',
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (!$this->meetupEvent) {
|
||||
$this->meetupEvent = new MeetupEvent(
|
||||
[
|
||||
'start' => now()
|
||||
->startOfDay()
|
||||
->addHours(17),
|
||||
]
|
||||
);
|
||||
} elseif (!auth()
|
||||
->user()
|
||||
->can('update', $this->meetupEvent)) {
|
||||
abort(403);
|
||||
}
|
||||
if (!$this->fromUrl) {
|
||||
$this->fromUrl = url()->previous();
|
||||
}
|
||||
}
|
||||
|
||||
public function updatedMeetupEventStart($value)
|
||||
{
|
||||
$this->validateOnly('meetupEvent.start');
|
||||
if ($this->recurring) {
|
||||
$this->updatedRecurring(true);
|
||||
}
|
||||
}
|
||||
|
||||
public function updatedRecurring($value)
|
||||
{
|
||||
$this->validateOnly('recurring');
|
||||
$series = [];
|
||||
if ($value && $this->meetupEvent->start) {
|
||||
for ($i = 0; $i < $this->repetitions; $i++) {
|
||||
$series[] = [
|
||||
'start' => $this->meetupEvent->start->addMonths($i + 1)
|
||||
->toDateTimeString(),
|
||||
];
|
||||
}
|
||||
}
|
||||
$this->series = $series;
|
||||
}
|
||||
|
||||
public function updatedRepetitions($value)
|
||||
{
|
||||
$this->validateOnly('repetitions');
|
||||
if ($this->recurring) {
|
||||
$this->updatedRecurring(true, $value);
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteMe()
|
||||
{
|
||||
$this->dialog()
|
||||
->confirm(
|
||||
[
|
||||
'title' => __('Delete event'),
|
||||
'description' => __('Are you sure you want to delete this event? This action cannot be undone.'),
|
||||
'icon' => 'warning',
|
||||
'accept' => [
|
||||
'label' => __('Yes, delete'),
|
||||
'method' => 'deleteEvent',
|
||||
],
|
||||
'reject' => [
|
||||
'label' => __('No, cancel'),
|
||||
'method' => 'cancel',
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function deleteEvent()
|
||||
{
|
||||
$this->meetupEvent->delete();
|
||||
|
||||
return to_route('meetup.table.meetupEvent', ['country' => $this->country]);
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
$this->validate();
|
||||
if (!$this->meetupEvent->id) {
|
||||
$hasAppointmentsOnThisDate = MeetupEvent::query()
|
||||
->where('meetup_id', $this->meetupEvent->meetup_id)
|
||||
->where('start', '>', Carbon::parse($this->meetupEvent->start)
|
||||
->startOfDay())
|
||||
->where('start', '<', Carbon::parse($this->meetupEvent->start)
|
||||
->endOfDay())
|
||||
->exists();
|
||||
if ($hasAppointmentsOnThisDate) {
|
||||
$this->notification()
|
||||
->warning(__('There is already an event on this date. Please choose another date or delete the existing events.'));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$this->meetupEvent->save();
|
||||
|
||||
if ($this->recurring) {
|
||||
foreach ($this->series as $event) {
|
||||
$hasAppointmentsOnThisDate = MeetupEvent::query()
|
||||
->where('meetup_id', $this->meetupEvent->meetup_id)
|
||||
->where('start', '>', Carbon::parse($event['start'])
|
||||
->startOfDay())
|
||||
->where('start', '<', Carbon::parse($event['start'])
|
||||
->endOfDay())
|
||||
->exists();
|
||||
|
||||
if ($hasAppointmentsOnThisDate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->meetupEvent->replicate()
|
||||
->fill($event)
|
||||
->saveQuietly();
|
||||
}
|
||||
}
|
||||
|
||||
$this->notification()
|
||||
->success(__('Event saved successfully.'));
|
||||
|
||||
return to_route('meetup.table.meetupEvent', ['country' => $this->country]);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.meetup.form.meetup-event-form');
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Meetup\Form;
|
||||
|
||||
use App\Models\Meetup;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
use WireUi\Traits\Actions;
|
||||
|
||||
class MeetupForm extends Component
|
||||
{
|
||||
use WithFileUploads;
|
||||
use Actions;
|
||||
|
||||
public string $country;
|
||||
|
||||
public ?Meetup $meetup = null;
|
||||
|
||||
public ?string $fromUrl = '';
|
||||
|
||||
public $image;
|
||||
|
||||
protected $queryString = [
|
||||
'fromUrl' => [
|
||||
'except' => null,
|
||||
],
|
||||
];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'image' => [Rule::requiredIf(!$this->meetup->id), 'nullable', 'mimes:jpeg,png,jpg,gif', 'max:10240'],
|
||||
|
||||
'meetup.city_id' => 'required',
|
||||
'meetup.name' => [
|
||||
'required',
|
||||
Rule::unique('meetups', 'name')
|
||||
->ignore($this->meetup),
|
||||
],
|
||||
'meetup.community' => 'required',
|
||||
'meetup.telegram_link' => 'string|nullable|required_without_all:meetup.webpage,meetup.nostr,meetup.twitter_username,meetup.matrix_group',
|
||||
'meetup.intro' => 'string|nullable',
|
||||
'meetup.webpage' => 'string|url|nullable|required_without_all:meetup.telegram_link,meetup.nostr,meetup.twitter_username,meetup.matrix_group',
|
||||
'meetup.nostr' => 'string|nullable|required_without_all:meetup.webpage,meetup.telegram_link,meetup.twitter_username,meetup.matrix_group',
|
||||
'meetup.twitter_username' => 'string|regex:/^[A-z0-9!@]+$/|nullable|required_without_all:meetup.webpage,meetup.telegram_link,meetup.nostr,meetup.matrix_group',
|
||||
'meetup.matrix_group' => 'string|nullable|required_without_all:meetup.webpage,meetup.telegram_link,meetup.nostr,meetup.twitter_username',
|
||||
'meetup.simplex' => 'string|nullable',
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (!$this->meetup) {
|
||||
$this->meetup = new Meetup([
|
||||
'community' => 'einundzwanzig',
|
||||
]);
|
||||
} elseif (
|
||||
!auth()
|
||||
->user()
|
||||
->can('update', $this->meetup)
|
||||
) {
|
||||
abort(403);
|
||||
}
|
||||
if (!$this->fromUrl) {
|
||||
$this->fromUrl = url()->previous();
|
||||
}
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
$this->validate();
|
||||
$this->meetup->save();
|
||||
|
||||
if ($this->image) {
|
||||
$this->meetup->addMedia($this->image)
|
||||
->usingFileName(md5($this->image->getClientOriginalName()) . '.' . $this->image->getClientOriginalExtension())
|
||||
->toMediaCollection('logo');
|
||||
}
|
||||
|
||||
auth()
|
||||
->user()
|
||||
->meetups()
|
||||
->syncWithoutDetaching($this->meetup->id);
|
||||
|
||||
return redirect($this->fromUrl);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.meetup.form.meetup-form');
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Meetup;
|
||||
|
||||
use App\Models\Country;
|
||||
use App\Models\Meetup;
|
||||
use App\Models\MeetupEvent;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class LandingPage extends Component
|
||||
{
|
||||
public Meetup $meetup;
|
||||
|
||||
public Country $country;
|
||||
|
||||
public ?int $activeEvent = null;
|
||||
|
||||
public ?int $year = null;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->meetup->load([
|
||||
'media',
|
||||
]);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.meetup.landing-page', [
|
||||
'meetupEvents' => MeetupEvent::query()
|
||||
->with([
|
||||
'meetup.city.country',
|
||||
])
|
||||
->where('meetup_events.meetup_id', $this->meetup->id)
|
||||
->where('meetup_events.start', '>=', now()->subDay())
|
||||
->orderBy('start')
|
||||
->get(),
|
||||
'events' => MeetupEvent::query()
|
||||
->with([
|
||||
'meetup.city.country',
|
||||
])
|
||||
->where('meetup_events.meetup_id', $this->meetup->id)
|
||||
->where('meetup_events.start', '>=', now()->subDay())
|
||||
->orderBy('start')
|
||||
->get()
|
||||
->map(fn ($event) => [
|
||||
'id' => $event->id,
|
||||
'startDate' => $event->start,
|
||||
'endDate' => $event->start->addHours(1),
|
||||
'location' => $event->location,
|
||||
'description' => $event->description,
|
||||
]),
|
||||
])
|
||||
->layout('layouts.guest', [
|
||||
'SEOData' => new SEOData(
|
||||
title: $this->meetup->name,
|
||||
description: __('Bitcoiner Meetups are a great way to meet other Bitcoiners in your area. You can learn from each other, share ideas, and have fun!'),
|
||||
image: $this->meetup->getFirstMediaUrl('logo'),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
public function showEvent($id)
|
||||
{
|
||||
$this->activeEvent = $id;
|
||||
}
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Meetup;
|
||||
|
||||
use App\Models\Country;
|
||||
use App\Models\Meetup;
|
||||
use App\Models\MeetupEvent;
|
||||
use App\Models\User;
|
||||
use App\Rules\UniqueAttendeeName;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class LandingPageEvent extends Component
|
||||
{
|
||||
public MeetupEvent $meetupEvent;
|
||||
|
||||
public Country $country;
|
||||
|
||||
public ?Meetup $meetup = null;
|
||||
|
||||
public bool $willShowUp = false;
|
||||
|
||||
public bool $perhapsShowUp = false;
|
||||
|
||||
public string $name = '';
|
||||
|
||||
public array $attendees = [];
|
||||
public array $mightAttendees = [];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'name' => [
|
||||
'required',
|
||||
new UniqueAttendeeName($this->meetupEvent),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->meetupEvent->load('meetup.users');
|
||||
$this->meetup = $this->meetupEvent->meetup;
|
||||
$this->name = auth()->check() ? auth()->user()->name : '';
|
||||
$this->checkShowUp();
|
||||
}
|
||||
|
||||
public function checkShowUp()
|
||||
{
|
||||
$attendees = collect($this->meetupEvent->attendees);
|
||||
$mightAttendees = collect($this->meetupEvent->might_attendees);
|
||||
|
||||
if (auth()->check() && $attendees->contains(fn($value) => str($value)->contains('id_'.auth()->id()))) {
|
||||
$this->name = str($attendees->filter(fn($value) => str($value)->contains('id_'.auth()->id()))
|
||||
->first())
|
||||
->after('|')
|
||||
->toString();
|
||||
$this->willShowUp = true;
|
||||
}
|
||||
|
||||
if (!auth()->check() && $attendees->contains(fn($value) => str($value)->contains('anon_'.session()->getId()))) {
|
||||
$this->name = str($attendees->filter(fn($value) => str($value)->contains('anon_'.session()->getId()))
|
||||
->first())
|
||||
->after('|')
|
||||
->toString();
|
||||
$this->willShowUp = true;
|
||||
}
|
||||
|
||||
if (auth()->check() && $mightAttendees->contains(fn($value) => str($value)->contains('id_'.auth()->id()))) {
|
||||
$this->name = str($mightAttendees->filter(fn($value) => str($value)->contains('id_'.auth()->id()))
|
||||
->first())
|
||||
->after('|')
|
||||
->toString();
|
||||
$this->perhapsShowUp = true;
|
||||
}
|
||||
|
||||
if (!auth()->check() && $mightAttendees->contains(fn($value
|
||||
) => str($value)->contains('anon_'.session()->getId()))) {
|
||||
$this->name = str($mightAttendees->filter(fn($value) => str($value)->contains('anon_'.session()->getId()))
|
||||
->first())
|
||||
->after('|')
|
||||
->toString();
|
||||
$this->perhapsShowUp = true;
|
||||
}
|
||||
|
||||
$this->attendees = $this->mapAttendees($attendees);
|
||||
$this->mightAttendees = $this->mapAttendees($mightAttendees);
|
||||
}
|
||||
|
||||
private function mapAttendees($collection) {
|
||||
return $collection->map(function ($value) {
|
||||
if (str($value)->contains('anon_')) {
|
||||
$id = -1;
|
||||
} else {
|
||||
$id = str($value)
|
||||
->before('|')
|
||||
->after('id_')
|
||||
->toString();
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => $id,
|
||||
'user' => $id > 0 ? User::withoutEvents(static fn() => User::query()
|
||||
->select([
|
||||
'id',
|
||||
'name',
|
||||
'profile_photo_path',
|
||||
])
|
||||
->find($id)
|
||||
?->append('profile_photo_url')
|
||||
->toArray())
|
||||
: null,
|
||||
'name' => str($value)
|
||||
->after('|')
|
||||
->toString(),
|
||||
];
|
||||
})
|
||||
->toArray();
|
||||
}
|
||||
|
||||
public function cannotCome()
|
||||
{
|
||||
$attendees = collect($this->meetupEvent->attendees);
|
||||
$mightAttendees = collect($this->meetupEvent->might_attendees);
|
||||
|
||||
if (auth()->check() && $attendees->contains(fn($value) => str($value)->contains('id_'.auth()->id()))) {
|
||||
$attendees = $attendees->filter(fn($value) => !str($value)->contains('id_'.auth()->id()));
|
||||
$this->willShowUp = false;
|
||||
}
|
||||
|
||||
if (!auth()->check() && $attendees->contains(fn($value) => str($value)->contains('anon_'.session()->getId()))) {
|
||||
$attendees = $attendees->filter(fn($value) => !str($value)->contains('anon_'.session()->getId()));
|
||||
$this->willShowUp = false;
|
||||
}
|
||||
|
||||
if (auth()->check() && $mightAttendees->contains(fn($value) => str($value)->contains('id_'.auth()->id()))) {
|
||||
$mightAttendees = $mightAttendees->filter(fn($value) => !str($value)->contains('id_'.auth()->id()));
|
||||
$this->perhapsShowUp = false;
|
||||
}
|
||||
|
||||
if (!auth()->check() && $mightAttendees->contains(fn($value
|
||||
) => str($value)->contains('anon_'.session()->getId()))) {
|
||||
$mightAttendees = $mightAttendees->filter(fn($value) => !str($value)->contains('anon_'.session()->getId()));
|
||||
$this->perhapsShowUp = false;
|
||||
}
|
||||
|
||||
$this->meetupEvent->update([
|
||||
'attendees' => $attendees->toArray(),
|
||||
'might_attendees' => $mightAttendees->toArray(),
|
||||
]);
|
||||
|
||||
$this->checkShowUp();
|
||||
}
|
||||
|
||||
public function attend()
|
||||
{
|
||||
$this->validate();
|
||||
$attendees = collect($this->meetupEvent->attendees);
|
||||
|
||||
if (auth()->check() && !$attendees->contains('id_'.auth()->id().'|'.$this->name)) {
|
||||
$attendees->push('id_'.auth()->id().'|'.$this->name);
|
||||
$this->willShowUp = true;
|
||||
}
|
||||
|
||||
if (!auth()->check() && !$attendees->contains('anon_'.session()->getId().'|'.$this->name)) {
|
||||
$attendees->push('anon_'.session()->getId().'|'.$this->name);
|
||||
$this->willShowUp = true;
|
||||
}
|
||||
|
||||
$this->meetupEvent->update([
|
||||
'attendees' => $attendees->toArray(),
|
||||
]);
|
||||
|
||||
$this->checkShowUp();
|
||||
}
|
||||
|
||||
public function mightAttend()
|
||||
{
|
||||
$this->validate();
|
||||
$mightAttendees = collect($this->meetupEvent->might_attendees);
|
||||
|
||||
if (auth()->check() && !$mightAttendees->contains('id_'.auth()->id().'|'.$this->name)) {
|
||||
$mightAttendees->push('id_'.auth()->id().'|'.$this->name);
|
||||
$this->perhapsShowUp = true;
|
||||
}
|
||||
|
||||
if (!auth()->check() && !$mightAttendees->contains('anon_'.session()->getId().'|'.$this->name)) {
|
||||
$mightAttendees->push('anon_'.session()->getId().'|'.$this->name);
|
||||
$this->perhapsShowUp = true;
|
||||
}
|
||||
|
||||
$this->meetupEvent->update([
|
||||
'might_attendees' => $mightAttendees->toArray(),
|
||||
]);
|
||||
|
||||
$this->checkShowUp();
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.meetup.landing-page-event')->layout('layouts.guest', [
|
||||
'SEOData' => new SEOData(
|
||||
title: $this->meetupEvent->start->asDateTime().' - '.$this->meetup->name,
|
||||
description: __('Here you can confirm your participation and find more information about the Meetup.').' - '.$this->meetupEvent->description,
|
||||
image: $this->meetup->getFirstMediaUrl('logo'),
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Meetup;
|
||||
|
||||
use App\Models\Country;
|
||||
use App\Models\MeetupEvent;
|
||||
use App\Traits\HasMapEmbedCodeTrait;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
use WireUi\Traits\Actions;
|
||||
|
||||
class MeetupEventTable extends Component
|
||||
{
|
||||
use Actions;
|
||||
use HasMapEmbedCodeTrait;
|
||||
|
||||
public Country $country;
|
||||
|
||||
public ?int $year = null;
|
||||
|
||||
protected $queryString = ['year'];
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (!$this->year) {
|
||||
$this->year = now()->year;
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.meetup.meetup-event-table', [
|
||||
'markers' => MeetupEvent::query()
|
||||
->with([
|
||||
'meetup.city.country',
|
||||
])
|
||||
->where('meetup_events.start', '>=', now()->subDay())
|
||||
->whereHas('meetup.city.country',
|
||||
fn($query) => $query->where('countries.code', $this->country->code))
|
||||
->get()
|
||||
->map(fn($event) => [
|
||||
'id' => $event->id,
|
||||
'name' => $event->meetup->name . ': ' . $event->location,
|
||||
'coords' => [$event->meetup->city->latitude, $event->meetup->city->longitude],
|
||||
]),
|
||||
'events' => MeetupEvent::query()
|
||||
->with([
|
||||
'meetup.city.country',
|
||||
])
|
||||
->where('meetup_events.start', '>=', now()->subDay())
|
||||
->whereHas('meetup.city.country',
|
||||
fn($query) => $query->where('countries.code', $this->country->code))
|
||||
->get()
|
||||
->map(fn($event) => [
|
||||
'id' => $event->id,
|
||||
'startDate' => $event->start,
|
||||
'endDate' => $event->start->addHours(1),
|
||||
'location' => $event->location,
|
||||
'description' => $event->description,
|
||||
]),
|
||||
])->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('Meetup dates'),
|
||||
description: __('List of all meetup dates'),
|
||||
image: asset('img/screenshot.png')
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
public function filterByMarker($id)
|
||||
{
|
||||
return to_route('meetup.table.meetupEvent', [
|
||||
'#table',
|
||||
'country' => $this->country->code,
|
||||
'year' => $this->year,
|
||||
'meetup_events' => [
|
||||
'filters' => [
|
||||
'byid' => $id,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function popover($content, $ids)
|
||||
{
|
||||
return to_route('meetup.table.meetupEvent', [
|
||||
'#table',
|
||||
'year' => $this->year,
|
||||
'country' => $this->country->code,
|
||||
'meetup_events' => [
|
||||
'filters' => [
|
||||
'byid' => $ids,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Meetup;
|
||||
|
||||
use App\Models\Country;
|
||||
use App\Models\Meetup;
|
||||
use App\Traits\HasMapEmbedCodeTrait;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class MeetupTable extends Component
|
||||
{
|
||||
use HasMapEmbedCodeTrait;
|
||||
|
||||
public Country $country;
|
||||
|
||||
public function filterByMarker($id)
|
||||
{
|
||||
$meetup = Meetup::with(['city.country'])
|
||||
->find($id);
|
||||
|
||||
return to_route('meetup.landing', [
|
||||
'country' => $meetup->city->country->code,
|
||||
'meetup' => $meetup,
|
||||
]);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
// let markers = [{name: 'VAK', coords: [50.0091294, 9.0371812], status: 'closed', offsets: [0, 2]}];
|
||||
|
||||
return view('livewire.meetup.meetup-table', [
|
||||
'markers' => Meetup::query()
|
||||
->where('visible_on_map', true)
|
||||
->with([
|
||||
'city.country',
|
||||
])
|
||||
->whereHas('city.country',
|
||||
fn($query) => $query->where('countries.code', $this->country->code))
|
||||
->get()
|
||||
->map(fn($meetup) => [
|
||||
'id' => $meetup->id,
|
||||
'name' => $meetup->name,
|
||||
'coords' => [$meetup->city->latitude, $meetup->city->longitude],
|
||||
]),
|
||||
])->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('Meetups'),
|
||||
description: __('Bitcoiner Meetups are a great way to meet other Bitcoiners in your area. You can learn from each other, share ideas, and have fun!'),
|
||||
image: asset('img/screenshot.png')
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Meetup;
|
||||
|
||||
use App\Models\Country;
|
||||
use App\Models\Meetup;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class WorldMap extends Component
|
||||
{
|
||||
public Country $country;
|
||||
|
||||
public function filterByMarker($id)
|
||||
{
|
||||
$meetup = Meetup::with(['city.country'])
|
||||
->find($id);
|
||||
|
||||
return to_route('meetup.landing', [
|
||||
'country' => $meetup->city->country->code,
|
||||
'meetup' => $meetup,
|
||||
]);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.meetup.world-map', [
|
||||
'allMarkers' => Meetup::query()
|
||||
->where('visible_on_map', true)
|
||||
->with([
|
||||
'city.country',
|
||||
])
|
||||
->get()
|
||||
->map(fn($meetup) => [
|
||||
'id' => $meetup->id,
|
||||
'name' => $meetup->name,
|
||||
'coords' => [$meetup->city->latitude, $meetup->city->longitude],
|
||||
]),
|
||||
])->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('World map of meetups'),
|
||||
image: asset('img/screenshot.png')
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\News;
|
||||
|
||||
use App\Models\LibraryItem;
|
||||
use App\Traits\NostrTrait;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
use WireUi\Traits\Actions;
|
||||
|
||||
class ArticleOverview extends Component
|
||||
{
|
||||
use Actions;
|
||||
use NostrTrait;
|
||||
|
||||
public $perPage = 9;
|
||||
|
||||
public array $filters = [];
|
||||
|
||||
protected $queryString = [
|
||||
'filters' => ['except' => ''],
|
||||
];
|
||||
|
||||
public function loadMore()
|
||||
{
|
||||
$this->perPage += 9;
|
||||
}
|
||||
|
||||
public function nostr($id)
|
||||
{
|
||||
$libraryItem = LibraryItem::query()
|
||||
->with([
|
||||
'lecturer',
|
||||
])
|
||||
->find($id);
|
||||
$libraryItem->setStatus('published');
|
||||
$libraryItemName = $libraryItem->name;
|
||||
if ($libraryItem->lecturer->nostr) {
|
||||
$libraryItemName .= ' von @'.$libraryItem->lecturer->nostr;
|
||||
} else {
|
||||
$libraryItemName .= ' von '.$libraryItem->lecturer->name;
|
||||
}
|
||||
$text = sprintf("Ein neuer News-Artikel wurde verfasst:\n\n%s\n\n%s\n\n#Bitcoin #News #Einundzwanzig #gesundesgeld #einundzwanzig_portal_%s",
|
||||
$libraryItemName,
|
||||
url()->route('article.view',
|
||||
['libraryItem' => $libraryItem->slug]),
|
||||
str($libraryItem->slug)->replace('-', '_')
|
||||
);
|
||||
$result = $this->publishOnNostr($libraryItem, $text);
|
||||
if ($result['success']) {
|
||||
$this->notification()
|
||||
->success(title: __('Published on Nostr'), description: $result['output']);
|
||||
} else {
|
||||
$this->notification()
|
||||
->error(title: __('Failed'),
|
||||
description: 'Exit Code: '.$result['exitCode'].' Reason: '.$result['errorOutput']);
|
||||
}
|
||||
}
|
||||
|
||||
public function approve($id)
|
||||
{
|
||||
$libraryItem = LibraryItem::find($id);
|
||||
$libraryItem->approved = true;
|
||||
$libraryItem->save();
|
||||
|
||||
$this->notification()
|
||||
->success(__('Article approved'));
|
||||
|
||||
$this->emit('$refresh');
|
||||
}
|
||||
|
||||
public function resetFiltering()
|
||||
{
|
||||
return to_route('article.overview');
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.news.article-overview', [
|
||||
'libraryItems' => LibraryItem::query()
|
||||
->with([
|
||||
'createdBy.roles',
|
||||
'lecturer',
|
||||
'tags',
|
||||
])
|
||||
->when(
|
||||
isset($this->filters['author']),
|
||||
fn($query) => $query->whereHas('lecturer',
|
||||
fn($query) => $query->where('lecturers.slug',
|
||||
$this->filters['author'])))
|
||||
->where('type', 'markdown_article')
|
||||
->where('news', true)
|
||||
->orderByDesc('created_at')
|
||||
->paginate($this->perPage),
|
||||
])->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('News'),
|
||||
description: __('Here we post important news that is relevant for everyone.'),
|
||||
image: asset('img/einundzwanzig-news-colored.png'),
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\News;
|
||||
|
||||
use App\Models\Lecturer;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class AuthorsOverview extends Component
|
||||
{
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.news.authors-overview', [
|
||||
'authors' => Lecturer::query()
|
||||
->whereHas('libraryItems', function ($query) {
|
||||
$query->where('library_items.news', true);
|
||||
})
|
||||
->withCount([
|
||||
'libraryItems' => fn($query) => $query->where('library_items.news', true),
|
||||
])
|
||||
->orderByDesc('library_items_count')
|
||||
->get(),
|
||||
])->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('News articles writer'),
|
||||
description: __('Click on any of the authors to see their articles.'),
|
||||
image: asset('img/einundzwanzig-news-colored.png'),
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\News\Form;
|
||||
|
||||
use App\Models\LibraryItem;
|
||||
use App\Traits\HasTagsTrait;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
|
||||
class NewsArticleForm extends Component
|
||||
{
|
||||
use HasTagsTrait;
|
||||
use WithFileUploads;
|
||||
|
||||
public ?LibraryItem $libraryItem = null;
|
||||
|
||||
public $image;
|
||||
|
||||
public $currentImage = 0;
|
||||
|
||||
public $images;
|
||||
|
||||
public $imagesCloned = [];
|
||||
|
||||
public array $temporaryUrls = [];
|
||||
|
||||
public ?string $fromUrl = '';
|
||||
|
||||
public string $type = '';
|
||||
|
||||
public bool $paid = false;
|
||||
|
||||
protected $queryString = ['fromUrl' => ['except' => ''], 'type' => ['except' => '']];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'image' => [Rule::requiredIf(!$this->libraryItem->id), 'nullable', 'mimes:jpeg,png,jpg,gif', 'max:10240'],
|
||||
|
||||
'selectedTags' => 'array|min:1',
|
||||
|
||||
'libraryItem.lecturer_id' => 'required',
|
||||
'libraryItem.name' => 'required',
|
||||
'libraryItem.type' => 'required',
|
||||
'libraryItem.language_code' => 'required',
|
||||
'libraryItem.value' => 'required',
|
||||
'libraryItem.value_to_be_paid' => [Rule::requiredIf($this->libraryItem->sats > 0), 'nullable', 'string',],
|
||||
'libraryItem.sats' => [
|
||||
Rule::requiredIf($this->libraryItem->sats > 0), 'nullable', 'numeric',
|
||||
],
|
||||
'libraryItem.subtitle' => 'string|nullable',
|
||||
'libraryItem.excerpt' => 'required',
|
||||
'libraryItem.main_image_caption' => 'string|nullable',
|
||||
'libraryItem.read_time' => 'numeric|nullable',
|
||||
'libraryItem.approved' => 'boolean',
|
||||
'libraryItem.news' => 'boolean',
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if ($this->type === 'paid') {
|
||||
$this->paid = true;
|
||||
}
|
||||
if (!$this->libraryItem) {
|
||||
$this->libraryItem = new LibraryItem([
|
||||
'type' => 'markdown_article',
|
||||
'value' => '',
|
||||
'value_to_be_paid' => '',
|
||||
'read_time' => 1,
|
||||
'sats' => $this->paid ? 21 : null,
|
||||
'news' => true,
|
||||
'language_code' => 'de',
|
||||
'approved' => false,
|
||||
]);
|
||||
$this->selectedTags[] = 'News';
|
||||
} else {
|
||||
$this->selectedTags = $this->libraryItem->tags()
|
||||
->where('type', 'library_item')
|
||||
->get()
|
||||
->map(fn($tag) => $tag->name)
|
||||
->toArray();
|
||||
}
|
||||
if (!$this->fromUrl) {
|
||||
$this->fromUrl = url()->previous();
|
||||
}
|
||||
if (!$this->libraryItem->value_to_be_paid) {
|
||||
$this->libraryItem->value_to_be_paid = '';
|
||||
}
|
||||
}
|
||||
|
||||
public function updatedImages($value)
|
||||
{
|
||||
$clonedImages = collect($this->imagesCloned);
|
||||
$clonedImages = $clonedImages->push($value);
|
||||
$this->imagesCloned = $clonedImages->toArray();
|
||||
|
||||
$temporaryUrls = collect($this->temporaryUrls);
|
||||
$temporaryUrls = $temporaryUrls->push($value->temporaryUrl());
|
||||
$this->temporaryUrls = $temporaryUrls->toArray();
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->validate();
|
||||
$this->libraryItem->save();
|
||||
|
||||
$this->libraryItem->syncTagsWithType(
|
||||
$this->selectedTags,
|
||||
'library_item'
|
||||
);
|
||||
|
||||
if ($this->image) {
|
||||
$this->libraryItem->addMedia($this->image)
|
||||
->usingFileName(md5($this->image->getClientOriginalName()).'.'.$this->image->getClientOriginalExtension())
|
||||
->toMediaCollection('main');
|
||||
}
|
||||
|
||||
return redirect($this->fromUrl);
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$this->libraryItem->delete();
|
||||
|
||||
return redirect($this->fromUrl);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.news.form.news-article-form');
|
||||
}
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\News;
|
||||
|
||||
use App\Models\LibraryItem;
|
||||
use App\Traits\LNBitsTrait;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
use SimpleSoftwareIO\QrCode\Facades\QrCode;
|
||||
use Spatie\CommonMarkShikiHighlighter\HighlightCodeExtension;
|
||||
use WireUi\Traits\Actions;
|
||||
|
||||
class InternArticleView extends Component
|
||||
{
|
||||
use Actions;
|
||||
use LNBitsTrait;
|
||||
|
||||
public LibraryItem $libraryItem;
|
||||
|
||||
public $qrCode = '';
|
||||
public $invoice = '';
|
||||
public $paymentHash = '';
|
||||
public $checkid = null;
|
||||
public $checkThisPaymentHash = '';
|
||||
public bool $invoicePaid = false;
|
||||
public bool $alreadyPaid = false;
|
||||
|
||||
public ?string $payNymQrCode = '';
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->libraryItem->load([
|
||||
'libraries',
|
||||
]);
|
||||
if ($this->libraryItem->libraries->where('is_public', false)
|
||||
->count() > 0 && !auth()->check()) {
|
||||
abort(403, __('Sorry! You are not authorized to perform this action.'));
|
||||
}
|
||||
if (auth()->check() && auth()
|
||||
->user()
|
||||
->paidArticles()
|
||||
->where('library_item_id', $this->libraryItem->id)
|
||||
->count() > 0) {
|
||||
$this->invoicePaid = true;
|
||||
}
|
||||
if ($this->libraryItem->lecturer->paynym) {
|
||||
$this->payNymQrCode = base64_encode(QrCode::format('png')
|
||||
->size(300)
|
||||
->merge($this->libraryItem->lecturer->getFirstMedia('avatar')
|
||||
? str(
|
||||
$this->libraryItem
|
||||
->lecturer
|
||||
->getFirstMediaPath('avatar'))
|
||||
->replace('/home/einundzwanzig/portal.einundzwanzig.space',
|
||||
''
|
||||
)
|
||||
: '/public/img/einundzwanzig.png',
|
||||
.3)
|
||||
->errorCorrection('H')
|
||||
->generate($this->libraryItem->lecturer->paynym));
|
||||
}
|
||||
}
|
||||
|
||||
public function pay()
|
||||
{
|
||||
try {
|
||||
$invoice = $this->createInvoice(
|
||||
sats: $this->libraryItem->sats,
|
||||
memo: 'Payment for: "'.$this->libraryItem->slug.'" on Einundzwanzig Portal.',
|
||||
lnbits: $this->libraryItem->createdBy->lnbits,
|
||||
);
|
||||
} catch (\Exception $e) {
|
||||
$this->notification()
|
||||
->error('LNBits error: '.$e->getMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
session('payment_hash_article_'.$this->libraryItem->id, $invoice['payment_hash']);
|
||||
$this->paymentHash = $invoice['payment_hash'];
|
||||
$this->qrCode = base64_encode(QrCode::format('png')
|
||||
->size(300)
|
||||
->merge($this->libraryItem->lecturer->getFirstMedia('avatar')
|
||||
? str(
|
||||
$this->libraryItem
|
||||
->lecturer
|
||||
->getFirstMediaPath('avatar'))
|
||||
->replace('/home/einundzwanzig/portal.einundzwanzig.space',
|
||||
''
|
||||
)
|
||||
: '/public/img/einundzwanzig.png',
|
||||
.3)
|
||||
->errorCorrection('H')
|
||||
->generate($invoice['payment_request']));
|
||||
$this->invoice = $invoice['payment_request'];
|
||||
$this->checkid = $invoice['checking_id'];
|
||||
}
|
||||
|
||||
public function checkPaymentHash()
|
||||
{
|
||||
try {
|
||||
$invoice = $this->check($this->checkid ?? $this->checkThisPaymentHash,
|
||||
$this->libraryItem->createdBy->lnbits);
|
||||
} catch (\Exception $e) {
|
||||
$this->notification()
|
||||
->error('LNBits error: '.$e->getMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
if (isset($invoice['paid']) && $invoice['paid']) {
|
||||
$this->invoicePaid = true;
|
||||
if (auth()->check()) {
|
||||
auth()
|
||||
->user()
|
||||
->paidArticles()
|
||||
->syncWithoutDetaching($this->libraryItem->id);
|
||||
}
|
||||
} else {
|
||||
Log::error(json_encode($invoice, JSON_THROW_ON_ERROR));
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.news.intern-article-view')->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: $this->libraryItem->name,
|
||||
description: strip_tags($this->libraryItem->excerpt) ?? __('Here we post important news that is relevant for everyone.'),
|
||||
author: $this->libraryItem->lecturer->name,
|
||||
image: $this->libraryItem->getFirstMedia('main')
|
||||
? $this->libraryItem->getFirstMediaUrl('main', 'seo')
|
||||
: url()->route('imgPublic', [
|
||||
'path' => 'img/einundzwanzig-wallpaper-benrath.png', 'h' => 630, 'w' => 1200, 'fit' => 'crop'
|
||||
]),
|
||||
published_time: Carbon::parse($this->libraryItem->created_at),
|
||||
type: 'article',
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Nostr;
|
||||
|
||||
use App\Models\User;
|
||||
use Livewire\Component;
|
||||
|
||||
class PlebsOverview extends Component
|
||||
{
|
||||
public array $plebsNpubs = [];
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->plebsNpubs = User::query()
|
||||
->select([
|
||||
'email',
|
||||
'public_key',
|
||||
'lightning_address',
|
||||
'lnurl',
|
||||
'node_id',
|
||||
'paynym',
|
||||
'lnbits',
|
||||
'nostr',
|
||||
'id',
|
||||
])
|
||||
->whereNotNull('nostr')
|
||||
->orderByDesc('id')
|
||||
->get()
|
||||
->unique('nostr')
|
||||
->pluck('nostr')
|
||||
->toArray();
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.nostr.plebs-overview');
|
||||
}
|
||||
}
|
||||
13
app/Http/Livewire/Nostr/Start.php
Normal file
13
app/Http/Livewire/Nostr/Start.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Nostr;
|
||||
|
||||
use Livewire\Component;
|
||||
|
||||
class Start extends Component
|
||||
{
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.nostr.start');
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Profile;
|
||||
|
||||
use App\Traits\LNBitsTrait;
|
||||
use Livewire\Component;
|
||||
use WireUi\Traits\Actions;
|
||||
|
||||
class LNBits extends Component
|
||||
{
|
||||
use Actions;
|
||||
use LNBitsTrait;
|
||||
|
||||
public array $settings = [
|
||||
'url' => 'https://legend.lnbits.com',
|
||||
'wallet_id' => '',
|
||||
'read_key' => '',
|
||||
];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'settings.url' => 'required|url',
|
||||
'settings.wallet_id' => 'required',
|
||||
'settings.read_key' => 'required',
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (auth()->user()->lnbits) {
|
||||
$this->settings = auth()->user()->lnbits;
|
||||
}
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->validate();
|
||||
if ($this->checkLnbitsSettings($this->settings['read_key'], $this->settings['url'], $this->settings['wallet_id']) === false) {
|
||||
$this->notification()
|
||||
->error(__('LNBits settings are not valid!'));
|
||||
|
||||
return;
|
||||
}
|
||||
$user = auth()->user();
|
||||
$user->lnbits = $this->settings;
|
||||
$user->save();
|
||||
|
||||
$this->notification()
|
||||
->success(__('LNBits settings saved successfully!'));
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.profile.l-n-bits');
|
||||
}
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Profile;
|
||||
|
||||
use App\Models\Meetup;
|
||||
use Livewire\Component;
|
||||
use WireUi\Traits\Actions;
|
||||
|
||||
class Meetups extends Component
|
||||
{
|
||||
use Actions;
|
||||
|
||||
public $search = '';
|
||||
|
||||
public $meetups;
|
||||
|
||||
public $myMeetups = [];
|
||||
|
||||
public $myMeetupNames = [];
|
||||
|
||||
public $hasMeetups = false;
|
||||
|
||||
public ?string $fromUrl = '';
|
||||
|
||||
protected $queryString = ['fromUrl' => ['except' => '']];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'search' => 'string',
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (!auth()->user()) {
|
||||
return to_route('auth.login');
|
||||
}
|
||||
|
||||
$this->meetups = Meetup::query()
|
||||
->with([
|
||||
'city',
|
||||
])
|
||||
->where('name', 'ilike', '%'.$this->search.'%')
|
||||
->orderBy('name')
|
||||
->limit(10)
|
||||
->get();
|
||||
$this->myMeetups = auth()
|
||||
->user()
|
||||
->meetups()
|
||||
->pluck('meetup_id')
|
||||
->toArray();
|
||||
$this->myMeetupNames = auth()
|
||||
->user()
|
||||
->meetups()
|
||||
->with([
|
||||
'city.country'
|
||||
])
|
||||
->select('meetups.id', 'meetups.city_id', 'meetups.name', 'meetups.slug')
|
||||
->get()
|
||||
->map(fn($meetup) => [
|
||||
'id' => $meetup->id,
|
||||
'name' => $meetup->name,
|
||||
'link' => route('meetup.landing', [
|
||||
'country' => $meetup->city->country->code,
|
||||
'meetup' => $meetup,
|
||||
])
|
||||
])
|
||||
->toArray();
|
||||
if (count($this->myMeetups) > 0) {
|
||||
$this->hasMeetups = true;
|
||||
}
|
||||
if (!$this->fromUrl) {
|
||||
$this->fromUrl = url()->previous();
|
||||
}
|
||||
}
|
||||
|
||||
public function next()
|
||||
{
|
||||
return redirect($this->fromUrl);
|
||||
}
|
||||
|
||||
public function updatedSearch($value)
|
||||
{
|
||||
$this->meetups = Meetup::query()
|
||||
->with([
|
||||
'city',
|
||||
])
|
||||
->where('name', 'ilike', '%'.$value.'%')
|
||||
->orderBy('name')
|
||||
->limit(10)
|
||||
->get();
|
||||
}
|
||||
|
||||
public function signUpForMeetup($id)
|
||||
{
|
||||
$user = auth()->user();
|
||||
$user->meetups()
|
||||
->toggle($id);
|
||||
$this->myMeetups = auth()
|
||||
->user()
|
||||
->meetups()
|
||||
->pluck('meetup_id')
|
||||
->toArray();
|
||||
if (count($this->myMeetups) > 0) {
|
||||
$this->hasMeetups = true;
|
||||
} else {
|
||||
$this->hasMeetups = false;
|
||||
}
|
||||
$this->myMeetupNames = auth()
|
||||
->user()
|
||||
->meetups()
|
||||
->with([
|
||||
'city.country'
|
||||
])
|
||||
->select('meetups.id', 'meetups.city_id', 'meetups.name', 'meetups.slug')
|
||||
->get()
|
||||
->map(fn($meetup) => [
|
||||
'id' => $meetup->id,
|
||||
'name' => $meetup->name,
|
||||
'link' => route('meetup.landing', [
|
||||
'country' => $meetup->city->country->code,
|
||||
'meetup' => $meetup,
|
||||
])
|
||||
])
|
||||
->toArray();
|
||||
$this->notification()
|
||||
->success(__('Saved.'));
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.profile.meetups');
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\ProjectProposal\Form;
|
||||
|
||||
use App\Models\Country;
|
||||
use App\Models\ProjectProposal;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
|
||||
class ProjectProposalForm extends Component
|
||||
{
|
||||
use WithFileUploads;
|
||||
|
||||
public Country $country;
|
||||
|
||||
public ?ProjectProposal $projectProposal = null;
|
||||
|
||||
public $image;
|
||||
|
||||
public ?string $fromUrl = '';
|
||||
|
||||
protected $queryString = [
|
||||
'fromUrl' => ['except' => ''],
|
||||
];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'image' => [
|
||||
'nullable', 'mimes:jpeg,png,jpg,gif', 'max:10240'
|
||||
],
|
||||
|
||||
'projectProposal.user_id' => 'required',
|
||||
'projectProposal.name' => 'required',
|
||||
'projectProposal.support_in_sats' => 'required|numeric',
|
||||
'projectProposal.description' => 'required',
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (!$this->projectProposal) {
|
||||
$this->projectProposal = new ProjectProposal([
|
||||
'user_id' => auth()->id(),
|
||||
'description' => '',
|
||||
]);
|
||||
}
|
||||
if (!$this->fromUrl) {
|
||||
$this->fromUrl = url()->previous();
|
||||
}
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->validate();
|
||||
$this->projectProposal->save();
|
||||
|
||||
if ($this->image) {
|
||||
$this->projectProposal->addMedia($this->image)
|
||||
->usingFileName(md5($this->image->getClientOriginalName()).'.'.$this->image->getClientOriginalExtension())
|
||||
->toMediaCollection('main');
|
||||
}
|
||||
|
||||
return redirect($this->fromUrl);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project-proposal.form.project-proposal-form', [
|
||||
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\ProjectProposal;
|
||||
|
||||
use App\Models\Country;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class ProjectProposalTable extends Component
|
||||
{
|
||||
public Country $country;
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project-proposal.project-proposal-table')->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('Project Proposal'),
|
||||
description: __('Submit a project proposal and let the community vote on it through the elected voters. All other community members can also vote.'),
|
||||
image: asset('img/voting.jpg')
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\ProjectProposal;
|
||||
|
||||
use App\Models\Country;
|
||||
use App\Models\ProjectProposal;
|
||||
use App\Models\User;
|
||||
use App\Models\Vote;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class ProjectProposalVoting extends Component
|
||||
{
|
||||
public ?ProjectProposal $projectProposal = null;
|
||||
public ?Vote $vote = null;
|
||||
|
||||
public ?string $fromUrl = '';
|
||||
|
||||
protected $queryString = [
|
||||
'fromUrl' => ['except' => ''],
|
||||
];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'vote.user_id' => 'required',
|
||||
'vote.project_proposal_id' => 'required',
|
||||
'vote.value' => 'required|boolean',
|
||||
'vote.reason' => [
|
||||
Rule::requiredIf(!$this->vote->value),
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->projectProposal->load('votes');
|
||||
$vote = Vote::query()
|
||||
->where('user_id', auth()->id())
|
||||
->where('project_proposal_id', $this->projectProposal->id)
|
||||
->first();
|
||||
if ($vote) {
|
||||
$this->vote = $vote;
|
||||
} else {
|
||||
$this->vote = new Vote();
|
||||
$this->vote->user_id = auth()->id();
|
||||
$this->vote->project_proposal_id = $this->projectProposal->id;
|
||||
$this->vote->value = false;
|
||||
}
|
||||
if (!$this->fromUrl) {
|
||||
$this->fromUrl = url()->previous();
|
||||
}
|
||||
}
|
||||
|
||||
public function yes()
|
||||
{
|
||||
$this->vote->value = true;
|
||||
$this->vote->save();
|
||||
|
||||
return to_route('voting.projectFunding',
|
||||
['projectProposal' => $this->projectProposal, 'fromUrl' => $this->fromUrl]);
|
||||
}
|
||||
|
||||
public function no()
|
||||
{
|
||||
$this->validate();
|
||||
|
||||
$this->vote->value = false;
|
||||
$this->vote->save();
|
||||
|
||||
return to_route('voting.projectFunding',
|
||||
['projectProposal' => $this->projectProposal, 'fromUrl' => $this->fromUrl]);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project-proposal.project-proposal-voting', [
|
||||
'entitledVoters' => User::query()
|
||||
->with([
|
||||
'votes' => fn($query) => $query->where('project_proposal_id',
|
||||
$this->projectProposal->id)
|
||||
])
|
||||
->withCount([
|
||||
'votes' => fn($query) => $query->where('project_proposal_id',
|
||||
$this->projectProposal->id)
|
||||
])
|
||||
->whereHas('roles', function ($query) {
|
||||
return $query->where('roles.name', 'entitled-voter');
|
||||
})
|
||||
->orderByDesc('votes_count')
|
||||
->get(),
|
||||
'otherVoters' => User::query()
|
||||
->with([
|
||||
'votes' => fn($query) => $query->where('project_proposal_id',
|
||||
$this->projectProposal->id)
|
||||
])
|
||||
->withCount([
|
||||
'votes' => fn($query) => $query->where('project_proposal_id',
|
||||
$this->projectProposal->id)
|
||||
])
|
||||
->whereDoesntHave('roles', function ($query) {
|
||||
return $query->where('roles.name', 'entitled-voter');
|
||||
})
|
||||
->orderByDesc('votes_count')
|
||||
->get(),
|
||||
])->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('Project Proposal'),
|
||||
description: __('Submit a project proposal and let the community vote on it through the elected voters. All other community members can also vote.'),
|
||||
image: asset('img/voting.jpg')
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\School;
|
||||
|
||||
use App\Models\Country;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class CityTable extends Component
|
||||
{
|
||||
public Country $country;
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.school.city-table')->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('Courses'),
|
||||
description: __('Choose your city, search for courses in the surrounding area and select a topic that suits you.'),
|
||||
image: asset('img/screenshot.png')
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\School;
|
||||
|
||||
use App\Models\Country;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class CourseTable extends Component
|
||||
{
|
||||
public Country $country;
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.school.course-table')->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('Courses'),
|
||||
description: __('Choose your city, search for courses in the surrounding area and select a topic that suits you.'),
|
||||
image: asset('img/screenshot.png')
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\School;
|
||||
|
||||
use App\Models\Country;
|
||||
use App\Models\CourseEvent;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class EventTable extends Component
|
||||
{
|
||||
public Country $country;
|
||||
|
||||
public ?int $year = null;
|
||||
|
||||
protected $queryString = ['year'];
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (! $this->year) {
|
||||
$this->year = now()->year;
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.school.event-table', [
|
||||
'markers' => CourseEvent::query()
|
||||
->with([
|
||||
'course',
|
||||
'venue.city.country',
|
||||
])
|
||||
->where('from', '>=', now())
|
||||
->where(fn ($query) => $query
|
||||
->whereHas('venue.city.country',
|
||||
fn ($query) => $query->where('countries.code', $this->country->code))
|
||||
)
|
||||
->get()
|
||||
->map(fn ($event) => [
|
||||
'id' => $event->id,
|
||||
'name' => $event->course->name,
|
||||
'coords' => [$event->venue->city->latitude, $event->venue->city->longitude],
|
||||
]),
|
||||
'events' => CourseEvent::query()
|
||||
->with([
|
||||
'course',
|
||||
'venue.city.country',
|
||||
])
|
||||
->where('from', '>=', now())
|
||||
->get()
|
||||
->map(fn ($event) => [
|
||||
'id' => $event->id,
|
||||
'startDate' => $event->from,
|
||||
'endDate' => $event->to,
|
||||
'location' => $event->course->name,
|
||||
'description' => $event->venue->name,
|
||||
]),
|
||||
])->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('Dates'),
|
||||
description: __('Dates for courses about Bitcoin.'),
|
||||
image: asset('img/screenshot.png')
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
public function filterByMarker($id)
|
||||
{
|
||||
return to_route('school.table.event', [
|
||||
'#table',
|
||||
'country' => $this->country->code,
|
||||
'year' => $this->year,
|
||||
'course_events' => [
|
||||
'filters' => [
|
||||
'byid' => $id,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function popover($content, $ids)
|
||||
{
|
||||
return to_route('school.table.event', [
|
||||
'#table',
|
||||
'country' => $this->country->code,
|
||||
'year' => $this->year,
|
||||
'course_events' => [
|
||||
'filters' => [
|
||||
'byid' => $ids,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\School\Form;
|
||||
|
||||
use App\Models\Course;
|
||||
use App\Models\CourseEvent;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
use WireUi\Traits\Actions;
|
||||
|
||||
class CourseEventForm extends Component
|
||||
{
|
||||
use WithFileUploads;
|
||||
use Actions;
|
||||
|
||||
public ?CourseEvent $courseEvent = null;
|
||||
|
||||
public ?string $fromUrl = '';
|
||||
|
||||
public $image;
|
||||
|
||||
protected $queryString = [
|
||||
'fromUrl' => [
|
||||
'except' => null,
|
||||
],
|
||||
];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'courseEvent.course_id' => 'required',
|
||||
'courseEvent.venue_id' => 'required',
|
||||
'courseEvent.from' => 'required',
|
||||
'courseEvent.to' => 'required',
|
||||
'courseEvent.link' => 'required',
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (!$this->courseEvent) {
|
||||
$this->courseEvent = new CourseEvent([]);
|
||||
} elseif (
|
||||
!auth()
|
||||
->user()
|
||||
->can('update', $this->courseEvent)
|
||||
) {
|
||||
abort(403);
|
||||
}
|
||||
if (!$this->fromUrl) {
|
||||
$this->fromUrl = url()->previous();
|
||||
}
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
$this->validate();
|
||||
$this->courseEvent->save();
|
||||
|
||||
return redirect($this->fromUrl);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.school.form.course-event-form');
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\School\Form;
|
||||
|
||||
use App\Models\Course;
|
||||
use App\Models\Tag;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
use WireUi\Traits\Actions;
|
||||
|
||||
class CourseForm extends Component
|
||||
{
|
||||
use WithFileUploads;
|
||||
use Actions;
|
||||
|
||||
public ?Course $course = null;
|
||||
|
||||
public ?string $fromUrl = '';
|
||||
|
||||
public $image;
|
||||
|
||||
public array $selectedTags = [];
|
||||
|
||||
protected $queryString = [
|
||||
'fromUrl' => [
|
||||
'except' => null,
|
||||
],
|
||||
];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'image' => [Rule::requiredIf(!$this->course->id), 'nullable', 'mimes:jpeg,png,jpg,gif', 'max:10240'],
|
||||
|
||||
'course.lecturer_id' => 'required',
|
||||
'course.name' => [
|
||||
'required',
|
||||
Rule::unique('courses', 'name')
|
||||
->ignore($this->course),
|
||||
],
|
||||
'course.description' => 'string|nullable',
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (!$this->course) {
|
||||
$this->course = new Course([
|
||||
'description' => '',
|
||||
]);
|
||||
} elseif (
|
||||
!auth()
|
||||
->user()
|
||||
->can('update', $this->course)
|
||||
) {
|
||||
abort(403);
|
||||
} else {
|
||||
$this->selectedTags = $this->course->tags()
|
||||
->where('type', 'course')
|
||||
->get()
|
||||
->map(fn($tag) => $tag->name)
|
||||
->toArray();
|
||||
}
|
||||
if (!$this->fromUrl) {
|
||||
$this->fromUrl = url()->previous();
|
||||
}
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
$this->validate();
|
||||
$this->course->save();
|
||||
|
||||
$this->course->syncTagsWithType(
|
||||
$this->selectedTags,
|
||||
'course'
|
||||
);
|
||||
|
||||
if ($this->image) {
|
||||
$this->course->addMedia($this->image)
|
||||
->usingFileName(md5($this->image->getClientOriginalName()).'.'.$this->image->getClientOriginalExtension())
|
||||
->toMediaCollection('logo');
|
||||
}
|
||||
|
||||
return redirect($this->fromUrl);
|
||||
}
|
||||
|
||||
public function selectTag($name)
|
||||
{
|
||||
$selectedTags = collect($this->selectedTags);
|
||||
if ($selectedTags->contains($name)) {
|
||||
$selectedTags = $selectedTags->filter(fn($tag) => $tag !== $name);
|
||||
} else {
|
||||
$selectedTags->push($name);
|
||||
}
|
||||
$this->selectedTags = $selectedTags->values()
|
||||
->toArray();
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.school.form.course-form', [
|
||||
'tags' => Tag::query()
|
||||
->where('type', 'course')
|
||||
->get(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\School;
|
||||
|
||||
use App\Models\Country;
|
||||
use App\Models\CourseEvent;
|
||||
use App\Models\Lecturer;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class LecturerLandingPage extends Component
|
||||
{
|
||||
public Lecturer $lecturer;
|
||||
|
||||
public Country $country;
|
||||
|
||||
public ?int $year = null;
|
||||
|
||||
public ?int $activeEvent = null;
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.school.lecturer-landing-page', [
|
||||
'courseEvents' => CourseEvent::query()
|
||||
->with([
|
||||
'venue.city',
|
||||
'course.tags',
|
||||
])
|
||||
->where('from', '>=', now())
|
||||
->whereHas('course', function ($query) {
|
||||
$query->where('lecturer_id', $this->lecturer->id);
|
||||
})
|
||||
->orderBy('from')
|
||||
->get(),
|
||||
'events' => CourseEvent::query()
|
||||
->with([
|
||||
'venue',
|
||||
'course',
|
||||
])
|
||||
->where('from', '>=', now())
|
||||
->whereHas('course', function ($query) {
|
||||
$query->where('lecturer_id', $this->lecturer->id);
|
||||
})
|
||||
->orderBy('from')
|
||||
->get()
|
||||
->map(fn($event) => [
|
||||
'id' => $event->id,
|
||||
'startDate' => $event->from,
|
||||
'endDate' => $event->to,
|
||||
'location' => $event->course->name,
|
||||
'description' => $event->venue->name,
|
||||
]),
|
||||
])
|
||||
->layout('layouts.guest', [
|
||||
'SEOData' => new SEOData(
|
||||
title: $this->lecturer->name,
|
||||
description: $this->lecturer->intro ?? __('This lecturer has not yet written an introduction.'),
|
||||
image: $this->lecturer->getFirstMediaUrl('avatar'),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
public function showEvent($id)
|
||||
{
|
||||
$this->activeEvent = $id;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\School;
|
||||
|
||||
use App\Models\Country;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class LecturerTable extends Component
|
||||
{
|
||||
public Country $country;
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.school.lecturer-table')->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('Lecturers'),
|
||||
description: __('Lecturers in the surrounding area.'),
|
||||
image: asset('img/screenshot.png')
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\School;
|
||||
|
||||
use App\Models\Tag;
|
||||
use Livewire\Component;
|
||||
|
||||
class SearchByTagComponent extends Component
|
||||
{
|
||||
public string $country = 'de';
|
||||
|
||||
public ?array $courses = [];
|
||||
|
||||
protected $queryString = [
|
||||
'courses',
|
||||
];
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.school.search-by-tag-component', [
|
||||
'tags' => Tag::query()
|
||||
->where('type', 'course')
|
||||
->with([
|
||||
'courses.lecturer',
|
||||
])
|
||||
->withCount([
|
||||
'courses',
|
||||
])
|
||||
->get(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\School;
|
||||
|
||||
use App\Models\Country;
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class VenueTable extends Component
|
||||
{
|
||||
public Country $country;
|
||||
|
||||
public bool $manage = false;
|
||||
|
||||
protected $queryString = ['manage' => ['except' => false]];
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.school.venue-table')->layout('layouts.app', [
|
||||
'SEOData' => new SEOData(
|
||||
title: __('Venues'),
|
||||
description: __('Venues in the surrounding area.'),
|
||||
image: asset('img/screenshot.png')
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Specials;
|
||||
|
||||
use Livewire\Component;
|
||||
use RalphJSmit\Laravel\SEO\Support\SEOData;
|
||||
|
||||
class BalticSeaCircle extends Component
|
||||
{
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.specials.baltic-sea-circle')
|
||||
->layout('layouts.guest', [
|
||||
'SEOData' => new SEOData(
|
||||
title: 'Baltic Sea Circle Rally Bitcoin Team 218',
|
||||
description: 'Besucht das Bitcoin Team 218 von Daktari und Cercatrova zum Start der diesjährigen Baltic Sea Circle Rally',
|
||||
image: asset('img/bsc/3.jpg'),
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Tables;
|
||||
|
||||
use App\Models\BitcoinEvent;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Rappasoft\LaravelLivewireTables\DataTableComponent;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Column;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Filters\TextFilter;
|
||||
|
||||
class BitcoinEventTable extends DataTableComponent
|
||||
{
|
||||
public string $country;
|
||||
|
||||
public string $tableName = 'bitcoin_events';
|
||||
|
||||
public function configure(): void
|
||||
{
|
||||
$this->setPrimaryKey('id')
|
||||
->setDefaultSort('from', 'asc')
|
||||
->setAdditionalSelects([
|
||||
'bitcoin_events.id',
|
||||
'bitcoin_events.venue_id',
|
||||
'bitcoin_events.created_by',
|
||||
])
|
||||
->setThAttributes(function (Column $column) {
|
||||
return [
|
||||
'class' => 'px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider dark:bg-gray-800 dark:text-gray-400',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setTdAttributes(function (Column $column, $row, $columnIndex, $rowIndex) {
|
||||
return [
|
||||
'class' => 'px-6 py-4 text-sm font-medium dark:text-white',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setColumnSelectStatus(false)
|
||||
->setPerPage(10)
|
||||
->setConfigurableAreas([
|
||||
'toolbar-left-end' => [
|
||||
'columns.bitcoin_events.areas.toolbar-left-end', [
|
||||
'country' => $this->country,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function filters(): array
|
||||
{
|
||||
return [
|
||||
TextFilter::make('Event by ID', 'byid')
|
||||
->hiddenFromMenus()
|
||||
->filter(function (Builder $builder, string $value) {
|
||||
$builder->whereIn('bitcoin_events.id', str($value)->explode(','));
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
public function columns(): array
|
||||
{
|
||||
return [
|
||||
Column::make(__('Country'), 'venue.city.country.name')
|
||||
->format(
|
||||
fn ($value, $row, Column $column) => view('columns.bitcoin_events.country')->withRow($row)
|
||||
)
|
||||
->sortable()
|
||||
->collapseOnMobile(),
|
||||
Column::make(__('Title'), 'title')
|
||||
->format(
|
||||
fn ($value, $row, Column $column) => view('columns.bitcoin_events.title')->withRow($row)
|
||||
)
|
||||
->sortable(),
|
||||
Column::make(__('From'), 'from')
|
||||
->format(
|
||||
fn ($value, $row, Column $column) => $value->asDateTime()
|
||||
),
|
||||
Column::make(__('To'), 'to')
|
||||
->format(
|
||||
fn ($value, $row, Column $column) => $value->asDateTime()
|
||||
)
|
||||
->collapseOnMobile(),
|
||||
Column::make(__('Venue'), 'venue.name')
|
||||
->collapseOnMobile(),
|
||||
Column::make(__('Link'), 'link')
|
||||
->format(
|
||||
fn ($value, $row, Column $column) => view('columns.bitcoin_events.link')->withRow($row)
|
||||
)
|
||||
->sortable()
|
||||
->collapseOnMobile(),
|
||||
];
|
||||
}
|
||||
|
||||
public function builder(): Builder
|
||||
{
|
||||
return BitcoinEvent::query()
|
||||
->with([
|
||||
'venue.city.country',
|
||||
])
|
||||
->where('bitcoin_events.from', '>=', now())
|
||||
->where(fn ($query) => $query
|
||||
->whereHas('venue.city.country',
|
||||
fn ($query) => $query->where('code', $this->country))
|
||||
->orWhere('show_worldwide', true)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Tables;
|
||||
|
||||
use App\Models\BookCase;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Rappasoft\LaravelLivewireTables\DataTableComponent;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Column;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Filters\TextFilter;
|
||||
use WireUi\Traits\Actions;
|
||||
|
||||
class BookCaseTable extends DataTableComponent
|
||||
{
|
||||
use Actions;
|
||||
|
||||
public string $country;
|
||||
|
||||
public string $tableName = 'bookcases';
|
||||
|
||||
public function configure(): void
|
||||
{
|
||||
$this->setPrimaryKey('id')
|
||||
->setAdditionalSelects(['id', 'homepage'])
|
||||
->setThAttributes(function (Column $column) {
|
||||
return [
|
||||
'class' => 'px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider dark:bg-gray-800 dark:text-gray-400',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setTdAttributes(function (Column $column, $row, $columnIndex, $rowIndex) {
|
||||
return [
|
||||
'class' => 'px-6 py-4 text-sm font-medium dark:text-white',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setColumnSelectStatus(false)
|
||||
->setPerPage(10);
|
||||
}
|
||||
|
||||
public function filters(): array
|
||||
{
|
||||
return [
|
||||
TextFilter::make('By IDs', 'byids')
|
||||
->hiddenFromMenus()
|
||||
->filter(function (Builder $builder, string $value) {
|
||||
$builder->whereIn('id', str($value)->explode(','));
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
public function columns(): array
|
||||
{
|
||||
return [
|
||||
Column::make('Name', 'title')
|
||||
->sortable()
|
||||
->searchable(
|
||||
function (Builder $query, $searchTerm) {
|
||||
$query->where('title', 'ilike', '%'.$searchTerm.'%');
|
||||
}
|
||||
),
|
||||
Column::make('Adresse', 'address')
|
||||
->sortable()
|
||||
->searchable(),
|
||||
Column::make('Bitcoin-Bücher')
|
||||
->label(
|
||||
fn (
|
||||
$row,
|
||||
Column $column
|
||||
) => $row->orangePills->sum('amount')
|
||||
)
|
||||
->collapseOnMobile(),
|
||||
Column::make('Letzter Input')
|
||||
->label(
|
||||
fn (
|
||||
$row,
|
||||
Column $column
|
||||
) => $row->orangePills()
|
||||
->latest()
|
||||
->first()?->date->asDate()
|
||||
)
|
||||
->collapseOnMobile(),
|
||||
Column::make('Link')
|
||||
->label(
|
||||
fn (
|
||||
$row,
|
||||
Column $column
|
||||
) => $row->homepage ? '<a target="_blank" class="underline text-amber-500" href="'.$this->url_to_absolute($row->homepage).'">Link</a>' : null
|
||||
)
|
||||
->html()
|
||||
->collapseOnMobile(),
|
||||
Column::make('Orange-Pilled', 'orange_pilled')
|
||||
->label(fn ($row, Column $column) => view('columns.book_cases.oranged-pilled')
|
||||
->withRow($row)
|
||||
->withCountry($this->country))
|
||||
->collapseOnMobile(),
|
||||
];
|
||||
}
|
||||
|
||||
private function url_to_absolute($url)
|
||||
{
|
||||
if (str($url)->contains('http')) {
|
||||
return $url;
|
||||
}
|
||||
if (! str($url)->contains('http')) {
|
||||
return str($url)->prepend('https://');
|
||||
}
|
||||
}
|
||||
|
||||
public function builder(): Builder
|
||||
{
|
||||
return BookCase::query()
|
||||
->active()
|
||||
->with([
|
||||
'orangePills',
|
||||
])
|
||||
->withCount([
|
||||
'orangePills',
|
||||
])
|
||||
->orderByDesc('orange_pills_count')
|
||||
->orderBy('book_cases.id');
|
||||
}
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Tables;
|
||||
|
||||
use App\Models\BookCase;
|
||||
use App\Models\City;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Rappasoft\LaravelLivewireTables\DataTableComponent;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Column;
|
||||
use WireUi\Traits\Actions;
|
||||
|
||||
class CityTable extends DataTableComponent
|
||||
{
|
||||
use Actions;
|
||||
|
||||
public string $country;
|
||||
|
||||
public string $type;
|
||||
|
||||
public bool $manage = false;
|
||||
|
||||
public string $tableName = 'cities';
|
||||
|
||||
public function configure(): void
|
||||
{
|
||||
$this->setPrimaryKey('id')
|
||||
->setAdditionalSelects(['cities.id', 'cities.created_by'])
|
||||
->setThAttributes(function (Column $column) {
|
||||
return [
|
||||
'class' => 'px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider dark:bg-gray-800 dark:text-gray-400',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setTdAttributes(function (Column $column, $row, $columnIndex, $rowIndex) {
|
||||
return [
|
||||
'class' => 'px-6 py-4 text-sm font-medium dark:text-white',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setColumnSelectStatus(false)
|
||||
->setPerPage(10)
|
||||
->setConfigurableAreas([
|
||||
'toolbar-left-end' => [
|
||||
'columns.cities.areas.toolbar-left-end', [
|
||||
'country' => $this->country,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function columns(): array
|
||||
{
|
||||
$columns = collect([
|
||||
Column::make('Stadt Name', 'name')
|
||||
->sortable()
|
||||
->searchable(fn ($builder, $term) => $builder->where('cities.name', 'ilike', '%'.$term.'%')),
|
||||
]);
|
||||
if ($this->type === 'school') {
|
||||
$columns = $columns->merge([
|
||||
Column::make('Veranstaltungs-Orte')
|
||||
->label(
|
||||
fn ($row, Column $column) => $row->venues_count
|
||||
)
|
||||
->collapseOnMobile(),
|
||||
Column::make('Termine')
|
||||
->label(
|
||||
fn ($row, Column $column) => $row->course_events_count
|
||||
)
|
||||
->collapseOnMobile(),
|
||||
]);
|
||||
}
|
||||
|
||||
return $columns->merge([
|
||||
Column::make('')
|
||||
->label(
|
||||
fn ($row, Column $column) => view('columns.cities.action')
|
||||
->withRow($row)
|
||||
->withType($this->type)
|
||||
->withManage($this->manage)
|
||||
),
|
||||
])
|
||||
->toArray();
|
||||
}
|
||||
|
||||
public function builder(): Builder
|
||||
{
|
||||
return City::query()
|
||||
->withCount([
|
||||
'venues',
|
||||
'courseEvents',
|
||||
])
|
||||
->whereHas('country', fn ($query) => $query->where('code', $this->country))
|
||||
->orderByDesc('course_events_count')
|
||||
->orderBy('cities.id');
|
||||
}
|
||||
|
||||
public function proximitySearch($id)
|
||||
{
|
||||
$city = City::query()
|
||||
->find($id);
|
||||
$query = City::radius($city->latitude, $city->longitude, 100)
|
||||
->where('id', '!=', $id);
|
||||
|
||||
return to_route('school.table.event', [
|
||||
'#table',
|
||||
'country' => $this->country,
|
||||
'course_events' => [
|
||||
'filters' => [
|
||||
'stadt' => $query->pluck('name')
|
||||
->push($city->name)
|
||||
->implode(','),
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function proximitySearchForBookCases($id)
|
||||
{
|
||||
$city = City::query()
|
||||
->find($id);
|
||||
$query = BookCase::active()->radius($city->latitude, $city->longitude, 25);
|
||||
$ids = $query->pluck('id');
|
||||
if ($ids->isEmpty()) {
|
||||
$this->notification()
|
||||
->error(__('No bookcases found in the radius of 5km'));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return to_route('bookCases.table.bookcases', [
|
||||
'#table',
|
||||
'country' => $this->country,
|
||||
'bookcases' => [
|
||||
'filters' => [
|
||||
'byids' => $ids->implode(','),
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Tables;
|
||||
|
||||
use App\Models\Course;
|
||||
use App\Models\Tag;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Rappasoft\LaravelLivewireTables\DataTableComponent;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Column;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Filters\MultiSelectFilter;
|
||||
|
||||
class CourseTable extends DataTableComponent
|
||||
{
|
||||
public string $country;
|
||||
|
||||
public string $tableName = 'courses';
|
||||
|
||||
public function configure(): void
|
||||
{
|
||||
$this->setPrimaryKey('id')
|
||||
->setAdditionalSelects(['courses.id', 'courses.created_by'])
|
||||
->setThAttributes(function (Column $column) {
|
||||
return [
|
||||
'class' => 'px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider dark:bg-gray-800 dark:text-gray-400',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setTdAttributes(function (Column $column, $row, $columnIndex, $rowIndex) {
|
||||
return [
|
||||
'class' => 'px-6 py-4 text-sm font-medium dark:text-white',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setColumnSelectStatus(false)
|
||||
->setPerPage(10)
|
||||
->setConfigurableAreas([
|
||||
'toolbar-left-end' => [
|
||||
'columns.courses.areas.toolbar-left-end', [
|
||||
'country' => $this->country,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function filters(): array
|
||||
{
|
||||
return [
|
||||
MultiSelectFilter::make('Tag')
|
||||
->options(
|
||||
Tag::query()
|
||||
->withType('course')
|
||||
->get()
|
||||
->mapWithKeys(fn ($item, $key) => [$item->name => $item->name])
|
||||
->toArray()
|
||||
)
|
||||
->filter(function (Builder $builder, array $values) {
|
||||
$builder->withAnyTags($values, 'course');
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
public function columns(): array
|
||||
{
|
||||
return [
|
||||
Column::make('Dozent', 'lecturer.name')
|
||||
->label(
|
||||
fn ($row, Column $column) => view('columns.courses.lecturer')->withRow($row)
|
||||
)
|
||||
->sortable()
|
||||
->collapseOnMobile(),
|
||||
Column::make('Name', 'name')
|
||||
->searchable(fn (Builder $query, string $term) => $query->where('name', 'ilike', '%'.$term.'%'))
|
||||
->sortable(),
|
||||
Column::make('Tags')
|
||||
->label(
|
||||
fn ($row, Column $column) => view('columns.courses.tags')->withRow($row)
|
||||
)
|
||||
->collapseOnMobile(),
|
||||
Column::make('Termine')
|
||||
->label(
|
||||
fn ($row, Column $column) => '<strong>'.$row->course_events_count.'</strong>'
|
||||
)
|
||||
->html()
|
||||
->sortable()
|
||||
->collapseOnMobile(),
|
||||
Column::make('Erstellt am', 'created_at')
|
||||
->sortable()
|
||||
->collapseOnMobile(),
|
||||
Column::make('')
|
||||
->label(
|
||||
fn ($row, Column $column) => view('columns.courses.action')->withRow($row)
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
public function builder(): Builder
|
||||
{
|
||||
return Course::query()
|
||||
->with([
|
||||
'lecturer',
|
||||
'tags',
|
||||
])
|
||||
->withCount([
|
||||
'courseEvents' => fn($query) => $query->where('course_events.from', '>', now()),
|
||||
])
|
||||
->orderByDesc('course_events_count')
|
||||
->orderBy('courses.id');
|
||||
}
|
||||
|
||||
public function courseSearch($id)
|
||||
{
|
||||
return to_route('school.table.event', [
|
||||
'#table',
|
||||
'country' => $this->country,
|
||||
'course_events' => [
|
||||
'filters' => [
|
||||
'course_id' => $id,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,202 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Tables;
|
||||
|
||||
use App\Models\Category;
|
||||
use App\Models\CourseEvent;
|
||||
use App\Models\Lecturer;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Rappasoft\LaravelLivewireTables\DataTableComponent;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Column;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Filters\MultiSelectFilter;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Filters\SelectFilter;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Filters\TextFilter;
|
||||
|
||||
class EventTable extends DataTableComponent
|
||||
{
|
||||
public string $country;
|
||||
|
||||
public bool $viewingModal = false;
|
||||
|
||||
public $currentModal;
|
||||
|
||||
public string $tableName = 'course_events';
|
||||
|
||||
public function configure(): void
|
||||
{
|
||||
$this
|
||||
->setPrimaryKey('id')
|
||||
->setDefaultSort('from', 'asc')
|
||||
->setAdditionalSelects([
|
||||
'course_events.id',
|
||||
'course_events.created_by',
|
||||
'course_id',
|
||||
'venue_id',
|
||||
])
|
||||
->setThAttributes(function (Column $column) {
|
||||
return [
|
||||
'class' => 'px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider dark:bg-gray-800 dark:text-gray-400',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setTdAttributes(function (Column $column, $row, $columnIndex, $rowIndex) {
|
||||
return [
|
||||
'class' => 'px-6 py-4 text-sm font-medium dark:text-white',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setColumnSelectStatus(false)
|
||||
->setPerPage(10)
|
||||
->setConfigurableAreas([
|
||||
'toolbar-left-end' => [
|
||||
'columns.course-events.areas.toolbar-left-end', [
|
||||
'country' => $this->country,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function filters(): array
|
||||
{
|
||||
return [
|
||||
TextFilter::make('Event by ID', 'byid')
|
||||
->hiddenFromMenus()
|
||||
->filter(function (Builder $builder, string $value) {
|
||||
$builder->whereIn('course_events.id', str($value)->explode(','));
|
||||
}),
|
||||
TextFilter::make(__('City'))
|
||||
->config([
|
||||
'placeholder' => __('Search City'),
|
||||
])
|
||||
->filter(function (Builder $builder, string $value) {
|
||||
if (str($value)->contains(',')) {
|
||||
$builder
|
||||
->whereHas('venue.city',
|
||||
function ($query) use ($value) {
|
||||
$query->whereIn('cities.name', str($value)->explode(','));
|
||||
});
|
||||
} else {
|
||||
$builder->whereHas('venue.city',
|
||||
fn ($query) => $query->where('cities.name', 'ilike', "%$value%"));
|
||||
}
|
||||
}),
|
||||
TextFilter::make(__('Venue'), 'venue')
|
||||
->config([
|
||||
'placeholder' => __('Search Venue'),
|
||||
])
|
||||
->filter(function (Builder $builder, string $value) {
|
||||
$builder->whereHas('venue',
|
||||
fn ($query) => $query->where('venues.name', 'ilike', "%$value%"));
|
||||
}),
|
||||
TextFilter::make(__('Course'))
|
||||
->config([
|
||||
'placeholder' => __('Search Course'),
|
||||
])
|
||||
->filter(function (Builder $builder, string $value) {
|
||||
$builder->whereHas('course',
|
||||
fn ($query) => $query->where('courses.name', 'ilike', "%$value%"));
|
||||
}),
|
||||
TextFilter::make('Course by ID', 'course_id')
|
||||
->hiddenFromMenus()
|
||||
->filter(function (Builder $builder, string $value) {
|
||||
$builder->whereHas('course',
|
||||
fn ($query) => $query->where('courses.id', '=', $value));
|
||||
}),
|
||||
MultiSelectFilter::make(__('Type'))
|
||||
->options(
|
||||
Category::query()
|
||||
->pluck('name', 'id')
|
||||
->toArray()
|
||||
)
|
||||
->filter(function (Builder $builder, array $values) {
|
||||
$builder->whereHas('course.categories',
|
||||
fn ($query) => $query->whereIn('categories.id', $values));
|
||||
}),
|
||||
SelectFilter::make(__('Lecturer'))
|
||||
->options(
|
||||
Lecturer::query()
|
||||
->pluck('name', 'id')
|
||||
->toArray()
|
||||
)
|
||||
->filter(function (Builder $builder, string $value) {
|
||||
$builder->whereHas('course.lecturer',
|
||||
fn ($query) => $query->where('lecturers.id', $value));
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
public function columns(): array
|
||||
{
|
||||
return [
|
||||
Column::make(_('City'), 'venue.city.name')
|
||||
->sortable()
|
||||
->collapseOnMobile(),
|
||||
Column::make(__('Venue'), 'venue.name')
|
||||
->sortable()
|
||||
->collapseOnMobile(),
|
||||
Column::make(__('Lecturer'), 'course.lecturer.name')
|
||||
->label(
|
||||
fn ($row, Column $column) => view('columns.events.lecturer')->withRow($row)
|
||||
)
|
||||
->sortable()
|
||||
->collapseOnMobile(),
|
||||
Column::make(__('Course'), 'course.name')
|
||||
->sortable(),
|
||||
Column::make(__('Type'))
|
||||
->label(
|
||||
fn ($row, Column $column) => view('columns.events.categories')->withRow($row)
|
||||
)
|
||||
->collapseOnMobile(),
|
||||
Column::make(__('From'), 'from')
|
||||
->format(
|
||||
fn ($value, $row, Column $column) => $value->asDateTime()
|
||||
)
|
||||
->sortable(),
|
||||
Column::make(__('To'), 'to')
|
||||
->format(
|
||||
fn ($value, $row, Column $column) => $value->asDateTime()
|
||||
)
|
||||
->sortable()
|
||||
->collapseOnMobile(),
|
||||
/*Column::make("Teilnehmer")
|
||||
->label(
|
||||
fn($row, Column $column) => '<strong>'.$row->registrations->count().'</strong>'
|
||||
)
|
||||
->html()
|
||||
->sortable(),*/
|
||||
Column::make(__('Actions'))
|
||||
->label(
|
||||
fn ($row, Column $column) => view('columns.events.action')->withRow($row)
|
||||
)
|
||||
->collapseOnMobile(),
|
||||
];
|
||||
}
|
||||
|
||||
public function builder(): Builder
|
||||
{
|
||||
return CourseEvent::query()
|
||||
->with([
|
||||
'course.lecturer',
|
||||
'course.categories',
|
||||
])
|
||||
->where('from', '>=', now())
|
||||
->whereHas('venue.city.country',
|
||||
fn ($query) => $query->where('countries.code', $this->country));
|
||||
}
|
||||
|
||||
public function viewHistoryModal($modelId): void
|
||||
{
|
||||
$this->viewingModal = true;
|
||||
$this->currentModal = CourseEvent::findOrFail($modelId);
|
||||
}
|
||||
|
||||
public function resetModal(): void
|
||||
{
|
||||
$this->reset('viewingModal', 'currentModal');
|
||||
}
|
||||
|
||||
public function customView(): string
|
||||
{
|
||||
return 'modals.events.register';
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Tables;
|
||||
|
||||
use App\Models\Lecturer;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Rappasoft\LaravelLivewireTables\DataTableComponent;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Column;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Columns\BooleanColumn;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Columns\ImageColumn;
|
||||
|
||||
class LecturerTable extends DataTableComponent
|
||||
{
|
||||
public string $country;
|
||||
|
||||
public string $tableName = 'lecturers';
|
||||
|
||||
public function configure(): void
|
||||
{
|
||||
$this->setPrimaryKey('id')
|
||||
->setAdditionalSelects(['id'])
|
||||
->setThAttributes(function (Column $column) {
|
||||
return [
|
||||
'class' => 'px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider dark:bg-gray-800 dark:text-gray-400',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setTdAttributes(function (Column $column, $row, $columnIndex, $rowIndex) {
|
||||
return [
|
||||
'class' => 'px-6 py-4 text-sm font-medium dark:text-white',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setColumnSelectStatus(false)
|
||||
->setPerPage(10)
|
||||
->setConfigurableAreas([
|
||||
'toolbar-left-end' => [
|
||||
'columns.lectures.areas.toolbar-left-end', [
|
||||
'country' => $this->country,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function columns(): array
|
||||
{
|
||||
return [
|
||||
ImageColumn::make('Bild')
|
||||
->location(
|
||||
fn ($row) => $row->getFirstMediaUrl('avatar', 'thumb')
|
||||
)
|
||||
->attributes(fn ($row) => [
|
||||
'class' => 'rounded h-16 w-16',
|
||||
'alt' => $row->name.' Avatar',
|
||||
])
|
||||
->collapseOnMobile(),
|
||||
Column::make('Name', 'name')
|
||||
->searchable(fn ($query, $term) => $query->where('name', 'ilike', '%'.$term.'%'))
|
||||
->sortable(),
|
||||
BooleanColumn::make('Aktiv', 'active')
|
||||
->sortable()
|
||||
->collapseOnMobile(),
|
||||
Column::make('Kurse')
|
||||
->label(
|
||||
fn ($row, Column $column) => $row->courses_count
|
||||
)
|
||||
->collapseOnMobile(),
|
||||
Column::make('Inhalte')
|
||||
->label(
|
||||
fn ($row, Column $column) => $row->library_items_count
|
||||
)
|
||||
->collapseOnMobile(),
|
||||
Column::make('')
|
||||
->label(
|
||||
fn ($row, Column $column) => view('columns.lectures.action')
|
||||
->withRow($row)
|
||||
->withCountry($this->country)
|
||||
),
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
public function builder(): Builder
|
||||
{
|
||||
return Lecturer::query()
|
||||
->withCount([
|
||||
'courses',
|
||||
'coursesEvents',
|
||||
'libraryItems' => fn($query) => $query->where('news', false)
|
||||
]);
|
||||
}
|
||||
|
||||
public function lecturerSearch($id, $event = true)
|
||||
{
|
||||
$lecturer = Lecturer::query()
|
||||
->find($id);
|
||||
|
||||
if ($event) {
|
||||
return to_route('school.table.event', [
|
||||
'#table',
|
||||
'country' => $this->country,
|
||||
'course_events' => [
|
||||
'filters' => [
|
||||
'dozent' => $lecturer->id,
|
||||
],
|
||||
],
|
||||
]);
|
||||
} else {
|
||||
return to_route('library.table.libraryItems', [
|
||||
'#table',
|
||||
'country' => $this->country,
|
||||
'filters' => [
|
||||
'lecturer_id' => $lecturer->id,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,187 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Tables;
|
||||
|
||||
use App\Enums\LibraryItemType;
|
||||
use App\Models\Library;
|
||||
use App\Models\LibraryItem;
|
||||
use App\Models\Tag;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Rappasoft\LaravelLivewireTables\DataTableComponent;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Column;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Filters\MultiSelectFilter;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Filters\SelectFilter;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Filters\TextFilter;
|
||||
use Spatie\LaravelOptions\Options;
|
||||
|
||||
class LibraryItemTable extends DataTableComponent
|
||||
{
|
||||
public string $currentTab;
|
||||
|
||||
public string $tableName = 'library_items';
|
||||
|
||||
public function configure(): void
|
||||
{
|
||||
$this
|
||||
->setPrimaryKey('id')
|
||||
->setAdditionalSelects(['id'])
|
||||
->setDefaultSort('order_column', 'asc')
|
||||
->setThAttributes(function (Column $column) {
|
||||
return [
|
||||
'class' => 'px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider dark:bg-gray-800 dark:text-gray-400',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setTdAttributes(function (Column $column, $row, $columnIndex, $rowIndex) {
|
||||
return [
|
||||
'class' => 'px-6 py-4 text-sm font-medium dark:text-white',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setColumnSelectStatus(false)
|
||||
->setPerPage(10);
|
||||
}
|
||||
|
||||
public function filters(): array
|
||||
{
|
||||
return [
|
||||
TextFilter::make(__('By id'), 'id')
|
||||
->hiddenFromMenus()
|
||||
->filter(function (Builder $builder, string $value) {
|
||||
$builder->where('library_items.id', '=', $value);
|
||||
}),
|
||||
TextFilter::make(__('By lecturer'), 'lecturer_id')
|
||||
->hiddenFromMenus()
|
||||
->filter(function (Builder $builder, string $value) {
|
||||
$builder->where('library_items.lecturer_id', '=', $value);
|
||||
}),
|
||||
MultiSelectFilter::make('Tag')
|
||||
->options(
|
||||
Tag::query()
|
||||
->where('type', 'library_item')
|
||||
->get()
|
||||
->pluck('name', 'id')
|
||||
->toArray()
|
||||
)
|
||||
->filter(function (Builder $builder, array $values) {
|
||||
$builder->whereHas('tags', function (Builder $query) use ($values) {
|
||||
$query->whereIn('tags.id', $values);
|
||||
});
|
||||
}),
|
||||
SelectFilter::make('Bibliothek')
|
||||
->options(
|
||||
Library::query()
|
||||
->where('is_public', true)
|
||||
->get()
|
||||
->prepend(new Library(['name' => '*']))
|
||||
->pluck('name', 'name')
|
||||
->toArray(),
|
||||
)
|
||||
->filter(function (Builder $builder, string $value) {
|
||||
if ($value === '*') {
|
||||
return;
|
||||
}
|
||||
if (str($value)->contains(',')) {
|
||||
$builder
|
||||
->whereHas('libraries',
|
||||
function ($query) use ($value) {
|
||||
$query->whereIn('libraries.name', str($value)->explode(','));
|
||||
});
|
||||
} else {
|
||||
$builder->whereHas('libraries',
|
||||
fn ($query) => $query->where('libraries.name', 'ilike', "%$value%"));
|
||||
}
|
||||
}),
|
||||
SelectFilter::make('Art')
|
||||
->options(
|
||||
collect(
|
||||
Options::forEnum(LibraryItemType::class)
|
||||
->toArray()
|
||||
)
|
||||
->mapWithKeys(fn ($value, $key) => [$value['value'] => $value['label']])
|
||||
->prepend('*', '')
|
||||
->toArray()
|
||||
)
|
||||
->filter(function (Builder $builder, string $value) {
|
||||
if ($value === '*') {
|
||||
return;
|
||||
}
|
||||
$builder->where('library_items.type', $value);
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
public function columns(): array
|
||||
{
|
||||
return [
|
||||
Column::make(__('Image'))
|
||||
->label(
|
||||
fn ($row, Column $column) => view('columns.library_items.image')->withRow($row)
|
||||
)
|
||||
->collapseOnMobile(),
|
||||
Column::make(__('Creator'), 'lecturer.name')
|
||||
->label(
|
||||
fn ($row, Column $column) => view('columns.courses.lecturer')->withRow($row)
|
||||
)
|
||||
->sortable()
|
||||
->collapseOnMobile(),
|
||||
Column::make('Name', 'name')
|
||||
->sortable(),
|
||||
Column::make('Art', 'type')
|
||||
->format(
|
||||
function ($value, $row, Column $column) {
|
||||
return '<span class="whitespace-nowrap inline-flex items-center rounded-full bg-amber-400 px-2.5 py-0.5 text-base font-medium text-gray-900"><i class="mr-2 fa fa-thin fa-'
|
||||
.LibraryItemType::icons()[$value]
|
||||
.'"></i>'
|
||||
.LibraryItemType::labels()[$value]
|
||||
.'</span>';
|
||||
})
|
||||
->html()
|
||||
->sortable()
|
||||
->collapseOnMobile(),
|
||||
Column::make('Tags')
|
||||
->label(
|
||||
fn ($row, Column $column) => view('columns.library_items.tags')->withRow($row)
|
||||
)
|
||||
->collapseOnMobile(),
|
||||
Column::make('')
|
||||
->label(
|
||||
fn ($row, Column $column) => view('columns.library_items.action')->withRow($row)
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
public function builder(): Builder
|
||||
{
|
||||
$shouldBePublic = request()
|
||||
?->route()
|
||||
?->getName() !== 'library.table.lecturer';
|
||||
|
||||
if ($this->currentTab !== '*') {
|
||||
$parentLibrary = Library::query()
|
||||
->where('name', $this->currentTab)
|
||||
->first();
|
||||
}
|
||||
|
||||
return LibraryItem::query()
|
||||
->with([
|
||||
'lecturer',
|
||||
'tags',
|
||||
])
|
||||
->whereHas('libraries', fn ($query) => $query->where('libraries.is_public', $shouldBePublic))
|
||||
->when($this->currentTab !== '*', fn ($query) => $query
|
||||
->whereHas('libraries',
|
||||
fn ($query) => $query
|
||||
->where('libraries.name', $this->currentTab)
|
||||
)
|
||||
->orWhereHas('libraries',
|
||||
fn ($query) => $query
|
||||
->where('libraries.parent_id', $parentLibrary->id)
|
||||
)
|
||||
)
|
||||
->withCount([
|
||||
'lecturer',
|
||||
])
|
||||
->currentStatus('published');
|
||||
}
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Tables;
|
||||
|
||||
use App\Models\MeetupEvent;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Rappasoft\LaravelLivewireTables\DataTableComponent;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Column;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Filters\TextFilter;
|
||||
|
||||
class MeetupEventTable extends DataTableComponent
|
||||
{
|
||||
public string $country;
|
||||
|
||||
public string $tableName = 'meetup_events';
|
||||
|
||||
public function configure(): void
|
||||
{
|
||||
$this->setPrimaryKey('id')
|
||||
->setAdditionalSelects(['meetup_events.id', 'meetup_events.meetup_id', 'attendees', 'might_attendees'])
|
||||
->setDefaultSort('start', 'asc')
|
||||
->setThAttributes(function (Column $column) {
|
||||
return [
|
||||
'class' => 'px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider dark:bg-gray-800 dark:text-gray-400',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setTdAttributes(function (Column $column, $row, $columnIndex, $rowIndex) {
|
||||
return [
|
||||
'class' => 'px-6 py-4 text-sm font-medium dark:text-white',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setColumnSelectStatus(false)
|
||||
->setPerPage(10)
|
||||
->setConfigurableAreas([
|
||||
'toolbar-left-end' => [
|
||||
'columns.meetup_events.areas.toolbar-left-end', [
|
||||
'country' => $this->country,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function filters(): array
|
||||
{
|
||||
return [
|
||||
TextFilter::make('Meetup-Event by ID', 'bymeetupid')
|
||||
->hiddenFromMenus()
|
||||
->filter(function (Builder $builder, string $value) {
|
||||
$builder->whereIn('meetup_events.meetup_id', str($value)->explode(','));
|
||||
}),
|
||||
TextFilter::make('Meetup-Event by ID', 'byid')
|
||||
->hiddenFromMenus()
|
||||
->filter(function (Builder $builder, string $value) {
|
||||
$builder->whereIn('meetup_events.id', str($value)->explode(','));
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
public function columns(): array
|
||||
{
|
||||
$columns = [
|
||||
Column::make(__('Meetup'), 'meetup.name')
|
||||
->format(
|
||||
fn ($value, $row, Column $column) => view('columns.meetup_events.name')
|
||||
->withRow($row)
|
||||
->withCountry($this->country)
|
||||
)
|
||||
->searchable(fn ($builder, $term) => $builder->where('meetups.name', 'ilike', '%'.$term.'%'))
|
||||
->sortable(),
|
||||
Column::make(__('Location'), 'location')
|
||||
->searchable(fn ($builder, $term) => $builder->where('location', 'ilike', '%'.$term.'%'))
|
||||
->sortable()
|
||||
->collapseOnMobile(),
|
||||
Column::make(__('Start'), 'start')
|
||||
->format(
|
||||
fn ($value, $row, Column $column) => $value->asDateTime()
|
||||
)
|
||||
->sortable()
|
||||
->collapseOnMobile(),
|
||||
Column::make(__('Confirmations'))
|
||||
->label(
|
||||
fn ($row, Column $column) => view('columns.meetup_events.confirmations')
|
||||
->withRow($row)
|
||||
)
|
||||
->collapseOnMobile(),
|
||||
Column::make(__('Link'))
|
||||
->label(
|
||||
fn ($row, Column $column) => view('columns.meetup_events.link')
|
||||
->withRow($row)
|
||||
)
|
||||
->collapseOnMobile(),
|
||||
];
|
||||
|
||||
$adminColumns = auth()->check() ? [
|
||||
Column::make(__('Actions'))
|
||||
->label(
|
||||
fn ($row, Column $column) => view('columns.meetup_events.manage')
|
||||
->withRow($row)
|
||||
)
|
||||
->collapseOnMobile(),
|
||||
] : [];
|
||||
|
||||
return array_merge($columns, $adminColumns);
|
||||
}
|
||||
|
||||
public function builder(): Builder
|
||||
{
|
||||
return MeetupEvent::query()
|
||||
->where('meetup_events.start', '>=', now()->subDay())
|
||||
->whereHas('meetup.city.country', fn ($query) => $query->where('code', $this->country))
|
||||
->with([
|
||||
'meetup.city.country',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Tables;
|
||||
|
||||
use App\Models\Meetup;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Rappasoft\LaravelLivewireTables\DataTableComponent;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Column;
|
||||
|
||||
class MeetupForBtcMapTable extends DataTableComponent
|
||||
{
|
||||
public function configure(): void
|
||||
{
|
||||
$this
|
||||
->setPrimaryKey('id')
|
||||
->setAdditionalSelects([
|
||||
'osm_relation',
|
||||
'simplified_geojson',
|
||||
'population',
|
||||
'population_date',
|
||||
'city_id',
|
||||
])
|
||||
->setPerPageAccepted([
|
||||
100000,
|
||||
])
|
||||
->setPerPage(100000);
|
||||
}
|
||||
|
||||
public function columns(): array
|
||||
{
|
||||
return [
|
||||
Column::make('Id', 'id')
|
||||
->sortable(),
|
||||
Column::make('Name', 'name')
|
||||
->sortable(),
|
||||
Column::make('City', 'city.name')
|
||||
->sortable(),
|
||||
Column::make('Country', 'city.country.name')
|
||||
->sortable(),
|
||||
Column::make('Actions')
|
||||
->label(fn($row, Column $column) => view('columns.meetups.osm-actions', ['row' => $row])),
|
||||
];
|
||||
}
|
||||
|
||||
public function builder(): Builder
|
||||
{
|
||||
return Meetup::query()
|
||||
->with([
|
||||
'city.country',
|
||||
])
|
||||
->where('community', '=', 'einundzwanzig')
|
||||
->orderBy('cities.population');
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Tables;
|
||||
|
||||
use App\Models\Meetup;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Rappasoft\LaravelLivewireTables\DataTableComponent;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Column;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Filters\TextFilter;
|
||||
|
||||
class MeetupTable extends DataTableComponent
|
||||
{
|
||||
public ?string $country = null;
|
||||
|
||||
public string $tableName = 'meetups';
|
||||
|
||||
public function configure(): void
|
||||
{
|
||||
$this->setPrimaryKey('id')
|
||||
->setAdditionalSelects(['meetups.id', 'meetups.slug', 'meetups.created_by'])
|
||||
->setThAttributes(function (Column $column) {
|
||||
return [
|
||||
'class' => 'px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider dark:bg-gray-800 dark:text-gray-400',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setTdAttributes(function (Column $column, $row, $columnIndex, $rowIndex) {
|
||||
return [
|
||||
'class' => 'px-6 py-4 text-sm font-medium dark:text-white',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setColumnSelectStatus(false)
|
||||
->setPerPage(10)
|
||||
->setConfigurableAreas([
|
||||
'toolbar-left-end' => [
|
||||
'columns.meetups.areas.toolbar-left-end', [
|
||||
'country' => $this->country,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function filters(): array
|
||||
{
|
||||
return [
|
||||
TextFilter::make('Meetup by ID', 'byid')
|
||||
->hiddenFromMenus()
|
||||
->filter(function (Builder $builder, string $value) {
|
||||
$builder->whereIn('meetups.id', str($value)->explode(','));
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
public function columns(): array
|
||||
{
|
||||
return [
|
||||
Column::make(__('Name'), 'name')
|
||||
->format(
|
||||
fn ($value, $row, Column $column) => view('columns.meetups.name')
|
||||
->withRow($row)
|
||||
)
|
||||
->searchable(fn ($builder, $term) => $builder->where('meetups.name', 'ilike', '%'.$term.'%')),
|
||||
Column::make(__('Plebs'))
|
||||
->label(fn ($row, Column $column) => $row->users_count)
|
||||
->collapseOnMobile(),
|
||||
Column::make(__('Links'))
|
||||
->label(
|
||||
fn ($row, Column $column) => view('columns.meetups.action')
|
||||
->withRow($row)
|
||||
->withIcs(route('meetup.ics',
|
||||
['country' => $this->country ?? $row->city->country->code, 'meetup' => $row->id]))
|
||||
->withCountry($this->country)
|
||||
)
|
||||
->collapseOnMobile(),
|
||||
];
|
||||
}
|
||||
|
||||
public function builder(): Builder
|
||||
{
|
||||
return Meetup::query()
|
||||
->with([
|
||||
'users',
|
||||
'city.country',
|
||||
'meetupEvents',
|
||||
])
|
||||
->when($this->country,
|
||||
fn ($query, $country) => $query->whereRelation('city.country', 'code', $this->country))
|
||||
->withCount([
|
||||
'users',
|
||||
'meetupEvents' => fn ($query) => $query->where('start', '>=',
|
||||
now()),
|
||||
])
|
||||
->when(! $this->country, fn ($query) => $query->orderByDesc('users_count')
|
||||
->orderBy('meetups.id'))
|
||||
->when($this->country, fn ($query) => $query->orderByDesc('meetup_events_count')
|
||||
->orderBy('meetups.id'));
|
||||
}
|
||||
|
||||
public function meetupEventSearch($id)
|
||||
{
|
||||
$meetup = Meetup::with(['city.country'])
|
||||
->find($id);
|
||||
|
||||
return to_route('meetup.table.meetupEvent', [
|
||||
'country' => $this->country ?? $meetup->city->country->code,
|
||||
'meetup_events' => [
|
||||
'filters' => ['bymeetupid' => $id],
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Tables;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Rappasoft\LaravelLivewireTables\DataTableComponent;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Column;
|
||||
use App\Models\ProjectProposal;
|
||||
|
||||
class ProjectProposalTable extends DataTableComponent
|
||||
{
|
||||
public ?string $country = null;
|
||||
|
||||
public string $tableName = 'project_proposals';
|
||||
|
||||
public function configure(): void
|
||||
{
|
||||
$this->setPrimaryKey('id')
|
||||
->setAdditionalSelects(['project_proposals.id', 'project_proposals.created_by', 'project_proposals.slug', 'project_proposals.user_id'])
|
||||
->setThAttributes(function (Column $column) {
|
||||
return [
|
||||
'class' => 'px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider dark:bg-gray-800 dark:text-gray-400',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setTdAttributes(function (Column $column, $row, $columnIndex, $rowIndex) {
|
||||
return [
|
||||
'class' => 'px-6 py-4 text-sm font-medium dark:text-white',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setColumnSelectStatus(false)
|
||||
->setPerPage(10)
|
||||
->setConfigurableAreas([
|
||||
'toolbar-left-end' => [
|
||||
'columns.project_proposals.areas.toolbar-left-end', [
|
||||
'country' => $this->country,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function columns(): array
|
||||
{
|
||||
return [
|
||||
Column::make("Id", "id")
|
||||
->sortable(),
|
||||
Column::make(__('From'))
|
||||
->label(
|
||||
fn ($row, Column $column) => view('columns.project_proposals.author')->withRow($row)
|
||||
),
|
||||
Column::make("Name", "name")
|
||||
->sortable(),
|
||||
Column::make(__('Intended support in sats'), "support_in_sats")
|
||||
->format(
|
||||
fn ($value, $row, Column $column) => number_format($value, 0, ',', '.')
|
||||
)
|
||||
->sortable(),
|
||||
Column::make('')
|
||||
->label(
|
||||
fn ($row, Column $column) => view('columns.project_proposals.action')->withRow($row)->withCountry($this->country)
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
public function builder(): Builder
|
||||
{
|
||||
return ProjectProposal::query()->with(['user']);
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Tables;
|
||||
|
||||
use App\Models\Venue;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Rappasoft\LaravelLivewireTables\DataTableComponent;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Column;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Columns\ImageColumn;
|
||||
|
||||
class VenueTable extends DataTableComponent
|
||||
{
|
||||
public string $country;
|
||||
|
||||
public bool $manage = false;
|
||||
|
||||
public string $tableName = 'venues';
|
||||
|
||||
public function configure(): void
|
||||
{
|
||||
$this->setPrimaryKey('id')
|
||||
->setAdditionalSelects(['venues.id', 'venues.created_by'])
|
||||
->setThAttributes(function (Column $column) {
|
||||
return [
|
||||
'class' => 'px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider dark:bg-gray-800 dark:text-gray-400',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setTdAttributes(function (Column $column, $row, $columnIndex, $rowIndex) {
|
||||
return [
|
||||
'class' => 'px-6 py-4 text-sm font-medium dark:text-white',
|
||||
'default' => false,
|
||||
];
|
||||
})
|
||||
->setColumnSelectStatus(false)
|
||||
->setPerPage(10)
|
||||
->setConfigurableAreas([
|
||||
'toolbar-left-end' => [
|
||||
'columns.venues.areas.toolbar-left-end', [
|
||||
'country' => $this->country,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function columns(): array
|
||||
{
|
||||
return [
|
||||
ImageColumn::make('Bild')
|
||||
->location(
|
||||
fn ($row) => $row->getFirstMediaUrl('images', 'thumb')
|
||||
)
|
||||
->attributes(fn ($row) => [
|
||||
'class' => 'rounded h-16 w-16',
|
||||
'alt' => $row->name.' Avatar',
|
||||
])
|
||||
->collapseOnMobile(),
|
||||
Column::make('Name', 'name')
|
||||
->searchable(fn ($query, $term) => $query->where('name', 'ilike', '%'.$term.'%'))
|
||||
->sortable(),
|
||||
Column::make('Street', 'street')
|
||||
->sortable()
|
||||
->collapseOnMobile(),
|
||||
Column::make('Termine')
|
||||
->label(
|
||||
fn ($row, Column $column) => $row->course_events_count
|
||||
)
|
||||
->collapseOnMobile(),
|
||||
Column::make('')
|
||||
->label(
|
||||
fn ($row, Column $column) => view('columns.venues.action')->withRow($row)->withManage($this->manage)
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
public function builder(): Builder
|
||||
{
|
||||
return Venue::query()
|
||||
->withCount([
|
||||
'courseEvents',
|
||||
])
|
||||
->whereHas('city.country', fn ($query) => $query->where('code', $this->country))
|
||||
->orderByDesc('course_events_count')
|
||||
->orderBy('venues.id');
|
||||
}
|
||||
|
||||
public function venueSearch($id)
|
||||
{
|
||||
$venue = Venue::query()
|
||||
->find($id);
|
||||
|
||||
return to_route('school.table.event', [
|
||||
'#table',
|
||||
'country' => $this->country,
|
||||
'course_events' => [
|
||||
'filters' => [
|
||||
'venue' => $venue->name,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Venue\Form;
|
||||
|
||||
use App\Models\Venue;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
||||
use WireUi\Traits\Actions;
|
||||
|
||||
class VenueForm extends Component
|
||||
{
|
||||
use WithFileUploads;
|
||||
use Actions;
|
||||
|
||||
public string $country;
|
||||
|
||||
public ?Venue $venue = null;
|
||||
|
||||
public $images;
|
||||
|
||||
public ?string $fromUrl = '';
|
||||
|
||||
protected $queryString = ['fromUrl' => ['except' => '']];
|
||||
|
||||
protected $listeners = ['refresh' => '$refresh'];
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'images.*' => [Rule::requiredIf(!$this->venue->id), 'nullable', 'mimes:jpeg,png,jpg,gif', 'max:10240'],
|
||||
|
||||
'venue.city_id' => 'required',
|
||||
'venue.name' => [
|
||||
'required',
|
||||
Rule::unique('venues', 'name')
|
||||
->ignore($this->venue),
|
||||
],
|
||||
'venue.street' => 'required',
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (!$this->venue) {
|
||||
$this->venue = new Venue();
|
||||
} elseif (!auth()
|
||||
->user()
|
||||
->can('update', $this->venue)) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
if (!$this->fromUrl) {
|
||||
$this->fromUrl = url()->previous();
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteMedia($id)
|
||||
{
|
||||
Media::query()
|
||||
->find($id)
|
||||
->delete();
|
||||
$this->notification()
|
||||
->success(__('Image deleted!'));
|
||||
$this->emit('refresh');
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
$this->validate();
|
||||
$this->venue->save();
|
||||
|
||||
if ($this->images && count($this->images) > 0) {
|
||||
foreach ($this->images as $item) {
|
||||
$this->venue->addMedia($item)
|
||||
->usingFileName(md5($item->getClientOriginalName()).'.'.$item->getClientOriginalExtension())
|
||||
->toMediaCollection('images');
|
||||
}
|
||||
}
|
||||
|
||||
return redirect($this->fromUrl);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.venue.form.venue-form');
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Wallet;
|
||||
|
||||
use App\Models\LoginKey;
|
||||
use eza\lnurl;
|
||||
use Livewire\Component;
|
||||
use SimpleSoftwareIO\QrCode\Facades\QrCode;
|
||||
|
||||
class LightningWallet extends Component
|
||||
{
|
||||
public ?string $k1 = null;
|
||||
public ?string $url = null;
|
||||
public ?string $lnurl = null;
|
||||
public ?string $qrCode = null;
|
||||
|
||||
public bool $confirmed = false;
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'k1' => 'required',
|
||||
'url' => 'required',
|
||||
'lnurl' => 'required',
|
||||
'qrCode' => 'required',
|
||||
];
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->k1 = bin2hex(str()->random(32));
|
||||
if (app()->environment('local')) {
|
||||
$this->url = 'https://einundzwanzig.eu-1.sharedwithexpose.com/api/lnurl-auth-callback?tag=login&k1='.$this->k1.'&action=login';
|
||||
} else {
|
||||
$this->url = url('/api/lnurl-auth-callback?tag=login&k1='.$this->k1.'&action=login');
|
||||
}
|
||||
$this->lnurl = lnurl\encodeUrl($this->url);
|
||||
$this->qrCode = base64_encode(QrCode::format('png')
|
||||
->size(300)
|
||||
->merge('/public/android-chrome-192x192.png', .3)
|
||||
->errorCorrection('H')
|
||||
->generate($this->lnurl));
|
||||
}
|
||||
|
||||
public function confirm()
|
||||
{
|
||||
$user = auth()->user();
|
||||
$user->change = $this->k1;
|
||||
$user->change_time = now();
|
||||
$user->save();
|
||||
$this->confirmed = true;
|
||||
}
|
||||
|
||||
public function checkAuth()
|
||||
{
|
||||
$loginKey = LoginKey::query()
|
||||
->where('k1', $this->k1)
|
||||
->whereDate('created_at', '>=', now()->subMinutes(5))
|
||||
->first();
|
||||
// you should also restrict this 👆🏻 by time, and find only the $k1 that were created in the last 5 minutes
|
||||
|
||||
if ($loginKey) {
|
||||
return to_route('welcome');
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.wallet.lightning-wallet');
|
||||
}
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
<div>
|
||||
<!-- Generate API Token -->
|
||||
<x-jet-form-section submit="createApiToken">
|
||||
<x-slot name="title">
|
||||
{{ __('Create API Token') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="description">
|
||||
{{ __('API tokens allow third-party services to authenticate with our application on your behalf.') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="form">
|
||||
<!-- Token Name -->
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
<x-jet-label for="name" value="{{ __('Token Name') }}" />
|
||||
<x-jet-input id="name" type="text" class="mt-1 block w-full" wire:model.defer="createApiTokenForm.name" autofocus />
|
||||
<x-jet-input-error for="name" class="mt-2" />
|
||||
</div>
|
||||
|
||||
<!-- Token Permissions -->
|
||||
@if (Laravel\Jetstream\Jetstream::hasPermissions())
|
||||
<div class="col-span-6">
|
||||
<x-jet-label for="permissions" value="{{ __('Permissions') }}" />
|
||||
|
||||
<div class="mt-2 grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
@foreach (Laravel\Jetstream\Jetstream::$permissions as $permission)
|
||||
<label class="flex items-center">
|
||||
<x-jet-checkbox wire:model.defer="createApiTokenForm.permissions" :value="$permission"/>
|
||||
<span class="ml-2 text-sm text-gray-600">{{ $permission }}</span>
|
||||
</label>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="actions">
|
||||
<x-jet-action-message class="mr-3" on="created">
|
||||
{{ __('Created.') }}
|
||||
</x-jet-action-message>
|
||||
|
||||
<x-jet-button>
|
||||
{{ __('Create') }}
|
||||
</x-jet-button>
|
||||
</x-slot>
|
||||
</x-jet-form-section>
|
||||
|
||||
@if ($this->user->tokens->isNotEmpty())
|
||||
<x-jet-section-border />
|
||||
|
||||
<!-- Manage API Tokens -->
|
||||
<div class="mt-10 sm:mt-0">
|
||||
<x-jet-action-section>
|
||||
<x-slot name="title">
|
||||
{{ __('Manage API Tokens') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="description">
|
||||
{{ __('You may delete any of your existing tokens if they are no longer needed.') }}
|
||||
</x-slot>
|
||||
|
||||
<!-- API Token List -->
|
||||
<x-slot name="content">
|
||||
<div class="space-y-6">
|
||||
@foreach ($this->user->tokens->sortBy('name') as $token)
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
{{ $token->name }}
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
@if ($token->last_used_at)
|
||||
<div class="text-sm text-gray-400">
|
||||
{{ __('Last used') }} {{ $token->last_used_at->diffForHumans() }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Laravel\Jetstream\Jetstream::hasPermissions())
|
||||
<button class="cursor-pointer ml-6 text-sm text-gray-400 underline" wire:click="manageApiTokenPermissions({{ $token->id }})">
|
||||
{{ __('Permissions') }}
|
||||
</button>
|
||||
@endif
|
||||
|
||||
<button class="cursor-pointer ml-6 text-sm text-red-500" wire:click="confirmApiTokenDeletion({{ $token->id }})">
|
||||
{{ __('Delete') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</x-slot>
|
||||
</x-jet-action-section>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Token Value Modal -->
|
||||
<x-jet-dialog-modal wire:model="displayingToken">
|
||||
<x-slot name="title">
|
||||
{{ __('API Token') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="content">
|
||||
<div>
|
||||
{{ __('Please copy your new API token. For your security, it won\'t be shown again.') }}
|
||||
</div>
|
||||
|
||||
<x-jet-input x-ref="plaintextToken" type="text" readonly :value="$plainTextToken"
|
||||
class="mt-4 bg-gray-100 px-4 py-2 rounded font-mono text-sm text-gray-500 w-full"
|
||||
autofocus autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
@showing-token-modal.window="setTimeout(() => $refs.plaintextToken.select(), 250)"
|
||||
/>
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="footer">
|
||||
<x-jet-secondary-button wire:click="$set('displayingToken', false)" wire:loading.attr="disabled">
|
||||
{{ __('Close') }}
|
||||
</x-jet-secondary-button>
|
||||
</x-slot>
|
||||
</x-jet-dialog-modal>
|
||||
|
||||
<!-- API Token Permissions Modal -->
|
||||
<x-jet-dialog-modal wire:model="managingApiTokenPermissions">
|
||||
<x-slot name="title">
|
||||
{{ __('API Token Permissions') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="content">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
@foreach (Laravel\Jetstream\Jetstream::$permissions as $permission)
|
||||
<label class="flex items-center">
|
||||
<x-jet-checkbox wire:model.defer="updateApiTokenForm.permissions" :value="$permission"/>
|
||||
<span class="ml-2 text-sm text-gray-600">{{ $permission }}</span>
|
||||
</label>
|
||||
@endforeach
|
||||
</div>
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="footer">
|
||||
<x-jet-secondary-button wire:click="$set('managingApiTokenPermissions', false)" wire:loading.attr="disabled">
|
||||
{{ __('Cancel') }}
|
||||
</x-jet-secondary-button>
|
||||
|
||||
<x-jet-button class="ml-3" wire:click="updateApiToken" wire:loading.attr="disabled">
|
||||
{{ __('Save') }}
|
||||
</x-jet-button>
|
||||
</x-slot>
|
||||
</x-jet-dialog-modal>
|
||||
|
||||
<!-- Delete Token Confirmation Modal -->
|
||||
<x-jet-confirmation-modal wire:model="confirmingApiTokenDeletion">
|
||||
<x-slot name="title">
|
||||
{{ __('Delete API Token') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="content">
|
||||
{{ __('Are you sure you would like to delete this API token?') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="footer">
|
||||
<x-jet-secondary-button wire:click="$toggle('confirmingApiTokenDeletion')" wire:loading.attr="disabled">
|
||||
{{ __('Cancel') }}
|
||||
</x-jet-secondary-button>
|
||||
|
||||
<x-jet-danger-button class="ml-3" wire:click="deleteApiToken" wire:loading.attr="disabled">
|
||||
{{ __('Delete') }}
|
||||
</x-jet-danger-button>
|
||||
</x-slot>
|
||||
</x-jet-confirmation-modal>
|
||||
</div>
|
||||
@@ -1,13 +0,0 @@
|
||||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
|
||||
{{ __('API Tokens') }}
|
||||
</h2>
|
||||
</x-slot>
|
||||
|
||||
<div>
|
||||
<div class="max-w-7xl mx-auto py-10 sm:px-6 lg:px-8">
|
||||
@livewire('api.api-token-manager')
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
@@ -1,28 +0,0 @@
|
||||
<x-guest-layout>
|
||||
<x-jet-authentication-card>
|
||||
<x-slot name="logo">
|
||||
<x-jet-authentication-card-logo />
|
||||
</x-slot>
|
||||
|
||||
<div class="mb-4 text-sm text-gray-600">
|
||||
{{ __('This is a secure area of the application. Please confirm your password before continuing.') }}
|
||||
</div>
|
||||
|
||||
<x-jet-validation-errors class="mb-4" />
|
||||
|
||||
<form method="POST" action="{{ route('password.confirm') }}">
|
||||
@csrf
|
||||
|
||||
<div>
|
||||
<x-jet-label for="password" value="{{ __('Password') }}" />
|
||||
<x-jet-input id="password" class="block mt-1 w-full" type="password" name="password" required autocomplete="current-password" autofocus />
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end mt-4">
|
||||
<x-jet-button class="ml-4">
|
||||
{{ __('Confirm') }}
|
||||
</x-jet-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-jet-authentication-card>
|
||||
</x-guest-layout>
|
||||
@@ -1,34 +0,0 @@
|
||||
<x-guest-layout>
|
||||
<x-jet-authentication-card>
|
||||
<x-slot name="logo">
|
||||
<x-jet-authentication-card-logo />
|
||||
</x-slot>
|
||||
|
||||
<div class="mb-4 text-sm text-gray-600">
|
||||
{{ __('Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.') }}
|
||||
</div>
|
||||
|
||||
@if (session('status'))
|
||||
<div class="mb-4 font-medium text-sm text-green-600">
|
||||
{{ session('status') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<x-jet-validation-errors class="mb-4" />
|
||||
|
||||
<form method="POST" action="{{ route('password.email') }}">
|
||||
@csrf
|
||||
|
||||
<div class="block">
|
||||
<x-jet-label for="email" value="{{ __('Email') }}" />
|
||||
<x-jet-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus />
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-end mt-4">
|
||||
<x-jet-button>
|
||||
{{ __('Email Password Reset Link') }}
|
||||
</x-jet-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-jet-authentication-card>
|
||||
</x-guest-layout>
|
||||
@@ -1,72 +0,0 @@
|
||||
<x-guest-layout>
|
||||
<x-jet-authentication-card>
|
||||
<x-slot name="logo">
|
||||
<x-jet-authentication-card-logo/>
|
||||
</x-slot>
|
||||
|
||||
<x-jet-validation-errors class="mb-4"/>
|
||||
|
||||
@if (session('status'))
|
||||
<div class="mb-4 font-medium text-sm text-green-600">
|
||||
{{ session('status') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form method="POST" action="{{ route('login') }}">
|
||||
|
||||
<div class="flex items-center justify-end mb-4">
|
||||
<x-button icon="arrow-left" secondary class="ml-4" href="/">
|
||||
{{ __('Back to the website') }}
|
||||
</x-button>
|
||||
</div>
|
||||
|
||||
@csrf
|
||||
|
||||
<div>
|
||||
<x-jet-label for="email" value="{{ __('Email') }}"/>
|
||||
<x-jet-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')"
|
||||
required autofocus/>
|
||||
@if(app()->environment())
|
||||
<pre>admin@einundzwanzig.space</pre>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<x-jet-label for="password" value="{{ __('Password') }}"/>
|
||||
<x-jet-input id="password" class="block mt-1 w-full" type="password" name="password" required
|
||||
autocomplete="current-password"/>
|
||||
@if(app()->environment())
|
||||
<pre>1234</pre>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="block mt-4">
|
||||
<label for="remember_me" class="flex items-center">
|
||||
<x-jet-checkbox id="remember_me" name="remember"/>
|
||||
<span class="ml-2 text-sm text-gray-600">{{ __('Remember me') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@if(app()->environment('local'))
|
||||
<div class="flex items-center justify-end mt-4">
|
||||
|
||||
@if (Route::has('password.request'))
|
||||
<a class="underline text-sm text-gray-600 hover:text-gray-900"
|
||||
href="{{ route('password.request') }}">
|
||||
{{ __('Forgot your password?') }}
|
||||
</a>
|
||||
@endif
|
||||
|
||||
<x-jet-button class="ml-4">
|
||||
{{ __('Log in') }}
|
||||
</x-jet-button>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="flex items-center justify-left mt-4">
|
||||
<x-button href="{{ route('auth.login') }}" primary icon="lightning-bolt">LNURL-Auth</x-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-jet-authentication-card>
|
||||
</x-guest-layout>
|
||||
@@ -1,86 +0,0 @@
|
||||
<x-guest-layout>
|
||||
<x-jet-authentication-card>
|
||||
<x-slot name="logo">
|
||||
<x-jet-authentication-card-logo/>
|
||||
</x-slot>
|
||||
|
||||
<x-jet-validation-errors class="mb-4"/>
|
||||
|
||||
<form method="POST" action="{{ route('register') }}">
|
||||
|
||||
<div class="flex items-center justify-end mb-4">
|
||||
<x-button icon="arrow-left" secondary class="ml-4" href="/">
|
||||
{{ __('Back to the website') }}
|
||||
</x-button>
|
||||
</div>
|
||||
|
||||
@csrf
|
||||
|
||||
<div>
|
||||
<x-jet-label for="name" value="{{ __('Name') }}"/>
|
||||
<x-jet-input id="name" class="block mt-1 w-full" type="text" name="name" :value="old('name')" required
|
||||
autofocus autocomplete="name"/>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<x-jet-label for="email" value="{{ __('Email') }}"/>
|
||||
<x-jet-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')"
|
||||
required/>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<x-jet-label for="password" value="{{ __('Password') }}"/>
|
||||
<x-jet-input id="password" class="block mt-1 w-full" type="password" name="password" required
|
||||
autocomplete="new-password"/>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<x-jet-label for="password_confirmation" value="{{ __('Confirm Password') }}"/>
|
||||
<x-jet-input id="password_confirmation" class="block mt-1 w-full" type="password"
|
||||
name="password_confirmation" required autocomplete="new-password"/>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<x-jet-label for="is_lecturer">
|
||||
<div class="flex items-center">
|
||||
<x-jet-checkbox name="is_lecturer" id="is_lecturer" required/>
|
||||
|
||||
<div class="ml-2">
|
||||
{{ __('I want to submit new courses on this platform') }}
|
||||
</div>
|
||||
</div>
|
||||
</x-jet-label>
|
||||
</div>
|
||||
|
||||
@if (Laravel\Jetstream\Jetstream::hasTermsAndPrivacyPolicyFeature())
|
||||
<div class="mt-4">
|
||||
<x-jet-label for="terms">
|
||||
<div class="flex items-center">
|
||||
<x-jet-checkbox name="terms" id="terms" required/>
|
||||
|
||||
<div class="ml-2">
|
||||
{!! __('I agree to the :terms_of_service and :privacy_policy', [
|
||||
'terms_of_service' => '<a target="_blank" href="'.route('terms.show').'" class="underline text-sm text-gray-600 hover:text-gray-900">'.__('Terms of Service').'</a>',
|
||||
'privacy_policy' => '<a target="_blank" href="'.route('policy.show').'" class="underline text-sm text-gray-600 hover:text-gray-900">'.__('Privacy Policy').'</a>',
|
||||
]) !!}
|
||||
</div>
|
||||
</div>
|
||||
</x-jet-label>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{--<div class="flex items-center justify-end mt-4">
|
||||
<a class="underline text-sm text-gray-600 hover:text-gray-900" href="{{ route('login') }}">
|
||||
{{ __('Already registered?') }}
|
||||
</a>
|
||||
<x-jet-button class="ml-4">
|
||||
{{ __('Register') }}
|
||||
</x-jet-button>
|
||||
</div>--}}
|
||||
|
||||
<div class="flex items-center justify-left mt-4">
|
||||
<x-button href="{{ route('auth.login') }}" primary icon="lightning-bolt">Login</x-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-jet-authentication-card>
|
||||
</x-guest-layout>
|
||||
@@ -1,36 +0,0 @@
|
||||
<x-guest-layout>
|
||||
<x-jet-authentication-card>
|
||||
<x-slot name="logo">
|
||||
<x-jet-authentication-card-logo />
|
||||
</x-slot>
|
||||
|
||||
<x-jet-validation-errors class="mb-4" />
|
||||
|
||||
<form method="POST" action="{{ route('password.update') }}">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" name="token" value="{{ $request->route('token') }}">
|
||||
|
||||
<div class="block">
|
||||
<x-jet-label for="email" value="{{ __('Email') }}" />
|
||||
<x-jet-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email', $request->email)" required autofocus />
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<x-jet-label for="password" value="{{ __('Password') }}" />
|
||||
<x-jet-input id="password" class="block mt-1 w-full" type="password" name="password" required autocomplete="new-password" />
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<x-jet-label for="password_confirmation" value="{{ __('Confirm Password') }}" />
|
||||
<x-jet-input id="password_confirmation" class="block mt-1 w-full" type="password" name="password_confirmation" required autocomplete="new-password" />
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-end mt-4">
|
||||
<x-jet-button>
|
||||
{{ __('Reset Password') }}
|
||||
</x-jet-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-jet-authentication-card>
|
||||
</x-guest-layout>
|
||||
@@ -1,57 +0,0 @@
|
||||
<x-guest-layout>
|
||||
<x-jet-authentication-card>
|
||||
<x-slot name="logo">
|
||||
<x-jet-authentication-card-logo />
|
||||
</x-slot>
|
||||
|
||||
<div x-data="{ recovery: false }">
|
||||
<div class="mb-4 text-sm text-gray-600" x-show="! recovery">
|
||||
{{ __('Please confirm access to your account by entering the authentication code provided by your authenticator application.') }}
|
||||
</div>
|
||||
|
||||
<div class="mb-4 text-sm text-gray-600" x-show="recovery">
|
||||
{{ __('Please confirm access to your account by entering one of your emergency recovery codes.') }}
|
||||
</div>
|
||||
|
||||
<x-jet-validation-errors class="mb-4" />
|
||||
|
||||
<form method="POST" action="{{ route('two-factor.login') }}">
|
||||
@csrf
|
||||
|
||||
<div class="mt-4" x-show="! recovery">
|
||||
<x-jet-label for="code" value="{{ __('Code') }}" />
|
||||
<x-jet-input id="code" class="block mt-1 w-full" type="text" inputmode="numeric" name="code" autofocus x-ref="code" autocomplete="one-time-code" />
|
||||
</div>
|
||||
|
||||
<div class="mt-4" x-show="recovery">
|
||||
<x-jet-label for="recovery_code" value="{{ __('Recovery Code') }}" />
|
||||
<x-jet-input id="recovery_code" class="block mt-1 w-full" type="text" name="recovery_code" x-ref="recovery_code" autocomplete="one-time-code" />
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-end mt-4">
|
||||
<button type="button" class="text-sm text-gray-600 hover:text-gray-900 underline cursor-pointer"
|
||||
x-show="! recovery"
|
||||
x-on:click="
|
||||
recovery = true;
|
||||
$nextTick(() => { $refs.recovery_code.focus() })
|
||||
">
|
||||
{{ __('Use a recovery code') }}
|
||||
</button>
|
||||
|
||||
<button type="button" class="text-sm text-gray-600 hover:text-gray-900 underline cursor-pointer"
|
||||
x-show="recovery"
|
||||
x-on:click="
|
||||
recovery = false;
|
||||
$nextTick(() => { $refs.code.focus() })
|
||||
">
|
||||
{{ __('Use an authentication code') }}
|
||||
</button>
|
||||
|
||||
<x-jet-button class="ml-4">
|
||||
{{ __('Log in') }}
|
||||
</x-jet-button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</x-jet-authentication-card>
|
||||
</x-guest-layout>
|
||||
@@ -1,45 +0,0 @@
|
||||
<x-guest-layout>
|
||||
<x-jet-authentication-card>
|
||||
<x-slot name="logo">
|
||||
<x-jet-authentication-card-logo />
|
||||
</x-slot>
|
||||
|
||||
<div class="mb-4 text-sm text-gray-600">
|
||||
{{ __('Before continuing, could you verify your email address by clicking on the link we just emailed to you? If you didn\'t receive the email, we will gladly send you another.') }}
|
||||
</div>
|
||||
|
||||
@if (session('status') == 'verification-link-sent')
|
||||
<div class="mb-4 font-medium text-sm text-green-600">
|
||||
{{ __('A new verification link has been sent to the email address you provided in your profile settings.') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="mt-4 flex items-center justify-between">
|
||||
<form method="POST" action="{{ route('verification.send') }}">
|
||||
@csrf
|
||||
|
||||
<div>
|
||||
<x-jet-button type="submit">
|
||||
{{ __('Resend Verification Email') }}
|
||||
</x-jet-button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div>
|
||||
<a
|
||||
href="{{ route('profile.show') }}"
|
||||
class="underline text-sm text-gray-600 hover:text-gray-900"
|
||||
>
|
||||
{{ __('Edit Profile') }}</a>
|
||||
|
||||
<form method="POST" action="{{ route('logout') }}" class="inline">
|
||||
@csrf
|
||||
|
||||
<button type="submit" class="underline text-sm text-gray-600 hover:text-gray-900 ml-2">
|
||||
{{ __('Log Out') }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</x-jet-authentication-card>
|
||||
</x-guest-layout>
|
||||
@@ -1,6 +0,0 @@
|
||||
<div class="w-full mb-4 md:w-auto md:mb-0">
|
||||
<x-button :href="route('bitcoinEvent.form', ['country' => $country, 'bitcoinEvent' => null])">
|
||||
<i class="fa fa-thin fa-plus"></i>
|
||||
{{ __('Register event') }}
|
||||
</x-button>
|
||||
</div>
|
||||
@@ -1,7 +0,0 @@
|
||||
<div class="flex flex-col space-y-1 justify-center items-center">
|
||||
<img class="h-8" src="{{ asset('vendor/blade-country-flags/1x1-'.$row->venue->city->country->code.'.svg') }}"
|
||||
alt="{{ $row->venue->city->country->code }}">
|
||||
<div>
|
||||
{{ $row->venue->city->country->code }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,13 +0,0 @@
|
||||
<div class="flex flex-col space-y-1">
|
||||
<a href="{{ $row->link }}" target="_blank">
|
||||
<x-badge class="whitespace-nowrap">{{ __('Link') }}</x-badge>
|
||||
</a>
|
||||
<div>
|
||||
@can('update', $row)
|
||||
<x-button primary xs :href="route('bitcoinEvent.form', ['bitcoinEvent' => $row])">
|
||||
<i class="fa-thin fa-edit"></i>
|
||||
{{ __('Edit') }}
|
||||
</x-button>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,6 +0,0 @@
|
||||
<div class="flex items-center space-x-2">
|
||||
<img class="h-12" src="{{ $row->getFirstMediaUrl('logo', 'thumb') }}" alt="{{ $row->title }}">
|
||||
<div>
|
||||
{{ $row->title }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,31 +0,0 @@
|
||||
<div class="flex flex-col space-y-1" wire:key="bookcase_action_{{ $row->id }}">
|
||||
@auth
|
||||
<div>
|
||||
@if($row->orange_pills_count > 0)
|
||||
<img class="aspect-auto max-h-12" src="{{ asset('img/social_credit_plus.webp') }}" alt="">
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
@if($row->orange_pills_count < 1)
|
||||
<img class="aspect-auto max-h-12" src="{{ asset('img/social_credit_minus.webp') }}" alt="">
|
||||
@endif
|
||||
</div>
|
||||
<div class="flex items-center space-x-1">
|
||||
<x-button xs
|
||||
:href="route('bookCases.form', ['bookCase' => $row->id, 'country' => $country])"
|
||||
class="whitespace-nowrap" primary class="text-21gray whitespace-nowrap"
|
||||
>
|
||||
{{ __('💊 Orange Pill Now') }}
|
||||
</x-button>
|
||||
<x-button xs class="whitespace-nowrap"
|
||||
:href="route('bookCases.comment.bookcase', ['bookCase' => $row->id, 'country' => $country])">{{ __('Details') }}</x-button>
|
||||
</div>
|
||||
@else
|
||||
<div>
|
||||
<x-badge class="whitespace-nowrap" amber>
|
||||
<i class="fa fa-thin fa-shelves-empty mr-2"></i>
|
||||
{{ __('no bitcoin books yet') }}
|
||||
</x-badge>
|
||||
</div>
|
||||
@endauth
|
||||
</div>
|
||||
@@ -1,40 +0,0 @@
|
||||
<div class="flex flex-col space-y-1">
|
||||
@if($type === 'school' && !$manage)
|
||||
<div>
|
||||
<div>
|
||||
@if($row->course_events_count > 0)
|
||||
<x-button xs amber wire:click="proximitySearch({{ $row->id }})" class="text-21gray">
|
||||
<i class="fa fa-thin fa-person-chalkboard mr-2"></i>
|
||||
{{ __('Perimeter search course date :name (100km)', ['name' => $row->name]) }}
|
||||
</x-button>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
@if($row->course_events_count < 1)
|
||||
<x-button xs outlined wire:click="proximitySearch({{ $row->id }})" class="text-21gray">
|
||||
<i class="fa fa-thin fa-person-chalkboard mr-2"></i>
|
||||
{{ __('Perimeter search course date :name (100km)', ['name' => $row->name]) }}
|
||||
</x-button>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
<div>
|
||||
@if($type === 'bookCase' && !$manage)
|
||||
<div>
|
||||
<x-button xs amber wire:click="proximitySearchForBookCases({{ $row->id }})" class="text-21gray">
|
||||
<i class="fa fa-thin fa-book mr-2"></i>
|
||||
{{ __('Perimeter search bookcase :name (25km)', ['name' => $row->name]) }}
|
||||
</x-button>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
@can('update', $row)
|
||||
<x-button xs :href="route('city.form', ['city' => $row])">
|
||||
<i class="fa fa-thin fa-edit"></i>
|
||||
{{ __('Edit') }}
|
||||
</x-button>
|
||||
@endcan
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,6 +0,0 @@
|
||||
<div class="w-full mb-4 md:w-auto md:mb-0">
|
||||
<x-button :href="route('city.form')">
|
||||
<i class="fa fa-thin fa-plus"></i>
|
||||
{{ __('New City') }}
|
||||
</x-button>
|
||||
</div>
|
||||
@@ -1,6 +0,0 @@
|
||||
<div class="w-full mb-4 md:w-auto md:mb-0">
|
||||
<x-button xs :href="route('course.form.courseEvent')">
|
||||
<i class="fa fa-thin fa-plus"></i>
|
||||
{{ __('Register course date') }}
|
||||
</x-button>
|
||||
</div>
|
||||
@@ -1,23 +0,0 @@
|
||||
<div class="flex flex-col space-y-1">
|
||||
@if($row->course_events_count > 0)
|
||||
<div>
|
||||
<x-button class="whitespace-nowrap" xs amber wire:click="courseSearch({{ $row->id }})">
|
||||
{{ __('Show dates') }} [{{ $row->course_events_count }}]
|
||||
</x-button>
|
||||
</div>
|
||||
@else
|
||||
<div>
|
||||
<x-button class="whitespace-nowrap" xs outline wire:click="courseSearch({{ $row->id }})">
|
||||
{{ __('Show dates') }}
|
||||
</x-button>
|
||||
</div>
|
||||
@endif
|
||||
@can('update', $row)
|
||||
<div>
|
||||
<x-button class="whitespace-nowrap" amber xs :href="route('course.form.course', ['course' => $row])">
|
||||
<i class="fa fa-thin fa-edit"></i>
|
||||
{{ __('Edit') }}
|
||||
</x-button>
|
||||
</div>
|
||||
@endcan
|
||||
</div>
|
||||
@@ -1,6 +0,0 @@
|
||||
<div class="w-full mb-4 md:w-auto md:mb-0">
|
||||
<x-button :href="route('course.form.course')">
|
||||
<i class="fa fa-thin fa-plus"></i>
|
||||
{{ __('Register course') }}
|
||||
</x-button>
|
||||
</div>
|
||||
@@ -1,6 +0,0 @@
|
||||
<div class="flex items-center space-x-2">
|
||||
<img class="h-12" src="{{ $row->lecturer->getFirstMediaUrl('avatar', 'thumb') }}" alt="{{ $row->lecturer->name }}">
|
||||
<div>
|
||||
{{ $row->lecturer->name }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,5 +0,0 @@
|
||||
<div class="flex items-center">
|
||||
@foreach($row->tags as $tag)
|
||||
<x-badge class="whitespace-nowrap">{{ $tag->name }}</x-badge>
|
||||
@endforeach
|
||||
</div>
|
||||
@@ -1,15 +0,0 @@
|
||||
<div class="flex flex-col space-y-1">
|
||||
<div>
|
||||
<x-button xs class="whitespace-nowrap" amber
|
||||
wire:click="viewHistoryModal({{ $row->id }})">{{ __('Register') }}</x-button>
|
||||
</div>
|
||||
@can('update', $row)
|
||||
<div>
|
||||
<x-button xs class="whitespace-nowrap" amber
|
||||
:href="route('course.form.courseEvent', ['courseEvent' => $row])">
|
||||
<i class="fa-thin fa-edit"></i>
|
||||
{{ __('Edit') }}
|
||||
</x-button>
|
||||
</div>
|
||||
@endcan
|
||||
</div>
|
||||
@@ -1,5 +0,0 @@
|
||||
<div class="flex space-x-1">
|
||||
@foreach($row->course->categories as $category)
|
||||
<x-badge class="whitespace-nowrap">{{ $category->name }}</x-badge>
|
||||
@endforeach
|
||||
</div>
|
||||
@@ -1,6 +0,0 @@
|
||||
<div class="flex items-center space-x-2">
|
||||
<img class="h-12" src="{{ $row->course->lecturer->getFirstMediaUrl('avatar', 'thumb') }}" alt="{{ $row->course->lecturer->name }}">
|
||||
<div>
|
||||
{{ $row->course->lecturer->name }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,59 +0,0 @@
|
||||
<div class="flex flex-col space-y-1">
|
||||
<div>
|
||||
@if($row->courses_count > 0)
|
||||
<x-button
|
||||
xs amber wire:click="lecturerSearch({{ $row->id }})">
|
||||
<i class="fa fa-thin fa-calendar mr-2"></i>
|
||||
{{ __('Show dates') }} ({{ $row->courses_events_count }})
|
||||
</x-button>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
@if($row->courses_count < 1)
|
||||
<x-button
|
||||
xs outlined wire:click="lecturerSearch({{ $row->id }})">
|
||||
<i class="fa fa-thin fa-calendar mr-2"></i>
|
||||
{{ __('Show dates') }} ({{ $row->courses_events_count }})
|
||||
</x-button>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
@if($row->library_items_count > 0)
|
||||
<x-button
|
||||
xs amber wire:click="lecturerSearch({{ $row->id }}, false)">
|
||||
<i class="fa fa-thin fa-book mr-2"></i>
|
||||
{{ __('Show content') }} ({{ $row->library_items_count }})
|
||||
</x-button>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
@if($row->library_items_count < 1)
|
||||
<x-button
|
||||
xs outlined wire:click="lecturerSearch({{ $row->id }}, false)">
|
||||
<i class="fa fa-thin fa-book mr-2"></i>
|
||||
{{ __('Show content') }} ({{ $row->library_items_count }})
|
||||
</x-button>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<x-button
|
||||
xs
|
||||
:href="route('school.landingPage.lecturer', ['country' => $country, 'lecturer' => $row->slug])"
|
||||
black>
|
||||
<i class="fa fa-thin fa-browser mr-2"></i>
|
||||
{{ __('Show landing page') }}
|
||||
</x-button>
|
||||
</div>
|
||||
<div>
|
||||
@if($row->created_by === auth()->id())
|
||||
<x-button
|
||||
:href="route('contentCreator.form', ['country' => $country, 'lecturer' => $row->id])"
|
||||
xs
|
||||
amber
|
||||
>
|
||||
<i class="fa fa-thin fa-edit mr-2"></i>
|
||||
{{ __('Edit') }}
|
||||
</x-button>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,6 +0,0 @@
|
||||
<div class="w-full mb-4 md:w-auto md:mb-0">
|
||||
<x-button :href="route('contentCreator.form', ['country' => $country, 'lecturer' => null])">
|
||||
<i class="fa fa-thin fa-plus"></i>
|
||||
{{ __('Register lecturer') }}
|
||||
</x-button>
|
||||
</div>
|
||||
@@ -1,58 +0,0 @@
|
||||
<div class="flex flex-col space-y-1">
|
||||
<div>
|
||||
@if(str($row->value)->contains('http'))
|
||||
<x-button xs amber :href="$row->value" target="_blank">
|
||||
<i class="fa fa-thin fa-book-open mr-2"></i>
|
||||
{{ __('Open') }}
|
||||
</x-button>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
@if($row->type === 'downloadable_file')
|
||||
<x-button xs amber :href="$row->getFirstMediaUrl('single_file')" target="_blank">
|
||||
<i class="fa fa-thin fa-download mr-2"></i>
|
||||
{{ __('Download') }}
|
||||
</x-button>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
@if($row->type === 'podcast_episode')
|
||||
<x-button xs amber :href="$row->episode->data['link']" target="_blank">
|
||||
<i class="fa fa-thin fa-headphones mr-2"></i>
|
||||
{{ __('Listen') }}
|
||||
</x-button>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
@if($row->type === 'markdown_article')
|
||||
<x-button xs amber :href="route('article.view', [$row])">
|
||||
<i class="fa fa-thin fa-newspaper mr-2"></i>
|
||||
{{ __('Read') }}
|
||||
</x-button>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@if($row->type !== 'markdown_article')
|
||||
<x-button
|
||||
x-data="{
|
||||
textToCopy: '{{ url()->route('library.table.libraryItems', ['country' => 'de', 'table' => ['filters' => ['id' => $row->id]]]) }}',
|
||||
}"
|
||||
@click.prevent="window.navigator.clipboard.writeText(textToCopy);window.$wireui.notify({title:'{{ __('Share url copied!') }}',icon:'success'});"
|
||||
xs black>
|
||||
<i class="fa fa-thin fa-copy mr-2"></i>
|
||||
{{ __('Share link') }}
|
||||
</x-button>
|
||||
@else
|
||||
<x-button
|
||||
x-data="{
|
||||
textToCopy: '{{ url()->route('library.table.libraryItems', ['country' => 'de', 'table' => ['filters' => ['id' => $row->id]]]) }}',
|
||||
}"
|
||||
@click.prevent="window.navigator.clipboard.writeText(textToCopy);window.$wireui.notify({title:'{{ __('Share url copied!') }}',icon:'success'});"
|
||||
xs black>
|
||||
<i class="fa fa-thin fa-copy mr-2"></i>
|
||||
{{ __('Share link') }}
|
||||
</x-button>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,3 +0,0 @@
|
||||
<div class="w-12 h-12">
|
||||
<img class="object-cover" src="{{ $row->getFirstMediaUrl('main', 'thumb') }}" alt="{{ $row->name }}">
|
||||
</div>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user