From 75ecabc81fd5ded798b355ba70b19e0a9acb6c9d Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Sun, 11 Feb 2024 19:42:29 +0100 Subject: [PATCH] Backend done? --- finanzfluss-addon.zip | Bin 2017 -> 4432 bytes src/contentScript.js | 89 ------------------------------------ src/head.js | 104 ++++++++++++++++++++++++++++++++++++++++++ src/manifest.json | 2 +- src/setup.js | 50 ++++++++++++++++++++ 5 files changed, 155 insertions(+), 90 deletions(-) delete mode 100644 src/contentScript.js create mode 100644 src/head.js create mode 100644 src/setup.js diff --git a/finanzfluss-addon.zip b/finanzfluss-addon.zip index a0acbe0619746dafd627a7087f82ca06c4857790..8f69ccaa57c33ac752223ee447d1c5e4899147bc 100644 GIT binary patch delta 4068 zcmZvf2T&8r)__9|H3StCq=o>}r9|mf={10W(nN@q(0fg!NN*B~(xghSQUyf>L8>H( zbm>)k5fFrjZ~i;?&VB#v?9S}Wp4l@ybH4NK9NiEHR!@_J^cnyFpa4h|%bJh`e{~8b z0|4%V001z68DQ<=?1^&rG_ZEJcl8u<@VIYC2_O+5Z9?^uG@-nFsR2Z!t0Vxxf0qi# zZDnwj@#)O=xcZGE&uSdj zdE)J25VmcUN2z8u-8G0oGktAG#gA1XSw+JIDrs#)riM_7iuBlrb|pPBhlMn7p?%`t z@hH*kE5}1@WSZaZnVsw5>a(v!D}1Ym46ev#a)ulsMq+bZSVLYhq*C`r6k{DNS3V4# zDy?#i+&!qXRAO8zNJ|~c$253HGW^DBgxl@(1GZbu1!Wib$i2shMl&cYK2aTm_^mAM z@(ch6r)}F58cUTG;}hq!*+%_hu&W#ag|Sps2E9zaOs`=2A^3veNV2Q$k&BP7%lJ(x z>t=i5hZSwR<1L%@!)AYtO)d*^Nl?0_(r0Vw_a=SN21iyAoPW#``89gBL}9U^E^bJ5 zi@QT~WKY3HOsx5SgVx$)Kv|dM*{aC+VTBm3IrBOWDF$`OQj(X3I5iU&lARRWZkXS^ z1W2mnQsBysi&|nca&K_m;UtpgdEyW`K~<%ut41}49z}3Jyhr^0dPL#{2T(l;^Qp@Q z8+m3B!nOE8zM9)beY>})B_11;cyA>sjXZRB2o(Y(_c^j=CzT(7MFoDeYo$q#7b7y# ziR0UO6$O36FUUzMX9f$K>8? zJ+BpLMzq;;!|FxDNK}?%quQ28Y0TNEt-;Vz(L-AYsPYx}I9shS$|zTr{7FSpnny`S z&pBc{f7M^}dz}|fSn=o|qv`I0kZpS6o+rHO`rYwG#K=CT+&cBK({XOamLv zSo_ZHZ=yFb-5wpJNKiVK)th-nb7Ao6f)7rh+%16dygzCRkk&>P+;gs|4gOBiOVT#- zp{2LJ)6B{=>H<4vKKI4^P5Cqs6XVV_0_oANL@dRKRdR7T&@}566s97|h~;XAd0t9g zaVjw7@3ka;5;!IwIQ4^Wwz2->5As#Jp<0}GCg6Y_#^;Q>hY`l^|4?t6nZXH+?vy$m zd2LA+`4^$IX+GOXS7ZfK37YD34-fcVIX)<-xrWM{VKOWD0*KLnTQ`~vOzxam~A~|5B!@8+EfjR8q@?E6NW(84DL+62Uw_-H^p!Hk&icHFq_ydX8Ek_g zqX7@1{q&KaOntIQ0V$sy-%UME4P6!GVM6TauCE{s^<=|#hpc4IZpEsC7VrtN`R;N? ziBAYBVl73E&5ECm4UecI>9W8Xo40@Zq`q{~pr%koDn6jVz8B)gP8;8cKLaa3CF3>; zyBN&ZCgX@^2PmFGgW`KH3D9CkX;0#B5SP>MWm(bP$#?!t#l0`9T!h9If_=bBJV9*6-hGq3;_=m|W z5lQ8pg24-2veW~a?sik-_qBwi8>1`jEf)_A%LDW&nzptiXD4-@Ke^vR1b4KzvToo# z&R{Rr=eMnfkIMU@o%(X`b1B}UELON!tmgC`goI%e^2&!+`s?TeuNEJM7=NAGN+GNV zWsCi6JmGkn=>o<`ieNT9J?QJ0RLok4wEGEFV#_(@fd&KNkE>Gs@xB(wht4&~%E+%p zq;H>+n$}F$YDs4w-TIsAuu@qQHrrG}+a=?Li2wlFOR76rIom%$dHex7*2Ve1On(P# zLTz5oe=%KKcK{S3O!NNqTHhck;(O%oDhbpjJW(WCt2-PWeD7mR%d1d}bd0=HTcvc@ zF?;Mfpd`CJw>CU&;{{oJB$3Q41QmAT>94eiJZ3zB&D?Y*73ZNr_@56#>?(J%&n&Vn zM1(4Wcs~qLsXK&c*bytNeO2p~AzqDA5s3L148z-HH16o$>Pzxz<58@bx3{M~c`hXw zvm!e%b_0EuXhX+4s%~eltFs`ft=b`GPl1R#5$oDetjn#)v)!+saI#Dy$7BEMZ{TWK z6P*zade~)uOQQtU+H$(N)mS!y)qi&_wqK*2 zCN0EfuOfB+HuMf%Tq{Y<-RqB*MJHi}z3@E=_AvEaT4av8#ww(j_N8Qy;h3U`o5oK| zRI?@g*x)rgiIv2_q1-sZlL%gNObaos?_#zirz*S+hP5N3pwSoFPA}T!DC2|q^f<@7 zt^7ZwoSG>g=YB}mI0lGd$BwUGrOt165Vos*N3^e#w^H(qqGfz(K!p3HrpkVT3ZFlT z$VBE1lQ7e5q3@a5*mR3CjQe|rca8!T8Q-cE89_ah36K>x#gy=B22TNA>l`nq$=TLu z{`Mj%q#S(iO}zWPA+u$0sJ{NQ_T~e<&Ie$BT|b>F58vyaQT9Xv*qe1TKz-)4E;W%J z$(A1?!wK$j?Q!_~AWP7V$Yz1t{itjfO}|lZWaE((K$_FnLzH&M+F2|22zSrw^pTwC zAbT#E?v~HhuW5zCQuss?F_&Zk>Z}9icjZVqW?toX&k$sp;L;b4-K6%_PVZYA5xXgq(H4kj$RZt!U`F zw8hs&oojj|<8`5{CM-ft#|&I+-+i}>@V=0XaOz(}(*8Bl*kr2iyXkXl-sI`D)Oy>y z4zJ}Cx)*LfTMK7#+Bh(1A4ov&E}nQuhh^jF^k&BtS$A0ngYC2ubFYIXJ%HZKV6Bj( zmxf_hcf<*M4AT2l3y@Il^!8X83$vNWmQ|k%2&Vpixtvd2QWufQF=##hk7A-62A#La zF3L#HoFX=3u?yvOm~z`~G^0FGJ9~{QKZh${0Q6`i;>@d~_f$Twf1jb95!fImqjZxv z!GIUxDoslA=5^`==LSTs#M@{j=qM4}u~y&7VGu0&gR&vhET_ZZxf?pSCrwgLdgu%E zHl;_YrRLn8gYsDB3ZqJ-tEvP~N}eWDvouD(xWM!Pt26T1+MF-!Al)mp9y(?@chQzE zXaQDsJ4J8u)rEL#QM_#CVKv_D6Dq7xO*8hj3EHcx7~GwCZM(fwyv@5z ze9_2pa58Qin7A8YBVoQz&wM8)e?%fsH)SpsV)!Doll9;eo2Iy#c+_B1WX~(nZW{6E zwT{M4+;Xa~J^ykZ&vUJfX@v03BjS$&*7kaJHRPOhSfE2tppEL0(DJr; zE|!i-yVR-d+j?xS5wPB7uCh;dKr^hen`4|7G`S5_FFceD4`Atdck%c*&-!@2WG;Ay z^#=}v2USk1Y)sJdTDppr>JU%CUQFYLA2~UJ9MQS+iu(3OA6@~yX-kek(v@zDZ?-^e zwC7}hcOAMiSra78BF~Z-fCcDZ0+-?vwjL-?FW0|li=k{n`Oy6jZQ~4(=t<#A+E#(X ztunsp)K(O7+OrWrcN%^c2Df+RM0+(TGxVsrXE<(RXC8R#OV&9Ca}uV5X0o>4_oX0G zp)CwM>K|?taIJ)uwAv>;s0_wVWWnRjOp^OU@R1aJec`FD7{36faj z{L#sxuWcNf85GV*N#)U{nnFc3G9IJEL~HP!+FAp5sjZ3-O|`P`zpTt$S|4>_JCd~q zA1-*fzTg@V3Fk1Q+biTpRXl`m{f^&wE@ql*C4=!%FkI_+_#^IAN5=;{n?j)RobcE< zYnXSR_4)nsNndaAFRnP!iNy>23raODl@~z*4KmDYR=?Kz$ zkyupJc!$fzNuio<5K%rt(%JLKL+(~po1ci;e57f{Wcp7^j{;b84z?>(b(Ge!Si3Z( zc2TfI6#`n$@uH)lZ<_knd+0bh7r{MT&irNZsd(%0x&s;kq+O&ECOg6BxT4^iiTlXu zrHq8?!ShJz{UnIxC)1Seq^&Jwc;}HfDzXthw>mG+rfuAzdUUdVW+CdBCob@1sn`_O zNMFT0W)Pt`RMI=j&zMGDXATeobOuZ;SmdhjK=d?;h*?SgzfUi2jhy$-_ZDXdWM=iL(a=xLIX|4EPRa-?16m{0d-_aD?&PV4{x delta 1685 zcmZvdX*Ao37Qp{WgjPy4WhhEVsX-WnqEw4WP_d9Mi=ggaP&%O8DbMF1}`|!K{1~YJmpBF?y z9RPq`00`rRzgQ|=7AgRM0t^7u09_z5jzT9==%*qR$W*#TG%YY-HvqB1HxR#)XJQHr z04Xd&i16g9wz!XS99k1H~EYu~%)!_Vij0ALRDz;>Hv7 z+wq_yj+p-Bh%aqIO|&83z$6NM|NhunLAAbiqaCU2P~G|n>~!T`B9@aoa~SfW!2LZ5 z75L;?US{^hva$vyjA>l)%k_m>4lf?Wue)>nz=Fh_zc**2U@9^nfEa&p7w7>~fF)HFsHBEJXEc$>mRg4Z88D917LT9}DU~Lq9zA#Zs z*i*_wh*0x`= zaYGnGYIecB+vkJBmGmgUwS1Cuvr2idjs^77!$I61pnZ3lxiM;}S`hc7ts%QhG4Q4l z2CALaFUZrWP0;?viViMC(2vG{dRbJ&yOwMDw2l1R-BQ7lA_f=YPHSgdG5s*Yixa|iR*z?@$I`) z{!o1+Bq5j=F3Y|aVwWQQWta16mvA_!EX%M=H$K6>m>urB#UQW< zekM0MO+uXNT7RqU&*{p1QFhL5og(SI?RDbPfO7%K|eV(MwwpmS6jGtg8O;-j0l05%*r|jf>8-P4hV5x%wgd zYZSwgUu$^9`vWhYct1*hf>fH=rNpQnHlr5wbWCW#bSC-AEt)0u<#R)Zmsj*{z%!bi z=xK?=Ry~bh-v265ynSnYXp=F#wyAw zNCJb^9zUD{ry9+<%~CQMtN%4>?2Guu?xNRt``g#kQyRXZADcwhmQ$g%tpfHIXjAru zBzaB>YOQ3WpgO5ajo*(gEDb$dZ@RHZGsW4w+QIX3Vaa|3DPZ}`_M>T9>Ioc9oWI$b z;kI2jxoMnQw#YZAQC>=@H(zfu3_%tZbry$guT{4Pg^SD%3P2%@oD;B>0RO8BPd)Pr zWIhH@&p3%SJ!duf;tidM1-hi!v~~sl*~K+D%qpE8tTe%iT%y2dewZJ6ay6wrE6$7@ zH`p`f=r1ELV-X3=5YC~|;mni#18cX&^23veN6IL|bJV0gRZsaxDk^8vLPxl7EaqHU zR&ZW3FN zsWwV8Kg)1F?Hlf|?d?_D%_>QSH{W)zc$nT0?N;h9-M@4r7NOI+fq-E81oSKO3W9-! z!9qVm&nfT~V@)3)>Wp`kAO5I)#k<=}g*v|@m0_c+nEgpC#<4!@7{* -

Konfiguriere Deine Zuordnungen

- -
-
- -
-` -configDiv.id = "configDiv" -configDiv.className = "MuiBox-root ff-addon-container" - -parent.parentNode.insertBefore(configDiv, parent) - diff --git a/src/head.js b/src/head.js new file mode 100644 index 0000000..1451837 --- /dev/null +++ b/src/head.js @@ -0,0 +1,104 @@ +async function doJsonFetch(token, method, url) { + const res = await fetch(url, + { + method: method, + credentials: 'same-origin', + headers: { + "Authorization": "Bearer "+token + } + }) + return await res.json() +} + +function getLoginToken() { + const loginToken = localStorage.getItem('LOGIN_TOKEN'); + const jsonToken = loginToken && JSON.parse(loginToken); + const accessToken = jsonToken?.access_token + if (!accessToken) onsole.error("No access token available!") + return accessToken +} + +async function onButtonClick() { + const accessToken = getLoginToken() + if (!accessToken) return; + + const householdBooks = await doJsonFetch(accessToken, "GET", "https://rentablo.de/api/v1/accounts/selectGroups/householdBook?fallbackAccountType[]=02_cash&excludeManuallyMaintainedFallbackAccounts=true") + console.log(householdBooks) + const accountIds = householdBooks.accountIds + const accountIdsQuery = "accountId[]="+accountIds.join("&accountId[]=") + const transactions = await doJsonFetch(accessToken, "GET", "https://rentablo.de/api/v1/transactions?"+accountIdsQuery+"&includeAdjustingEntries=false&skipManuallyCreatedTransactions=true&minDate=2024-01-01&maxDate=2024-01-31&order=date+desc&perPage=5000") + console.log(transactions) +} + +async function onInit() { + const accessToken = getLoginToken() + if (!accessToken) return; + + /** + * Represents the structure of the JSON data for categories. + * + * @typedef {Object} Category + * @property {number} id - The unique identifier for the category. + * @property {string} name - The name of the category. + * @property {number|null} parentId - The identifier of the parent category, or null if it's a top-level category. + * @property {boolean} isCustom - Indicates whether the category is custom. + * @property {number[]} children - An array of child categories. + */ + + /** + * + * @type {Category[]} + */ + const categories = (await doJsonFetch(accessToken, "GET", "https://rentablo.de/api/v1/categories")).categories + console.log(categories) + const nodes = {} + const roots = [] + for (const category of categories) { + nodes[category.id] = { + id: category.id, + name: category.name, + children: category.children + } + if (typeof category.parentId !== "number") roots.push(category.id) + } + + console.log(nodes) + console.log(roots) + + function replaceChildrenIds(ids) { + return ids.map(id => { + const node = nodes[id] + node.children = replaceChildrenIds(node.children) + return node + }) + } + const newRoots = replaceChildrenIds(roots) + console.log(newRoots) + + const tableContainer = document.getElementsByClassName("ff-addon-table-container").item(0) + // language=HTML + tableContainer.innerHTML = ` +
+
Participant
+
Subject
+
Min. Volume
+
Max. Volume
+
Categories
+ + + + + + +
+ + + ` + +} + +onInit().catch(console.error) diff --git a/src/manifest.json b/src/manifest.json index c5a5410..e97d5e8 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -6,7 +6,7 @@ "content_scripts": [ { "matches": [""], - "js": ["contentScript.js"] + "js": ["setup.js", "head.js"] } ] } \ No newline at end of file diff --git a/src/setup.js b/src/setup.js new file mode 100644 index 0000000..928ff0b --- /dev/null +++ b/src/setup.js @@ -0,0 +1,50 @@ +const styleElement = document.createElement('style'); +// language=CSS +styleElement.textContent = ` +.ff-addon-title { + margin: 0; + font-weight: 600; + line-height: 30px; + font-size: 18px; +} + +.ff-addon-title-container { + margin-bottom: 12px; + width: 100%; +} + +.ff-addon-hr { + margin: 0px 0px 16px; + border-width: 0px 0px thin; + border-style: solid; + border-color: rgb(54, 58, 61); +} + +.ff-addon-container { + margin-bottom: 18px; +}`; +document.head.appendChild(styleElement); + +let parent +const paragraphs = document.getElementsByTagName('p'); +for (let i = 0; i < paragraphs.length; i++) { + if (paragraphs[i].textContent.includes('Transaktionen')) { + parent = paragraphs[i].parentNode.parentNode; + break; // Stop searching once found + } +} + +const configDiv = document.getElementById("configDiv") || document.createElement("div") +configDiv.remove() +// language=HTML +configDiv.innerHTML = ` +
+

Konfiguriere Deine Zuordnungen

+
+
+
+` +configDiv.id = "configDiv" +configDiv.className = "MuiBox-root ff-addon-container" + +parent.parentNode.insertBefore(configDiv, parent)