Skip to content

Commit

Permalink
Stop inserting already existing books from wook into db
Browse files Browse the repository at this point in the history
Much better API for using IPC
  • Loading branch information
diogotcorreia committed Jul 2, 2021
1 parent 7d63837 commit f058468
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 37 deletions.
62 changes: 36 additions & 26 deletions src/components/Orders/imports/ImportFromSchool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ import { useSnackbar } from 'notistack';
import React, { useState } from 'react';
import wookLogo from '../../../assets/wook.png';
import { Book } from '../../../types/database';

const { ipcRenderer } = require('electron');
import {
importFromWook,
insertOrGetBooks,
parseImportFromWook,
} from '../../../utils/api';

type Props = {
addBooks: (books: Array<Book>) => void;
Expand All @@ -38,43 +41,50 @@ const useStyles = makeStyles((theme) => ({
}));

export default function ImportFromSchool({ addBooks }: Props) {
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
const classes = useStyles();
const { enqueueSnackbar } = useSnackbar();

const openWook = () => {
ipcRenderer.send('order-import-wook-open');
const openWook = async () => {
setOpen(true);
const wookIds = await importFromWook();
setOpen(false);

if (!wookIds) {
enqueueSnackbar(`Operação cancelada.`, { variant: 'error' });
return;
}

setLoading(true);
const bookData = await parseImportFromWook(wookIds);
const insertedBookData = await insertOrGetBooks(bookData);

setLoading(false);
if (!insertedBookData) {
enqueueSnackbar('Ocorreu um erro a guardar os livros', {
variant: 'error',
});
return;
}

ipcRenderer.once(
'order-import-wook-result',
(_: never, result: string[]) => {
if (result) {
setLoading(true);
ipcRenderer.send('order-import-wook-parse', result);
addBooks(insertedBookData);

ipcRenderer.once(
'order-import-wook-parse-result',
(__: never, parseResult: Book[]) => {
setLoading(false);
parseResult.forEach((book) =>
ipcRenderer.send('db-books-insert', book)
);
addBooks(parseResult);
}
);
return;
}
enqueueSnackbar(`Operação cancelada.`, { variant: 'error' });
}
);
if (wookIds.length > insertedBookData.length)
enqueueSnackbar(
`Não foi possível importar ${
wookIds.length - insertedBookData.length
} livro(s)`,
{ variant: 'warning' }
);
};

/* TODO Disable navigation and screen interaction while Wook is open */

return (
<div className={classes.root}>
<Card className={classes.cardContent}>
<CardActionArea disabled={loading} onClick={openWook}>
<CardActionArea disabled={open || loading} onClick={openWook}>
<img className={classes.cardImage} src={wookLogo} alt="Wook" />
<CardContent>
<Typography variant="h5">Importar por ano e escola</Typography>
Expand Down
57 changes: 51 additions & 6 deletions src/server/queries/books.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ipcMain, IpcMainEvent } from 'electron';
import log from 'electron-log';
import db from '../database';
import getBookMetadata from '../../utils/bookMetadata';
import { Book } from '../../types/database';

ipcMain.on('db-books-find', async (event: IpcMainEvent) => {
const result = await db
Expand All @@ -11,13 +12,8 @@ ipcMain.on('db-books-find', async (event: IpcMainEvent) => {
event.reply('db-result-books-find', result);
});

type BookInsertArgs = {
isbn: string;
name: string;
publisher: string;
type: 'manual' | 'ca' | 'other';
type BookInsertArgs = Book & {
schoolYear: string;
codePe: string;
stock: string;
};

Expand Down Expand Up @@ -46,6 +42,55 @@ ipcMain.on(
}
);

ipcMain.on(
'db-books-insert-or-get',
async (event: IpcMainEvent, args: Book[]) => {
try {
const books = await db.transaction(async (trx) => {
return Promise.all(
args.map(async (book) => {
const result = await trx
.select(
'isbn',
'name',
'publisher',
'type',
'schoolYear',
'codePe',
'stock',
'created_at',
'updated_at'
)
.where('isbn', book?.isbn)
.from('books');
if (result.length === 0) {
await trx
.insert({
created_at: db.fn.now(),
updated_at: db.fn.now(),
isbn: book.isbn,
name: book.name || '',
publisher: book.publisher || '',
type: book.type || '',
codePe: book.codePe || '',
stock: book.stock || 0,
schoolYear: book.schoolYear || null,
})
.into('books');
return book;
}
return result[0];
})
);
});
event.reply('db-books-insert-or-get-result', books);
} catch (e) {
log.error(e);
event.reply('db-books-insert-or-get-result', false);
}
}
);

ipcMain.on('db-book-find-one', async (event: IpcMainEvent, isbn: string) => {
try {
const bookData = await db
Expand Down
17 changes: 13 additions & 4 deletions src/server/queries/orderImports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ ipcMain.on('order-import-wook-open', (event: IpcMainEvent) => {

if (data.length > 0) {
clearInterval(intervalId);
event.reply('order-import-wook-result', data);
event.reply('order-import-wook-open-result', data);
window.destroy();
}
} catch (e) {
Expand All @@ -42,16 +42,25 @@ ipcMain.on('order-import-wook-open', (event: IpcMainEvent) => {

window.on('close', () => {
clearInterval(intervalId);
event.reply('order-import-wook-result', false);
event.reply('order-import-wook-open-result', false);
});
});

ipcMain.on(
'order-import-wook-parse',
async (event: IpcMainEvent, books: string[]) => {
const booksUnique = [...new Set(books)];

const metadata = await Promise.all(
books.map((url) => getMetadataByURL(`https://wook.pt/Artigos/?id=${url}`))
booksUnique.map((url) =>
getMetadataByURL(`https://wook.pt/Artigos/?id=${url}`)
)
);

event.reply(
'order-import-wook-parse-result',
// filter out failed books
metadata.filter((book) => !!book)
);
event.reply('order-import-wook-parse-result', metadata);
}
);
1 change: 0 additions & 1 deletion src/server/queries/orders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ ipcMain.on('db-order-find-one', async (event: IpcMainEvent, id: number) => {
'pickedup_quantity as pickedupQuantity',
'name',
'publisher',
'provider',
'type',
'schoolYear',
'codePe',
Expand Down
25 changes: 25 additions & 0 deletions src/utils/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Book } from '../types/database';

const { ipcRenderer } = require('electron');

export const fetchFromIpc = <T>(channel: string, ...args: unknown[]) =>
new Promise<T>((resolve) => {
ipcRenderer.once(`${channel}-result`, (_: unknown, result: T) =>
resolve(result)
);

ipcRenderer.send(channel, ...args);
});

/* orderImports.ts */

export const importFromWook = () =>
fetchFromIpc<string[] | false>('order-import-wook-open');

export const parseImportFromWook = (wookIds: string[]) =>
fetchFromIpc<Book[]>('order-import-wook-parse', wookIds);

/* books.ts */

export const insertOrGetBooks = (books: Book[]) =>
fetchFromIpc<Book[]>('db-books-insert-or-get', books);
3 changes: 3 additions & 0 deletions src/utils/bookMetadata.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import axios from 'axios';
import log from 'electron-log';

const WOOK_REGEX = /<script type="application\/ld\+json">[^]*?({[^]+})[^]*?<\/script>[^]*?<!-- Fim Google/;

Expand Down Expand Up @@ -37,6 +38,7 @@ const getBookCodeFromPEGroup = async (publisherUrl: string) => {
)?.[1] || '',
};
} catch (e) {
log.error('Failed to get book code from PE group', publisherUrl, e);
return {};
}
};
Expand Down Expand Up @@ -95,6 +97,7 @@ export const getMetadataByURL = async (url: string) => {
};
return metadata;
} catch (e) {
log.error('Failed to get book metadata', url, e);
return false;
}
};
Expand Down

0 comments on commit f058468

Please sign in to comment.