Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event Importer (Meetup + Eventbrite) along with Events Api + Org Api #186

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d4b996d
Events + Org Api
bogdankharchenko Oct 28, 2023
bbb733a
Support for tags and event date filtering
bogdankharchenko Oct 31, 2023
94ee51b
style
bogdankharchenko Oct 31, 2023
9cebef5
tests
bogdankharchenko Oct 31, 2023
6476c29
Update CancelEventCommandTest.php
bogdankharchenko Oct 31, 2023
a069186
event_id's no longer needed
bogdankharchenko Nov 1, 2023
7d98d8b
Update ImportEventForOrganization.php
bogdankharchenko Nov 1, 2023
a18c3fa
Fix cast of service_id and add .env.example for EventBrite API token
ThorntonMatthewD Nov 2, 2023
0c07744
Merge pull request #1 from ThorntonMatthewD/fix-service-id-cast-and-a…
bogdankharchenko Nov 2, 2023
cd5f709
Use event sales status instead of looking at json ld
bogdankharchenko Nov 9, 2023
67487b1
Update EventBriteHandler.php
bogdankharchenko Nov 9, 2023
3cd7866
Update EventBriteHandler.php
bogdankharchenko Nov 9, 2023
6edd0a0
Tag support, resolve PR comments
bogdankharchenko Nov 15, 2023
420f527
Add support for tag filtering
bogdankharchenko Nov 15, 2023
4931f13
Update EventApiV0Controller.php
bogdankharchenko Nov 15, 2023
58d7719
Change Schedule
bogdankharchenko Nov 15, 2023
138c3a8
composer.json tweaks
bogdankharchenko Nov 15, 2023
6db635b
Remove stripe
bogdankharchenko Nov 15, 2023
5ae8665
Ensure longitude is passed correctly
bogdankharchenko Nov 16, 2023
5bfbd5c
Use date_format
bogdankharchenko Nov 16, 2023
5592031
Add modules to tests
bogdankharchenko Nov 16, 2023
96db344
Org tag filter
bogdankharchenko Nov 17, 2023
852f263
Update EventApiV0Controller.php
bogdankharchenko Nov 17, 2023
3395b2a
Update EventApiV0Controller.php
bogdankharchenko Nov 17, 2023
ec49abe
Add api middleware
bogdankharchenko Nov 17, 2023
15ea77f
Add support for data import thresholds
bogdankharchenko Nov 20, 2023
f0ca3cb
style
bogdankharchenko Nov 20, 2023
dac2362
Update .env.example
bogdankharchenko Nov 21, 2023
9732b90
Default days
bogdankharchenko Dec 1, 2023
d876560
Update EventApiV0Controller.php
bogdankharchenko Dec 1, 2023
adcdfcf
Change attr name for Eventbrite cancellation check
ThorntonMatthewD Dec 6, 2023
43c0af2
Adjust EventFactory
ThorntonMatthewD Dec 6, 2023
15f745c
Fix MeetupRestTest
ThorntonMatthewD Dec 6, 2023
e099092
Merge pull request #2 from ThorntonMatthewD/events-importer-eventbrit…
bogdankharchenko Dec 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,10 @@ GOOGLE_TAG_MANAGER=
HCAPTCHA_SITEKEY=
HCAPTCHA_SECRET=
SLACK_CONTACT_WEBHOOK=

EVENTBRITE_PRIVATE_TOKEN=
bogdankharchenko marked this conversation as resolved.
Show resolved Hide resolved

EVENT_IMPORTER_MAX_DAYS_IN_PAST=30
EVENT_IMPORTER_MAX_DAYS_IN_FUTURE=180

EVENTS_API_DEFAULT_DAYS=1
26 changes: 26 additions & 0 deletions app-modules/api/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "hack-greenville/api",
"description": "",
"type": "library",
"version": "1.0",
"license": "proprietary",
"require": {},
"autoload": {
"psr-4": {
"HackGreenville\\Api\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"HackGreenville\\Api\\Tests\\": "tests/"
}
},
"minimum-stability": "stable",
"extra": {
"laravel": {
"providers": [
"HackGreenville\\Api\\Providers\\ApiServiceProvider"
]
}
}
}
11 changes: 11 additions & 0 deletions app-modules/api/routes/api-routes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

use HackGreenville\Api\Http\Controllers\EventApiV0Controller;
use HackGreenville\Api\Http\Controllers\OrgsApiV0Controller;

