Skip to content

Commit 4abebb3

Browse files
committed
Merge remote-tracking branch 'origin/main' into time-machine
2 parents 77c1105 + 4002fca commit 4abebb3

File tree

142 files changed

+2753
-141
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

142 files changed

+2753
-141
lines changed

packages/hallway-core/composer.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
"name": "artisan-build/hallway-core",
33
"description": "The core files of the hallway.fm community software",
44
"keywords": [
5-
65
],
76
"homepage": "https://hallway.fm",
87
"license": "proprietary",
@@ -15,7 +14,10 @@
1514
],
1615
"require": {
1716
"php": "^8.3",
18-
"illuminate/contracts": "^11.0"
17+
"illuminate/contracts": "^11.0",
18+
"ext-dom": "*",
19+
"ext-libxml": "*",
20+
"ext-fileinfo": "*"
1921
},
2022
"require-dev": {
2123
"roave/security-advisories": "dev-latest",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace ArtisanBuild\Hallway\Attachments\Enums;
6+
7+
use Illuminate\Support\Facades\Blade;
8+
9+
enum AttachmentDisplayTemplates: string
10+
{
11+
case Image = 'image';
12+
case Video = 'video';
13+
case Pdf = 'pdf';
14+
15+
case Other = 'other';
16+
17+
public function render(string $url): string
18+
{
19+
return match ($this) {
20+
self::Image => app()->has('message_image_template')
21+
? view(app()->get('message_image_template'), ['url' => $url])->toHtml()
22+
: Blade::render('<img class="h-full w-full object-contain" src="'.$url.'" alt="">'),
23+
24+
// TODO: Implement the other template options and ensure that we have them bound in the Hallway Flux provider
25+
default => Blade::render('<flux:link href="'.$url.'">'.$url.'</flux:link>'),
26+
};
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace ArtisanBuild\Hallway\Attachments\Events;
6+
7+
use ArtisanBuild\Hallway\Attachments\States\AttachmentState;
8+
use ArtisanBuild\Hallway\Channels\States\ChannelState;
9+
use ArtisanBuild\Hallway\Members\States\MemberState;
10+
use ArtisanBuild\Hallway\Messages\States\MessageState;
11+
use Thunk\Verbs\Attributes\Autodiscovery\StateId;
12+
use Thunk\Verbs\Event;
13+
14+
class FileAttachedToMessage extends Event
15+
{
16+
#[StateId(MessageState::class)]
17+
public int $message_id;
18+
19+
#[StateId(AttachmentState::class)]
20+
public int $attachment_id;
21+
22+
#[StateId(MemberState::class)]
23+
public int $member_id;
24+
25+
public string $url;
26+
27+
public function applyToMemberState(MemberState $member): void
28+
{
29+
$member->attachment_ids[] = $this->attachment_id;
30+
}
31+
32+
public function applyToMessageState(MessageState $message): void
33+
{
34+
$message->attachment_ids[] = $this->attachment_id;
35+
ChannelState::load($message->channel_id)->attachment_ids[] = $this->attachment_id;
36+
}
37+
38+
public function applyToAttachmentState(AttachmentState $attachment): void
39+
{
40+
$attachment->message_id = $this->message_id;
41+
$attachment->url = $this->url;
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace ArtisanBuild\Hallway\Attachments\States;
6+
7+
use ArtisanBuild\Hallway\Attachments\Enums\AttachmentDisplayTemplates;
8+
use ArtisanBuild\Hallway\Channels\States\ChannelState;
9+
use ArtisanBuild\Hallway\Messages\States\MessageState;
10+
use Thunk\Verbs\State;
11+
12+
class AttachmentState extends State
13+
{
14+
public int $message_id;
15+
16+
public string $url;
17+
18+
public AttachmentDisplayTemplates $template = AttachmentDisplayTemplates::Image;
19+
20+
public function message(): MessageState
21+
{
22+
return MessageState::load($this->message_id);
23+
}
24+
25+
public function channel(): ChannelState
26+
{
27+
return ChannelState::load($this->message()->channel_id);
28+
}
29+
}

packages/hallway-core/src/Calendar/Events/GatheringCancelled.php

-1
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,4 @@ class GatheringCancelled extends Event
1313
MemberRoles::Owner,
1414
MemberRoles::Admin,
1515
];
16-
1716
}

packages/hallway-core/src/Calendar/Events/GatheringCreated.php

+20-11
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use ArtisanBuild\Adverbs\Traits\ReturnsModelInstanceOnHandle;
88
use ArtisanBuild\Hallway\Calendar\Enums\InvitationLevels;
9+
use ArtisanBuild\Hallway\Calendar\States\CalendarRangeState;
910
use ArtisanBuild\Hallway\Calendar\States\GatheringState;
1011
use ArtisanBuild\Hallway\Members\Actions\GetMemberTimeZone;
1112
use ArtisanBuild\Hallway\Members\Enums\MemberRoles;
@@ -15,9 +16,11 @@
1516
use ArtisanBuild\VerbsFlux\Attributes\EventInput;
1617
use ArtisanBuild\VerbsFlux\Enums\InputTypes;
1718
use Carbon\Carbon;
19+
use Thunk\Verbs\Attributes\Autodiscovery\AppliesToSingletonState;
1820
use Thunk\Verbs\Attributes\Autodiscovery\StateId;
1921
use Thunk\Verbs\Event;
2022

23+
#[AppliesToSingletonState(CalendarRangeState::class)]
2124
#[EventForm(
2225
submit_text: 'Create New Gathering',
2326
has_time_machine: true,
@@ -35,7 +38,6 @@ class GatheringCreated extends Event
3538
#[StateId(GatheringState::class)]
3639
public ?int $gathering_id = null;
3740

38-
3941
#[EventInput(
4042
type: InputTypes::Text,
4143
)]
@@ -73,6 +75,7 @@ class GatheringCreated extends Event
7375
options: ['No', 'Yes'],
7476
)]
7577
public bool $published = false;
78+
7679
public ?Carbon $cancelled_at = null;
7780

