added new features
This commit is contained in:
@@ -26,6 +26,25 @@ class RMLWorkorderAdminController extends TTCrud
|
||||
['key' => 'deadlineDate', 'text' => 'Deadline', 'modal' => false, 'table' => ['filter' => 'date']],
|
||||
];
|
||||
|
||||
private function getStatusText(string $statusKey): string {
|
||||
$statusColumn = null;
|
||||
foreach ($this->columns as $column) {
|
||||
if ($column['key'] === 'status') {
|
||||
$statusColumn = $column;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($statusColumn) {
|
||||
foreach ($statusColumn['table']['filterOptions'] as $option) {
|
||||
if ($option['value'] === $statusKey) {
|
||||
return $option['text'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return ucfirst(str_replace('_', ' ', $statusKey)); // Fallback
|
||||
}
|
||||
|
||||
protected function indexAction()
|
||||
{
|
||||
$campaigns = Helper::getPreorderCampaignFromUser($this->user, true);
|
||||
@@ -105,20 +124,52 @@ class RMLWorkorderAdminController extends TTCrud
|
||||
protected function getDocumentationAction() {
|
||||
if(empty($this->request->workorderId)) self::sendError("Workorder ID missing.");
|
||||
|
||||
$docs = RMLWorkorderDocumentationModel::getAll(['workorderId' => $this->request->workorderId], null, 0, ['key' => 'create', 'order' => 'DESC']);
|
||||
$docs = RMLWorkorderDocumentationModel::getAll(['workorderId' => $this->request->workorderId], null, 0, ['key' => 'create', 'order' => 'ASC']);
|
||||
$journals = RMLWorkorderJournalModel::getAll(['workorderId' => $this->request->workorderId], null, 0, ['key' => 'create', 'order' => 'DESC']);
|
||||
$users = UserModel::search();
|
||||
|
||||
$translationMap = [
|
||||
'photo_hup_mounted' => 'Foto_montierter_HÜP',
|
||||
'photo_hup_open' => 'Foto_offener_HÜP',
|
||||
'photo_splice_cassette_hup' => 'Foto_Spleißkassette_HÜP',
|
||||
'photo_splice_cassette_fcp' => 'Foto_Spleißkassette_FCP',
|
||||
'photo_hup_closed_stickers' => 'Foto_geschlossener_HÜP_mit_Aufklebern',
|
||||
'photo_fcp_labeled' => 'Foto_FCP_beschriftet',
|
||||
'photo_patch_position_osp' => 'Foto_Patch-Position_OSP-Seite',
|
||||
'photo_patch_position_anb' => 'Foto_Patch-Position_ANB-Seite',
|
||||
'measurement_protocol_otdr' => 'ODTR_Messung',
|
||||
'other' => 'Sonstiges_Dokument'
|
||||
];
|
||||
|
||||
$responseDocs = [];
|
||||
$typeCounts = [];
|
||||
|
||||
foreach($docs as $doc) {
|
||||
$file = new File($doc->fileId);
|
||||
$doc->fileName = $file->orig_filename ?? $file->filename;
|
||||
$doc->userName = UserModel::getOne($doc->createBy)->name ?? 'Unbekannt';
|
||||
$doc->mimetype = $file->mimetype ?? 'application/octet-stream';
|
||||
$documentTypeKey = $doc->documentType;
|
||||
|
||||
$typeCounts[$documentTypeKey] = ($typeCounts[$documentTypeKey] ?? 0) + 1;
|
||||
|
||||
$originalFilename = $file->orig_filename ?? $file->filename;
|
||||
$extension = pathinfo($originalFilename, PATHINFO_EXTENSION);
|
||||
$translatedType = $translationMap[$documentTypeKey] ?? $documentTypeKey;
|
||||
$newFilename = "{$translatedType}_{$typeCounts[$documentTypeKey]}." . strtolower($extension);
|
||||
|
||||
$responseDocs[] = [
|
||||
'id' => $doc->id,
|
||||
'fileId' => $doc->fileId,
|
||||
'fileName' => $newFilename,
|
||||
'description' => $doc->description,
|
||||
'documentType' => $documentTypeKey,
|
||||
'userName' => UserModel::getOne($doc->createBy)->name ?? 'Unbekannt',
|
||||
'mimetype' => $file->mimetype ?? 'application/octet-stream',
|
||||
];
|
||||
}
|
||||
|
||||
foreach($journals as $journal) {
|
||||
$journal->createByName = UserModel::getOne($journal->createBy)->name ?? 'Unbekannt';
|
||||
}
|
||||
self::returnJson(['docs' => $docs, 'journals' => $journals]);
|
||||
|
||||
self::returnJson(['docs' => $responseDocs, 'journals' => $journals]);
|
||||
}
|
||||
|
||||
private function assignSingleWorkorder($workorderId, $companyId, $deadline, $userId) {
|
||||
@@ -200,9 +251,9 @@ class RMLWorkorderAdminController extends TTCrud
|
||||
|
||||
RMLWorkorderJournalModel::create([
|
||||
'workorderId' => $workorder->id,
|
||||
'text' => $post['text'],
|
||||
'text' => "Korrektur angefordert. Grund: " . $post['text'],
|
||||
'fileIds' => !empty($post['fileIds']) ? json_encode($post['fileIds']) : null,
|
||||
'statusChange' => "$oldStatus -> correction_requested",
|
||||
'statusChange' => $this->getStatusText($oldStatus) . " -> " . $this->getStatusText('correction_requested'),
|
||||
'create' => time(),
|
||||
'createBy' => $this->user->id,
|
||||
]);
|
||||
@@ -283,7 +334,7 @@ class RMLWorkorderAdminController extends TTCrud
|
||||
RMLWorkorderJournalModel::create([
|
||||
'workorderId' => $workorder->id,
|
||||
'text' => 'Dokumentation wurde akzeptiert und der Auftrag abgeschlossen.',
|
||||
'statusChange' => "$oldStatus -> completed",
|
||||
'statusChange' => $this->getStatusText($oldStatus) . " -> " . $this->getStatusText('completed'),
|
||||
'create' => time(),
|
||||
'createBy' => $this->user->id,
|
||||
]);
|
||||
@@ -292,11 +343,6 @@ class RMLWorkorderAdminController extends TTCrud
|
||||
}
|
||||
|
||||
protected function setToProblemSolvedAction() {
|
||||
// const response = await axios.post(`${window.TT_CONFIG.BASE_PATH}/RMLWorkorderAdmin/setToProblemSolved`, {
|
||||
// workorderId: row.id,
|
||||
// text: text
|
||||
// });
|
||||
|
||||
$post = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
if (empty($post['workorderId']) || empty($post['text'])) {
|
||||
@@ -317,13 +363,10 @@ class RMLWorkorderAdminController extends TTCrud
|
||||
$workorder->status = 'problem_solved';
|
||||
RMLWorkorderModel::update((array)$workorder);
|
||||
|
||||
$oldStatusText = $oldStatus === 'intervention_required' ? 'Eingriff benötigt' : $oldStatus;
|
||||
$problem_solved = 'Problem gelöst';
|
||||
|
||||
RMLWorkorderJournalModel::create([
|
||||
'workorderId' => $workorder->id,
|
||||
'text' => $post['text'],
|
||||
'statusChange' => "$oldStatusText -> $problem_solved",
|
||||
'text' => "Problem behoben: " . $post['text'],
|
||||
'statusChange' => $this->getStatusText($oldStatus) . " -> " . $this->getStatusText('problem_solved'),
|
||||
'create' => time(),
|
||||
'createBy' => $this->user->id,
|
||||
]);
|
||||
|
||||
@@ -26,6 +26,25 @@ class RMLWorkorderCompanyController extends TTCrud
|
||||
|
||||
protected array $additionalJSVariables = ['COMPANY_ID' => '0'];
|
||||
|
||||
private function getStatusText(string $statusKey): string {
|
||||
$statusColumn = null;
|
||||
foreach ($this->columns as $column) {
|
||||
if ($column['key'] === 'status') {
|
||||
$statusColumn = $column;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($statusColumn) {
|
||||
foreach ($statusColumn['table']['filterOptions'] as $option) {
|
||||
if ($option['value'] === $statusKey) {
|
||||
return $option['text'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return ucfirst(str_replace('_', ' ', $statusKey)); // Fallback
|
||||
}
|
||||
|
||||
protected function prepareCrudConfig() {
|
||||
$company = RMLWorkorderCompanyModel::getFirst(['addressId' => $this->user->address_id]);
|
||||
if ($company) {
|
||||
@@ -197,7 +216,7 @@ class RMLWorkorderCompanyController extends TTCrud
|
||||
RMLWorkorderJournalModel::create([
|
||||
'workorderId' => $workorder->id,
|
||||
'text' => "Eingriff benötigt: " . $post['journalText'],
|
||||
'statusChange' => "$oldStatus -> intervention_required",
|
||||
'statusChange' => $this->getStatusText($oldStatus) . " -> " . $this->getStatusText('intervention_required'),
|
||||
'create' => time(),
|
||||
'createBy' => $this->user->id,
|
||||
]);
|
||||
@@ -205,7 +224,6 @@ class RMLWorkorderCompanyController extends TTCrud
|
||||
self::returnJson(['success' => true, 'message' => 'Eingriff wurde angefordert.']);
|
||||
}
|
||||
|
||||
|
||||
protected function uploadDocumentationAction()
|
||||
{
|
||||
if (empty($_FILES['files']) || empty($_POST['workorderId'])) {
|
||||
@@ -271,20 +289,21 @@ class RMLWorkorderCompanyController extends TTCrud
|
||||
$translationMap = [
|
||||
'photo_hup_mounted' => 'Foto_montierter_HÜP',
|
||||
'photo_hup_open' => 'Foto_offener_HÜP',
|
||||
'photo_splice_cassette' => 'Foto_Spleißkassette',
|
||||
'photo_splice_cassette_hup' => 'Foto_Spleißkassette_HÜP',
|
||||
'photo_splice_cassette_fcp' => 'Foto_Spleißkassette_FCP',
|
||||
'photo_hup_closed_stickers' => 'Foto_geschlossener_HÜP_mit_Aufklebern',
|
||||
'photo_fcp_labeled' => 'Foto_FCP_beschriftet',
|
||||
'photo_patch_position_osp' => 'Foto_Patch-Position_OSP-Seite',
|
||||
'photo_patch_position_anb' => 'Foto_Patch-Position_ANB-Seite',
|
||||
'measurement_protocol_otdr' => 'ODTR_Messung',
|
||||
'other' => 'Sonstiges_Dokument'
|
||||
];
|
||||
|
||||
foreach($docs as $doc) {
|
||||
$file = new File($doc->fileId);
|
||||
$documentTypeKey = $doc->documentType;
|
||||
if (!isset($typeCounts[$documentTypeKey])) {
|
||||
$typeCounts[$documentTypeKey] = 1;
|
||||
} else {
|
||||
$typeCounts[$documentTypeKey]++;
|
||||
}
|
||||
|
||||
$typeCounts[$documentTypeKey] = ($typeCounts[$documentTypeKey] ?? 0) + 1;
|
||||
|
||||
$originalFilename = $file->orig_filename ?? $file->filename;
|
||||
$extension = pathinfo($originalFilename, PATHINFO_EXTENSION);
|
||||
@@ -295,6 +314,7 @@ class RMLWorkorderCompanyController extends TTCrud
|
||||
'id' => $doc->id,
|
||||
'fileId' => $doc->fileId,
|
||||
'fileName' => $newFilename,
|
||||
'description' => $doc->description,
|
||||
'documentType' => $documentTypeKey,
|
||||
'mimetype' => $file->mimetype,
|
||||
];
|
||||
|
||||
@@ -1,33 +1,40 @@
|
||||
/*
|
||||
* CSS for Workorder Table Row Highlighting (Balanced Colors)
|
||||
* CSS for Workorder Table Row Highlighting
|
||||
*/
|
||||
|
||||
/* 🔴 Urgent: Deadline passed or less than 1 week away */
|
||||
/* Urgent: Deadline passed or less than 1 week away */
|
||||
.table-hover .tt-rml-workorder-urgent:hover,
|
||||
.tt-rml-workorder-urgent {
|
||||
background-color: #f8d7da !important; /* Balanced Red */
|
||||
background-color: #fbe9e7 !important; /* Soft Red */
|
||||
}
|
||||
|
||||
/* 🟠 High Priority: Deadline less than 2 weeks away */
|
||||
.table-hover .tt-rml-workorder-high:hover,
|
||||
.tt-rml-workorder-high {
|
||||
background-color: #ffd5a1 !important; /* Balanced Orange */
|
||||
}
|
||||
|
||||
/* 🟡 Medium: Deadline less than 3 weeks away */
|
||||
/* Medium: Deadline less than 3 weeks away */
|
||||
.table-hover .tt-rml-workorder-medium:hover,
|
||||
.tt-rml-workorder-medium {
|
||||
background-color: #fff3cd !important; /* Balanced Yellow */
|
||||
background-color: #fff8e1 !important; /* Soft Yellow */
|
||||
}
|
||||
|
||||
/* 🟢 On Track: Deadline more than 3 weeks away */
|
||||
/* On Track: Deadline more than 3 weeks away */
|
||||
.table-hover .tt-rml-workorder-ontrack:hover,
|
||||
.tt-rml-workorder-ontrack {
|
||||
background-color: #d4edda !important; /* Balanced Green */
|
||||
background-color: #e8f5e9 !important; /* Soft Green */
|
||||
}
|
||||
|
||||
/* ⚫ Irrelevant: No deadline or status makes it not applicable */
|
||||
/* Irrelevant: No deadline or status makes it not applicable */
|
||||
.table-hover .tt-rml-workorder-irrelevant:hover,
|
||||
.tt-rml-workorder-irrelevant {
|
||||
background-color: #e9ecef !important; /* Balanced Grey */
|
||||
}
|
||||
background-color: #fafafa !important; /* Very light grey */
|
||||
}
|
||||
|
||||
.table-hover .tt-rml-workorder-high:hover,
|
||||
.tt-rml-workorder-high {
|
||||
background-color: #f8d7da !important; /* A slightly more intense red for high priority issues */
|
||||
}
|
||||
|
||||
.tt-file-gallery-item.border.border-danger {
|
||||
border: 4px solid #f1556c!important;
|
||||
}
|
||||
|
||||
.RMLWorkorderCompany-table .modal-body {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ Vue.component('r-m-l-workorder-admin', {
|
||||
additional-class="btn-link btn-sm p-0"
|
||||
title="Auftrag auf Problem behoben setzen"
|
||||
/>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<template v-slot:companyname="{ row }">
|
||||
@@ -297,10 +297,10 @@ Vue.component('r-m-l-workorder-admin', {
|
||||
}
|
||||
},
|
||||
async setToProblemSolved(row) {
|
||||
// add a browser dialog to add some text
|
||||
const text = prompt('Bitte geben Sie einen kurzen Text für den Eintrag ein:', '');
|
||||
const text = prompt('Bitte geben Sie einen kurzen Text für den Journaleintrag ein:', '');
|
||||
|
||||
if (!text) {
|
||||
if (text === null) return; // User cancelled
|
||||
if (!text.trim()) {
|
||||
window.notify('error', 'Bitte geben Sie einen Text ein.');
|
||||
return;
|
||||
}
|
||||
@@ -364,7 +364,14 @@ Vue.component('rml-documentation-viewer-admin', {
|
||||
<div class="card mb-3">
|
||||
<div class="card-header"><h5><i class="fas fa-check-circle text-success mr-2"></i>Dokumentation akzeptieren</h5></div>
|
||||
<div class="card-body">
|
||||
<p class="small text-muted">Wenn die Dokumentation korrekt ist, können Sie sie hier akzeptieren.</p>
|
||||
<p class="small text-muted">Prüfen Sie, ob alle erforderlichen Dokumente vorhanden und korrekt sind.</p>
|
||||
<ul class="list-unstyled">
|
||||
<li v-for="docType in requiredDocTypes" :key="docType.value" class="mb-2 d-flex align-items-center small">
|
||||
<i :class="isUploaded(docType.value) ? 'fas fa-check-circle text-success' : 'far fa-circle text-muted'" class="fa-fw mr-2"></i>
|
||||
<span>{{ docType.text }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<hr>
|
||||
<tt-button text="Dokumentation akzeptieren"
|
||||
@click="$emit('accept-documentation', workorderId)"
|
||||
additional-class="btn-success float-right"
|
||||
@@ -409,9 +416,23 @@ Vue.component('rml-documentation-viewer-admin', {
|
||||
correctionText: '',
|
||||
newJournalMessage: '',
|
||||
addingJournalEntry: false,
|
||||
requiredDocTypes: [
|
||||
{ value: 'photo_hup_mounted', text: 'Foto vom montierten HÜP' },
|
||||
{ value: 'photo_hup_open', text: 'Foto von dem offenen HÜP' },
|
||||
{ value: 'photo_splice_cassette_hup', text: 'Foto der Spleißkassette – HÜP' },
|
||||
{ value: 'photo_splice_cassette_fcp', text: 'Foto der Spleißkassette - FCP' },
|
||||
{ value: 'photo_hup_closed_stickers', text: 'Foto vom geschlossenen HÜP mit allen Aufklebern' },
|
||||
{ value: 'photo_fcp_labeled', text: 'Foto vom FCP beschriftet' },
|
||||
{ value: 'photo_patch_position_osp', text: 'Foto der Patch-Position - OSP-Seite' },
|
||||
{ value: 'photo_patch_position_anb', text: 'Foto der Patch-Position - ANB-Seite' },
|
||||
{ value: 'measurement_protocol_otdr', text: 'ODTR – Messung (1310nm & 1550nm)' },
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isUploaded(docType) {
|
||||
return this.docs.some(doc => doc.documentType === docType);
|
||||
},
|
||||
async fetchData() {
|
||||
this.loading = true;
|
||||
try {
|
||||
|
||||
@@ -25,6 +25,12 @@
|
||||
.tt-rml-workorder-irrelevant {
|
||||
background-color: #fafafa !important; /* Very light grey */
|
||||
}
|
||||
|
||||
.table-hover .tt-rml-workorder-high:hover,
|
||||
.tt-rml-workorder-high {
|
||||
background-color: #f8d7da !important; /* A slightly more intense red for high priority issues */
|
||||
}
|
||||
|
||||
.tt-file-gallery-item.border.border-danger {
|
||||
border: 4px solid #f1556c!important;
|
||||
}
|
||||
@@ -266,7 +266,7 @@ Vue.component('documentation-manager', {
|
||||
<div class="card mb-3" v-if="workorder.status !== 'documented' && workorder.status !== 'completed'">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Neues Dokument hochladen</h5>
|
||||
<tt-select label="Dokumententyp" :options="requiredDocTypes" v-model="uploadData.documentType" sm row />
|
||||
<tt-select label="Dokumententyp" :options="allDocTypes" v-model="uploadData.documentType" sm row />
|
||||
<tt-input label="Beschreibung" v-model="uploadData.description" sm row placeholder="Optional"/>
|
||||
<div class="form-group row">
|
||||
<label class="col-form-label col-sm-4 col-form-label-sm">Dateien</label>
|
||||
@@ -288,7 +288,7 @@ Vue.component('documentation-manager', {
|
||||
<template v-slot:file-edit="{ file }">
|
||||
<tt-select
|
||||
label="Dokumententyp"
|
||||
:options="requiredDocTypes"
|
||||
:options="allDocTypes"
|
||||
v-model="file.documentType"
|
||||
sm
|
||||
/>
|
||||
@@ -334,15 +334,23 @@ Vue.component('documentation-manager', {
|
||||
requiredDocTypes: [
|
||||
{ value: 'photo_hup_mounted', text: 'Foto vom montierten HÜP' },
|
||||
{ value: 'photo_hup_open', text: 'Foto von dem offenen HÜP' },
|
||||
{ value: 'photo_splice_cassette', text: 'Foto der Spleißkassette' },
|
||||
{ value: 'photo_splice_cassette_hup', text: 'Foto der Spleißkassette – HÜP' },
|
||||
{ value: 'photo_splice_cassette_fcp', text: 'Foto der Spleißkassette - FCP' },
|
||||
{ value: 'photo_hup_closed_stickers', text: 'Foto vom geschlossenen HÜP mit allen Aufklebern' },
|
||||
{ value: 'photo_fcp_labeled', text: 'Foto vom FCP beschriftet' },
|
||||
{ value: 'photo_patch_position', text: 'Foto der Patch-Position' },
|
||||
{ value: 'photo_patch_position_osp', text: 'Foto der Patch-Position - OSP-Seite' },
|
||||
{ value: 'photo_patch_position_anb', text: 'Foto der Patch-Position - ANB-Seite' },
|
||||
{ value: 'measurement_protocol_otdr', text: 'ODTR – Messung (1310nm & 1550nm)' },
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
allDocTypes() {
|
||||
return [
|
||||
...this.requiredDocTypes,
|
||||
{ value: 'other', text: 'Sonstiges Dokument (optional)' }
|
||||
];
|
||||
},
|
||||
canComplete() {
|
||||
return this.requiredDocTypes.every(docType => this.isUploaded(docType.value));
|
||||
},
|
||||
|
||||
@@ -193,6 +193,26 @@
|
||||
margin: 20px 0; /* Add some vertical margin for spacing */
|
||||
}
|
||||
|
||||
.tt-file-gallery-filename {
|
||||
padding: 4px 8px 0;
|
||||
font-weight: 500;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tt-file-gallery-description {
|
||||
padding: 0 8px 4px;
|
||||
font-size: 0.75rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
color: #6c757d; /* Bootstrap's text-muted color */
|
||||
}
|
||||
|
||||
|
||||
.tt-fullscreen-nav-btn {
|
||||
position: absolute;
|
||||
|
||||
@@ -40,7 +40,6 @@ Vue.component('tt-fullscreen-viewer', {
|
||||
return this.currentItem?.fileId ? `/File/download?id=${this.currentItem.fileId}` : '#';
|
||||
}
|
||||
},
|
||||
// NEW: Watcher to trigger PDF.js rendering when item changes in standalone mode
|
||||
watch: {
|
||||
currentItem(newItem) {
|
||||
if (this.isPdf(newItem) && this.isStandalone) {
|
||||
@@ -106,16 +105,12 @@ Vue.component('tt-fullscreen-viewer', {
|
||||
onTouchStart(e) {},
|
||||
onTouchMove(e) {},
|
||||
onTouchEnd(e) {},
|
||||
|
||||
// NEW: Method to dynamically load the PDF.js library
|
||||
loadPdfJsScript() {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (document.getElementById('pdfjs-script')) {
|
||||
// Script tag exists, check if library is loaded
|
||||
if (window.pdfjsLib) {
|
||||
resolve();
|
||||
} else {
|
||||
// Tag exists but script not loaded yet, wait for it
|
||||
document.getElementById('pdfjs-script').addEventListener('load', () => resolve());
|
||||
document.getElementById('pdfjs-script').addEventListener('error', (e) => reject(e));
|
||||
}
|
||||
@@ -134,8 +129,6 @@ Vue.component('tt-fullscreen-viewer', {
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
},
|
||||
|
||||
// NEW: Method to render PDF onto a canvas using PDF.js
|
||||
async renderPdfWithJs(url) {
|
||||
if (!url) return;
|
||||
this.isLoading = true;
|
||||
@@ -146,12 +139,11 @@ Vue.component('tt-fullscreen-viewer', {
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://unpkg.com/pdfjs-dist@5.4.54/build/pdf.worker.min.mjs';
|
||||
|
||||
const pdf = await pdfjsLib.getDocument(url).promise;
|
||||
// For simplicity, we render the first page. Add pagination controls as needed.
|
||||
const page = await pdf.getPage(1);
|
||||
|
||||
const canvas = this.$refs.pdfCanvas;
|
||||
if (!canvas) return; // Exit if canvas is not available
|
||||
const container = canvas.parentElement; // Get the container to calculate size from
|
||||
if (!canvas) return;
|
||||
const container = canvas.parentElement;
|
||||
if (!container) return;
|
||||
|
||||
const context = canvas.getContext('2d');
|
||||
@@ -170,17 +162,14 @@ Vue.component('tt-fullscreen-viewer', {
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error rendering PDF with PDF.js:', error);
|
||||
// Optionally show an error message to the user
|
||||
} finally {
|
||||
this.onContentLoad(); // Use existing method to hide loader
|
||||
this.onContentLoad();
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.currentItem = this.item;
|
||||
this.currentImageIndex = this.initialIndex;
|
||||
|
||||
// NEW: Check for standalone mode on component creation
|
||||
if (typeof window !== 'undefined' && window.matchMedia) {
|
||||
this.isStandalone = window.matchMedia('(display-mode: standalone)').matches;
|
||||
}
|
||||
@@ -189,8 +178,6 @@ Vue.component('tt-fullscreen-viewer', {
|
||||
document.body.style.overflow = 'hidden';
|
||||
this.$nextTick(() => {
|
||||
this.$refs.viewer?.focus();
|
||||
|
||||
// NEW: Trigger initial PDF render on mount if in standalone mode
|
||||
if (this.isPdf(this.currentItem) && this.isStandalone) {
|
||||
this.renderPdfWithJs(this.contentSrc);
|
||||
}
|
||||
@@ -199,7 +186,6 @@ Vue.component('tt-fullscreen-viewer', {
|
||||
beforeDestroy() {
|
||||
document.body.style.overflow = '';
|
||||
},
|
||||
//language=Vue
|
||||
template: `
|
||||
<div class="tt-fullscreen-overlay" @click.self="closeViewer" @keydown="handleKeyDown" tabindex="-1" ref="viewer">
|
||||
<div class="tt-fullscreen-toolbar">
|
||||
@@ -342,12 +328,13 @@ Vue.component('tt-file-gallery', {
|
||||
</div>
|
||||
</div>
|
||||
<div class="tt-file-gallery-filename" :title="file.fileName">
|
||||
<span>{{ file.fileName }}</span>
|
||||
<i v-if="editMode" class="fas fa-edit text-primary ml-1 action-icon"
|
||||
@click="startEdit(file, $event)"></i>
|
||||
<i v-if="deleteMode" class="fas fa-trash text-danger ml-1 action-icon"
|
||||
@click="deleteFile(file, $event)"></i>
|
||||
<span style="overflow: hidden; text-overflow: ellipsis;">{{ file.fileName }}</span>
|
||||
<div>
|
||||
<i v-if="editMode" class="fas fa-edit text-primary ml-1 action-icon" @click="startEdit(file, $event)"></i>
|
||||
<i v-if="deleteMode" class="fas fa-trash text-danger ml-1 action-icon" @click="deleteFile(file, $event)"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="file.description" class="tt-file-gallery-description" :title="file.description">{{ file.description }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user