Route::middleware('api')
->prefix('api/')
->group(function () {
Route::get('v0/events', EventApiV0Controller::class)->name('api.v0.events.index');
Route::get('v0/orgs', OrgsApiV0Controller::class)->name('api.v0.orgs.index');
});
34 changes: 34 additions & 0 deletions app-modules/api/src/Http/Controllers/EventApiV0Controller.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace HackGreenville\Api\Http\Controllers;

use App\Models\Event;
use HackGreenville\Api\Http\Requests\EventApiV0Request;
use HackGreenville\Api\Resources\Events\V0\EventCollection;
use Illuminate\Database\Eloquent\Builder;

class EventApiV0Controller
{
public function __invoke(EventApiV0Request $request)
{
return new EventCollection(
resource: Event::query()
->when($request->filled('start_date'), function (Builder $query) use ($request) {
$query->where('active_at', '>=', $request->date('start_date'));
})
->when($request->filled('end_date'), function (Builder $query) use ($request) {
$query->where('active_at', '<=', $request->date('end_date'));
})
->when($request->filled('tags'), function (Builder $query) use ($request) {
$query->whereHas('organization.tags', function (Builder $query) use ($request) {
$query->where('id', $request->integer('tags'));
});
})
->when($request->isNotFilled(['start_date', 'end_date']), function (Builder $query) {
$query->where('active_at', '>=', now()->subDays(config('events-api.default_days')));
})
->oldest('active_at')
->get()
);
}
}
25 changes: 25 additions & 0 deletions app-modules/api/src/Http/Controllers/OrgsApiV0Controller.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace HackGreenville\Api\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\Org;
use HackGreenville\Api\Http\Requests\OrgsApiV0Request;
use HackGreenville\Api\Resources\Orgs\V0\OrganizationsCollection;
use Illuminate\Database\Eloquent\Builder;

class OrgsApiV0Controller extends Controller
{
public function __invoke(OrgsApiV0Request $request)
{
return new OrganizationsCollection(
resource: Org::query()
->when($request->filled('tags'), function (Builder $query) use ($request) {
bogdankharchenko marked this conversation as resolved.
Show resolved Hide resolved
$query->whereHas('tags', function ($query) use ($request) {
$query->where('id', $request->integer('tags'));
});
})
->get()
);
}
}
32 changes: 32 additions & 0 deletions app-modules/api/src/Http/Requests/EventApiV0Request.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace HackGreenville\Api\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class EventApiV0Request extends FormRequest
{
public function authorize()
{
return true;
}

public function rules()
{
return [
'start_date' => [
'nullable',
'sometimes',
'date_format:Y-m-d',
'before_or_equal:end_date',
],
'end_date' => [
'nullable',
'sometimes',
'date',
'date_format:Y-m-d',
'after_or_equal:start_date',
],
];
}
}
24 changes: 24 additions & 0 deletions app-modules/api/src/Http/Requests/OrgsApiV0Request.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace HackGreenville\Api\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class OrgsApiV0Request extends FormRequest
{
public function authorize()
{
return true;
}

public function rules()
{
return [
'tags' => [
'nullable',
'sometimes',
'integer',
],
];
}
}
16 changes: 16 additions & 0 deletions app-modules/api/src/Providers/ApiServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace HackGreenville\Api\Providers;

use Illuminate\Support\ServiceProvider;

class ApiServiceProvider extends ServiceProvider
{
public function register()
{
}

public function boot()
{
}
}
21 changes: 21 additions & 0 deletions app-modules/api/src/Resources/Events/V0/EventCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace HackGreenville\Api\Resources\Events\V0;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;

/**
* This exists merely to handle legacy events api.
*/
class EventCollection extends ResourceCollection
{
public static $wrap = null;

public $collects = EventResource::class;

public function toArray(Request $request): array
{
return $this->collection->toArray();
}
}
34 changes: 34 additions & 0 deletions app-modules/api/src/Resources/Events/V0/EventResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace HackGreenville\Api\Resources\Events\V0;

