$dt->format(self::DATE_FORMAT_SHORT), 'subtitle' => $dt->diffForHumans(), ] ); } public function dataTable(QueryBuilder $query): EloquentDataTable { $data_table = new EloquentDataTable($query); $rawColumns = [ 'priority_icon', 'report_status_led', ]; foreach ($this->renderCustomColumns() as $column => $content) { $data_table->addColumn($column, $content); $rawColumns[] = $column; } $data_table ->orderColumn(WorklistColumn::PatientName->value, sprintf('%s $1', WorklistColumn::PatientName->value)) ->rawColumns($rawColumns) ->setRowId('id'); return $data_table; } /** * Get the query source of dataTable. */ public function query(Study $model): QueryBuilder { return WorklistFactory::getLister()->query(); // return $model->newQuery(); } /** * Optional method if you want to use the html builder. */ public function html(): HtmlBuilder { return $this->builder() ->setTableId('worklist-table') ->columns($this->getColumns()) ->minifiedAjax() ->searchPanes(SearchPane::make(['show' => true, 'hideCount' => true])) ->parameters( [ // 'dom' => 'Pfrtip', // 'dom' => 'Bfrtip', 'buttons' => [ 'searchPanes', 'excel', // 'csv', // 'pdf', // 'print', // 'reset', // 'reload', ], 'order' => [ [0, 'desc'], [8, 'desc'], ], ]) // ->selectStyleSingle() ->pageLength(15) ->lengthMenu([15, 25, 50, 100, 250]); } /** * Get the dataTable columns definition. */ public function getColumns(): array { $columns = []; foreach (WorklistGuard::worklistColumns() as $col) { switch ($col) { case WorklistColumn::Priority: $columns[] = Column::make($col->value) ->searchable(false) ->hidden(); $columns[] = Column::make('priority_icon') ->searchable(false) ->orderable(false) ->addClass('text-center p-0 ps-1') ->width('18px') ->title(''); break; case WorklistColumn::ReportStatus: $columns[] = Column::make($col->value) ->searchable(false) ->hidden(); $columns[] = Column::make('report_status_led') ->searchable(false) ->orderable(false) ->addClass('text-center p-0 ps-2') ->width('18px') ->title(''); break; case WorklistColumn::History: $columns[] = Column::make($col->value) ->searchable(false) ->orderable(false) ->addClass('text-center') ->width('16px') ->title(''); break; case WorklistColumn::PatientSexAge: $columns[] = Column::make($col->value) ->searchable(false) ->orderable(false) ->addClass('text-center') ->title('Age'); break; case WorklistColumn::StudyDate: $columns[] = Column::make($col->value)->searchable(false)->title('Scanned'); break; case WorklistColumn::ReceiveDate: $columns[] = Column::make($col->value)->searchable(false)->title('Received'); break; case WorklistColumn::ReportDate: $columns[] = Column::make($col->value)->searchable(false)->title('Read At'); break; case WorklistColumn::AssignedPhysician: $columns[] = Column::make($col->value) ->searchable(false) ->title('Rad'); break; case WorklistColumn::ReadingPhysician: $columns[] = Column::make($col->value) ->searchable(false) ->title('Read By'); break; case WorklistColumn::ActionButtons: case WorklistColumn::ViewerButtons: case WorklistColumn::ReportButtons: $columns[] = Column::computed($col->value) ->searchable(false) ->orderable(false) ->exportable(false) ->printable(false) // ->width(60) ->addClass('p-0 ps-2') ->title(''); break; case WorklistColumn::PatientId: $columns[] = Column::make($col->value)->title('ID'); break; case WorklistColumn::PatientName: $columns[] = Column::make($col->value)->title('Patient'); break; case WorklistColumn::StudyDescription: $columns[] = Column::make($col->value)->title('Study'); break; default: // dd(Str::slug($col->value, '-')); $columns[] = Column::make($col->value)->title($this->columTitle($col->value)); break; } } return $columns; } /** * Get the filename for export. */ protected function filename(): string { $parts = [ config('app.name'), 'worklist', date('YmdHi'), ]; return Str::slug(implode(' ', $parts), '_'); } private function columTitle(string $str): string { return Str::of($str)->slug()->replace('-', ' ')->title()->toString(); } private function physicianColumn(Study $study): ?string { $user = $study->readingPhysician; if ($user === null) { if ($study->assigned_at !== null) { return ''; } return null; } $dt = $study->read_at; return Blade::render('staff.worklist.partials._radiologist-listing', [ 'avatar_url' => $user->avatar(), 'name' => $user->display_name, 'time' => $dt?->format(self::DATE_FORMAT_SHORT) ?? '~', 'human_time' => $dt?->diffForHumans() ?? '', ] ); } /** * @return array */ private function renderCustomColumns(): array { $columns = []; foreach (WorklistGuard::worklistColumns() as $col) { switch ($col) { case WorklistColumn::PatientName: $columns[$col->value] = static function (Study $study) { if (me()->isRadiologist() || ! $study->canEditMetadata()) { return $study->sanitizedPatientName(); } return '' . $study->sanitizedPatientName() . ''; }; break; case WorklistColumn::StudyDescription: $columns[$col->value] = static fn (Study $study) => $study->sanitizedStudyDescription(); break; case WorklistColumn::AssignedPhysician: $columns[$col->value] = static function (Study $study) { if ($study->assigned_at !== null) { return ''; } return null; }; break; case WorklistColumn::ReadingPhysician: $columns[$col->value] = fn (Study $study) => $this->physicianColumn($study); break; case WorklistColumn::Series: $columns[$col->value] = fn (Study $study) => Blade::render( 'staff.worklist.partials._multi-value-cell', [ 'title' => $study->numInstances(), 'subtitle' => human_filesize($study->disk_size), ] ); break; case WorklistColumn::StudyDate: case WorklistColumn::ReceiveDate: case WorklistColumn::ReportDate: case WorklistColumn::AssignDate: case WorklistColumn::AuthorizeDate: case WorklistColumn::ArchiveDate: $columns[$col->value] = fn (Study $study) => self::renderDateColumn($study->{$col->value}); break; case WorklistColumn::History: $columns[$col->value] = fn (Study $study) => sprintf(' ', $study->hash, ($study->body_part_examined) ? 'text-muted' : 'text-primary'); break; case WorklistColumn::ActionButtons: $columns[$col->value] = fn (Study $study) => $this->generateActionButtons($study); break; case WorklistColumn::ViewerButtons: $columns[$col->value] = fn (Study $study) => $this->generateViewerButtons($study); break; case WorklistColumn::ReportButtons: $columns[$col->value] = fn (Study $study) => $this->generateReportingButtons($study); break; } } return $columns; } private function generateReportingButtons(Study $study): string { if (me()->isRadiologist() && $study->canEditReport() && ! $study->hasReports()) { // fresh untouched study, can edit report: take the rad directly to the edit page return ''; } return $this->renderButton($study->hash, 'fa-eye', 'show-reports btn-outline', 'R'); } private function renderButton(string $data_id, string $fa_icon, string $data_class, string $text, string $url = '#', bool $blank = false): string { return Blade::render('staff.worklist.partials._column-button', [ 'data_id' => $data_id, 'url' => $url, 'fa_icon' => $fa_icon, 'data_class' => $data_class, 'text' => $text, 'blank' => $blank, ] ); } private function renderImageLink(string $data_id, string $img_src, string $data_class, string $text, string $url = '#', bool $blank = false, int $width = 18): string { return Blade::render('staff.worklist.partials._image-link', [ 'data_id' => $data_id, 'url' => $url, 'img_src' => asset('imgs/' . $img_src), 'data_class' => $data_class, 'text' => $text, 'blank' => $blank, 'width' => $width, ] ); } private function generateViewerButtons(Study $study): string { $btns = []; $btns[] = $this->renderButton($study->hash, 'fa-eye', 'btn-outline', '', route('viewer.ohif', $study->hash), true); $btns[] = Blade::render('staff.worklist.partials._dropdown-menu', [ 'items' => [ [ 'url' => route('viewer.stone', $study->hash), 'text' => 'Stone', 'blank' => true, 'icon' => 'fa-circle-info', ], ], ] ); return implode("\r", $btns); } private function generateActionButtons(Study $study): string { $btns = []; foreach (WorklistGuard::worklistButtons($study) as $button) { switch ($button) { case WorklistButton::StudyMetadata: $btns[] = $this->renderImageLink($study->hash, 'info.png', 'showStudy', 'Info'); break; case WorklistButton::Assign: $btns[] = $this->renderImageLink($study->hash, 'doctor.png', 'show-assign', 'Assign'); break; case WorklistButton::Notes: $btns[] = $this->renderImageLink($study->hash, 'chat.png', 'show-notes', 'Chat'); break; } } return implode("\r", $btns); } }