Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions extralit-frontend/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ These are the section headers that we use:
* "Security" in case of vulnerabilities.
-->

## [Extralit] [0.6.1](https://github.com/extralit/extralit/compare/v0.5.0...v0.6.1)
### Changed
- Refactored the frontend to use a single fetchDocument method that queries documents by any identifier and workspace, replacing the previous fetchDocumentByID and fetchDocumentByPubmedID methods. The view model and use case now expect and handle the new API response format

## [Extralit] [0.6.0](https://github.com/extralit/extralit/compare/v0.4.1...v0.6.0)

### Added
Expand Down
21 changes: 3 additions & 18 deletions extralit-frontend/components/base/base-pdf-viewer/PDFViewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
</div>
</template>

<script>
<script lang="ts">
import { PDFView } from "@jonnytran/vue-pdf-viewer";

export default {
Expand All @@ -44,8 +44,8 @@ export default {
},

watch: {
pageNumber(newPageNumber) {
this.currentPageNumber = newPageNumber;
pageNumber(newPageNumber: Number | String) {
this.currentPageNumber = newPageNumber ? Number(newPageNumber) : 1;
},
},

Expand All @@ -56,21 +56,6 @@ export default {
};
},

mounted() {
window.addEventListener("hashchange", this.onHashChange);
this.onHashChange(); // Call on component mount to handle initial hash
},

methods: {
onHashChange() {
const hash = window.location.hash.substring(1); // Remove the '#' from the hash
const [key, value] = hash.split(".");
if (key === "page_number" && !isNaN(value)) {
this.currentPageNumber = Number(value);
}
},
},

errorCaptured(err, component, info) {
this.error = err;
console.error(`Error caught from ${component}: ${err}`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
import { useDataset } from "@/v1/infrastructure/storage/DatasetStorage";
import { waitForAsyncValue } from "@/v1/infrastructure/services/useWait";
import { useNotifications } from "~/v1/infrastructure/services/useNotifications";
import { useWorkspaces } from "~/v1/infrastructure/storage/WorkspaceStorage";

export const useDocumentViewModel = (props: { record: any }) => {
const notification = useNotifications();
const getDocument = useResolve(GetDocumentByIdUseCase);
const { state: workspaces } = useWorkspaces();
const { state: dataset } = useDataset();
const { state: document, set: setDocument, clear: clearDocument } = useDocument();
const isLoading = ref(false);
Expand All @@ -17,44 +19,54 @@
const hasDocumentLoaded = computed(() => {
return document.id !== null;
});
const hasDocument = computed(() => {

Check failure on line 22 in extralit-frontend/components/features/annotation/container/mode/useDocumentViewModel.ts

View workflow job for this annotation

GitHub Actions / Build extralit-frontend

'hasDocument' is assigned a value but never used
return (
props.record.metadata === null || props.record.metadata?.doc_id != null || props.record.metadata?.pmid != null
props.record.metadata === null || props.record.metadata?.reference != null || props.record.metadata?.pmid != null
);
});

const fetchDocumentByID = async (id: string) => {
const fetchDocument = async (metadata: any) => {
try {
await getDocument.setDocumentByID(id);
} catch (e) {
notification.notify({
message: `Error fetching document with ID ${id}`,
type: "danger",
});
clearDocument();
}
};
await waitForAsyncValue(() => workspaces.selectedWorkspace?.id);

const fetchDocumentByPubmedID = async (pmid: string) => {
try {
await getDocument.setDocumentByPubmedID(pmid);
const params: {
workspace_id: string;
doc_id?: string;
pmid?: string;
doi?: string;
reference?: string;
} = { workspace_id: workspaces.selectedWorkspace!.id };

if (metadata?.reference) params.reference = metadata.reference;
if (metadata?.doc_id) params.doc_id = metadata.doc_id;
if (metadata?.pmid) params.pmid = metadata.pmid;
if (metadata?.doi) params.doi = metadata.doi;

// Ensure at least one identifier is provided
if (Object.keys(params).length === 0) {
throw new Error("No valid document identifier found in metadata");
}

await getDocument.setDocument(params);
} catch (e) {
const identifier = metadata?.pmid || metadata?.doi || metadata?.doc_id || metadata?.reference || "unknown";
console.error(`Error fetching document with identifier "${identifier}":`, e);
notification.notify({
message: `Error fetching document with pmid "${pmid}"`,
message: `Error fetching document with identifier "${identifier}"`,
type: "danger",
});
clearDocument();
}
};

const updateDocument = async (metadata: any) => {

Check failure on line 62 in extralit-frontend/components/features/annotation/container/mode/useDocumentViewModel.ts

View workflow job for this annotation

GitHub Actions / Build extralit-frontend

Async arrow function has no 'await' expression
if (metadata?.pmid != null) {
if (document.pmid !== metadata.pmid) {
fetchDocumentByPubmedID(metadata.pmid);
}
if (metadata?.pmid != null && document.pmid !== metadata.pmid) {
fetchDocument(metadata);
} else if (metadata?.doi != null && document.doi !== metadata.doi) {
fetchDocument(metadata);
} else if (metadata?.doc_id != null && document.id !== metadata.doc_id) {
fetchDocumentByID(metadata.doc_id);
} else if (!metadata?.pmid && !metadata?.doc_id && hasDocumentLoaded.value) {
fetchDocument(metadata);
} else if (!metadata?.pmid && !metadata?.doi && !metadata?.doc_id && hasDocumentLoaded.value) {
clearDocument();
}

Expand Down Expand Up @@ -107,8 +119,6 @@

return {
document,
fetchDocumentByID,
fetchDocumentByPubmedID,
fetchDocumentSegments,
focusDocumentPageNumber,
clearDocument,
Expand Down
15 changes: 8 additions & 7 deletions extralit-frontend/v1/domain/entities/document/Document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ export class Segment {
public readonly header: string | null,
public readonly page_number: number | null,
public readonly type: string | null,
) {}
) { }

public static getDescription(segment: Segment): string {
let segmentDescription = Object.entries(segment)
.filter(([key, value]) => !['header', 'doc_id'].includes(key))
.map(([key, value]) => `${key}: ${value}`)
.join('\n');
return segmentDescription;
let segmentDescription = Object.entries(segment)
.filter(([key, value]) => !['header', 'doc_id'].includes(key))
.map(([key, value]) => `${key}: ${value}`)
.join('\n');
return segmentDescription;
}
}

export interface Segments {
items: Segment[];
items: Segment[];
}

export class Document {
Expand All @@ -27,6 +27,7 @@ export class Document {
public readonly url?: string,
public readonly file_name?: string,
public readonly pmid?: string,
public readonly doi?: string,
public readonly page_number?: number | string,
public reference?: string,
public segments?: Segment[],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,26 @@ export class GetDocumentByIdUseCase {
private readonly documentStorage: IDocumentStorage
) {}

async setDocumentByID(id: string) {
const document = await this.documentRepository.getDocumentById(id);
async setDocument(params: {
workspace_id: string;
doc_id?: string;
pmid?: string;
doi?: string;
reference?: string;
}) {
const documents = await this.documentRepository.getDocuments(params);

this.documentStorage.set(document);
}
if (documents.length === 0) {
throw new Error("No documents found with the provided criteria");
}

async setDocumentByPubmedID(id: string) {
const document = await this.documentRepository.getDocumentByPubmedID(id);
// For now, we'll use the first document found
// In the future, you might want to add logic to handle multiple documents
if (documents.length > 1) {
console.warn(`Multiple documents found (${documents.length}). Using the first one.`);
}

this.documentStorage.set(document);
this.documentStorage.set(documents[0]);
}

async setSegments(workspace: string, reference: string): Promise<Segment[]> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,29 @@ import { Document, Segment, Segments } from "@/v1/domain/entities/document/Docum

const DOCUMENT_API_ERRORS = {
ERROR_FETCHING_DOCUMENT: "ERROR_FETCHING_DOCUMENT",
ERROR_FETCHING_SEGMENTS: "ERROR_FETCHING_SEGMENTS",
};

export class DocumentRepository {
constructor(private readonly axios: NuxtAxiosInstance) {}

async getDocumentByPubmedID(pmid: string): Promise<Document> {
async getDocuments(params: {
workspace_id: string;
doc_id?: string;
pmid?: string;
doi?: string;
reference?: string;
}): Promise<Document[]> {
try {
const { data } = await this.axios.get<Document>(`/v1/documents/by-pmid/${pmid}`);
return data;
} catch (error) {
throw {
response: DOCUMENT_API_ERRORS.ERROR_FETCHING_DOCUMENT,
};
}
}
const queryParams = Object.fromEntries(Object.entries(params).filter(([_, value]) => value !== undefined));

async getDocumentById(id: string): Promise<Document> {
try {
const { data } = await this.axios.get<Document>(`/v1/documents/by-id/${id}`);
if (Object.keys(queryParams).length === 0) {
throw new Error("At least one identifier parameter must be provided");
}

const { data } = await this.axios.get<Document[]>("/v1/documents", {
params: queryParams,
});
return data;
} catch (error) {
throw {
Expand All @@ -39,7 +43,7 @@ export class DocumentRepository {
return data.items;
} catch (error) {
throw {
response: DOCUMENT_API_ERRORS.ERROR_FETCHING_DOCUMENT,
response: DOCUMENT_API_ERRORS.ERROR_FETCHING_SEGMENTS,
};
}
}
Expand Down
5 changes: 5 additions & 0 deletions extralit-server/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ These are the section headers that we use:
* "Security" in case of vulnerabilities.
-->

## [Extralit] [0.6.1](https://github.com/extralit/extralit/compare/v0.5.0...v0.6.1)

### Changed
- Replaced separate /documents/by-id/{id} and /documents/by-pmid/{pmid} endpoints with a single /documents endpoint that accepts workspace_id and one or more identifiers (id, pmid, doi, reference), returning a list of matching documents

## [Extralit] [0.6.0](https://github.com/extralit/extralit/compare/v0.5.0...v0.6.0)

### Added
Expand Down
Loading
Loading