7881
#[EventInput(
@@ -93,18 +96,24 @@ class GatheringCreated extends Event
9396
)]
9497
public ?string $url = null;
9598

96-
public function apply(GatheringState $state): void
99+
public function applyToCalendarRangeState(CalendarRangeState $range): void
97100
{
98-
$start = Carbon::parse($this->start->format('Y-m-d\TH:i'), $this->timezone)->setTimezone('UTC');
101+
$end = $this->start->copy()->addMinutes($this->duration);
102+
$range->first_gathering_start = $range->first_gathering_start?->isBefore($this->start) ? $range->first_gathering_start : $this->start;
103+
$range->last_gathering_end = $range->last_gathering_end?->isAfter($end) ? $range->last_gathering_end : $end;
104+
}
99105

106+
public function applyToGatheringState(GatheringState $gathering): void
107+
{
108+
$start = Carbon::parse($this->start->format('Y-m-d\TH:i'), $this->timezone)->setTimezone('UTC');
100109

101-
$state->title = $this->title;
102-
$state->description = $this->description;
103-
$state->start = $start;
104-
$state->end = $start->copy()->addMinutes($this->duration);
105-
$state->published_at = $this->published ? now() : null;
106-
$state->cancelled_at = $this->cancelled_at;
107-
$state->invitation_level = $this->invitation_level;
110+
$gathering->title = $this->title;
111+
$gathering->description = $this->description;
112+
$gathering->start = $start;
113+
$gathering->end = $start->copy()->addMinutes($this->duration);
114+
$gathering->published_at = $this->published ? now() : null;
115+
$gathering->cancelled_at = $this->cancelled_at;
116+
$gathering->invitation_level = $this->invitation_level;
117+
$gathering->capacity = $this->capacity;
108118
}
109-
110119
}

packages/hallway-core/src/Calendar/Events/GatheringPublished.php

-1
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,4 @@ class GatheringPublished extends Event
1313
MemberRoles::Owner,
1414
MemberRoles::Admin,
1515
];
16-
1716
}

packages/hallway-core/src/Calendar/Events/GatheringUpdated.php

+45
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,16 @@
99
use ArtisanBuild\Hallway\Calendar\States\GatheringState;
1010
use ArtisanBuild\Hallway\Members\Enums\MemberRoles;
1111
use ArtisanBuild\Hallway\Members\Traits\AuthorizesBasedOnMemberState;
12+
use ArtisanBuild\VerbsFlux\Attributes\EventForm;
13+
use ArtisanBuild\VerbsFlux\Attributes\EventInput;
14+
use ArtisanBuild\VerbsFlux\Enums\InputTypes;
1215
use Carbon\Carbon;
1316
use Thunk\Verbs\Attributes\Autodiscovery\StateId;
1417
use Thunk\Verbs\Event;
1518

