From 0d4a17307dacf2ec6f0c2a77c661d0a5b015f771 Mon Sep 17 00:00:00 2001 From: Dr Masroor Ehsan Date: Sat, 25 Jan 2025 22:45:47 +0600 Subject: [PATCH 1/4] wip - bookmarks --- .../Controllers/Staff/BookmarkController.php | 22 +++++++++++ .../Controllers/StudyBookmarkController.php | 38 ------------------- ...25_114600_create_study_bookmarks_table.php | 2 + routes/web.php | 6 +++ 4 files changed, 30 insertions(+), 38 deletions(-) create mode 100644 app/Http/Controllers/Staff/BookmarkController.php delete mode 100644 app/Http/Controllers/StudyBookmarkController.php diff --git a/app/Http/Controllers/Staff/BookmarkController.php b/app/Http/Controllers/Staff/BookmarkController.php new file mode 100644 index 0000000..b162693 --- /dev/null +++ b/app/Http/Controllers/Staff/BookmarkController.php @@ -0,0 +1,22 @@ +validated()); + } + + public function delete(StudyBookmark $studyBookmark) + { + $studyBookmark->delete(); + + return response()->json(); + } +} diff --git a/app/Http/Controllers/StudyBookmarkController.php b/app/Http/Controllers/StudyBookmarkController.php deleted file mode 100644 index 3f0ea02..0000000 --- a/app/Http/Controllers/StudyBookmarkController.php +++ /dev/null @@ -1,38 +0,0 @@ -validated()); - } - - public function show(StudyBookmark $studyBookmark) - { - return $studyBookmark; - } - - public function update(BookmarkCrudRequest $request, StudyBookmark $studyBookmark) - { - $studyBookmark->update($request->validated()); - - return $studyBookmark; - } - - public function destroy(StudyBookmark $studyBookmark) - { - $studyBookmark->delete(); - - return response()->json(); - } -} diff --git a/database/migrations/2025_01_25_114600_create_study_bookmarks_table.php b/database/migrations/2025_01_25_114600_create_study_bookmarks_table.php index d79d654..6c7f5f7 100644 --- a/database/migrations/2025_01_25_114600_create_study_bookmarks_table.php +++ b/database/migrations/2025_01_25_114600_create_study_bookmarks_table.php @@ -2,6 +2,8 @@ use App\Models\Study; use App\Models\User; +use Illuminate\Database\Migrations\Migration; +use Illuminate\Database\Schema\Blueprint; return new class extends Migration { diff --git a/routes/web.php b/routes/web.php index 81f93d1..a0ec46c 100644 --- a/routes/web.php +++ b/routes/web.php @@ -6,6 +6,7 @@ use App\Http\Controllers\Staff\AssignmentController; use App\Http\Controllers\Staff\AttachmentController; use App\Http\Controllers\Staff\AuditLogController; +use App\Http\Controllers\Staff\BookmarkController; use App\Http\Controllers\Staff\DicomViewerController; use App\Http\Controllers\Staff\HistoryController; use App\Http\Controllers\Staff\MetadataController; @@ -85,6 +86,11 @@ Route::group(['prefix' => 'audit', 'as' => 'audit.'], function () { Route::get('popup', [AuditLogController::class, 'popup'])->name('popup'); }); + + Route::group(['prefix' => 'bookmark', 'as' => 'bookmark.'], function () { + Route::post('/', [BookmarkController::class, 'create'])->name('create'); + Route::delete('{hashid}', [BookmarkController::class, 'delete'])->name('delete'); + }); }); }); From 17938e608c59ea59fdc65fc9db7994cc5e311263 Mon Sep 17 00:00:00 2001 From: Dr Masroor Ehsan Date: Sat, 25 Jan 2025 23:53:35 +0600 Subject: [PATCH 2/4] wip - bookmark --- app/DataTables/WorklistDataTable.php | 21 ++++++++++++++++++ app/Domain/ACL/Permission.php | 1 + .../Controllers/Staff/BookmarkController.php | 9 +++++--- app/Http/Requests/BookmarkCrudRequest.php | 4 ++-- app/Models/Study.php | 5 +++++ app/Services/ACL/WorklistButton.php | 1 + app/Services/ACL/WorklistGuard.php | 5 +++++ database/seeders/RoleSeeder.php | 2 ++ resources/imgs/bookmark-delete.png | Bin 0 -> 822 bytes resources/imgs/bookmark.png | Bin 0 -> 1083 bytes .../partials/bookmarks/_create.blade.php | 7 ++++++ .../partials/bookmarks/_delete.blade.php | 7 ++++++ .../partials/bookmarks/_form.blade.php | 8 +++++++ routes/web.php | 2 +- 14 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 resources/imgs/bookmark-delete.png create mode 100644 resources/imgs/bookmark.png create mode 100644 resources/views/staff/worklist/partials/bookmarks/_create.blade.php create mode 100644 resources/views/staff/worklist/partials/bookmarks/_delete.blade.php create mode 100644 resources/views/staff/worklist/partials/bookmarks/_form.blade.php diff --git a/app/DataTables/WorklistDataTable.php b/app/DataTables/WorklistDataTable.php index 6cf8bb5..e99d1e9 100644 --- a/app/DataTables/WorklistDataTable.php +++ b/app/DataTables/WorklistDataTable.php @@ -609,6 +609,27 @@ private function generateActionButtons(Study $study): string case WorklistButton::Audit: $btns[] = $this->renderImageLink($study->hash, 'audit.png', 'show-audit', 'Audit Trail'); break; + case WorklistButton::Bookmark: + if ($study->isBookmarkedBy()) { + $btns[] = Blade::render('staff.worklist.partials.bookmarks._delete', + [ + 'study_id' => $study->id, + 'user_id' => me()->id, + 'url' => route('staff.bookmark.delete'), + 'img' => asset('imgs/bookmark-delete.png'), + 'tip' => 'Remove bookmark', + ]); + } else { + $btns[] = Blade::render('staff.worklist.partials.bookmarks._create', + [ + 'study_id' => $study->id, + 'user_id' => me()->id, + 'url' => route('staff.bookmark.create'), + 'img' => asset('imgs/bookmark.png'), + 'tip' => 'Bookmark study', + ]); + } + break; } } diff --git a/app/Domain/ACL/Permission.php b/app/Domain/ACL/Permission.php index 81853a4..70f4d71 100644 --- a/app/Domain/ACL/Permission.php +++ b/app/Domain/ACL/Permission.php @@ -26,4 +26,5 @@ enum Permission: string case UnassignRadiologist = 'unassign_radiologist'; case AccessAllWorklists = 'access_all_worklists'; case AuditLogView = 'audit_log_view'; + case BookmarkCreate = 'bookmark_create'; } diff --git a/app/Http/Controllers/Staff/BookmarkController.php b/app/Http/Controllers/Staff/BookmarkController.php index b162693..08b1724 100644 --- a/app/Http/Controllers/Staff/BookmarkController.php +++ b/app/Http/Controllers/Staff/BookmarkController.php @@ -10,13 +10,16 @@ class BookmarkController extends Controller { public function create(BookmarkCrudRequest $request) { - return StudyBookmark::create($request->validated()); + StudyBookmark::create($request->validated()); + + return redirect()->route('staff.worklist.index'); } - public function delete(StudyBookmark $studyBookmark) + public function delete(BookmarkCrudRequest $request) { + $studyBookmark = StudyBookmark::where($request->validated())->firstOrFail(); $studyBookmark->delete(); - return response()->json(); + return redirect()->route('staff.worklist.index'); } } diff --git a/app/Http/Requests/BookmarkCrudRequest.php b/app/Http/Requests/BookmarkCrudRequest.php index 1369beb..1a658ae 100644 --- a/app/Http/Requests/BookmarkCrudRequest.php +++ b/app/Http/Requests/BookmarkCrudRequest.php @@ -9,8 +9,8 @@ class BookmarkCrudRequest extends FormRequest public function rules(): array { return [ - 'study_id' => ['required', 'exists:studies'], - 'user_id' => ['required', 'exists:users'], + 'study_id' => ['required', 'exists:studies,id'], + 'user_id' => ['required', 'exists:users,id'], ]; } diff --git a/app/Models/Study.php b/app/Models/Study.php index f61fb8e..6b45321 100644 --- a/app/Models/Study.php +++ b/app/Models/Study.php @@ -443,6 +443,11 @@ public function isReadBy(User|int|null $user = null): bool return $this->reading_physician_id === me($user)->id; } + public function isBookmarkedBy(User|int|null $user = null): bool + { + return $this->bookmarkedByUsers()->where('user_id', me($user)->id)->exists(); + } + /** * Returns true if study has been locked by the given user or is unlocked. Returns false if the study was locked by another user. */ diff --git a/app/Services/ACL/WorklistButton.php b/app/Services/ACL/WorklistButton.php index 0825814..2066456 100644 --- a/app/Services/ACL/WorklistButton.php +++ b/app/Services/ACL/WorklistButton.php @@ -11,4 +11,5 @@ enum WorklistButton: string case Assign = 'assign'; case Report = 'report'; case Audit = 'audit'; + case Bookmark = 'bookmark'; } diff --git a/app/Services/ACL/WorklistGuard.php b/app/Services/ACL/WorklistGuard.php index ccfdbab..16b923f 100644 --- a/app/Services/ACL/WorklistGuard.php +++ b/app/Services/ACL/WorklistGuard.php @@ -58,6 +58,7 @@ public static function worklistButtons(Study $study, User|int|null $usr = null): WorklistButton::StudyMetadata, WorklistButton::Notes, // WorklistButton::Audit, + WorklistButton::Bookmark, ]); } @@ -75,6 +76,10 @@ public static function worklistButtons(Study $study, User|int|null $usr = null): $buttons->push(WorklistButton::Audit); } + if (may(Permission::BookmarkCreate)) { + $buttons->push(WorklistButton::Bookmark); + } + return $buttons; } } diff --git a/database/seeders/RoleSeeder.php b/database/seeders/RoleSeeder.php index df693c9..1a90702 100644 --- a/database/seeders/RoleSeeder.php +++ b/database/seeders/RoleSeeder.php @@ -34,6 +34,7 @@ public function run(): void Permission::StudyNotesCreate, Permission::StudyNotesView, Permission::AttachmentDownload, + Permission::BookmarkCreate, ]); $tech->givePermissionTo([ @@ -49,6 +50,7 @@ public function run(): void Permission::StudyArchive, Permission::ReportDownload, Permission::AuditLogView, + Permission::BookmarkCreate, ]); $adm->givePermissionTo(SpatiePermission::all()); diff --git a/resources/imgs/bookmark-delete.png b/resources/imgs/bookmark-delete.png new file mode 100644 index 0000000000000000000000000000000000000000..a18504a60749f9dfdf30e20269780d0f8b0afd4f GIT binary patch literal 822 zcmV-61Ihe}P)eo} zK~z|U&DYOs6G0Tf@$c+znxswBB>e$JXe(42O{JAy^x~mP74#(Hp*O*kC_Q))gd$2o z=tWRG3H}4to1kI|h@M(JSgS1vMQK$U)89$cG}-a6o0@Ku=GUh9V991@-g}>!(+vD4 z@gA4}S}fmNff3*n5Cde9&j#=jxSykD&X_b4r?L`yfz=Y4=6lwF%lR4$^S2oo2aW?X zKtJ&NwC4Vx3FXu+SAY|mizcBKvlwDhXEK%GVPc7w+Z&jWE5P%7fL#ayvu@~*!LRMc zuE$7my{OJP;=yK=;mrsbJJAV5vd5LI_Xuzn_$Hw%plF{x(Bg>B-ayDF_puw3#|+bu7;em4m1kJ8kNV0RYe}R9<`A=vJNl)Kfm6qD@zV z$QOA52Zh)da1e-sfNCR(0#p-GG@x3Dk^t2}lnk&NQ5L{XMA-nl5ETLJKvWE<6k!XX z5`=AlLWuJY&y;O|RjD(UTxT>9Wi%0GEV<5_)OQfC>e~pJh|J0ABb$GCwzW#kY?z5Up>WmNz#VrJjY4HnPjhbl2h-^-4k_Bwik>}UOCxtIC}vF5fYFdp=1)`z+J#yMDt9z&78QUR#AxTi7$YT5*k~h!>nO# zE-~(+IU|g586Bvgu{8$FnqiEUPXO<1tY3co1**b;B-|4XDgXcg07*qoM6N<$f|#vs A*Z=?k literal 0 HcmV?d00001 diff --git a/resources/imgs/bookmark.png b/resources/imgs/bookmark.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d79fb42cdd1ac45dcf8d880e9a8445c88ddb4d GIT binary patch literal 1083 zcmV-B1jPG^P))M=*14ULJ?kt~C0Bn@RQb{hVi6j_^X zje4cM9=-PN_QJ$$>!M8wg2_%2j9Fyz3ihb2m7z9BP)w}8n>8`H%haYdO99~J6eJ#mFu7-y zC<)WlY>z?xPK8+P;=rS)Gh_f#jssBSOf`?{;8N--z=8qflnCG92KWv)Ku(EE55Ri5 zP%QaSEcw8Cx)uzez6<7&oJwN!y8{?Fx&{Q1f%V%yMM=$8WEx1_SqrKF+t-aMw;3-u z&2SZFqk6RkY+v_6qO?^Y=<^^vd>KOMS8zcVgcQfgFRC8TA8cNM>UTcEcuyOw%S*sG z%3!ao!}2vXiwB6`55afnEwneUfNPT(uA&#=urvSgloVtk)LV;CSisn16l3>>@cyAQ z$USl!Af8(s0A;p;H0L2DXJW(J{5ic2I|GNE!JR-1l*JA*I~R!0oj>n4Ko}`(Y`c#A zXYQl(^!R*s96itClT&}7djF3gjQ?u=`T+odw&r6)+ck9bL~zzKmDYFGGlc`^IBaYm z#4|RBmT2v}fVSA-tZPO8O)jmc|0V}#T`OpdU2CkqZ5aRU7Tiuc?R-Ts1tEA#PozEo zesUP)r4|4{C@i3*!;h8@KSE*Q5rE5zSYY_c0dPSUHY!%JbphyV#f7iDf%Q#aqqKG_YLD#$X|e(UN;fs*r*GTvRZ|ySufMGeK>bKY z(!!QYLi(4jL%xWDgbc7v=9DxOGtQp>|DFe)0sw%>a}fFTjp>O3jQ5?8E;Kr$7aE<> z@xBw%k^u-0f5-P9)Tl`{-TPwymxA%C<(ACygr}=RD|HOX+5EwWw^=w-i{nJ0t zF7lB|0HXi`A|H7%wp2EPvEwP7zU+#!8?o9v_vn-07 zOdOMwiQb{^z278f;>*f6?=IAmJ$D5Z1tV9#lrQaYM<0xOKM1T@y(@vaa&o z-K9UD`uOyir%P8g9*ZF9nfj9fCBLj{nl$AM0w~g-f&$W%GnnmuE#*8ip%AnwrTI?A zlGkHkvbanmwH;~NwMJza8FRBC%ND1fef|eE!(U->UOPRQR + @include('_partials._img-tooltip', ['src' => $img, 'class' => $class ?? 'msg-icon', 'tip' => $tip]) + @include('staff.worklist.partials.bookmarks._form', ['form_id' => $form_id, 'url' => $url, 'study_id' => $study_id, 'user_id' => $user_id, 'delete' => false]) + diff --git a/resources/views/staff/worklist/partials/bookmarks/_delete.blade.php b/resources/views/staff/worklist/partials/bookmarks/_delete.blade.php new file mode 100644 index 0000000..e25defa --- /dev/null +++ b/resources/views/staff/worklist/partials/bookmarks/_delete.blade.php @@ -0,0 +1,7 @@ +@php + $form_id = 'bm-del_' . $study_id; +@endphp + + @include('_partials._img-tooltip', ['src' => $img, 'class' => $class ?? 'msg-icon', 'tip' => $tip]) + @include('staff.worklist.partials.bookmarks._form', ['form_id' => $form_id, 'url' => $url, 'study_id' => $study_id, 'user_id' => $user_id, 'delete' => true]) + diff --git a/resources/views/staff/worklist/partials/bookmarks/_form.blade.php b/resources/views/staff/worklist/partials/bookmarks/_form.blade.php new file mode 100644 index 0000000..e8028f7 --- /dev/null +++ b/resources/views/staff/worklist/partials/bookmarks/_form.blade.php @@ -0,0 +1,8 @@ + diff --git a/routes/web.php b/routes/web.php index a0ec46c..75abe74 100644 --- a/routes/web.php +++ b/routes/web.php @@ -89,7 +89,7 @@ Route::group(['prefix' => 'bookmark', 'as' => 'bookmark.'], function () { Route::post('/', [BookmarkController::class, 'create'])->name('create'); - Route::delete('{hashid}', [BookmarkController::class, 'delete'])->name('delete'); + Route::delete('/', [BookmarkController::class, 'delete'])->name('delete'); }); }); From 8780175d20721b0dc1fd6b56bcf32202dd0b66d4 Mon Sep 17 00:00:00 2001 From: Dr Masroor Ehsan Date: Sun, 26 Jan 2025 00:00:46 +0600 Subject: [PATCH 3/4] wip bookmarks --- app/DataTables/WorklistDataTable.php | 5 +++++ resources/views/staff/worklist/partials/_nav-top.blade.php | 1 + 2 files changed, 6 insertions(+) diff --git a/app/DataTables/WorklistDataTable.php b/app/DataTables/WorklistDataTable.php index e99d1e9..9086b4a 100644 --- a/app/DataTables/WorklistDataTable.php +++ b/app/DataTables/WorklistDataTable.php @@ -337,6 +337,11 @@ private function filterStatus(QueryBuilder $query, ?string $status): void case 'orphan': $query->whereNull('assigned_at'); break; + case 'bookmark': + $query->whereHas('bookmarkedByUsers', function ($q) { + $q->where('user_id', auth()->id()); + }); + break; } } diff --git a/resources/views/staff/worklist/partials/_nav-top.blade.php b/resources/views/staff/worklist/partials/_nav-top.blade.php index f64ceab..e3b1908 100644 --- a/resources/views/staff/worklist/partials/_nav-top.blade.php +++ b/resources/views/staff/worklist/partials/_nav-top.blade.php @@ -7,6 +7,7 @@ @include('staff.worklist.partials._nav-item', ['id' => 'nav__orphan', 'text' => 'Unassigned', 'active' => '', 'icon' => 'price-tag-3-line', 'tip' => 'Unassigned studies']) @include('staff.worklist.partials._nav-item', ['id' => 'nav__assigned', 'text' => 'Assigned', 'active' => '', 'icon' => 'team-line', 'tip' => 'Studies assigned to radiologists']) @endif + @include('staff.worklist.partials._nav-item', ['id' => 'nav__bookmark', 'text' => 'Bookmarked', 'active' => '', 'icon' => 'bookmark-line', 'tip' => 'Bookmarked studies']) @include('staff.worklist.partials._nav-item', ['id' => 'nav__all', 'text' => 'All', 'active' => '', 'icon' => 'stack-line', 'tip' => 'All studies']) From 2a61d0b0209dfcca664908cebb5c517fc8e79a58 Mon Sep 17 00:00:00 2001 From: Dr Masroor Ehsan Date: Sun, 26 Jan 2025 00:07:40 +0600 Subject: [PATCH 4/4] FIX #32 - bookmark module --- app/Http/Controllers/Staff/BookmarkController.php | 5 +++++ app/Services/AuditTrail/Activity.php | 2 ++ 2 files changed, 7 insertions(+) diff --git a/app/Http/Controllers/Staff/BookmarkController.php b/app/Http/Controllers/Staff/BookmarkController.php index 08b1724..cffa248 100644 --- a/app/Http/Controllers/Staff/BookmarkController.php +++ b/app/Http/Controllers/Staff/BookmarkController.php @@ -5,6 +5,7 @@ use App\Http\Controllers\Controller; use App\Http\Requests\BookmarkCrudRequest; use App\Models\StudyBookmark; +use App\Services\AuditTrail\Activity; class BookmarkController extends Controller { @@ -12,6 +13,8 @@ public function create(BookmarkCrudRequest $request) { StudyBookmark::create($request->validated()); + audit()->did(Activity::Study_Bookmark)->on($request->study_id)->log(); + return redirect()->route('staff.worklist.index'); } @@ -20,6 +23,8 @@ public function delete(BookmarkCrudRequest $request) $studyBookmark = StudyBookmark::where($request->validated())->firstOrFail(); $studyBookmark->delete(); + audit()->did(Activity::Study_Unmark)->on($request->study_id)->log(); + return redirect()->route('staff.worklist.index'); } } diff --git a/app/Services/AuditTrail/Activity.php b/app/Services/AuditTrail/Activity.php index c76e0dc..88a057b 100644 --- a/app/Services/AuditTrail/Activity.php +++ b/app/Services/AuditTrail/Activity.php @@ -28,6 +28,8 @@ enum Activity: int case Attachment_Upload = 112; case Attachment_Download = 113; case Attachment_Delete = 114; + case Study_Bookmark = 115; + case Study_Unmark = 116; // image case Image_Download = 150;