diff --git a/app/DataTables/WorklistDataTable.php b/app/DataTables/WorklistDataTable.php
index 11bc796..2f69df3 100644
--- a/app/DataTables/WorklistDataTable.php
+++ b/app/DataTables/WorklistDataTable.php
@@ -507,18 +507,14 @@ private function renderImageLink(string $data_id, string $img_src, string $data_
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',
- ],
- ],
- ]
+ $btns[] = $this->renderImageLink(
+ $study->hash, 'eye.png', '', 'OHIF Viewer', route('viewer.ohif', $study->hash), true
+ );
+ $btns[] = $this->renderImageLink(
+ $study->hash, 'weasis.png', '', 'WEASIS Viewer', $study->links()['weasis'], false
+ );
+ $btns[] = $this->renderImageLink(
+ $study->hash, 'live.png', '', 'STONE Viewer', route('viewer.stone', $study->hash), true
);
return implode("\r", $btns);
diff --git a/app/Filament/Resources/DicomServerResource.php b/app/Filament/Resources/DicomServerResource.php
new file mode 100644
index 0000000..84e9edb
--- /dev/null
+++ b/app/Filament/Resources/DicomServerResource.php
@@ -0,0 +1,76 @@
+schema([
+ //
+ ]);
+ }
+
+ public static function table(Table $table): Table
+ {
+ return $table
+ ->columns([
+ Tables\Columns\TextColumn::make('id')
+ ->label('ID')
+ ->sortable(),
+ Tables\Columns\CheckboxColumn::make('is_active')
+ ->label('Active')
+ ->disabled()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('server_name')
+ ->label('Name')
+ ->searchable()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('host')
+ ->searchable()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('port')
+ ->searchable()
+ ->sortable(),
+ ])
+ ->filters([
+ //
+ ])
+ ->actions([
+ Tables\Actions\EditAction::make(),
+ ])
+ ->bulkActions([
+ Tables\Actions\BulkActionGroup::make([
+ Tables\Actions\DeleteBulkAction::make(),
+ ]),
+ ]);
+ }
+
+ public static function getRelations(): array
+ {
+ return [
+ //
+ ];
+ }
+
+ public static function getPages(): array
+ {
+ return [
+ 'index' => Pages\ListDicomServers::route('/'),
+ 'create' => Pages\CreateDicomServer::route('/create'),
+ 'edit' => Pages\EditDicomServer::route('/{record}/edit'),
+ ];
+ }
+}
diff --git a/app/Filament/Resources/DicomServerResource/Pages/CreateDicomServer.php b/app/Filament/Resources/DicomServerResource/Pages/CreateDicomServer.php
new file mode 100644
index 0000000..2674c65
--- /dev/null
+++ b/app/Filament/Resources/DicomServerResource/Pages/CreateDicomServer.php
@@ -0,0 +1,11 @@
+schema([
+ //
+ ]);
+ }
+
+ public static function table(Table $table): Table
+ {
+ return $table
+ ->columns([
+ Tables\Columns\TextColumn::make('id')
+ ->label('ID')
+ ->sortable(),
+ Tables\Columns\CheckboxColumn::make('is_active')
+ ->label('Active')
+ ->disabled()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('name')
+ ->searchable()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('institute.name')
+ ->name('Institute')
+ ->searchable()
+ ->sortable(),
+ ])
+ ->filters([
+ //
+ ])
+ ->actions([
+ Tables\Actions\EditAction::make(),
+ ])
+ ->bulkActions([
+ Tables\Actions\BulkActionGroup::make([
+ Tables\Actions\DeleteBulkAction::make(),
+ ]),
+ ]);
+ }
+
+ public static function getRelations(): array
+ {
+ return [
+ //
+ ];
+ }
+
+ public static function getPages(): array
+ {
+ return [
+ 'index' => Pages\ListFacilities::route('/'),
+ 'create' => Pages\CreateFacility::route('/create'),
+ 'edit' => Pages\EditFacility::route('/{record}/edit'),
+ ];
+ }
+}
diff --git a/app/Filament/Resources/FacilityResource/Pages/CreateFacility.php b/app/Filament/Resources/FacilityResource/Pages/CreateFacility.php
new file mode 100644
index 0000000..3857a24
--- /dev/null
+++ b/app/Filament/Resources/FacilityResource/Pages/CreateFacility.php
@@ -0,0 +1,11 @@
+schema([
+ //
+ ]);
+ }
+
+ public static function table(Table $table): Table
+ {
+ return $table
+ ->columns([
+ Tables\Columns\TextColumn::make('id')
+ ->label('ID')
+ ->sortable(),
+ Tables\Columns\CheckboxColumn::make('is_active')
+ ->label('Active')
+ ->disabled()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('name')
+ ->searchable()
+ ->sortable(),
+ ])
+ ->filters([
+ //
+ ])
+ ->actions([
+ Tables\Actions\EditAction::make(),
+ ])
+ ->bulkActions([
+ Tables\Actions\BulkActionGroup::make([
+ Tables\Actions\DeleteBulkAction::make(),
+ ]),
+ ]);
+ }
+
+ public static function getRelations(): array
+ {
+ return [
+ //
+ ];
+ }
+
+ public static function getPages(): array
+ {
+ return [
+ 'index' => Pages\ListInstitutes::route('/'),
+ 'create' => Pages\CreateInstitute::route('/create'),
+ 'edit' => Pages\EditInstitute::route('/{record}/edit'),
+ ];
+ }
+}
diff --git a/app/Filament/Resources/InstituteResource/Pages/CreateInstitute.php b/app/Filament/Resources/InstituteResource/Pages/CreateInstitute.php
new file mode 100644
index 0000000..64f5957
--- /dev/null
+++ b/app/Filament/Resources/InstituteResource/Pages/CreateInstitute.php
@@ -0,0 +1,11 @@
+schema([
+ //
+ ]);
+ }
+
+ public static function table(Table $table): Table
+ {
+ return $table
+ ->columns([
+ //
+ ])
+ ->filters([
+ //
+ ])
+ ->actions([
+ Tables\Actions\EditAction::make(),
+ ])
+ ->bulkActions([
+ Tables\Actions\BulkActionGroup::make([
+ Tables\Actions\DeleteBulkAction::make(),
+ ]),
+ ]);
+ }
+
+ public static function getRelations(): array
+ {
+ return [
+ //
+ ];
+ }
+
+ public static function getPages(): array
+ {
+ return [
+ 'index' => Pages\ListRadiologists::route('/'),
+ 'create' => Pages\CreateRadiologist::route('/create'),
+ 'edit' => Pages\EditRadiologist::route('/{record}/edit'),
+ ];
+ }
+}
diff --git a/app/Filament/Resources/RadiologistResource/Pages/CreateRadiologist.php b/app/Filament/Resources/RadiologistResource/Pages/CreateRadiologist.php
new file mode 100644
index 0000000..c70440a
--- /dev/null
+++ b/app/Filament/Resources/RadiologistResource/Pages/CreateRadiologist.php
@@ -0,0 +1,11 @@
+schema([
+ //
+ ]);
+ }
+
+ public static function table(Table $table): Table
+ {
+ return $table
+ ->columns([
+ Tables\Columns\TextColumn::make('id')
+ ->label('ID')
+ ->sortable(),
+ Tables\Columns\CheckboxColumn::make('is_active')
+ ->label('Active')
+ ->disabled()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('username')
+ ->label('Username')
+ ->searchable()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('display_name')
+ ->label('Name')
+ ->searchable()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('institute.name')
+ ->label('Institute')
+ ->searchable()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('facility.name')
+ ->label('Fac')
+ ->searchable()
+ ->sortable(),
+ ])
+ ->filters([
+ //
+ ])
+ ->actions([
+ Tables\Actions\EditAction::make(),
+ ])
+ ->bulkActions([
+ Tables\Actions\BulkActionGroup::make([
+ Tables\Actions\DeleteBulkAction::make(),
+ ]),
+ ]);
+ }
+
+ public static function getRelations(): array
+ {
+ return [
+ //
+ ];
+ }
+
+ public static function getPages(): array
+ {
+ return [
+ 'index' => Pages\ListUsers::route('/'),
+ 'create' => Pages\CreateUser::route('/create'),
+ 'edit' => Pages\EditUser::route('/{record}/edit'),
+ ];
+ }
+}
diff --git a/app/Filament/Resources/UserResource/Pages/CreateUser.php b/app/Filament/Resources/UserResource/Pages/CreateUser.php
new file mode 100644
index 0000000..78a3894
--- /dev/null
+++ b/app/Filament/Resources/UserResource/Pages/CreateUser.php
@@ -0,0 +1,11 @@
+restEndpoint($this->ohif_viewer_path);
}
+ public function wadoUrl(): Uri
+ {
+ return $this->restEndpoint($this->wado_path);
+ }
+
private function restEndpoint(string $path): Uri
{
return Uri::of($this->rest_api_endpoint)->withPath($path);
diff --git a/app/Models/Institute.php b/app/Models/Institute.php
index d080d4d..da99505 100644
--- a/app/Models/Institute.php
+++ b/app/Models/Institute.php
@@ -4,12 +4,18 @@
use App\Models\Traits\Active;
use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Relations\HasMany;
class Institute extends BaseModel
{
use Active;
use HasFactory;
+ public function facilities(): HasMany
+ {
+ return $this->hasMany(Facility::class);
+ }
+
protected function casts(): array
{
return [
diff --git a/app/Models/Study.php b/app/Models/Study.php
index 83b18dc..c0a6305 100644
--- a/app/Models/Study.php
+++ b/app/Models/Study.php
@@ -237,6 +237,15 @@ public function getOhifMprLink(): ?string
return null;
}
+ public function getWeasisLink(): ?string
+ {
+ if (me()->may(Permission::StudyDownload)) {
+ return PacsUrlGen::weasisUrl($this->dicomServer, $this);
+ }
+
+ return null;
+ }
+
public function links(): array
{
return [
@@ -245,6 +254,7 @@ public function links(): array
'zip' => $this->getArchiveLink(),
'stone' => $this->getStoneLink(),
'ohif' => $this->getOhifLink(),
+ 'weasis' => $this->getWeasisLink(),
'ohif.mpr' => $this->getOhifMprLink(),
'ohif.seg' => $this->getOhifSegmentationLink(),
];
@@ -256,6 +266,7 @@ public function allowed(): array
'zip' => filled($this->getArchiveLink()),
'stone' => filled($this->getStoneLink()),
'ohif' => filled($this->getOhifLink()),
+ 'weasis' => filled($this->getWeasisLink()),
'ohif.mpr' => filled($this->getOhifMprLink()),
'ohif.seg' => filled($this->getOhifSegmentationLink()),
];
diff --git a/app/Models/User.php b/app/Models/User.php
index d9635f8..18c1f22 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -9,8 +9,10 @@
use App\Services\UserService;
use Carbon\Carbon;
use Database\Factories\UserFactory;
+use Filament\Models\Contracts\FilamentUser;
use Filament\Panel;
use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Foundation\Auth\User as Authenticatable;
@@ -156,6 +158,21 @@ public function radiologistProfile(): HasOne
return $this->hasOne(RadiologistProfile::class);
}
+ public function institute(): BelongsTo
+ {
+ return $this->belongsTo(Institute::class);
+ }
+
+ public function facility(): BelongsTo
+ {
+ return $this->belongsTo(Facility::class);
+ }
+
+ public function canAccessPanel(Panel $panel): bool
+ {
+ return $this->isAdmin();
+ }
+
/**
* Get the attributes that should be cast.
*
@@ -170,9 +187,4 @@ protected function casts(): array
'password' => 'hashed',
];
}
-
- public function canAccessPanel(Panel $panel): bool
- {
- return $this->isAdmin();
- }
}
diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php
new file mode 100644
index 0000000..6694332
--- /dev/null
+++ b/app/Providers/Filament/AdminPanelProvider.php
@@ -0,0 +1,58 @@
+default()
+ ->id('admin')
+ ->path('admin')
+ ->login()
+ ->colors([
+ 'primary' => Color::Amber,
+ ])
+ ->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources')
+ ->discoverPages(in: app_path('Filament/Pages'), for: 'App\\Filament\\Pages')
+ ->pages([
+ Pages\Dashboard::class,
+ ])
+ ->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\Filament\\Widgets')
+ ->widgets([
+ Widgets\AccountWidget::class,
+ Widgets\FilamentInfoWidget::class,
+ ])
+ ->middleware([
+ EncryptCookies::class,
+ AddQueuedCookiesToResponse::class,
+ StartSession::class,
+ AuthenticateSession::class,
+ ShareErrorsFromSession::class,
+ VerifyCsrfToken::class,
+ SubstituteBindings::class,
+ DisableBladeIconComponents::class,
+ DispatchServingFilamentEvent::class,
+ ])
+ ->authMiddleware([
+ Authenticate::class,
+ ]);
+ }
+}
diff --git a/app/Services/Pacs/PacsUrlGen.php b/app/Services/Pacs/PacsUrlGen.php
index b07fa54..d61b244 100644
--- a/app/Services/Pacs/PacsUrlGen.php
+++ b/app/Services/Pacs/PacsUrlGen.php
@@ -4,7 +4,7 @@
use App\Models\DicomServer;
use App\Models\Study;
-use Uri;
+use Illuminate\Support\Uri;
final class PacsUrlGen
{
@@ -34,6 +34,19 @@ public static function ohifViewerMpr(DicomServer $host, Study $study): string
return (string) $url;
}
+ public static function weasisUrl(DicomServer $host, Study $study, bool $close = false): string
+ {
+ $parts = [];
+ if ($close) {
+ $parts[] = '$dicom:close --all';
+ }
+ $parts[] = sprintf('$dicom:rs --url "%s"', $host->wadoUrl());
+ $parts[] = sprintf('-r "studyUID=%s"', $study->study_instance_uid);
+ // $parts[] = '--query-ext "&includedefaults=false"';
+
+ return sprintf('weasis://%s', urlencode(implode(' ', $parts)));
+ }
+
public static function ohifSegmentation(DicomServer $host, Study $study): string
{
$url = $host->ohifViewerUrl()
diff --git a/database/migrations/0000_01_31_074312_create_dicom_servers_table.php b/database/migrations/0000_01_31_074312_create_dicom_servers_table.php
index 21d8fcc..83f695a 100644
--- a/database/migrations/0000_01_31_074312_create_dicom_servers_table.php
+++ b/database/migrations/0000_01_31_074312_create_dicom_servers_table.php
@@ -20,6 +20,7 @@ public function up(): void
$table->string('ae_title')->nullable();
$table->string('username')->nullable();
$table->string('password')->nullable();
+ $table->string('wado_path')->nullable();
$table->string('stone_viewer_path')->nullable();
$table->string('ohif_viewer_path')->nullable();
$table->string('meddream_viewer_path')->nullable();
diff --git a/database/seeders/InstituteSeeder.php b/database/seeders/InstituteSeeder.php
index 786210d..34161a4 100644
--- a/database/seeders/InstituteSeeder.php
+++ b/database/seeders/InstituteSeeder.php
@@ -63,6 +63,7 @@ public function run(): void
'host' => 'pacs.mylabctg.com',
'port' => 8042,
'rest_api_endpoint' => 'http://pacs.mylabctg.com:8042/',
+ 'wado_path' => 'dicom-web',
'ae_title' => 'RADFUSION',
'stone_viewer_path' => 'stone-webviewer/index.html',
'ohif_viewer_path' => 'ohif/viewer',
@@ -76,6 +77,7 @@ public function run(): void
'port' => 8043,
'rest_api_endpoint' => 'http://pacs.mylabctg.com:8042/',
'ae_title' => 'RADFUSION',
+ 'wado_path' => 'dicom-web',
'stone_viewer_path' => 'stone-webviewer/index.html',
'ohif_viewer_path' => 'ohif/viewer',
'institute_id' => $chev->id,
diff --git a/resources/views/_partials/_img-tooltip.blade.php b/resources/views/_partials/_img-tooltip.blade.php
index ba6d37a..9d8ea6f 100644
--- a/resources/views/_partials/_img-tooltip.blade.php
+++ b/resources/views/_partials/_img-tooltip.blade.php
@@ -1 +1 @@
-
+
diff --git a/resources/views/_partials/_tooltip.blade.php b/resources/views/_partials/_tooltip.blade.php
index 022e100..a4ea385 100644
--- a/resources/views/_partials/_tooltip.blade.php
+++ b/resources/views/_partials/_tooltip.blade.php
@@ -1 +1 @@
-data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="{{ $tip }}"
+data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="{{ $tip }}" title="{{ $tip }}"
diff --git a/resources/views/staff/studies/index.blade.php b/resources/views/staff/studies/index.blade.php
index f4fdf99..acc2769 100644
--- a/resources/views/staff/studies/index.blade.php
+++ b/resources/views/staff/studies/index.blade.php
@@ -132,6 +132,9 @@ class="d-flex justify-content-between align-items-start border-end pb-4 pb-sm-0
@if ($study->allowed()['ohif'])
O |
@endif
+ @if ($study->allowed()['weasis'])
+ O |
+ @endif
@if ($study->allowed()['ohif.mpr'])
OM |
@endif
diff --git a/resources/views/staff/worklist/partials/_image-link.blade.php b/resources/views/staff/worklist/partials/_image-link.blade.php
index 750309a..b8a52a0 100644
--- a/resources/views/staff/worklist/partials/_image-link.blade.php
+++ b/resources/views/staff/worklist/partials/_image-link.blade.php
@@ -1,3 +1,4 @@
- $text])>
+ $text]) data-id="{{ $data_id }}" class="me-2 {{ $data_class }}">
+