diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml
index 145fe8bef..3cfc64ab9 100644
--- a/.github/workflows/workflow.yml
+++ b/.github/workflows/workflow.yml
@@ -14,15 +14,21 @@ env:
jobs:
pre-commit:
runs-on: ubuntu-latest
+ permissions:
+ packages: read
+
steps:
- uses: actions/checkout@v3.5.3
- name: Cache dependencies
uses: actions/setup-node@v3
with:
- node-version: '16'
+ node-version: '20'
cache: 'npm'
+ - name: set npm auth
+ run: echo "//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}" > ~/.npmrc
+
- name: install node modules
run: npm ci
@@ -30,6 +36,8 @@ jobs:
cypress:
runs-on: ubuntu-latest
+ permissions:
+ packages: read
# Current backend version as service container
services:
@@ -44,6 +52,9 @@ jobs:
steps:
- uses: actions/checkout@v3.5.3
+ - name: set npm auth
+ run: echo "//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}" > ~/.npmrc
+
- uses: cypress-io/github-action@v5.8.3
env:
PORT: 3001
@@ -106,9 +117,9 @@ jobs:
- name: Build and push Docker image
uses: docker/build-push-action@v4.1.1
with:
- context: .
push: ${{ steps.push_check.outputs.push }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
REACT_APP_VERSION=${{ github.ref_name }}
+ GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 000000000..13a79428e
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+@envelope-zero:registry=https://npm.pkg.github.com
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1a819e650..fd6dadada 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -4,11 +4,12 @@ Contributions are welcome. Please note the [Code of Conduct](CODE_OF_CONDUCT.md)
## Tool & Repository setup
-You will need the following tools:
+You will need to:
-- [pre-commit](https://pre-commit.com/)
+- Install [pre-commit](https://pre-commit.com/)
+- Set up a GitHub Personal Access Token to read from the GitHub package repository. Follow the steps in https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry#authenticating-with-a-personal-access-token.
-Once those are installed, run `make setup` to perform the repository setup.
+Once these steps are done, run `make setup` to perform the repository setup.
## Development server
diff --git a/Dockerfile b/Dockerfile
index da2a398ac..fb72855e5 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,10 +1,13 @@
-FROM node:20.5.1-alpine AS builder
+FROM node:20.3.1-alpine AS builder
ENV NODE_ENV production
WORKDIR /app
# copy package.json first to avoid unnecessary npm install
COPY package.json package-lock.json /app/
-RUN npm install --production
+
+ARG GITHUB_TOKEN
+RUN echo "//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}" > ~/.npmrc && \
+ npm install --production
# Copy app files
COPY src /app/src
diff --git a/cypress/e2e/transaction-import.cy.ts b/cypress/e2e/transaction-import.cy.ts
index 66797f2fb..1025bcd15 100644
--- a/cypress/e2e/transaction-import.cy.ts
+++ b/cypress/e2e/transaction-import.cy.ts
@@ -35,9 +35,7 @@ describe('Transaction Import', () => {
cy.contains('My Other Account')
cy.contains('My Account').click()
- cy.getInputFor('File').selectFile(
- 'cypress/fixtures/transactions-parsed.csv'
- )
+ cy.getInputFor('File').selectFile('cypress/fixtures/comdirect.csv')
cy.clickAndWait('Submit')
@@ -163,9 +161,7 @@ describe('Transaction Import', () => {
cy.awaitLoading()
cy.getInputFor('Account').type('My account{enter}')
- cy.getInputFor('File').selectFile(
- 'cypress/fixtures/transactions-parsed.csv'
- )
+ cy.getInputFor('File').selectFile('cypress/fixtures/comdirect.csv')
cy.clickAndWait('Submit')
cy.contains('This is a duplicate of an existing transaction')
diff --git a/cypress/fixtures/comdirect.csv b/cypress/fixtures/comdirect.csv
new file mode 100644
index 000000000..6d291a3a1
--- /dev/null
+++ b/cypress/fixtures/comdirect.csv
@@ -0,0 +1,11 @@
+;
+"Umsätze Verrechnungskonto ";"Zeitraum: 30 Tage";
+"Neuer Kontostand";"16,94 EUR";
+
+"Buchungstag";"Wertstellung (Valuta)";"Vorgang";"Buchungstext";"Umsatz in EUR";
+"20.06.2023";"20.06.2023";"Irrevevant";"Empfänger: Non Existing Account Buchungstext: Text Ref. 000000000/0 ";"-84,76";
+"19.06.2023";"19.06.2023";"Irrevevant";"Auftraggeber: My Other Account Buchungstext: Transfer from my other account Ref. 0000000000000/0 ";"5,00";
+"16.06.2023";"16.06.2023";"Irrevevant";"Empfänger: New Account Buchungstext: REDACTED Ref. 000000000/0 ";"-784,94";
+"15.06.2023";"15.06.2023";"Irrevevant";"Auftraggeber: External Account Buchungstext: Text Ref. 000000000/0 ";"-52,03";
+
+"Alter Kontostand";"16,89 EUR";
diff --git a/cypress/fixtures/transactions-parsed.csv b/cypress/fixtures/transactions-parsed.csv
deleted file mode 100644
index bb3558940..000000000
--- a/cypress/fixtures/transactions-parsed.csv
+++ /dev/null
@@ -1,5 +0,0 @@
-Date,Payee,Memo,Outflow,Inflow
-06/20/2023,Non Existing Account,Text,84.76,
-06/19/2023,My Other Account,Transfer from my other account,,5.00
-06/16/2023,New Account,REDACTED,784.94,
-06/15/2023,External Account,Text,52.03,
diff --git a/package-lock.json b/package-lock.json
index 5320ead01..c541662e2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6,6 +6,7 @@
"": {
"name": "envelope-zero-frontend",
"dependencies": {
+ "@envelope-zero/ynap-parsers": "1.15.11",
"@headlessui/react": "1.7.16",
"@heroicons/react": "2.0.18",
"@tailwindcss/forms": "0.5.4",
@@ -16,6 +17,7 @@
"@types/node": "18.17.5",
"@types/react": "18.2.20",
"@types/react-dom": "18.2.7",
+ "buffer": "6.0.3",
"flowbite": "1.8.1",
"flowbite-react": "0.5.0",
"http-proxy-middleware": "2.0.6",
@@ -2303,6 +2305,25 @@
"ms": "^2.1.1"
}
},
+ "node_modules/@envelope-zero/ynap-parsers": {
+ "version": "1.15.11",
+ "resolved": "https://npm.pkg.github.com/download/@envelope-zero/ynap-parsers/1.15.11/b0a58550aa25ec7c951ab18141501146412a41de",
+ "integrity": "sha512-sQCVJPeGaW/RmUoYqnNoQxjzwyiMe9gRBiUyhcLJrWbLE7AWr8HZCl3PgUEFPRai8ArXsptcXhteBE4yxhdmBQ==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer": "6.0.3",
+ "date-fns": "2.30.0",
+ "iban": "0.0.14",
+ "iconv-lite": "0.6.3",
+ "jschardet": "3.0.0",
+ "lodash": "4.17.21",
+ "mdn-polyfills": "5.20.0",
+ "mt940-js": "1.0.0",
+ "papaparse": "5.4.1",
+ "slugify": "1.6.6",
+ "xlsx": "^0.18.0"
+ }
+ },
"node_modules/@eslint/eslintrc": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz",
@@ -4872,6 +4893,14 @@
"node": ">=8.9"
}
},
+ "node_modules/adler-32": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz",
+ "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@@ -5555,7 +5584,6 @@
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -5759,10 +5787,9 @@
}
},
"node_modules/buffer": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
- "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
- "dev": true,
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+ "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
"funding": [
{
"type": "github",
@@ -5779,7 +5806,7 @@
],
"dependencies": {
"base64-js": "^1.3.1",
- "ieee754": "^1.1.13"
+ "ieee754": "^1.2.1"
}
},
"node_modules/buffer-crc32": {
@@ -5916,6 +5943,18 @@
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==",
"dev": true
},
+ "node_modules/cfb": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz",
+ "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
+ "dependencies": {
+ "adler-32": "~1.3.0",
+ "crc-32": "~1.2.0"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -6119,6 +6158,14 @@
"node": ">= 4.0"
}
},
+ "node_modules/codepage": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
+ "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/collect-v8-coverage": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz",
@@ -6354,6 +6401,17 @@
"node": ">=10"
}
},
+ "node_modules/crc-32": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
+ "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
+ "bin": {
+ "crc32": "bin/crc32.njs"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -6854,6 +6912,30 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
+ "node_modules/cypress/node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
"node_modules/cypress/node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -7025,6 +7107,21 @@
"node": ">=10"
}
},
+ "node_modules/date-fns": {
+ "version": "2.30.0",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
+ "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
+ "dependencies": {
+ "@babel/runtime": "^7.21.0"
+ },
+ "engines": {
+ "node": ">=0.11"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/date-fns"
+ }
+ },
"node_modules/dayjs": {
"version": "1.11.5",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.5.tgz",
@@ -9000,6 +9097,14 @@
"node": ">= 0.6"
}
},
+ "node_modules/frac": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
+ "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/fraction.js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
@@ -9701,6 +9806,11 @@
"@babel/runtime": "^7.22.5"
}
},
+ "node_modules/iban": {
+ "version": "0.0.14",
+ "resolved": "https://registry.npmjs.org/iban/-/iban-0.0.14.tgz",
+ "integrity": "sha512-+rocNKk+Ga9m8Lr9fTMWd+87JnsBrucm0ZsIx5ROOarZlaDLmd+FKdbtvb0XyoBw9GAFOYG2GuLqoNB16d+p3w=="
+ },
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
@@ -9743,7 +9853,6 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -12406,6 +12515,14 @@
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
"dev": true
},
+ "node_modules/jschardet": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-3.0.0.tgz",
+ "integrity": "sha512-lJH6tJ77V8Nzd5QWRkFYCLc13a3vADkh3r/Fi8HupZGWk2OVVDfnZP8V/VgQgZ+lzW0kG2UGb5hFgt3V3ndotQ==",
+ "engines": {
+ "node": ">=0.1.90"
+ }
+ },
"node_modules/jsdom": {
"version": "16.7.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz",
@@ -12971,6 +13088,11 @@
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz",
"integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA=="
},
+ "node_modules/mdn-polyfills": {
+ "version": "5.20.0",
+ "resolved": "https://registry.npmjs.org/mdn-polyfills/-/mdn-polyfills-5.20.0.tgz",
+ "integrity": "sha512-AbTv1ytcoOUAkxw6u5oo2QPf27kEZgxBAQr49jFb4i2VnTnFGfJbcIQ9UDBOdfNECeXsgkYFwB2BkdeTfOzztw=="
+ },
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@@ -13205,6 +13327,11 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
+ "node_modules/mt940-js": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/mt940-js/-/mt940-js-1.0.0.tgz",
+ "integrity": "sha512-9iFCkaGoUbo8FfkchMyMsUBxwmOVQbIQpgc7C0tHf6xDSzv+soVvx4PNNng/eQm/vFvCGl7ot4zJRK7Zs4veww=="
+ },
"node_modules/multicast-dns": {
"version": "7.2.4",
"resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.4.tgz",
@@ -13612,6 +13739,11 @@
"node": ">=6"
}
},
+ "node_modules/papaparse": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz",
+ "integrity": "sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw=="
+ },
"node_modules/param-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
@@ -16416,6 +16548,14 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
+ "node_modules/slugify": {
+ "version": "1.6.6",
+ "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz",
+ "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
"node_modules/sockjs": {
"version": "0.3.24",
"resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz",
@@ -16549,6 +16689,17 @@
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
},
+ "node_modules/ssf": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz",
+ "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
+ "dependencies": {
+ "frac": "~1.1.2"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/sshpk": {
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
@@ -18239,6 +18390,22 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/wmf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz",
+ "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/word": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz",
+ "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
@@ -18745,6 +18912,26 @@
}
}
},
+ "node_modules/xlsx": {
+ "version": "0.18.5",
+ "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz",
+ "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==",
+ "dependencies": {
+ "adler-32": "~1.3.0",
+ "cfb": "~1.2.1",
+ "codepage": "~1.15.0",
+ "crc-32": "~1.2.1",
+ "ssf": "~0.11.2",
+ "wmf": "~1.0.1",
+ "word": "~0.3.0"
+ },
+ "bin": {
+ "xlsx": "bin/xlsx.njs"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/xml-name-validator": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
@@ -20338,6 +20525,24 @@
}
}
},
+ "@envelope-zero/ynap-parsers": {
+ "version": "1.15.11",
+ "resolved": "https://npm.pkg.github.com/download/@envelope-zero/ynap-parsers/1.15.11/b0a58550aa25ec7c951ab18141501146412a41de",
+ "integrity": "sha512-sQCVJPeGaW/RmUoYqnNoQxjzwyiMe9gRBiUyhcLJrWbLE7AWr8HZCl3PgUEFPRai8ArXsptcXhteBE4yxhdmBQ==",
+ "requires": {
+ "buffer": "6.0.3",
+ "date-fns": "2.30.0",
+ "iban": "0.0.14",
+ "iconv-lite": "0.6.3",
+ "jschardet": "3.0.0",
+ "lodash": "4.17.21",
+ "mdn-polyfills": "5.20.0",
+ "mt940-js": "1.0.0",
+ "papaparse": "5.4.1",
+ "slugify": "1.6.6",
+ "xlsx": "^0.18.0"
+ }
+ },
"@eslint/eslintrc": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz",
@@ -22257,6 +22462,11 @@
"regex-parser": "^2.2.11"
}
},
+ "adler-32": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz",
+ "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A=="
+ },
"agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@@ -22747,8 +22957,7 @@
"base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
- "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
- "dev": true
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
},
"batch": {
"version": "0.6.1",
@@ -22899,13 +23108,12 @@
}
},
"buffer": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
- "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
- "dev": true,
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+ "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
"requires": {
"base64-js": "^1.3.1",
- "ieee754": "^1.1.13"
+ "ieee754": "^1.2.1"
}
},
"buffer-crc32": {
@@ -22995,6 +23203,15 @@
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==",
"dev": true
},
+ "cfb": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz",
+ "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
+ "requires": {
+ "adler-32": "~1.3.0",
+ "crc-32": "~1.2.0"
+ }
+ },
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -23146,6 +23363,11 @@
"q": "^1.1.2"
}
},
+ "codepage": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
+ "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA=="
+ },
"collect-v8-coverage": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz",
@@ -23327,6 +23549,11 @@
"yaml": "^1.10.0"
}
},
+ "crc-32": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
+ "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="
+ },
"cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -23672,6 +23899,16 @@
"color-convert": "^2.0.1"
}
},
+ "buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "dev": true,
+ "requires": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -23799,6 +24036,14 @@
"whatwg-url": "^8.0.0"
}
},
+ "date-fns": {
+ "version": "2.30.0",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
+ "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
+ "requires": {
+ "@babel/runtime": "^7.21.0"
+ }
+ },
"dayjs": {
"version": "1.11.5",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.5.tgz",
@@ -25256,6 +25501,11 @@
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
},
+ "frac": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
+ "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA=="
+ },
"fraction.js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
@@ -25756,6 +26006,11 @@
"@babel/runtime": "^7.22.5"
}
},
+ "iban": {
+ "version": "0.0.14",
+ "resolved": "https://registry.npmjs.org/iban/-/iban-0.0.14.tgz",
+ "integrity": "sha512-+rocNKk+Ga9m8Lr9fTMWd+87JnsBrucm0ZsIx5ROOarZlaDLmd+FKdbtvb0XyoBw9GAFOYG2GuLqoNB16d+p3w=="
+ },
"iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
@@ -25786,8 +26041,7 @@
"ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
- "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
- "dev": true
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
},
"ignore": {
"version": "5.2.0",
@@ -27689,6 +27943,11 @@
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
"dev": true
},
+ "jschardet": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-3.0.0.tgz",
+ "integrity": "sha512-lJH6tJ77V8Nzd5QWRkFYCLc13a3vADkh3r/Fi8HupZGWk2OVVDfnZP8V/VgQgZ+lzW0kG2UGb5hFgt3V3ndotQ=="
+ },
"jsdom": {
"version": "16.7.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz",
@@ -28113,6 +28372,11 @@
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz",
"integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA=="
},
+ "mdn-polyfills": {
+ "version": "5.20.0",
+ "resolved": "https://registry.npmjs.org/mdn-polyfills/-/mdn-polyfills-5.20.0.tgz",
+ "integrity": "sha512-AbTv1ytcoOUAkxw6u5oo2QPf27kEZgxBAQr49jFb4i2VnTnFGfJbcIQ9UDBOdfNECeXsgkYFwB2BkdeTfOzztw=="
+ },
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@@ -28272,6 +28536,11 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
+ "mt940-js": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/mt940-js/-/mt940-js-1.0.0.tgz",
+ "integrity": "sha512-9iFCkaGoUbo8FfkchMyMsUBxwmOVQbIQpgc7C0tHf6xDSzv+soVvx4PNNng/eQm/vFvCGl7ot4zJRK7Zs4veww=="
+ },
"multicast-dns": {
"version": "7.2.4",
"resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.4.tgz",
@@ -28553,6 +28822,11 @@
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
},
+ "papaparse": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz",
+ "integrity": "sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw=="
+ },
"param-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
@@ -30455,6 +30729,11 @@
}
}
},
+ "slugify": {
+ "version": "1.6.6",
+ "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz",
+ "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw=="
+ },
"sockjs": {
"version": "0.3.24",
"resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz",
@@ -30569,6 +30848,14 @@
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
},
+ "ssf": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz",
+ "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
+ "requires": {
+ "frac": "~1.1.2"
+ }
+ },
"sshpk": {
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
@@ -31788,6 +32075,16 @@
"is-typed-array": "^1.1.10"
}
},
+ "wmf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz",
+ "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw=="
+ },
+ "word": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz",
+ "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA=="
+ },
"word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
@@ -32245,6 +32542,20 @@
"integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==",
"requires": {}
},
+ "xlsx": {
+ "version": "0.18.5",
+ "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz",
+ "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==",
+ "requires": {
+ "adler-32": "~1.3.0",
+ "cfb": "~1.2.1",
+ "codepage": "~1.15.0",
+ "crc-32": "~1.2.1",
+ "ssf": "~0.11.2",
+ "wmf": "~1.0.1",
+ "word": "~0.3.0"
+ }
+ },
"xml-name-validator": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
diff --git a/package.json b/package.json
index 4c3d4a0da..33780486b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,7 @@
{
"name": "envelope-zero-frontend",
"dependencies": {
+ "@envelope-zero/ynap-parsers": "1.15.11",
"@headlessui/react": "1.7.16",
"@heroicons/react": "2.0.18",
"@tailwindcss/forms": "0.5.4",
@@ -11,6 +12,7 @@
"@types/node": "18.17.5",
"@types/react": "18.2.20",
"@types/react-dom": "18.2.7",
+ "buffer": "6.0.3",
"flowbite": "1.8.1",
"flowbite-react": "0.5.0",
"http-proxy-middleware": "2.0.6",
@@ -50,10 +52,7 @@
"start": "react-scripts start",
"build": "react-scripts build",
"server:dev": "docker-compose --project-name frontend-dev --file docker-compose-dev.yml up",
- "server:test": "docker-compose --project-name frontend-test --file docker-compose-test.yml up --detach",
- "server:test:stop": "docker-compose --project-name frontend-test --file docker-compose-test.yml down",
- "server:test:restart": "docker-compose --project-name frontend-test --file docker-compose-test.yml restart",
- "server:test:logs": "docker-compose --project-name frontend-test --file docker-compose-test.yml logs --follow",
+ "server:test": "docker-compose --project-name frontend-test --file docker-compose-test.yml up",
"test": "cypress run",
"test:watch": "cypress open",
"eject": "react-scripts eject",
diff --git a/src/components/TransactionImport/Form.tsx b/src/components/TransactionImport/Form.tsx
index 89090600b..2c6b0b564 100644
--- a/src/components/TransactionImport/Form.tsx
+++ b/src/components/TransactionImport/Form.tsx
@@ -2,6 +2,7 @@ import { useTranslation } from 'react-i18next'
import { useState } from 'react'
import { Link } from 'react-router-dom'
import { Account, TransactionPreview, Translation } from '../../types'
+import { parseFile } from '@envelope-zero/ynap-parsers'
import { checkStatus, parseJSON } from '../../lib/fetch-helper'
import Error from '../Error'
import FormFields from '../FormFields'
@@ -29,23 +30,40 @@ const Form = ({ accounts, isLoading, setIsLoading, setResult }: Props) => {
event.preventDefault()
setIsLoading(true)
+ const file = (event.target as any).file.files[0] // TODO: without `any`
- fetch(`/api/v1/import/ynab-import-preview?accountId=${accountId}`, {
- method: 'POST',
- body: new FormData(event.target as HTMLFormElement),
- })
- .then(checkStatus)
- .then(parseJSON)
- .then(body => {
- setIsLoading(false)
- if (error) {
- setError('')
- }
- setResult(body.data, accountId)
+ parseFile(file)
+ .then(result => {
+ // Get the data and transform it to FormData for the backend
+ const data = new FormData()
+ data.append(
+ 'file',
+ new File([new Blob([result[0].data])], 'ynap-transactions.csv', {
+ type: 'text/csv;charset=utf-8;',
+ })
+ )
+
+ fetch(`/api/v1/import/ynab-import-preview?accountId=${accountId}`, {
+ method: 'POST',
+ body: data,
+ })
+ .then(checkStatus)
+ .then(parseJSON)
+ .then(body => {
+ setIsLoading(false)
+ if (error) {
+ setError('')
+ }
+ setResult(body.data, accountId)
+ })
+ .catch(error => {
+ setIsLoading(false)
+ setError(error.message)
+ })
})
.catch(error => {
setIsLoading(false)
- setError(error.message)
+ setError(error)
})
}}
>
@@ -64,20 +82,12 @@ const Form = ({ accounts, isLoading, setIsLoading, setResult }: Props) => {
) : (
<>
- {t('transactions.import.description')} -
-