Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for PDF reports #319

Merged
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
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ bfx-reports-framework/config/*.json
bfx-reports-framework/config/facs/*.json
bfx-reports-framework/logs/*.log
bfx-reports-framework/csv
bfx-reports-framework/report-files
bfx-report-ui/build
bfx-report-ui/bfx-report-express/logs/*.log
bfx-report-ui/bfx-report-express/config/*.json
Expand Down
1 change: 1 addition & 0 deletions electron-builder-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ module.exports = {
'!bfx-reports-framework/*/*.sh',
'!bfx-reports-framework/*.sh',
'!bfx-reports-framework/.mocharc.json',
'!bfx-reports-framework/node_modules/phantomjs-prebuilt',

'!**/.dockerignore',
'!**/*Dockerfile*',
Expand Down
18 changes: 11 additions & 7 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const {

const {
WrongPathToUserDataError,
WrongPathToUserCsvError,
WrongPathToUserReportFilesError,
WrongSecretKeyError
} = require('./src/errors')

Expand Down Expand Up @@ -76,7 +76,9 @@ const allowedProcessMessagesSet = _getAllowedStatesSet({

'RESPONSE_GET_BACKUP_FILES_METADATA',

'RESPONSE_UPDATE_USERS_SYNC_ON_STARTUP_REQUIRED_STATE'
'RESPONSE_UPDATE_USERS_SYNC_ON_STARTUP_REQUIRED_STATE',

'REQUEST_PDF_CREATION'
]
})
const allowedProcessStatesSet = _getAllowedStatesSet({
Expand All @@ -92,14 +94,16 @@ const allowedProcessStatesSet = _getAllowedStatesSet({

'REQUEST_GET_BACKUP_FILES_METADATA',

'REQUEST_UPDATE_USERS_SYNC_ON_STARTUP_REQUIRED_STATE'
'REQUEST_UPDATE_USERS_SYNC_ON_STARTUP_REQUIRED_STATE',

'RESPONSE_PDF_CREATION'
]
})

;(async () => {
try {
const pathToUserData = process.env.PATH_TO_USER_DATA
const pathToUserCsv = process.env.PATH_TO_USER_CSV
const pathToUserReportFiles = process.env.PATH_TO_USER_REPORT_FILES
const schedulerRule = process.env.SCHEDULER_RULE
const secretKey = process.env.SECRET_KEY
const grape1DhtPort = process.env.GRAPE_1DHT_PORT
Expand All @@ -116,8 +120,8 @@ const allowedProcessStatesSet = _getAllowedStatesSet({
if (!pathToUserData) {
throw new WrongPathToUserDataError()
}
if (!pathToUserCsv) {
throw new WrongPathToUserCsvError()
if (!pathToUserReportFiles) {
throw new WrongPathToUserReportFilesError()
}

const grape = `http://127.0.0.1:${grape2ApiPort}`
Expand Down Expand Up @@ -162,7 +166,7 @@ const allowedProcessStatesSet = _getAllowedStatesSet({
'--isSchedulerEnabled=true',
'--isElectronjsEnv=true',
'--isLoggerDisabled=false',
`--csvFolder=${pathToUserCsv}`,
`--reportFolder=${pathToUserReportFiles}`,
`--tempFolder=${pathToUserData}/temp`,
`--logsFolder=${pathToUserData}/logs`,
`--dbFolder=${pathToUserData}`,
Expand Down
6 changes: 3 additions & 3 deletions src/change-reports-folder.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const { dialog, BrowserWindow } = require('electron')

const { CSV_PATH_VERSION } = require('./const')
const { REPORT_FILES_PATH_VERSION } = require('./const')

const {
InvalidFilePathError,
Expand Down Expand Up @@ -52,8 +52,8 @@ module.exports = ({ pathToUserDocuments }) => {
await pauseApp()
const isSaved = await getConfigsKeeperByName('main')
.saveConfigs({
csvPathVersion: CSV_PATH_VERSION,
pathToUserCsv: filePaths[0]
reportFilesPathVersion: REPORT_FILES_PATH_VERSION,
pathToUserReportFiles: filePaths[0]
})

if (!isSaved) {
Expand Down
4 changes: 2 additions & 2 deletions src/const.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const DB_FILE_NAME = 'db-sqlite_sync_m0.db'
const DB_SHM_FILE_NAME = `${DB_FILE_NAME}-shm`
const DB_WAL_FILE_NAME = `${DB_FILE_NAME}-wal`
const SECRET_KEY_FILE_NAME = 'secret-key'
const CSV_PATH_VERSION = 1
const REPORT_FILES_PATH_VERSION = 1

module.exports = {
CONFIGS_FILE_NAME,
Expand All @@ -15,5 +15,5 @@ module.exports = {
DB_SHM_FILE_NAME,
DB_WAL_FILE_NAME,
SECRET_KEY_FILE_NAME,
CSV_PATH_VERSION
REPORT_FILES_PATH_VERSION
}
6 changes: 3 additions & 3 deletions src/errors/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ class WrongPathToUserDataError extends BaseError {
}
}

class WrongPathToUserCsvError extends BaseError {
constructor (message = 'ERR_WRONG_PATH_TO_USER_CSV') {
class WrongPathToUserReportFilesError extends BaseError {
constructor (message = 'ERR_WRONG_PATH_TO_USER_REPORT_FILES') {
super(message)
}
}
Expand Down Expand Up @@ -124,7 +124,7 @@ module.exports = {
AppInitializationError,
FreePortError,
WrongPathToUserDataError,
WrongPathToUserCsvError,
WrongPathToUserReportFilesError,
WrongSecretKeyError,
ReportsFolderChangingError,
SyncFrequencyChangingError,
Expand Down
60 changes: 17 additions & 43 deletions src/initialize-app.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
const { app } = require('electron')
const path = require('path')

const { CSV_PATH_VERSION } = require('./const')
const { REPORT_FILES_PATH_VERSION } = require('./const')

const triggerSyncAfterUpdates = require('./trigger-sync-after-updates')
const triggerElectronLoad = require('./trigger-electron-load')
Expand Down Expand Up @@ -41,6 +41,7 @@ const enforceMacOSAppLocation = require(
const manageWorkerMessages = require(
'./manage-worker-messages'
)
const printToPDF = require('./print-to-pdf')

const pathToLayouts = path.join(__dirname, 'layouts')
const pathToLayoutAppInitErr = path
Expand All @@ -50,52 +51,26 @@ const { rule: schedulerRule } = require(
'../bfx-reports-framework/config/schedule.json'
)

const _resetCsvPath = async (
const _resetReportFilesPath = async (
configsKeeper,
opts = {}
) => {
const {
pathToUserCsv,
isRelativeCsvPath
pathToUserReportFiles
} = opts

// Need to use a new csv folder path for export
const storedPathToUserCsv = configsKeeper
.getConfigByName('pathToUserCsv')
const csvPathVersion = configsKeeper
.getConfigByName('csvPathVersion')

if (csvPathVersion === CSV_PATH_VERSION) {
return
}
if (
(
isRelativeCsvPath &&
!storedPathToUserCsv.endsWith('csv')
) ||
(
!isRelativeCsvPath &&
!storedPathToUserCsv.endsWith('bitfinex/reports')
) ||
(
!isRelativeCsvPath &&
!path.isAbsolute(storedPathToUserCsv)
) ||
(
isRelativeCsvPath &&
path.isAbsolute(storedPathToUserCsv)
)
) {
await configsKeeper.saveConfigs({
csvPathVersion: CSV_PATH_VERSION,
pathToUserCsv
})
// Need to use a new report folder path for export
const reportFilesPathVersion = configsKeeper
.getConfigByName('reportFilesPathVersion') ??
configsKeeper.getConfigByName('csvPathVersion') // For back compatibility

if (reportFilesPathVersion === REPORT_FILES_PATH_VERSION) {
return
}

await configsKeeper.saveConfigs({
csvPathVersion: CSV_PATH_VERSION
reportFilesPathVersion: REPORT_FILES_PATH_VERSION,
pathToUserReportFiles
})
}

Expand Down Expand Up @@ -153,26 +128,23 @@ const _manageConfigs = (params = {}) => {
pathToUserDocuments
} = params

const pathToUserCsv = path.join(
const pathToUserReportFiles = path.join(
pathToUserDocuments,
'bitfinex/reports'
)

const configsKeeper = configsKeeperFactory(
{ pathToUserData },
{
pathToUserCsv,
pathToUserReportFiles,
schedulerRule,
shownChangelogVer: '0.0.0',
triggeredSyncAfterUpdatesVer: '0.0.0'
}
)
_resetCsvPath(
_resetReportFilesPath(
configsKeeper,
{
pathToUserCsv,
isRelativeCsvPath: true
}
{ pathToUserReportFiles }
)
}

Expand Down Expand Up @@ -222,6 +194,8 @@ module.exports = async () => {
await triggerElectronLoad(portsMap)
await checkForUpdatesAndNotify()
await manageChangelog()

printToPDF()
} catch (err) {
await createErrorWindow(pathToLayoutAppInitErr)

Expand Down
109 changes: 109 additions & 0 deletions src/print-to-pdf/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
'use strict'

const { BrowserWindow } = require('electron')
const fs = require('fs/promises')
const path = require('path')

const ipcs = require('../ipcs')
const wins = require('../windows')

const PROCESS_MESSAGES = require(
'../../bfx-reports-framework/workers/loc.api/process.message.manager/process.messages'
)
const PROCESS_STATES = require(
'../../bfx-reports-framework/workers/loc.api/process.message.manager/process.states'
)

module.exports = () => {
ipcs.serverIpc.on('message', async (mess) => {
try {
if (mess?.state !== PROCESS_MESSAGES.REQUEST_PDF_CREATION) {
return
}

const {
templateFilePath,
template = 'No data',
format = 'portrait',
orientation = 'Letter',
uid = null
} = mess?.data ?? {}

const isTemplateFilePathUsed = (
templateFilePath &&
typeof templateFilePath === 'string'
)

const html = isTemplateFilePathUsed
? await fs.readFile(templateFilePath, { encoding: 'utf8' })
: template

if (isTemplateFilePathUsed) {
await fs.rm(templateFilePath, { force: true, maxRetries: 3 })
}

const win = new BrowserWindow({
show: false,
parent: wins.mainWindow,
webPreferences: {
nodeIntegration: true
}
})
win.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(html)}`)

await new Promise((resolve, reject) => {
win.webContents.on('did-finish-load', resolve)
win.webContents.on('did-fail-load', (e, code, err) => {
reject(err)
})
})
const buffer = await win.webContents.printToPDF({
landscape: format !== 'portrait',
pageSize: orientation,
margins: {
top: 0,
bottom: 0,
left: 0,
right: 0
},
displayHeaderFooter: true,
footerTemplate: `\
<span style="
position: absolute;
right: 10px;
bottom: 10px;
font-weight: 400;
font-size: 8px;
">
Page <span class=pageNumber></span> from <span class=totalPages></span>
</span>`
})

if (isTemplateFilePathUsed) {
const { dir, name } = path.parse(templateFilePath)
const pdfFilePath = path.format({ dir, name, ext: '.pdf' })

await fs.writeFile(pdfFilePath, buffer)

ipcs.serverIpc.send({
state: PROCESS_STATES.RESPONSE_PDF_CREATION,
data: { pdfFilePath, uid }
})

return
}

ipcs.serverIpc.send({
state: PROCESS_STATES.RESPONSE_PDF_CREATION,
data: { buffer, uid }
})
} catch (err) {
ipcs.serverIpc.send({
state: PROCESS_STATES.RESPONSE_PDF_CREATION,
data: { err, uid: mess?.data?.uid ?? null }
})

console.error(err)
}
})
}
4 changes: 2 additions & 2 deletions src/run-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ module.exports = ({
const env = {
...process.env,
PATH_TO_USER_DATA: pathToUserData,
PATH_TO_USER_CSV: mainConfsKeeper
.getConfigByName('pathToUserCsv'),
PATH_TO_USER_REPORT_FILES: mainConfsKeeper
.getConfigByName('pathToUserReportFiles'),
SCHEDULER_RULE: mainConfsKeeper
.getConfigByName('schedulerRule'),
SECRET_KEY: secretKey,
Expand Down