19+
#[EventForm(
20+
submit_text: 'Update Gathering',
21+
)]
1622
class GatheringUpdated extends Event
1723
{
1824
use AuthorizesBasedOnMemberState;
@@ -26,12 +32,51 @@ class GatheringUpdated extends Event
2632
#[StateId(GatheringState::class)]
2733
public int $gathering_id;
2834

35+
#[EventInput(
36+
type: InputTypes::Text,
37+
)]
2938
public ?string $title = null;
39+
40+
#[EventInput(
41+
type: InputTypes::Textarea,
42+
)]
3043
public ?string $description = null;
44+
45+
#[EventInput(
46+
type: InputTypes::DatetimeLocal,
47+
)]
3148
public ?Carbon $start = null;
49+
50+
#[EventInput(
51+
type: InputTypes::DatetimeLocal,
52+
)]
3253
public ?Carbon $end = null;
54+
55+
#[EventInput(
56+
type: InputTypes::DatetimeLocal,
57+
)]
3358
public ?Carbon $published_at = null;
59+
60+
#[EventInput(
61+
type: InputTypes::DatetimeLocal,
62+
)]
3463
public ?Carbon $cancelled_at = null;
64+
65+
#[EventInput(
66+
type: InputTypes::Select,
67+
options: InvitationLevels::class,
68+
)]
3569
public ?InvitationLevels $invitation_level = null;
3670

71+
#[EventInput(
72+
type: InputTypes::Number,
73+
description: 'If you set a capacity, members will be required to log in or register and RSVP',
74+
)]
75+
public ?int $capacity = null;
76+
77+
#[EventInput(
78+
type: InputTypes::Url,
79+
description: 'Link where participants should go at the start of the gathering (Zoom, Google Meet, etc)',
80+
)]
81+
public ?string $url = null;
3782
}

packages/hallway-core/src/Calendar/Events/GatheringsRequested.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class GatheringsRequested extends Event
1616
#[Once]
1717
public function handle(): Collection
1818
{
19-
return Gathering::orderBy('start')->where('start', '>', now()->startOfMonth())->get();
19+
return Gathering::orderBy('start')->where('start', '>', now()->startOfMonth())->get()
20+
->map(fn ($gathering) => $gathering->verbs_state());
2021
}
21-
2222
}

packages/hallway-core/src/Calendar/Models/Gathering.php

+4-5
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,22 @@ class Gathering extends Model
2727
public function day(): Attribute
2828
{
2929
return Attribute::make(
30-
get: fn() => $this->start->format('Y-m-d'),
30+
get: fn () => $this->start->format('Y-m-d'),
3131
);
3232
}
3333

3434
public function month(): Attribute
3535
{
3636
return Attribute::make(
37-
get: fn() => $this->start->format('Y-m'),
37+
get: fn () => $this->start->format('Y-m'),
3838
);
3939
}
4040

4141
public function casts()
4242
{
4343
return [
44-
'start' => 'immutable_datetime',
45-
'end' => 'immutable_datetime',
44+
'start' => 'datetime',
45+
'end' => 'datetime',
4646
];
4747
}
48-
4948
}

packages/hallway-core/src/Calendar/Providers/CalendarServiceProvider.php

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
class CalendarServiceProvider extends ServiceProvider
1010
{
11+
#[\Override]
1112
public function register(): void {}
1213

1314
public function boot(): void {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace ArtisanBuild\Hallway\Calendar\States;
6+
7+
use Carbon\Carbon;
8+
use Thunk\Verbs\State;
9+
10+
class CalendarRangeState extends State
11+
{
12+
public ?Carbon $first_gathering_start = null;
13+
14+
public ?Carbon $last_gathering_end = null;
15+
}

packages/hallway-core/src/Calendar/States/GatheringState.php

+11-4
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,23 @@
77
use ArtisanBuild\Hallway\Calendar\Enums\InvitationLevels;
88
use ArtisanBuild\Hallway\Members\States\MemberState;
99
use Carbon\Carbon;
10+
use Illuminate\Support\Facades\Session;
1011
use Thunk\Verbs\State;
1112

1213
class GatheringState extends State
1314
{
1415
public string $title;
16+
1517
public string $description;
18+
1619
public Carbon $start;
20+
1721
public Carbon $end;
22+
1823
public ?Carbon $published_at = null;
24+
1925
public ?Carbon $cancelled_at = null;
26+
2027
public InvitationLevels $invitation_level;
2128

2229
// Allow events to be added to channels
@@ -26,11 +33,11 @@ class GatheringState extends State
2633

2734
public ?string $url = null;
2835

29-
public function forMember(MemberState $member): static
36+
public function forMember(?MemberState $member = null): static
3037
{
31-
$this->start = $this->start->setTimezone($member->timezone);
32-
$this->end = $this->end->setTimezone($member->timezone);
38+
$this->start = $this->start->setTimezone($member?->timezone ?? Session::get('timezone', 'UTC'));
39+
$this->end = $this->end->setTimezone($member?->timezone ?? Session::get('timezone', 'UTC'));
40+
3341
return $this;
3442
}
35-
3643
}

0 commit comments

Comments
 (0)