use App\Models\Event;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class EventResource extends JsonResource
{
/** @var Event $resource */
public $resource;

public function toArray(Request $request): array
{
return [
'event_name' => $this->resource->event_name,
'group_name' => $this->resource->group_name,
'group_url' => $this->resource->organization->home_page,
'url' => $this->resource->url,
'time' => $this->resource->active_at->toISOString(),
'tags' => $this->resource->organization->tags->first()?->id ?? '',
'status' => $this->resource->getStatusAttribute(),
'rsvp_count' => $this->resource->rsvp_count,
'description' => $this->resource->description,
'uuid' => $this->resource->event_uuid,
'data_as_of' => now()->toISOString(),
'service_id' => $this->resource->service_id,
'service' => $this->resource->service,
'venue' => new VenueResource($this->resource->venue),
'created_at' => $this->resource->created_at->toISOString(),
];
}
}
27 changes: 27 additions & 0 deletions app-modules/api/src/Resources/Events/V0/VenueResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace HackGreenville\Api\Resources\Events\V0;

use App\Models\Venue;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class VenueResource extends JsonResource
{
/** @var Venue $resource */
public $resource;

public function toArray(Request $request): array
{
return [
'name' => $this->resource->name,
'address' => $this->resource->address,
'city' => $this->resource->city,
'state' => $this->resource->state->abbr,
'zip' => $this->resource->zipcode,
'country' => $this->resource->country,
'lat' => $this->resource->lat,
'lon' => $this->resource->lng,
];
}
}
34 changes: 34 additions & 0 deletions app-modules/api/src/Resources/Orgs/V0/OrgResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace HackGreenville\Api\Resources\Orgs\V0;

use App\Models\Org;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class OrgResource extends JsonResource
{
/** @var Org $resource */
public $resource;

public function toArray(Request $request): array
{
return [
'title' => $this->resource->title,
'path' => $this->resource->path,
'changed' => $this->resource->updated_at->toISOString(),
'field_city' => $this->resource->city,
'field_event_service' => $this->resource->service,
'field_events_api_key' => $this->resource->service_api_key,
'field_focus_area' => $this->resource->focus_area,
'field_homepage' => $this->resource->home_page,
'field_event_calendar_homepage' => $this->resource->event_calendar_uri,
bogdankharchenko marked this conversation as resolved.
Show resolved Hide resolved
'field_primary_contact_person' => $this->resource->primary_contact_person,
'field_org_status' => $this->resource->status,
'field_organization_type' => $this->resource->organization_type,
'field_year_established' => $this->resource->established_at->year,
'field_org_tags' => $this->resource->tags->first()?->id ?? '',
'uuid' => $this->resource->id,
];
}
}
21 changes: 21 additions & 0 deletions app-modules/api/src/Resources/Orgs/V0/OrganizationsCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace HackGreenville\Api\Resources\Orgs\V0;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;

/**
* This exists merely to handle legacy events api.
*/
class OrganizationsCollection extends ResourceCollection
{
public $collects = OrgResource::class;

public static $wrap = null;

public function toArray(Request $request): array
{
return $this->collection->toArray();
}
}
55 changes: 55 additions & 0 deletions app-modules/api/tests/Feature/EventApiV0Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace HackGreenville\Api\Tests\Feature;

use App\Models\Event;
use App\Models\Tag;
use Tests\DatabaseTestCase;

class EventApiV0Test extends DatabaseTestCase
{
public function test_event_api_v0_return_correct_data(): void
{
// Lock-in the time
$this->travelTo(now());

$event = Event::factory()->create([
'cancelled_at' => now(),
]);

$tag = Tag::factory()->create();

$event->organization->tags()->attach($tag->id);

$this->getJson(route('api.v0.events.index'))
->assertSessionDoesntHaveErrors()
->assertExactJson([
[
'event_name' => $event->event_name,
'group_name' => $event->group_name,
'group_url' => $event->organization->home_page,
'url' => $event->url,
'time' => $event->active_at->toISOString(),
'tags' => $event->organization->tags->first()->id,
'rsvp_count' => $event->rsvp_count,
'created_at' => $event->created_at->toISOString(),
'description' => $event->description,
'uuid' => $event->event_uuid,
'data_as_of' => now()->toISOString(),
'status' => 'cancelled',
'service_id' => $event->service_id,
'service' => $event->service->value,
'venue' => [
'name' => $event->venue->name,
'address' => $event->venue->address,
'city' => $event->venue->city,
'state' => $event->venue->state->abbr,
'zip' => $event->venue->zipcode,
'country' => $event->venue->country,
'lat' => $event->venue->lat,
'lon' => $event->venue->lng,
],
],
]);
}
}
Loading
Loading