Skip to content

Commit

Permalink
Add integration with Pencil Spaces (#12)
Browse files Browse the repository at this point in the history
* Add integration with pencil space

* Add test
  • Loading branch information
mako321 authored Aug 8, 2023
1 parent 143e692 commit 6affacc
Show file tree
Hide file tree
Showing 17 changed files with 363 additions and 5 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ sequenceDiagram
end
```

If you don't send the `meeting_url` during the approval, an automatic space will be created in [Pencil Spaces](https://www.pencilspaces.com/), and that link will be saved. You can find more information [here](https://github.com/EscolaLMS/Pencil-Spaces).

## Listeners

This package does not listen for any events.
Expand Down
12 changes: 10 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"escolalms/core": "^1",
"escolalms/settings": "^0",
"escolalms/consultations": "^0",
"laravel/framework": "^8|^9"
"laravel/framework": "^8|^9",
"escolalms/pencil-spaces": "dev-main"
},
"require-dev": {
"phpunit/phpunit": "^9.0",
Expand Down Expand Up @@ -43,5 +44,12 @@
"sort-packages": true
},
"minimum-stability": "dev",
"prefer-stable": true
"prefer-stable": true,
"repositories": [
{
"type": "vcs",
"url": "https://github.com/EscolaLMS/Pencil-Spaces.git"
}
]

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddMeetingLinkTypeFieldToConsultationAccessEnquiriesTable extends Migration
{
public function up(): void
{
Schema::table('consultation_access_enquiries', function (Blueprint $table) {
$table->string('meeting_link_type')->nullable();
});
}

public function down(): void
{
Schema::table('consultation_access_enquiries', function (Blueprint $table) {
$table->dropColumn('meeting_link_type');
});
}
}
9 changes: 9 additions & 0 deletions src/Enum/MeetingLinkTypeEnum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace EscolaLms\ConsultationAccess\Enum;

class MeetingLinkTypeEnum
{
public const CUSTOM = 'custom';
public const PENCIL_SPACES = 'pencil_spaces';
}
2 changes: 2 additions & 0 deletions src/EscolaLmsConsultationAccessServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use EscolaLms\ConsultationAccess\Services\ConsultationAccessEnquiryService;
use EscolaLms\ConsultationAccess\Services\Contracts\ConsultationAccessEnquiryServiceContract;
use EscolaLms\Consultations\EscolaLmsConsultationsServiceProvider;
use EscolaLms\PencilSpaces\EscolaLmsPencilSpacesServiceProvider;
use Illuminate\Support\ServiceProvider;

/**
Expand Down Expand Up @@ -38,5 +39,6 @@ public function register()
{
$this->app->register(AuthServiceProvider::class);
$this->app->register(EscolaLmsConsultationsServiceProvider::class);
$this->app->register(EscolaLmsPencilSpacesServiceProvider::class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use EscolaLms\ConsultationAccess\Http\Requests\UpdateConsultationAccessEnquiryRequest;
use EscolaLms\ConsultationAccess\Http\Resources\ConsultationAccessEnquiryResource;
use EscolaLms\ConsultationAccess\Http\Requests\CreateConsultationAccessEnquiryRequest;
use EscolaLms\ConsultationAccess\Http\Resources\JoinConsultationAccessResource;
use EscolaLms\ConsultationAccess\Services\Contracts\ConsultationAccessEnquiryServiceContract;
use EscolaLms\Core\Http\Controllers\EscolaLmsBaseController;
use Illuminate\Http\JsonResponse;
Expand Down Expand Up @@ -54,4 +55,9 @@ public function read(ReadConsultationAccessEnquiryRequest $request): JsonRespons
{
return $this->sendResponseForResource(ConsultationAccessEnquiryResource::make($request->getEnquiry()));
}

public function join(ReadConsultationAccessEnquiryRequest $request): JsonResponse
{
return $this->sendResponseForResource(JoinConsultationAccessResource::make($request->getEnquiry()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,48 @@ public function index(ListConsultationAccessEnquiryRequest $request): JsonRespon
*/
public function read(ReadConsultationAccessEnquiryRequest $request): JsonResponse;

/**
* @OA\Get(
* path="/api/consultation-access-enquiries/{id}/join",
* summary="Get url to consultation by enquiry id",
* tags={"Consultation Access"},
* security={
* {"passport": {}},
* },
* @OA\Parameter(
* name="id",
* required=true,
* in="path",
* @OA\Schema(
* type="integer",
* ),
* ),
* @OA\Response(
* response=200,
* description="Successfull operation",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(
* property="success",
* type="boolean"
* ),
* @OA\Property(
* property="data",
* ref="#/components/schemas/JoinConsultationAccessResource"
* ),
* @OA\Property(
* property="message",
* type="string"
* )
* )
* )
* )
* )
*/
public function join(ReadConsultationAccessEnquiryRequest $request): JsonResponse;

/**
* @OA\Post(
* path="/api/consultation-access-enquiries",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
/**
* @OA\Schema(
* schema="AdminApproveConsultationAccessEnquiryRequest",
* required={"meeting_link"},
* @OA\Property(
* property="meeting_link",
* description="meeting_link",
Expand All @@ -30,7 +29,7 @@ public function rules(): array
{
return [
'proposed_term_id' => ['required', 'integer', 'exists:consultation_access_enquiry_proposed_terms,id'],
'meeting_link' => ['sometimes', 'string', 'url'],
'meeting_link' => ['nullable', 'string', 'url'],
];
}

Expand Down
1 change: 1 addition & 0 deletions src/Http/Resources/ConsultationAccessEnquiryResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public function toArray($request): array
'description' => $this->description,
'consultation_term' => $this->consultationUser ? ConsultationTermsResource::make($this->consultationUser) : null,
'meeting_link' => $this->meeting_link,
'meeting_link_type' => $this->meeting_link_type,
'related_type' => $this->related_type,
'related_id' => $this->related_id,
'title' => $this->title,
Expand Down
44 changes: 44 additions & 0 deletions src/Http/Resources/JoinConsultationAccessResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace EscolaLms\ConsultationAccess\Http\Resources;

use EscolaLms\ConsultationAccess\Enum\MeetingLinkTypeEnum;
use EscolaLms\ConsultationAccess\Models\ConsultationAccessEnquiry;
use EscolaLms\PencilSpaces\Facades\PencilSpace;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\Auth;

/**
* @OA\Schema(
* schema="JoinConsultationAccessResource",
* @OA\Property(
* property="id",
* description="id",
* type="number"
* ),
* @OA\Property(
* property="meeting_link",
* type="string"
* ),
* @OA\Property(
* property="meeting_link_type",
* type="string"
* ),
* )
*
*/

/** @mixin ConsultationAccessEnquiry */
class JoinConsultationAccessResource extends JsonResource
{
public function toArray($request): array
{
return [
'id' => $this->id,
'meeting_link_type' => $this->meeting_link_type,
'meeting_link' => $this->meeting_link_type === MeetingLinkTypeEnum::PENCIL_SPACES
? PencilSpace::getDirectLoginUrl(Auth::id(), $this->meeting_link)
: $this->meeting_link,
];
}
}
60 changes: 60 additions & 0 deletions src/Jobs/CreatePencilSpaceJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace EscolaLms\ConsultationAccess\Jobs;

use EscolaLms\ConsultationAccess\Enum\MeetingLinkTypeEnum;
use EscolaLms\ConsultationAccess\Events\ConsultationAccessEnquiryApprovedEvent;
use EscolaLms\ConsultationAccess\Models\ConsultationAccessEnquiry;
use EscolaLms\ConsultationAccess\Repositories\Contracts\ConsultationAccessEnquiryRepositoryContract;
use EscolaLms\PencilSpaces\Facades\PencilSpace;
use EscolaLms\PencilSpaces\Resource\CreatePencilSpaceResource;
use Exception;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;

class CreatePencilSpaceJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

private int $consultationAccessEnquiryId;

public function __construct(int $consultationAccessEnquiryId)
{
$this->consultationAccessEnquiryId = $consultationAccessEnquiryId;
}

public function handle(ConsultationAccessEnquiryRepositoryContract $consultationAccessEnquiryRepository): void
{
try {
/** @var ?ConsultationAccessEnquiry $enquiry */
$enquiry = $consultationAccessEnquiryRepository->find($this->consultationAccessEnquiryId);

if (!$enquiry) {
return;
}

$resource = new CreatePencilSpaceResource(
$enquiry->title ?? 'Consultation X ' . $enquiry->user->name,
collect($enquiry->consultation->author_id),
collect($enquiry->user_id)
);

$space = PencilSpace::createSpace($resource);

$consultationAccessEnquiryRepository->update([
'meeting_link' => Arr::get($space, 'link'),
'meeting_link_type' => MeetingLinkTypeEnum::PENCIL_SPACES,
], $this->consultationAccessEnquiryId);

event(new ConsultationAccessEnquiryApprovedEvent($enquiry->user, $enquiry));
} catch (Exception $e) {
Log::error('[ConsultationAccess][CreatePencilSpaceJob] Fails', ['error' => $e->getMessage()]);
$this->fail();
}
}
}
2 changes: 2 additions & 0 deletions src/Models/ConsultationAccessEnquiry.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* @property string $description
* @property int $consultation_user_id
* @property string $meeting_link
* @property ?string $meeting_link_type
* @property ?string $title
* @property ?string $related_type
* @property ?int $related_id
Expand All @@ -42,6 +43,7 @@ class ConsultationAccessEnquiry extends Model
'description',
'consultation_user_id',
'meeting_link',
'meeting_link_type',
'title',
'related_type',
'related_id',
Expand Down
9 changes: 8 additions & 1 deletion src/Services/ConsultationAccessEnquiryService.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
use EscolaLms\ConsultationAccess\Dtos\PageDto;
use EscolaLms\ConsultationAccess\Dtos\UpdateConsultationAccessEnquiryDto;
use EscolaLms\ConsultationAccess\Enum\EnquiryStatusEnum;
use EscolaLms\ConsultationAccess\Enum\MeetingLinkTypeEnum;
use EscolaLms\ConsultationAccess\Events\ConsultationAccessEnquiryAdminCreatedEvent;
use EscolaLms\ConsultationAccess\Events\ConsultationAccessEnquiryAdminUpdatedEvent;
use EscolaLms\ConsultationAccess\Events\ConsultationAccessEnquiryApprovedEvent;
use EscolaLms\ConsultationAccess\Events\ConsultationAccessEnquiryDisapprovedEvent;
use EscolaLms\ConsultationAccess\Exceptions\ConsultationAccessException;
use EscolaLms\ConsultationAccess\Exceptions\EnquiryAlreadyApprovedException;
use EscolaLms\ConsultationAccess\Exceptions\TermIsBusyException;
use EscolaLms\ConsultationAccess\Jobs\CreatePencilSpaceJob;
use EscolaLms\ConsultationAccess\Models\ConsultationAccessEnquiry;
use EscolaLms\ConsultationAccess\Models\ConsultationAccessEnquiryProposedTerm;
use EscolaLms\ConsultationAccess\Repositories\Contracts\ConsultationAccessEnquiryProposedTermRepositoryContract;
Expand Down Expand Up @@ -104,9 +106,14 @@ public function approveByProposedTerm(ApproveConsultationAccessEnquiryDto $dto):
'consultation_user_id' => $consultationUser->getKey(),
'status' => EnquiryStatusEnum::APPROVED,
'meeting_link' => $dto->getMeetingLink(),
'meeting_link_type' => $dto->getMeetingLink() ? MeetingLinkTypeEnum::CUSTOM : null,
], $enquiry->getKey());

event(new ConsultationAccessEnquiryApprovedEvent($enquiry->user, $enquiry));
if (!$dto->getMeetingLink()) {
CreatePencilSpaceJob::dispatch($enquiry->getKey());
} else {
event(new ConsultationAccessEnquiryApprovedEvent($enquiry->user, $enquiry));
}
});
}

Expand Down
1 change: 1 addition & 0 deletions src/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
Route::get(null, [ConsultationAccessEnquiryApiController::class, 'index']);
Route::post(null, [ConsultationAccessEnquiryApiController::class, 'create']);
Route::get('{id}', [ConsultationAccessEnquiryApiController::class, 'read'])->whereNumber('id');
Route::get('{id}/join', [ConsultationAccessEnquiryApiController::class, 'join'])->whereNumber('id');
Route::patch('{id}', [ConsultationAccessEnquiryApiController::class, 'update'])->whereNumber('id');
Route::delete('{id}', [ConsultationAccessEnquiryApiController::class, 'delete'])->whereNumber('id');
});
Expand Down
24 changes: 24 additions & 0 deletions tests/Api/Admin/ConsultationAccessEnquiryAdminApproveApiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@

use EscolaLms\ConsultationAccess\Database\Seeders\ConsultationAccessPermissionSeeder;
use EscolaLms\ConsultationAccess\Enum\EnquiryStatusEnum;
use EscolaLms\ConsultationAccess\Enum\MeetingLinkTypeEnum;
use EscolaLms\ConsultationAccess\Jobs\CreatePencilSpaceJob;
use EscolaLms\Consultations\Enum\ConsultationTermStatusEnum;
use EscolaLms\ConsultationAccess\Models\ConsultationAccessEnquiry;
use EscolaLms\ConsultationAccess\Models\ConsultationAccessEnquiryProposedTerm;
use EscolaLms\ConsultationAccess\Tests\TestCase;
use EscolaLms\Consultations\Models\ConsultationUserPivot;
use EscolaLms\Core\Tests\CreatesUsers;
use Illuminate\Support\Facades\Bus;

class ConsultationAccessEnquiryAdminApproveApiTest extends TestCase
{
Expand Down Expand Up @@ -44,6 +47,7 @@ public function testConsultationAccessEnquiryAdminApprove(): void
'status' => EnquiryStatusEnum::APPROVED,
'consultation_id' => $proposedTerm->consultationAccessEnquiry->consultation_id,
'meeting_link' => $meetingLink,
'meeting_link_type' => MeetingLinkTypeEnum::CUSTOM,
]);

$this->assertDatabaseHas('consultation_user', [
Expand Down Expand Up @@ -93,4 +97,24 @@ public function testConsultationAccessEnquiryAdminApproveProposedTermIsBusyExcep
'message' => __('Term is busy'),
]);
}

public function testConsultationAccessEnquiryAdminApproveWithoutMeetingLink(): void
{
Bus::fake([CreatePencilSpaceJob::class]);

/** @var ConsultationAccessEnquiryProposedTerm $proposedTerm */
$proposedTerm = ConsultationAccessEnquiryProposedTerm::factory()->create();
$this->actingAs($this->makeAdmin(), 'api')
->postJson('api/admin/consultation-access-enquiries/approve/' . $proposedTerm->getKey())
->assertOk();

$proposedTerm->refresh();

$this->assertDatabaseHas('consultation_access_enquiries', [
'status' => EnquiryStatusEnum::APPROVED,
'consultation_id' => $proposedTerm->consultationAccessEnquiry->consultation_id,
]);

Bus::assertDispatched(CreatePencilSpaceJob::class);
}
}
Loading

0 comments on commit 6affacc

Please sign in to comment.