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

Use config manager in Importers #54

Merged
merged 13 commits into from
Jun 12, 2020
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ app/renderer.prod.js.map
app/style.css
app/style.css.map
dist
dist_electron
dll
main.js
main.js.map
Expand Down
16 changes: 11 additions & 5 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ module.exports = {

env: {
browser: true,
node: true,
jest: true
node: true
},

extends: ['airbnb-base', 'plugin:vue/recommended'],
Expand Down Expand Up @@ -56,18 +55,25 @@ module.exports = {
'max-len': ['error', { code: 150 }],
'comma-dangle': 'off',
'no-await-in-loop': 'off',
'import/prefer-default-export': 'off'
'import/prefer-default-export': 'off',
'no-unused-vars': ['error', { args: 'after-used', argsIgnorePattern: '^_' }]
},

overrides: [
{
files: [
'**/__tests__/*.{j,t}s?(x)',
'**/tests/unit/**/*.spec.{j,t}s?(x)',
'**/test/**/*.spec.{j,t}s?(x)',
'**/*.test.{j,t}s?(x)'
],
env: {
jest: true,
},
},
{
files: ['src/originalBudgetTrackingApp/**/*'],
rules: {
'no-console': 'off'
}
}
],
};
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,5 @@ client_secret.json

src/originalBudgetTrackingApp/mockData
src/originalBudgetTrackingApp/categoryCalculationScript.js
config.json
config.encrypted
googleApiToken.json
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"vue-router": "^3.1.6",
"vuetify": "^2.2.22",
"vuex": "^3.1.3",
"vuex-electron": "^1.0.3",
"vuex-persist": "^2.2.0",
"ynab": "^1.19.0"
},
"devDependencies": {
Expand Down
29 changes: 16 additions & 13 deletions src/components/MainPage/Importers.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</v-toolbar>
<v-expansion-panels>
<v-expansion-panel
v-for="importer in importers"
v-for="importer in getImporters"
:key="importer.id"
class="ma-1"
>
Expand Down Expand Up @@ -51,12 +51,12 @@
</v-toolbar-title>
</v-toolbar>
<v-expansion-panels>
<add-scraper
v-for="scraper in scrapers"
:key="scraper.key"
:scraper="scraper"
class="add-scraper"
@scraperAdded="drawer = !drawer"
<add-importer
v-for="importer in importersToAdd"
:key="importer.key"
:importer="importer"
class="add-importer"
@importerAdded="drawer = !drawer"
/>
</v-expansion-panels>
</v-navigation-drawer>
Expand All @@ -80,24 +80,27 @@
</template>

<script>
import { GET_IMPORTERS_GETTER } from '@/store/modules/config';
import { mapGetters } from 'vuex';
import { scrapers } from '@/modules/scrapers';
import AddScraper from './Importers/AddScraper';
import importers from '@/modules/importers';
import AddImporter from './Importers/AddImporter';
import Importer from './Importers/Importer';

export default {
components: { AddScraper, Importer },
components: { AddImporter, Importer },
data() {
return {
id: null,
drawer: null,
};
},
computed: {
scrapers() {
return scrapers;
importersToAdd() {
return importers;
},
...mapGetters(['importers']),
...mapGetters({
getImporters: GET_IMPORTERS_GETTER
}),
},
methods: {
iconClass(success) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
<v-expansion-panel class="ma-1">
<v-expansion-panel-header
expand-icon="mdi-menu-down"
:data-test="scraper.key"
:data-test="importer.key"
>
{{ scraper.name }}
{{ importer.name }}
</v-expansion-panel-header>
<v-expansion-panel-content>
<v-form
Expand Down Expand Up @@ -48,27 +48,25 @@

<script>
import { mapActions } from 'vuex';
import { encryptProperty } from '@/modules/encryption/credentials';
import { ADD_IMPORTER_ACTION } from '@/store/modules/config';

function scraperToImporter(scraper) {
const importer = { ...scraper, loginFields: {} };
scraper.loginFields.forEach((element) => {
importer.loginFields[element] = null;
function initData(importerProp) {
const importerToAdd = { ...importerProp, loginFields: {} };
importerProp.loginFields.forEach((element) => {
importerToAdd.loginFields[element] = null;
});
return importer;
return { importerToAdd };
}

export default {
props: {
scraper: {
importer: {
type: Object,
required: true,
},
},
data() {
return {
importerToAdd: scraperToImporter(this.scraper),
};
return initData(this.importer);
},
computed: {
isFormValid() {
Expand All @@ -80,19 +78,17 @@ export default {
methods: {
async submitForm() {
if (this.isFormValid) {
const encrypted = await encryptProperty(
this.importerToAdd,
'loginFields',
);
this.addImporterAction(encrypted);
this.addImporter(this.importerToAdd);
this.resetForm();
this.$emit('scraperAdded', true);
this.$emit('importerAdded', true);
}
},
resetForm() {
Object.assign(this.$data.importerToAdd, scraperToImporter(this.scraper));
Object.assign(this.$data, initData(this.importer));
},
...mapActions(['addImporterAction']),
...mapActions({
addImporter: ADD_IMPORTER_ACTION
})
},
};
</script>
Expand Down
123 changes: 52 additions & 71 deletions src/components/MainPage/Importers/Importer.vue
Original file line number Diff line number Diff line change
@@ -1,65 +1,57 @@
<template>
<div>
<v-card
v-if="decryptedImporter"
<v-card>
<v-checkbox
v-model="showBrowser"
label="Show browser"
/>
<div
v-for="(value, loginField) in importer.loginFields"
:key="loginField"
>
{{ loginField }}:
{{ loginField != "password" ? value : "*".repeat(value.length) }}
</div>
<v-btn
color="primary"
class="mx-1"
:loading="importing"
@click="scrape()"
>
Import
</v-btn>
<v-btn
color="error"
dark
class="mx-1"
@click="deleteDialog = true"
>
<v-checkbox
v-model="showBrowser"
:label="`Show browser`"
/>
<div
v-for="(value, loginField) in decryptedImporter.loginFields"
:key="loginField"
>
{{ loginField }}:
{{ loginField != "password" ? value : "*".repeat(value.length) }}
</div>
<v-btn
color="primary"
class="mx-1"
:loading="importing"
@click="scrape()"
>
Import
</v-btn>
<v-btn
color="error"
dark
class="mx-1"
@click="deleteDialog = true"
>
<v-icon>mdi-delete</v-icon>
Delete
</v-btn>
<DeleteImporterDialog
v-model="deleteDialog"
@confirm="DeleteImporter"
/>
<v-progress-linear
v-show="importing"
v-model="percentage"
height="25"
reactive
>
<template v-slot="{ value }">
<strong>{{ value }}%</strong>
</template>
</v-progress-linear>
<div v-show="importing">
{{ step }}
</div>
</v-card>
<v-skeleton-loader
v-else
type="paragraph"
<v-icon>mdi-delete</v-icon>
Delete
</v-btn>
<DeleteImporterDialog
v-model="deleteDialog"
@confirm="DeleteImporter"
/>
</div>
<v-progress-linear
v-show="importing"
v-model="percentage"
height="25"
reactive
>
<template v-slot="{ value }">
<strong>{{ value }}%</strong>
</template>
</v-progress-linear>
<div v-show="importing">
{{ step }}
</div>
</v-card>
</template>

<script>
import { mapActions } from 'vuex';
import { remote } from 'electron';
import { decryptProperty } from '@/modules/encryption/credentials';
import { REMOVE_IMPORTER_ACTION } from '@/store/modules/config';
import { scrape } from '@/modules/scrapers';
import DeleteImporterDialog from '@/components/MainPage/Importers/DeleteImporterDialog';

Expand All @@ -76,34 +68,23 @@ export default {
data() {
return {
importing: false,
// TODO: show browser should be in config. Also maybe one for all accounts
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes and yes. In general I think the common usecase is scrape all importers and then this type of configuration is global

showBrowser: false,
decryptedImporter: null,
percentage: 0,
step: '',
status: undefined,
deleteDialog: false,
};
},
created() {
this.decryptedImporter = decryptProperty(this.importer, 'loginFields').then(
(decrypted) => {
this.$logger.info(
`Importer '${this.importer.name}' with id:${this.importer.id} `
+ `decrypted with ${Object.keys(decrypted.loginFields).length} fields`,
);
this.decryptedImporter = decrypted;
},
);
},
methods: {
async scrape() {
this.importing = true;
this.onProgress({ percent: 0, message: `Request to import ${this.decryptedImporter.key}` });
this.onProgress({ percent: 0, message: `Request to import ${this.importer.key}` });
try {
const result = await scrape(
remote.app.getPath('cache'),
this.decryptedImporter.key,
this.decryptedImporter.loginFields,
this.importer.key,
this.importer.loginFields,
this.showBrowser,
this.onProgress,
this.$logger,
Expand Down Expand Up @@ -148,10 +129,10 @@ export default {
},
DeleteImporter() {
this.deleteDialog = false;
this.removeImporterAction(this.decryptedImporter.id);
this[REMOVE_IMPORTER_ACTION](this.importer.id);
},
...mapActions([
'removeImporterAction',
REMOVE_IMPORTER_ACTION,
'addTransactionsAction',
'updateImporterStatus',
]),
Expand Down
5 changes: 5 additions & 0 deletions src/modules/importers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import scrapers from './scrapers';

export default [
...scrapers
];
7 changes: 7 additions & 0 deletions src/modules/importers/scrapers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { SCRAPERS } from 'israeli-bank-scrapers-core';

export default Object.keys(SCRAPERS)
.map((key) => ({
key,
...SCRAPERS[key],
}));
9 changes: 1 addition & 8 deletions src/modules/scrapers.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
/* eslint-disable max-len */
import { createScraper, SCRAPERS } from 'israeli-bank-scrapers-core';
import { createScraper } from 'israeli-bank-scrapers-core';
import getChrome from './downloadChromium';

Copy link
Owner

@brafdlog brafdlog Jun 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change broke the import in Launch.spec.js and importers.vue.spec.js

export const scrapers = Object.keys(SCRAPERS)
.filter((key) => key !== 'leumiCard')
.map((key) => ({
key,
...SCRAPERS[key],
}));

export async function scrape(
installPath,
scraperName,
Expand Down
Loading