Fixed bugs on Submit presentation flow
* added tags per allowed track * updated presentation progress * added presentation progress on presentation serializer * added new endpoint to mark presentation as completed PUT /api/v1/summits/{id}/presentations/{presentation_id}/completed Change-Id: I23ec05341f74498312f074236b691dd6473700b1
This commit is contained in:
parent
76b206edbe
commit
aebbcd1bd4
@ -284,6 +284,7 @@ final class OAuth2PresentationApiController extends OAuth2ProtectedController
|
|||||||
'attending_media' => 'required|boolean',
|
'attending_media' => 'required|boolean',
|
||||||
'links' => 'sometimes|url_array',
|
'links' => 'sometimes|url_array',
|
||||||
'extra_questions' => 'sometimes|entity_value_array',
|
'extra_questions' => 'sometimes|entity_value_array',
|
||||||
|
'tags' => 'sometimes|string_array',
|
||||||
];
|
];
|
||||||
|
|
||||||
$data = $data->all();
|
$data = $data->all();
|
||||||
@ -360,6 +361,7 @@ final class OAuth2PresentationApiController extends OAuth2ProtectedController
|
|||||||
'attending_media' => 'sometimes|boolean',
|
'attending_media' => 'sometimes|boolean',
|
||||||
'links' => 'sometimes|url_array',
|
'links' => 'sometimes|url_array',
|
||||||
'extra_questions' => 'sometimes|entity_value_array',
|
'extra_questions' => 'sometimes|entity_value_array',
|
||||||
|
'tags' => 'sometimes|string_array',
|
||||||
];
|
];
|
||||||
|
|
||||||
$data = $data->all();
|
$data = $data->all();
|
||||||
@ -405,6 +407,51 @@ final class OAuth2PresentationApiController extends OAuth2ProtectedController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $summit_id
|
||||||
|
* @param $presentation_id
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function completePresentationSubmission($summit_id, $presentation_id){
|
||||||
|
try {
|
||||||
|
|
||||||
|
$summit = SummitFinderStrategyFactory::build($this->summit_repository, $this->resource_server_context)->find($summit_id);
|
||||||
|
if (is_null($summit)) return $this->error404();
|
||||||
|
|
||||||
|
$member_id = $this->resource_server_context->getCurrentUserExternalId();
|
||||||
|
if(is_null($member_id))
|
||||||
|
return $this->error403();
|
||||||
|
|
||||||
|
$member = $this->member_repository->getById($member_id);
|
||||||
|
|
||||||
|
if(is_null($member))
|
||||||
|
return $this->error403();
|
||||||
|
|
||||||
|
$presentation = $this->presentation_service->completePresentationSubmission
|
||||||
|
(
|
||||||
|
$summit,
|
||||||
|
$presentation_id,
|
||||||
|
$member
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->updated(SerializerRegistry::getInstance()->getSerializer($presentation)->serialize());
|
||||||
|
}
|
||||||
|
catch (EntityNotFoundException $ex1)
|
||||||
|
{
|
||||||
|
Log::warning($ex1);
|
||||||
|
return $this->error404();
|
||||||
|
}
|
||||||
|
catch (ValidationException $ex2)
|
||||||
|
{
|
||||||
|
Log::warning($ex2);
|
||||||
|
return $this->error412($ex2->getMessages());
|
||||||
|
}
|
||||||
|
catch (Exception $ex)
|
||||||
|
{
|
||||||
|
Log::error($ex);
|
||||||
|
return $this->error500($ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @param $presentation_id
|
* @param $presentation_id
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
@ -288,6 +288,8 @@ Route::group([
|
|||||||
// opened without role CFP - valid selection plan on CFP status
|
// opened without role CFP - valid selection plan on CFP status
|
||||||
Route::put('', 'OAuth2PresentationApiController@updatePresentationSubmission');
|
Route::put('', 'OAuth2PresentationApiController@updatePresentationSubmission');
|
||||||
|
|
||||||
|
Route::put('completed', 'OAuth2PresentationApiController@completePresentationSubmission');
|
||||||
|
|
||||||
Route::delete('', 'OAuth2PresentationApiController@deletePresentation');
|
Route::delete('', 'OAuth2PresentationApiController@deletePresentation');
|
||||||
|
|
||||||
Route::group(['prefix' => 'videos'], function () {
|
Route::group(['prefix' => 'videos'], function () {
|
||||||
|
@ -27,6 +27,7 @@ class PresentationSerializer extends SummitEventSerializer
|
|||||||
'ToRecord' => 'to_record:json_boolean',
|
'ToRecord' => 'to_record:json_boolean',
|
||||||
'AttendingMedia' => 'attending_media:json_boolean',
|
'AttendingMedia' => 'attending_media:json_boolean',
|
||||||
'StatusNice' => 'status:json_string',
|
'StatusNice' => 'status:json_string',
|
||||||
|
'ProgressNice' => 'progress:json_string',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected static $allowed_fields = [
|
protected static $allowed_fields = [
|
||||||
@ -38,6 +39,7 @@ class PresentationSerializer extends SummitEventSerializer
|
|||||||
'to_record',
|
'to_record',
|
||||||
'attending_media',
|
'attending_media',
|
||||||
'status',
|
'status',
|
||||||
|
'progress',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected static $allowed_relations = [
|
protected static $allowed_relations = [
|
||||||
|
@ -463,6 +463,32 @@ class Presentation extends SummitEvent
|
|||||||
return $this->status;
|
return $this->status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getProgressNice(){
|
||||||
|
switch($this->progress){
|
||||||
|
case self::PHASE_NEW:
|
||||||
|
return 'NEW';
|
||||||
|
break;
|
||||||
|
case self::PHASE_SUMMARY:
|
||||||
|
return 'SUMMARY';
|
||||||
|
break;
|
||||||
|
case self::PHASE_TAGS:
|
||||||
|
return 'TAGS';
|
||||||
|
break;
|
||||||
|
case self::PHASE_SPEAKERS:
|
||||||
|
return 'SPEAKERS';
|
||||||
|
break;
|
||||||
|
case self::PHASE_COMPLETE:
|
||||||
|
return 'COMPLETE';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 'NEW';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
@ -472,7 +498,7 @@ class Presentation extends SummitEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed $progress
|
* @param int $progress
|
||||||
*/
|
*/
|
||||||
public function setProgress($progress)
|
public function setProgress($progress)
|
||||||
{
|
{
|
||||||
|
@ -285,6 +285,17 @@ class PresentationCategory extends SilverstripeBaseModel
|
|||||||
$this->allowed_tags->clear();
|
$this->allowed_tags->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $tag_value
|
||||||
|
* @return Tag|null
|
||||||
|
*/
|
||||||
|
public function getAllowedTagByVal($tag_value){
|
||||||
|
$criteria = Criteria::create();
|
||||||
|
$criteria->where(Criteria::expr()->eq('tag', trim($tag_value)));
|
||||||
|
$res = $this->allowed_tags->matching($criteria)->first();
|
||||||
|
return $res === false ? null : $res;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Tag $tag
|
* @param Tag $tag
|
||||||
* @return $this
|
* @return $this
|
||||||
|
@ -68,6 +68,17 @@ interface IPresentationService
|
|||||||
*/
|
*/
|
||||||
public function updatePresentationSubmission(Summit $summit, $presentation_id, Member $member, array $data);
|
public function updatePresentationSubmission(Summit $summit, $presentation_id, Member $member, array $data);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Summit $summit
|
||||||
|
* @param int $presentation_id
|
||||||
|
* @param Member $member
|
||||||
|
* @return Presentation
|
||||||
|
* @throws ValidationException
|
||||||
|
* @throws EntityNotFoundException
|
||||||
|
*/
|
||||||
|
public function completePresentationSubmission(Summit $summit, $presentation_id, Member $member);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Member $member
|
* @param Member $member
|
||||||
* @param int $presentation_id
|
* @param int $presentation_id
|
||||||
|
@ -20,6 +20,7 @@ use App\Models\Foundation\Summit\Events\Presentations\TrackQuestions\TrackAnswer
|
|||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
use models\exceptions\EntityNotFoundException;
|
use models\exceptions\EntityNotFoundException;
|
||||||
use models\exceptions\ValidationException;
|
use models\exceptions\ValidationException;
|
||||||
|
use models\main\ITagRepository;
|
||||||
use models\main\Member;
|
use models\main\Member;
|
||||||
use models\summit\factories\IPresentationVideoFactory;
|
use models\summit\factories\IPresentationVideoFactory;
|
||||||
use models\summit\ISpeakerRepository;
|
use models\summit\ISpeakerRepository;
|
||||||
@ -49,23 +50,38 @@ final class PresentationService
|
|||||||
*/
|
*/
|
||||||
private $video_factory;
|
private $video_factory;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ISpeakerRepository
|
* @var ISpeakerRepository
|
||||||
*/
|
*/
|
||||||
private $speaker_repository;
|
private $speaker_repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ITagRepository
|
||||||
|
*/
|
||||||
|
private $tag_repository;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PresentationService constructor.
|
||||||
|
* @param IPresentationVideoFactory $video_factory
|
||||||
|
* @param ISummitEventRepository $presentation_repository
|
||||||
|
* @param ISpeakerRepository $speaker_repository
|
||||||
|
* @param ITagRepository $tag_repository
|
||||||
|
* @param ITransactionService $tx_service
|
||||||
|
*/
|
||||||
public function __construct
|
public function __construct
|
||||||
(
|
(
|
||||||
IPresentationVideoFactory $video_factory,
|
IPresentationVideoFactory $video_factory,
|
||||||
ISummitEventRepository $presentation_repository,
|
ISummitEventRepository $presentation_repository,
|
||||||
ISpeakerRepository $speaker_repository,
|
ISpeakerRepository $speaker_repository,
|
||||||
|
ITagRepository $tag_repository,
|
||||||
ITransactionService $tx_service
|
ITransactionService $tx_service
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
parent::__construct($tx_service);
|
parent::__construct($tx_service);
|
||||||
$this->presentation_repository = $presentation_repository;
|
$this->presentation_repository = $presentation_repository;
|
||||||
$this->speaker_repository = $speaker_repository;
|
$this->speaker_repository = $speaker_repository;
|
||||||
|
$this->tag_repository = $tag_repository;
|
||||||
$this->video_factory = $video_factory;
|
$this->video_factory = $video_factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,19 +298,25 @@ final class PresentationService
|
|||||||
|
|
||||||
$presentation = $summit->getEvent($presentation_id);
|
$presentation = $summit->getEvent($presentation_id);
|
||||||
|
|
||||||
|
|
||||||
if (is_null($presentation))
|
if (is_null($presentation))
|
||||||
throw new EntityNotFoundException(trans(
|
throw new EntityNotFoundException(trans(
|
||||||
'not_found_errors.PresentationService.updatePresentationSubmission.PresentationNotFound',
|
'not_found_errors.PresentationService.updatePresentationSubmission.PresentationNotFound',
|
||||||
['presentation_id' => $presentation_id]
|
['presentation_id' => $presentation_id]
|
||||||
));
|
));
|
||||||
|
|
||||||
|
if (!$presentation instanceof Presentation)
|
||||||
|
throw new EntityNotFoundException(trans(
|
||||||
|
'not_found_errors.PresentationService.updatePresentationSubmission.PresentationNotFound',
|
||||||
|
['presentation_id' => $presentation_id]
|
||||||
|
));
|
||||||
|
|
||||||
if(!$presentation->canEdit($current_speaker))
|
if(!$presentation->canEdit($current_speaker))
|
||||||
throw new ValidationException(trans(
|
throw new ValidationException(trans(
|
||||||
'validation_errors.PresentationService.updatePresentationSubmission.CurrentSpeakerCanNotEditPresentation',
|
'validation_errors.PresentationService.updatePresentationSubmission.CurrentSpeakerCanNotEditPresentation',
|
||||||
['presentation_id' => $presentation_id]
|
['presentation_id' => $presentation_id]
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
||||||
return $this->saveOrUpdatePresentation
|
return $this->saveOrUpdatePresentation
|
||||||
(
|
(
|
||||||
$summit,
|
$summit,
|
||||||
@ -387,6 +409,31 @@ final class PresentationService
|
|||||||
// add me as speaker
|
// add me as speaker
|
||||||
$presentation->addSpeaker($current_speaker);
|
$presentation->addSpeaker($current_speaker);
|
||||||
|
|
||||||
|
if (isset($data['tags'])) {
|
||||||
|
$presentation->clearTags();
|
||||||
|
|
||||||
|
if(count($data['tags']) > 0){
|
||||||
|
if($presentation->getProgress() == Presentation::PHASE_SUMMARY)
|
||||||
|
$presentation->setProgress(Presentation::PHASE_TAGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($data['tags'] as $tag_value) {
|
||||||
|
$tag = $track->getAllowedTagByVal($tag_value);
|
||||||
|
if(is_null($tag)){
|
||||||
|
throw new ValidationException(
|
||||||
|
trans(
|
||||||
|
'validation_errors.PresentationService.saveOrUpdatePresentation.TagNotAllowed',
|
||||||
|
[
|
||||||
|
'tag' => $tag_value,
|
||||||
|
'track_id' => $track->getId()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$presentation->addTag($tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($data['links'])) {
|
if (isset($data['links'])) {
|
||||||
$presentation->clearLinks();
|
$presentation->clearLinks();
|
||||||
|
|
||||||
@ -476,4 +523,46 @@ final class PresentationService
|
|||||||
$this->event_repository->delete($presentation);
|
$this->event_repository->delete($presentation);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Summit $summit
|
||||||
|
* @param int $presentation_id
|
||||||
|
* @param Member $member
|
||||||
|
* @return Presentation
|
||||||
|
* @throws ValidationException
|
||||||
|
* @throws EntityNotFoundException
|
||||||
|
*/
|
||||||
|
public function completePresentationSubmission(Summit $summit, $presentation_id, Member $member)
|
||||||
|
{
|
||||||
|
return $this->tx_service->transaction(function () use ($summit, $member, $presentation_id) {
|
||||||
|
|
||||||
|
$current_speaker = $this->speaker_repository->getByMember($member);
|
||||||
|
if(is_null($current_speaker))
|
||||||
|
throw new EntityNotFoundException(sprintf("member %s does not has a speaker profile", $member->getId()));
|
||||||
|
|
||||||
|
$presentation = $summit->getEvent($presentation_id);
|
||||||
|
if(is_null($presentation))
|
||||||
|
throw new EntityNotFoundException(sprintf("presentation %s not found", $presentation_id));
|
||||||
|
|
||||||
|
if(!$presentation instanceof Presentation)
|
||||||
|
throw new EntityNotFoundException(sprintf("presentation %s not found", $presentation_id));
|
||||||
|
|
||||||
|
if(!$presentation->canEdit($current_speaker))
|
||||||
|
throw new ValidationException(sprintf("member %s can not edit presentation %s",
|
||||||
|
$member->getId(),
|
||||||
|
$presentation_id
|
||||||
|
));
|
||||||
|
|
||||||
|
if($presentation->getProgress() != Presentation::PHASE_SPEAKERS){
|
||||||
|
throw new ValidationException
|
||||||
|
(
|
||||||
|
sprintf("presentation %s is not allowed to mark as completed", $presentation_id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$presentation->setProgress(Presentation::PHASE_COMPLETE);
|
||||||
|
|
||||||
|
return $presentation;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
@ -1691,6 +1691,9 @@ final class SummitService extends AbstractService implements ISummitService
|
|||||||
if (is_null($speaker))
|
if (is_null($speaker))
|
||||||
throw new EntityNotFoundException(sprintf('speaker %s not found', $speaker_id));
|
throw new EntityNotFoundException(sprintf('speaker %s not found', $speaker_id));
|
||||||
|
|
||||||
|
if($presentation->getProgress() == Presentation::PHASE_TAGS)
|
||||||
|
$presentation->setProgress(Presentation::PHASE_SPEAKERS);
|
||||||
|
|
||||||
$presentation->addSpeaker($speaker);
|
$presentation->addSpeaker($speaker);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1732,6 +1735,9 @@ final class SummitService extends AbstractService implements ISummitService
|
|||||||
if (is_null($speaker))
|
if (is_null($speaker))
|
||||||
throw new EntityNotFoundException(sprintf('speaker %s not found', $speaker_id));
|
throw new EntityNotFoundException(sprintf('speaker %s not found', $speaker_id));
|
||||||
|
|
||||||
|
if($presentation->getProgress() == Presentation::PHASE_TAGS)
|
||||||
|
$presentation->setProgress(Presentation::PHASE_SPEAKERS);
|
||||||
|
|
||||||
$presentation->removeSpeaker($speaker);
|
$presentation->removeSpeaker($speaker);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1772,6 +1778,9 @@ final class SummitService extends AbstractService implements ISummitService
|
|||||||
if (is_null($speaker))
|
if (is_null($speaker))
|
||||||
throw new EntityNotFoundException(sprintf('speaker %s not found', $speaker_id));
|
throw new EntityNotFoundException(sprintf('speaker %s not found', $speaker_id));
|
||||||
|
|
||||||
|
if($presentation->getProgress() == Presentation::PHASE_TAGS)
|
||||||
|
$presentation->setProgress(Presentation::PHASE_SPEAKERS);
|
||||||
|
|
||||||
$presentation->setModerator($speaker);
|
$presentation->setModerator($speaker);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1813,6 +1822,9 @@ final class SummitService extends AbstractService implements ISummitService
|
|||||||
if (is_null($speaker))
|
if (is_null($speaker))
|
||||||
throw new EntityNotFoundException(sprintf('speaker %s not found', $speaker_id));
|
throw new EntityNotFoundException(sprintf('speaker %s not found', $speaker_id));
|
||||||
|
|
||||||
|
if($presentation->getProgress() == Presentation::PHASE_TAGS)
|
||||||
|
$presentation->setProgress(Presentation::PHASE_SPEAKERS);
|
||||||
|
|
||||||
$presentation->unsetModerator();
|
$presentation->unsetModerator();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1471,6 +1471,16 @@ class ApiEndpointsSeeder extends Seeder
|
|||||||
sprintf(SummitScopes::WritePresentationData, $current_realm)
|
sprintf(SummitScopes::WritePresentationData, $current_realm)
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'name' => 'complete-submit-presentation',
|
||||||
|
'route' => '/api/v1/summits/{id}/presentations/{presentation_id}/completed',
|
||||||
|
'http_method' => 'PUT',
|
||||||
|
'scopes' => [
|
||||||
|
sprintf(SummitScopes::WriteSummitData, $current_realm),
|
||||||
|
sprintf(SummitScopes::WriteEventData, $current_realm),
|
||||||
|
sprintf(SummitScopes::WritePresentationData, $current_realm)
|
||||||
|
],
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'name' => 'delete-submit-presentation',
|
'name' => 'delete-submit-presentation',
|
||||||
'route' => '/api/v1/summits/{id}/presentations/{presentation_id}',
|
'route' => '/api/v1/summits/{id}/presentations/{presentation_id}',
|
||||||
|
@ -89,6 +89,7 @@ return [
|
|||||||
'PresentationService.updatePresentationSubmission.NotValidSpeaker' => 'Current Member not has a valid speaker profile',
|
'PresentationService.updatePresentationSubmission.NotValidSpeaker' => 'Current Member not has a valid speaker profile',
|
||||||
'PresentationService.updatePresentationSubmission.NotValidSelectionPlan' => 'Current Summit not has a valid selection plan',
|
'PresentationService.updatePresentationSubmission.NotValidSelectionPlan' => 'Current Summit not has a valid selection plan',
|
||||||
'PresentationService.updatePresentationSubmission.CurrentSpeakerCanNotEditPresentation' => 'Current Speaker can not edit :presentation_id presentation',
|
'PresentationService.updatePresentationSubmission.CurrentSpeakerCanNotEditPresentation' => 'Current Speaker can not edit :presentation_id presentation',
|
||||||
|
'PresentationService.saveOrUpdatePresentation.TagNotAllowed' => 'tag :tag is not allowed on track :track_id',
|
||||||
// organizations
|
// organizations
|
||||||
'OrganizationService.addOrganization.alreadyExistName' => 'Organization name :name already exists!',
|
'OrganizationService.addOrganization.alreadyExistName' => 'Organization name :name already exists!',
|
||||||
// track tag groups
|
// track tag groups
|
||||||
|
Loading…
x
Reference in New Issue
Block a user