From 1b3de1aacb61e7e6642cdf70f915f1640f53dad2 Mon Sep 17 00:00:00 2001 From: Dr Masroor Ehsan Date: Sat, 4 Jan 2025 17:56:53 +0600 Subject: [PATCH] wip --- app/DAL/Studies/WorklistBase.php | 9 +++++++- app/DataTables/WorklistDataTable.php | 33 +++++++++++++++++++++++---- app/Models/Study.php | 9 ++++++++ app/helpers.php | 12 ++++++++++ resources/imgs/ct.png | Bin 0 -> 688 bytes resources/imgs/mg.png | Bin 0 -> 648 bytes resources/imgs/mr.png | Bin 0 -> 1278 bytes resources/imgs/us.png | Bin 0 -> 737 bytes resources/imgs/xr.png | Bin 0 -> 788 bytes 9 files changed, 58 insertions(+), 5 deletions(-) create mode 100644 resources/imgs/ct.png create mode 100644 resources/imgs/mg.png create mode 100644 resources/imgs/mr.png create mode 100644 resources/imgs/us.png create mode 100644 resources/imgs/xr.png diff --git a/app/DAL/Studies/WorklistBase.php b/app/DAL/Studies/WorklistBase.php index 28e986b..57eeefd 100644 --- a/app/DAL/Studies/WorklistBase.php +++ b/app/DAL/Studies/WorklistBase.php @@ -42,11 +42,15 @@ abstract class WorklistBase implements IUserStudyLister public function setRadiologist(int $radiologist_id): self { $this->radiologist_id = $radiologist_id; + + return $this; } public function setStudyStatus(StudyLevelStatus $status): self { $this->studyStatus = $status; + + return $this; } private function applyRadiologist(Builder $query): Builder @@ -55,7 +59,7 @@ private function applyRadiologist(Builder $query): Builder $rad = $this->radiologist_id; $query = $query->where(function ($query) use ($rad) { $query->Where('assigned_physician_id', '=', $rad); - $query->orWhere('reading_physician_id', '=', $rad); + $query->orWhere('reporting_physician_id', '=', $rad); }); } @@ -92,6 +96,8 @@ private function applyReportStatus(Builder $query): Builder public function setReportStatus(ReportStatus $status): self { $this->reportStatus = $status; + + return $this; } protected static function reportCompleteQuery(Builder $query): Builder @@ -120,6 +126,7 @@ public function query(?int $user_id = null): Builder { $query = $this->buildQuery($user_id); $query = $this->applySort($query); + $query = $this->applyRadiologist($query); return $query; } diff --git a/app/DataTables/WorklistDataTable.php b/app/DataTables/WorklistDataTable.php index e05c3c1..23c66d4 100644 --- a/app/DataTables/WorklistDataTable.php +++ b/app/DataTables/WorklistDataTable.php @@ -4,7 +4,9 @@ use App\DAL\Studies\WorklistFactory; use App\Models\Study; +use Carbon\Carbon; use Illuminate\Database\Eloquent\Builder as QueryBuilder; +use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; use Yajra\DataTables\EloquentDataTable; use Yajra\DataTables\Html\Builder as HtmlBuilder; @@ -20,12 +22,34 @@ class WorklistDataTable extends DataTable * * @param QueryBuilder $query Results from query() method. */ + // const DATE_FORMAT = 'DD.MM.YYYY HH:mm'; + const DATE_FORMAT = 'DD MMM HH:mm'; + public function dataTable(QueryBuilder $query): EloquentDataTable { return (new EloquentDataTable($query)) ->addColumn('action', 'worklist.action') + ->editColumn('reader', function ($study) { + if ($study->readingPhysician == null) { + return ''; + } + + return ''.$study->readingPhysician->display_name; + }) + ->editColumn('images', function (Study $study) { + return $study->numInstances().'
'.human_filesize($study->disk_size).''; + }) + ->editColumn('study_date', function ($data) { + return Carbon::parse($data->study_date)->isoFormat(self::DATE_FORMAT); + }) + ->editColumn('reported_at', function ($data) { + return Carbon::parse($data->reported_at)->isoFormat(self::DATE_FORMAT); + }) + ->editColumn('received_at', function ($data) { + return Carbon::parse($data->received_at)->isoFormat(self::DATE_FORMAT); + }) ->orderColumn('patient_name', 'patient_name $1') - ->rawColumns(['priority_icon', 'report_status_led']) + ->rawColumns(['priority_icon', 'report_status_led', 'images', 'reader']) ->setRowId('id'); } @@ -81,7 +105,7 @@ public function html(): HtmlBuilder public function getColumns(): array { return [ - Column::checkbox(''), + // Column::checkbox(''), Column::make('priority_icon') ->searchable(false) ->orderable(false) @@ -107,9 +131,10 @@ public function getColumns(): array Column::make('reported_at')->searchable(false)->title('Reported'), Column::make('study_description'), - Column::make('reporting_physician_id'), + Column::make('reader') + ->title('Reader'), // Column::make('body_part_examined'), - Column::make('num_instances') + Column::make('images') ->searchable(false) ->orderable(false) ->addClass('text-center') diff --git a/app/Models/Study.php b/app/Models/Study.php index c6a090a..8d00d76 100644 --- a/app/Models/Study.php +++ b/app/Models/Study.php @@ -9,6 +9,7 @@ use App\Models\Traits\HashableId; use App\Services\Pacs\PacsUrlGen; use Carbon\Carbon; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; @@ -108,6 +109,11 @@ public function numInstances(): string return "{$this->image_count} / {$this->series_count}"; } + public function readingPhysician(): BelongsTo + { + return $this->belongsTo(User::class, 'reporting_physician_id'); + } + public function getReportStatusLedAttribute(): string { $color = match ($this->report_status) { @@ -194,6 +200,9 @@ public function allowed(): array public function toArray(): array { return array_merge(parent::toArray(), [ + 'disk_size_human' => human_filesize($this->disk_size), + 'reader_name' => $this->readingPhysician?->display_name, + 'reader_photo' => $this->readingPhysician?->profile_photo_url, 'report_status_led' => $this->getReportStatusLedAttribute(), 'priority_icon' => $this->getPriorityIcon(), 'sex_age' => $this->sexAge(), diff --git a/app/helpers.php b/app/helpers.php index 52db5aa..d24fc58 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -72,3 +72,15 @@ function may(BackedEnum|iterable|string $perm): bool return auth()->user()->can($perm); } } +if (! function_exists('human_filesize')) { + function human_filesize(int $bytes, $dec = 0): string + { + $size = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + $factor = floor((strlen($bytes) - 1) / 3); + if ($factor == 0) { + $dec = 0; + } + + return sprintf("%.{$dec}f %s", $bytes / (1024 ** $factor), $size[$factor]); + } +} diff --git a/resources/imgs/ct.png b/resources/imgs/ct.png new file mode 100644 index 0000000000000000000000000000000000000000..7be8a5b6c4924b407275aef43b70e55ba543cdbe GIT binary patch literal 688 zcmV;h0#E&kP)mw3k$KZuu)i8 z(3CK885-AYEER@v3DHEdprNsN&S$>)8XxnOg;P)O^Pcyd^FNpW^Su1;k}1Nc8i&!N zfK4gR;CL}foxqeo*z~|X^e!m^pdX%N2JYZ4reZ7Jpb3NU4tw)n+T0hwWG^mAw<=@Fd4+B2GoNld-%2zz?jCrvVbB`k^X< z_WzCJu=rk4Ab2M!#RiFL4{!vnm=wCB*cMea;SfGzEN=WQ$Qe{heY+pJJ!rwgcwdEA z*dopC*53v%lQ{hW({&8)ItJsiH1ryLmpEP>e%qrOI4_Z)OMnd8C8o55z7~zKUo25{ zR8)2j2X)YPA?hN@Ry4-?5xfdtaWI2xSc%#AjD1*w_hCF6bEN?f#QeNqPw_BMSBDp<&;Ad} zq&9uUCR~u(l`mPl+|{>GDH&Xp+R&b(ufznYHJ>6-cUx44hD-!6m_-rNF7Mj@XYv!B WLVAc0q>Io10000(_L`WtLQudgI5=mI7Stz#@ zYnPgAgbm6{F+0&n(Jbu7W#ux%Mwtc+mxWw1qjAe%ES~q6nQy*xoH73O*7^EB@Bg{J z&!KYcMK_*d#W3zwgqiq-3uwoKN-vJ8&~63_c!XD&HOv6Zq8i6U27T$gN5lURACH^( zjuTje&A5^r9T};E14-x_re(NBk=62Y0)@Xgc#0pGiz?i}U3B6DF5(jQ4Kr{s4nMII z)3G1d@lJm)`q26>;!u+Www2%(phaX<5>;im9`s^f4)-ygDWX*Wj9cPSlObS=cK`C6g4|48vO)qIRa;K8*4?=vv??0$RQlZ*YsPHs9UjI zC()H7utWcP*qy_7rMpDqJ5v_wQ(8SKwLYB65opFsEW+p<{!F^tjZb35uP&0y#CYDr zdPBGDQt{ySP+*_~Y*r~ypCm;i}j3`(Mj_4NTUenG^K z1{EYR5d;E8G4T%4TB!Q%e{NtS48HVBFd_G?bya+5T7K?`) z8yjmU%%HisxoU85uw6vLLZPs>v$OMDI-On(JS!rZ39?n7T}0jp!|gwt`KQ4ozp`jfjvONsLM||I(76d^~MBWpT>_nxE=bBXY!ypKbCK8FOqbPb9 zc*pns?W0Z}KqixER#mmuZp&t~S?63UaO(u1m$F(BS)EKK4_a&YC6mdzWHRY`dwWk9 z0Owr2wRUS$Q_~I3x&6TO2|!K(N8;!71nV<^{i#$cX{~)-Rqp^uG&eU__4oIG0g%t< zcZXeiCZ7_$SoUqn6+f}m0usikJK*@bawO6@>J zMa6?{ZEXVpK@iL`#%L~=I~jjhipXA7y{|M#MD7m5@H;>ZBfA0TTuT}FuY-ew54E+m z4P>*~Y!C#Uz#q=J-XI8~bUGbaYx_OVTLtu#2CC{~qr=f%B*4-#6`Q)dyZ_B(GPgPB z4l({jr$prN+_`gSA3JvJoQP~L6SsVHU;t97)O6t5G8Oyd_a@*fpvxF@6L2%o4ODub z_i`-evoeAi4Gj&~j1d@P%75&TwYE1Nr(>e`bGh8_*4p2I58|~9KrWZ-0Scu6i9}-7 z7y-~#M4&Dn#U-y1KgUaduAud7v{E)!y3LItV2_CJ2HTfLDRdz)D71#bRsi zH%wxwRBC}SrWH6PB5$hdMpb=2ilQxJ8N{{|I18)?W~=JKL?SWiZ3QqqJbYADKL%#1 z>PFyi-}iTou8-@I>2&%@5!nsAYmC|8oO{j~v%63zTxpDX)bqS8#bR+??EYt8U*ERs z>gqMa!^3-g-+xI&o>A47D2n!sVvf6Tq9}SxRUfd{wiJuSslemTxuu@xtpHk7wHjEd zs-K9+yqcPt6~OAs%E~EG6s-l8m4aVH5R>d9ZXc@J2?VNI5Bw6l%n*_Fs#@=P-nXT( z*4hK*coz|rnurWBa*7cVji-B@b8CPzg+k$$$>Jv^@H}q__!-CnM^yEvL?SVysy}pe obesXcRMn}#@qvMX;Y;EC2SKUq!R%WjKL7v#07*qoM6N<$g8pz(a{vGU literal 0 HcmV?d00001 diff --git a/resources/imgs/us.png b/resources/imgs/us.png new file mode 100644 index 0000000000000000000000000000000000000000..ae6b014e84e64826670ccaae1442fac115055f09 GIT binary patch literal 737 zcmV<70v`Q|P)wKzD%%;jLY1yY9w?i0P_Da6u|`V}w$0Ly6LrEv^z2(mjhJ5p!I8?P{nYlJ1rZt_+XXZaksU8u%Qe%0GO^v4e02^^CA{Ma+ zKa|*BT+Pgz<3xuFL`2|HX3j;#di;p*@qVHFg5wdfJ2U_4RLD%_JKVq)^bmNn9N-F$ zw7iOcq{OBwtcPWIt;Lp&5Y5b-(@erbX3h@b%wnN%2JKO22j%wxT*u16(^okw3+F)9 z!3rFF!s!sWQxiKx4&qKF5O`@R0@Iksd2AX|cvFeZW4aR9jO#6L6<;-i(j&~jdiM-kx T(vHf}00000NkvXXu0mjfEbUVJ literal 0 HcmV?d00001 diff --git a/resources/imgs/xr.png b/resources/imgs/xr.png new file mode 100644 index 0000000000000000000000000000000000000000..a35994a7c3679a4c96d66107d2c18202ddc3f696 GIT binary patch literal 788 zcmV+v1MB>WP)R0L6cl&&h@IO1cG zE?oIsxF`y-mMV(4lUxXcNP=ZE8qQyF^0hc;oSEPJ{-c2he(<~Jp7TBTJnlKS29xj= z?&GO9Ljy1rM`~~cUt>@jd%GZf84s!e4aVdGuQPQzakv&83I1bREzNFO?1{N9k6Yr$^73{!We4KmF67;$#(RB&jj@z$eU>i2;&dCJb`8Xpk z*8-87Kd>p~24Fijyvjg3z7cgi1XpnyABbebUfjV#ED^1wlDe<-U?)c4A5r6r#bvsS zZ_|U%@NNRHN}MMAT?8vj^7cI4NbEx!4vOSY#|#nkLwSgnl>IApOFft-ZtVrpU-pZ; z@O^^7&zPD2T|Mhp(K*+OaCUj{3Et{ypgs*q&@%cGCq#&vu`Bs)`nHPtqJc76girAc z&f=n|Fru}?9MK}q<5U?)wO%wHqp=1bimJJmCvVRGz4$0)Mx{<4s^-BL*eb$tGy%4W zDMd`ZUAUF&Ln5?Ss~M>1J