From eab335d34c4a92d46b26909219b85e7e4bf70c14 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Thu, 9 Jan 2025 02:33:06 +0800 Subject: [PATCH] Admin Workflow - Admin UI to search and export data --- .../General/Eloquent/Filters/AnswerLike.php | 22 +++ .../General/Eloquent/Filters/WithAnswers.php | 10 +- .../ExportQAWithGroupsLogic.php | 64 +++++++ ...gic.php => ExportQAWithoutGroupsLogic.php} | 21 +-- ...onsAnswers.php => ExportsQAWithGroups.php} | 5 +- .../Services/ExportsQAWithoutGroups.php | 80 ++++++++ .../ValueObjects/Constants/QuestionGroup.php | 26 +-- .../ExportQuestionsAnswersController.php | 17 +- .../Resources/QuestionnaireSetsResource.php | 2 +- .../Resources/QuestionsAnswersResource.php | 9 +- database/seeds/QAWorkFlowSeeder.php | 2 +- .../elements/QuestionAnswer2Component.vue | 172 ++++++++++++++++++ .../elements/QuestionAnswerComponent.vue | 4 +- .../elements/QuestionAnswerInnerComponent.vue | 70 ++++--- .../QuestionAnswerSection2Component.vue | 154 ++++++++++++++++ .../QuestionAnswerSectionComponent.vue | 30 +-- .../admin-workflow/list-workflow.blade.php | 44 ++++- routes/questionnaires.php | 3 +- 18 files changed, 632 insertions(+), 103 deletions(-) create mode 100644 app/Classes/General/Eloquent/Filters/AnswerLike.php create mode 100644 app/Classes/Modules/Exports/ControllersLogic/ExportQAWithGroupsLogic.php rename app/Classes/Modules/Exports/ControllersLogic/{ExportQuestionsAnswersLogic.php => ExportQAWithoutGroupsLogic.php} (64%) rename app/Classes/Modules/Exports/Services/{ExportsQuestionsAnswers.php => ExportsQAWithGroups.php} (93%) create mode 100644 app/Classes/Modules/Exports/Services/ExportsQAWithoutGroups.php create mode 100644 resources/assets/vue/components/admin-workflow/elements/QuestionAnswer2Component.vue create mode 100644 resources/assets/vue/components/admin-workflow/sections/QuestionAnswerSection2Component.vue diff --git a/app/Classes/General/Eloquent/Filters/AnswerLike.php b/app/Classes/General/Eloquent/Filters/AnswerLike.php new file mode 100644 index 00000000..2c197501 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/AnswerLike.php @@ -0,0 +1,22 @@ +where('answer', 'like', '%' . $value . '%') + ->orWhereHas('answer', function ($subquery) use($value){ + $subquery->where('display_text', 'like', '%' . $value . '%'); + }); + } +} diff --git a/app/Classes/General/Eloquent/Filters/WithAnswers.php b/app/Classes/General/Eloquent/Filters/WithAnswers.php index a8ff3bb9..1cce3d2a 100644 --- a/app/Classes/General/Eloquent/Filters/WithAnswers.php +++ b/app/Classes/General/Eloquent/Filters/WithAnswers.php @@ -2,9 +2,8 @@ namespace App\Classes\General\Eloquent\Filters; -use App\Classes\ValueObjects\Constants\QuestionGroup; -use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Builder; class WithAnswers implements Filter { @@ -16,12 +15,7 @@ class WithAnswers implements Filter public static function apply(Builder $builder, $value) { return $builder->where(function ($query) use($value){ - if($value){ - $query->where('answer', '=', $value); - } - else{ - $query->whereIn('answer', QuestionGroup::QUESTION_GROUPS); - } + $query->whereIn('answer', $value); }); } } diff --git a/app/Classes/Modules/Exports/ControllersLogic/ExportQAWithGroupsLogic.php b/app/Classes/Modules/Exports/ControllersLogic/ExportQAWithGroupsLogic.php new file mode 100644 index 00000000..1f8d0ffb --- /dev/null +++ b/app/Classes/Modules/Exports/ControllersLogic/ExportQAWithGroupsLogic.php @@ -0,0 +1,64 @@ + 'Export Questions & Answers', + 'message' => 'You have successfully exported data' + ]; + } + + /** @var ExportsQAWithGroups */ + private $exportsQAWithGroups; + + /** @var CanExportQuestionsAnswers */ + private $canExport; + + /** + * ExportQAWithGroupsLogic constructor. + * @param ExportsQAWithGroups $exportsQAWithGroups + * @param CanExportQuestionsAnswers $canExport + */ + public function __construct(ExportsQAWithGroups $exportsQAWithGroups, CanExportQuestionsAnswers $canExport) + { + $this->exportsQAWithGroups = $exportsQAWithGroups; + $this->canExport = $canExport; + } + + + /** + * @param Request $request + * @return Response + */ + public function logic(Request $request) : JsonResponse + { + $this->canExport->passes(); + + $this->exportsQAWithGroups->setFilters(Helper::deserializeFilters($request->input('filters'))); + + $exportFileName = 'qas.xls'; + $filesystemDriver = Storage::getDefaultDriver(); + if($filesystemDriver === 's3'){ + return $this->response([ 'src' => AWSS3Helper::S3Exportable($exportFileName, $this->exportsQAWithGroups) ]); + } + + return $this->response([ 'src' => null ]); + } + +} diff --git a/app/Classes/Modules/Exports/ControllersLogic/ExportQuestionsAnswersLogic.php b/app/Classes/Modules/Exports/ControllersLogic/ExportQAWithoutGroupsLogic.php similarity index 64% rename from app/Classes/Modules/Exports/ControllersLogic/ExportQuestionsAnswersLogic.php rename to app/Classes/Modules/Exports/ControllersLogic/ExportQAWithoutGroupsLogic.php index 4c8c1500..b67f1098 100644 --- a/app/Classes/Modules/Exports/ControllersLogic/ExportQuestionsAnswersLogic.php +++ b/app/Classes/Modules/Exports/ControllersLogic/ExportQAWithoutGroupsLogic.php @@ -4,7 +4,7 @@ namespace App\Classes\Modules\Exports\ControllersLogic; use App\Classes\General\Abstracts\AbstractControllerLogic; -use App\Classes\Modules\Exports\Services\ExportsQuestionsAnswers; +use App\Classes\Modules\Exports\Services\ExportsQAWithoutGroups; use App\Classes\Modules\Exports\Standards\Rules\CanExportQuestionsAnswers; use Illuminate\Http\Request; use App\Classes\General\AWSS3Helper; @@ -13,7 +13,7 @@ use Illuminate\Support\Facades\Storage; use Illuminate\Http\JsonResponse; -class ExportQuestionsAnswersLogic extends AbstractControllerLogic +class ExportQAWithoutGroupsLogic extends AbstractControllerLogic { /** * @return array @@ -25,20 +25,20 @@ class ExportQuestionsAnswersLogic extends AbstractControllerLogic ]; } - /** @var ExportsQuestionsAnswers */ - private $exportsQuestionsAnswers; + /** @var ExportsQAWithoutGroups */ + private $exportsQAWithoutGroups; /** @var CanExportQuestionsAnswers */ private $canExport; /** - * ExportFeedbackDataLogic constructor. - * @param ExportsQuestionsAnswers $exportsQuestionsAnswers + * ExportQAWithoutGroupsLogic constructor. + * @param ExportsQAWithoutGroups $exportsQAWithoutGroups * @param CanExportQuestionsAnswers $canExport */ - public function __construct(ExportsQuestionsAnswers $exportsQuestionsAnswers, CanExportQuestionsAnswers $canExport) + public function __construct(ExportsQAWithoutGroups $exportsQAWithoutGroups, CanExportQuestionsAnswers $canExport) { - $this->exportsQuestionsAnswers = $exportsQuestionsAnswers; + $this->exportsQAWithoutGroups = $exportsQAWithoutGroups; $this->canExport = $canExport; } @@ -51,15 +51,14 @@ class ExportQuestionsAnswersLogic extends AbstractControllerLogic { $this->canExport->passes(); - $this->exportsQuestionsAnswers->setFilters(Helper::deserializeFilters($request->input('filters'))); + $this->exportsQAWithoutGroups->setFilters(Helper::deserializeFilters($request->input('filters'))); $exportFileName = 'qas.xls'; $filesystemDriver = Storage::getDefaultDriver(); if($filesystemDriver === 's3'){ - return $this->response([ 'src' => AWSS3Helper::S3Exportable($exportFileName, $this->exportsQuestionsAnswers) ]); + return $this->response([ 'src' => AWSS3Helper::S3Exportable($exportFileName, $this->exportsQAWithoutGroups) ]); } return $this->response([ 'src' => null ]); } - } diff --git a/app/Classes/Modules/Exports/Services/ExportsQuestionsAnswers.php b/app/Classes/Modules/Exports/Services/ExportsQAWithGroups.php similarity index 93% rename from app/Classes/Modules/Exports/Services/ExportsQuestionsAnswers.php rename to app/Classes/Modules/Exports/Services/ExportsQAWithGroups.php index 6c12713e..5ef09b89 100644 --- a/app/Classes/Modules/Exports/Services/ExportsQuestionsAnswers.php +++ b/app/Classes/Modules/Exports/Services/ExportsQAWithGroups.php @@ -15,7 +15,7 @@ use App\Classes\General\Eloquent\ApplyFiltersToQuery; use App\Classes\ValueObjects\Constants\QuestionGroup; use Carbon\Carbon; -class ExportsQuestionsAnswers implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize +class ExportsQAWithGroups implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize { use Exportable; @@ -63,6 +63,7 @@ class ExportsQuestionsAnswers implements FromQuery, WithHeadings, WithHeadingRow $source = $userAnswer->userSource; $user = $userAnswer->source_id === 0 ? $userAnswer->user : null; $answer = $userAnswer->answer()->first(); + $questionGroups = explode(',', $userAnswer->question->questionnaire->group); $rows = [[ $userAnswer->id, $userAnswer->question->questionnaire->version, @@ -78,7 +79,7 @@ class ExportsQuestionsAnswers implements FromQuery, WithHeadings, WithHeadingRow $nextId = QAUserAnswerSelected::where('id', '>', $userAnswer->id) - ->whereIn('answer', QuestionGroup::QUESTION_GROUPS) + ->whereIn('answer', $questionGroups) ->orderBy('id', 'asc') ->limit(1) ->value('id'); diff --git a/app/Classes/Modules/Exports/Services/ExportsQAWithoutGroups.php b/app/Classes/Modules/Exports/Services/ExportsQAWithoutGroups.php new file mode 100644 index 00000000..410f0ecc --- /dev/null +++ b/app/Classes/Modules/Exports/Services/ExportsQAWithoutGroups.php @@ -0,0 +1,80 @@ +filters = $filters; + } + + /** + * @return \Illuminate\Support\Collection|mixed + */ + public function query() + { + $data = (new ApplyFiltersToQuery())->execute(QAUserAnswerSelected::query(), $this->filters, true); + + return $data; + } + + /** + * @param QAUserAnswerSelected $userAnswer + * + * @return array + */ + public function map($userAnswer): array + { + $source = $userAnswer->userSource; + $user = $userAnswer->source_id === 0 ? $userAnswer->user : null; + $answer = $userAnswer->answer()->first(); + $questionGroups = explode(',', $userAnswer->question->questionnaire->group); + $rows = [[ + $userAnswer->id, + $userAnswer->question->questionnaire->version, + $userAnswer->question->questionnaire->description, + $userAnswer->question->question_title, + $answer ? $answer->display_text : null, + $answer ? $answer->value : null, + $user ? $user->email : $source->email, + $userAnswer->time_used_seconds, + Carbon::parse($userAnswer->created_at)->format('d-m-Y'), + $answer ? in_array($answer->value, $questionGroups) : false, + ]]; + + return $rows; + } +} diff --git a/app/Classes/ValueObjects/Constants/QuestionGroup.php b/app/Classes/ValueObjects/Constants/QuestionGroup.php index 3491792d..2fa7a0a8 100644 --- a/app/Classes/ValueObjects/Constants/QuestionGroup.php +++ b/app/Classes/ValueObjects/Constants/QuestionGroup.php @@ -4,19 +4,19 @@ namespace App\Classes\ValueObjects\Constants; final class QuestionGroup { - public const _1688 = '1688'; - public const APPROVE_PO = 'approve_po'; - public const FILL_PO = 'fill_po'; + // public const _1688 = '1688'; + // public const APPROVE_PO = 'approve_po'; + // public const FILL_PO = 'fill_po'; - const OPTIONS_QUESTION_GROUP = [ - ['text' => '1688', 'id' => QuestionGroup::_1688], - ['text' => 'approve_po', 'id' => QuestionGroup::APPROVE_PO], - ['text' => 'fill_po', 'id' => QuestionGroup::FILL_PO], - ]; + // const OPTIONS_QUESTION_GROUP = [ + // ['text' => '1688', 'id' => QuestionGroup::_1688], + // ['text' => 'approve_po', 'id' => QuestionGroup::APPROVE_PO], + // ['text' => 'fill_po', 'id' => QuestionGroup::FILL_PO], + // ]; - const QUESTION_GROUPS = [ - QuestionGroup::_1688, - QuestionGroup::APPROVE_PO, - QuestionGroup::FILL_PO, - ]; + // const QUESTION_GROUPS = [ + // QuestionGroup::_1688, + // QuestionGroup::APPROVE_PO, + // QuestionGroup::FILL_PO, + // ]; } diff --git a/app/Http/Controllers/Exports/ExportQuestionsAnswersController.php b/app/Http/Controllers/Exports/ExportQuestionsAnswersController.php index 58c05a5d..92262915 100644 --- a/app/Http/Controllers/Exports/ExportQuestionsAnswersController.php +++ b/app/Http/Controllers/Exports/ExportQuestionsAnswersController.php @@ -3,7 +3,8 @@ namespace App\Http\Controllers\Exports; -use App\Classes\Modules\Exports\ControllersLogic\ExportQuestionsAnswersLogic; +use App\Classes\Modules\Exports\ControllersLogic\ExportQAWithGroupsLogic; +use App\Classes\Modules\Exports\ControllersLogic\ExportQAWithoutGroupsLogic; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\BinaryFileResponse; use Illuminate\Http\JsonResponse; @@ -12,11 +13,21 @@ class ExportQuestionsAnswersController { /** * @param Request $request - * @param ExportQuestionsAnswersLogic $logic + * @param ExportQAWithGroupsLogic $logic * @return BinaryFileResponse * @return JsonResponse */ - public function export(Request $request, ExportQuestionsAnswersLogic $logic) { + public function exportWithGroups(Request $request, ExportQAWithGroupsLogic $logic) { return $logic->execute($request); } + + /** + * @param Request $request + * @param ExportQAWithoutGroupsLogic $logic + * @return BinaryFileResponse + * @return JsonResponse + */ + public function exportWithoutGroups(Request $request, ExportQAWithoutGroupsLogic $logic) { + return $logic->execute($request); + } } diff --git a/app/Http/Resources/QuestionnaireSetsResource.php b/app/Http/Resources/QuestionnaireSetsResource.php index 5072a2a6..0865de6d 100644 --- a/app/Http/Resources/QuestionnaireSetsResource.php +++ b/app/Http/Resources/QuestionnaireSetsResource.php @@ -19,7 +19,7 @@ class QuestionnaireSetsResource extends JsonResource 'id' => $this->id, 'name' => $this->name, 'description' => $this->description, - 'group' => $this->group, + 'group' => explode(',', $this->group), 'version' => $this->version, ]; } diff --git a/app/Http/Resources/QuestionsAnswersResource.php b/app/Http/Resources/QuestionsAnswersResource.php index f5bf38f6..45fcae0c 100644 --- a/app/Http/Resources/QuestionsAnswersResource.php +++ b/app/Http/Resources/QuestionsAnswersResource.php @@ -4,7 +4,6 @@ namespace App\Http\Resources; use App\Classes\ValueObjects\Constants\DocumentType; -use App\Classes\ValueObjects\Constants\QuestionGroup; use Illuminate\Http\Resources\Json\JsonResource; use App\Models\QAAnswerOptions; use App\Models\QAQuestions; @@ -24,17 +23,13 @@ class QuestionsAnswersResource extends JsonResource $source = new UserSourceResource($this->userSource); $user = $this->source_id === 0 ? new UserResource($this->user) : null; $answerOption = QAAnswerOptions::where('id', $this->answer_option_id)->first(); - + $questionGroups = explode(',', $this->question->questionnaire->group); $user_marking = ''; - // if($user){ - // $companyModule = $user->companyModule()->first(); - // $user_marking = $companyModule ? $companyModule->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference : ""; - // } return [ 'id' => $this->id, 'question_id' => $this->question_id, - 'question_groups' => QuestionGroup::QUESTION_GROUPS, + 'question_groups' => $questionGroups, 'questionnaire' => new QuestionnaireSetsResource($this->question->questionnaire), 'question_title' => $question ? $question->question_title : null, 'question_type' => $question ? $question->question_type : 0, diff --git a/database/seeds/QAWorkFlowSeeder.php b/database/seeds/QAWorkFlowSeeder.php index 3fce1e65..c57ad4b1 100644 --- a/database/seeds/QAWorkFlowSeeder.php +++ b/database/seeds/QAWorkFlowSeeder.php @@ -22,7 +22,7 @@ class QAWorkFlowSeeder extends Seeder [ 'name' => 'Admin Work Flow', 'description' => 'Admin Work Flow', - 'group' => 'workflow', + 'group' => '1688,approve_po,fill_po', 'version' => 1, 'questions' => [ [ diff --git a/resources/assets/vue/components/admin-workflow/elements/QuestionAnswer2Component.vue b/resources/assets/vue/components/admin-workflow/elements/QuestionAnswer2Component.vue new file mode 100644 index 00000000..da571a3b --- /dev/null +++ b/resources/assets/vue/components/admin-workflow/elements/QuestionAnswer2Component.vue @@ -0,0 +1,172 @@ + + + diff --git a/resources/assets/vue/components/admin-workflow/elements/QuestionAnswerComponent.vue b/resources/assets/vue/components/admin-workflow/elements/QuestionAnswerComponent.vue index e10b4223..f8a52d20 100644 --- a/resources/assets/vue/components/admin-workflow/elements/QuestionAnswerComponent.vue +++ b/resources/assets/vue/components/admin-workflow/elements/QuestionAnswerComponent.vue @@ -1,7 +1,7 @@