release v2.0.0 #4
|
@ -2,6 +2,9 @@
|
|||
.thumbs.db
|
||||
node_modules
|
||||
|
||||
# We use yarn, so ignore npm
|
||||
package-lock.json
|
||||
|
||||
# Quasar core related directories
|
||||
.quasar
|
||||
/dist
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
"@quasar/extras": "^1.9.10",
|
||||
"@vue/composition-api": "^0.6.4",
|
||||
"axios": "^0.21.0",
|
||||
"cordova": "^10.0.0",
|
||||
"core-js": "^3.7.0",
|
||||
"quasar": "^1.14.5",
|
||||
"vue-router": "3.3.2"
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="1024"
|
||||
height="1024"
|
||||
viewBox="0 0 270.93333 270.93334"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
sodipodi:docname="flaschengeist-logo-dark.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.7"
|
||||
inkscape:cx="427.27412"
|
||||
inkscape:cy="505.5186"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1015"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-26.06665)">
|
||||
<g
|
||||
id="g875"
|
||||
transform="matrix(0.04643093,-0.35277275,0.35277275,0.04643093,7.9696963,229.75997)"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
<g
|
||||
id="g819"
|
||||
transform="translate(-233.70212,301.68819)"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
<path
|
||||
id="path817"
|
||||
d="m 206.836,94.524 c 0,-17.132 0,-94.524 0,-94.524 h -12.723 -7.534 -12.717 c 0,0 0,77.392 0,94.524 0,17.132 -32.207,37.929 -32.207,62.346 0,24.411 0,201.009 0,207.236 0,6.229 4.166,16.615 13.501,16.615 6.355,0 22.012,0 31.435,0 4.45,0 7.534,0 7.534,0 9.423,0 25.073,0 31.429,0 9.342,0 13.513,-10.387 13.513,-16.615 0,-6.228 0,-182.826 0,-207.236 -0.001,-24.417 -32.231,-45.203 -32.231,-62.346 z m -25.857,27.757 c -2.085,2.847 -4.415,6.437 -6.947,10.579 -2.562,4.153 -4.99,8.993 -7.459,14.244 -0.941,2.684 -1.906,5.496 -2.713,8.313 -0.029,2.986 -0.976,5.188 -0.563,8.935 0.25,6.948 0.523,14.256 0.801,21.82 0.5,15.133 0.593,31.284 0.721,47.422 -0.035,32.287 -1.011,64.588 -2.521,88.801 -0.662,12.107 -1.748,22.191 -2.26,29.256 -0.627,7.064 -1.15,11.107 -1.15,11.107 0,0 -0.528,-4.043 -1.156,-11.107 -0.511,-7.064 -1.598,-17.148 -2.26,-29.256 -1.51,-24.213 -2.487,-56.514 -2.521,-88.801 0.116,-16.139 0.209,-32.289 0.72,-47.422 0.279,-7.563 0.552,-14.872 0.802,-21.82 -0.122,-3.224 1.092,-7.604 1.784,-11.09 1.342,-3.282 2.829,-6.327 4.247,-9.196 1.726,-2.638 3.358,-5.165 4.926,-7.564 1.784,-2.19 3.474,-4.258 5.054,-6.222 3.288,-3.788 6.21,-6.989 8.761,-9.487 5.042,-5.042 8.278,-7.517 8.278,-7.517 0,0 -2.524,3.224 -6.544,9.005 z"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1" />
|
||||
|
||||
</g>
|
||||
<g
|
||||
id="g821"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g823"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g825"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g827"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g829"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g831"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g833"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g835"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g837"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g839"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g841"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g843"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g845"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g847"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g849"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.44061947;stroke-opacity:1"
|
||||
d="m 154.04963,46.75413 c -2.62014,0.516924 -5.22545,1.168424 -7.80617,1.95206 -42.75163,12.981828 -43.91253,68.68501 -54.129684,109.64785 -13.512037,49.65839 -58.120549,32.45922 -53.364321,57.25551 4.247764,22.14545 69.262455,44.34715 71.908285,44.72513 7.43909,1.06272 -52.780019,-26.79368 -40.437456,-42.16974 10.871821,-13.54384 54.907216,-1.28617 101.792266,-18.34148 41.23972,-15.24969 76.0405,-52.05406 67.35884,-95.66274 -8.0739,-40.556134 -44.95534,-65.37088 -85.32176,-57.40659 z m 2.80071,29.231473 5.1e-4,-9.9e-5 c 2.13365,-0.334266 3.95652,0.01931 5.31987,1.031879 4.77648,3.547266 2.89647,14.166887 -4.19904,23.719127 -7.09532,9.55196 -16.7189,14.41932 -21.49476,10.87151 -4.77606,-3.54747 -2.89605,-14.166665 4.19913,-23.718615 4.83297,-6.506353 11.08277,-11.106027 16.17429,-11.903802 z m 47.56936,23.874148 c 2.13386,-0.334401 3.95691,0.01915 5.32037,1.031789 4.77577,3.54775 2.89554,14.16692 -4.19964,23.7187 -7.09514,9.55189 -16.7186,14.41945 -21.49466,10.87203 -4.77578,-3.54775 -2.89554,-14.16693 4.19965,-23.71872 4.83296,-6.50635 11.08277,-11.10602 16.17428,-11.903799 z M 151.12801,132.2755 c 2.17877,-0.55401 4.13861,-0.53197 5.77959,0.065 7.31131,2.65972 6.76636,15.88363 -1.21719,29.5365 -7.98356,13.65282 -20.38249,22.56458 -27.69389,19.90504 -7.31132,-2.65972 -6.76637,-15.88364 1.21719,-29.53651 5.96208,-10.19594 14.66479,-18.12654 21.9143,-19.97007 z"
|
||||
id="path897"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccsssccccccscccccccccccccccc" />
|
||||
<ellipse
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
|
||||
id="path962"
|
||||
cx="128.25729"
|
||||
cy="26.431171"
|
||||
rx="17.575893"
|
||||
ry="21.733631"
|
||||
transform="rotate(16.845913)" />
|
||||
<ellipse
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.29560357;stroke-opacity:1"
|
||||
id="path964"
|
||||
cx="245.22121"
|
||||
cy="-179.49768"
|
||||
rx="18.099041"
|
||||
ry="22.821976"
|
||||
transform="matrix(0.33166949,0.94339565,-0.88087771,0.47334392,0,0)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 7.2 KiB |
|
@ -0,0 +1,139 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="1024"
|
||||
height="1024"
|
||||
viewBox="0 0 270.93333 270.93334"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
sodipodi:docname="flaschengeist-logo-white-with-kontur.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.7"
|
||||
inkscape:cx="427.27412"
|
||||
inkscape:cy="505.5186"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1015"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-26.06665)">
|
||||
<g
|
||||
id="g875"
|
||||
transform="matrix(0.04643093,-0.35277275,0.35277275,0.04643093,7.9696963,229.75997)"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1">
|
||||
<g
|
||||
id="g819"
|
||||
transform="translate(-233.70212,301.68819)"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1">
|
||||
<path
|
||||
id="path817"
|
||||
d="m 206.836,94.524 c 0,-17.132 0,-94.524 0,-94.524 h -12.723 -7.534 -12.717 c 0,0 0,77.392 0,94.524 0,17.132 -32.207,37.929 -32.207,62.346 0,24.411 0,201.009 0,207.236 0,6.229 4.166,16.615 13.501,16.615 6.355,0 22.012,0 31.435,0 4.45,0 7.534,0 7.534,0 9.423,0 25.073,0 31.429,0 9.342,0 13.513,-10.387 13.513,-16.615 0,-6.228 0,-182.826 0,-207.236 -0.001,-24.417 -32.231,-45.203 -32.231,-62.346 z m -25.857,27.757 c -2.085,2.847 -4.415,6.437 -6.947,10.579 -2.562,4.153 -4.99,8.993 -7.459,14.244 -0.941,2.684 -1.906,5.496 -2.713,8.313 -0.029,2.986 -0.976,5.188 -0.563,8.935 0.25,6.948 0.523,14.256 0.801,21.82 0.5,15.133 0.593,31.284 0.721,47.422 -0.035,32.287 -1.011,64.588 -2.521,88.801 -0.662,12.107 -1.748,22.191 -2.26,29.256 -0.627,7.064 -1.15,11.107 -1.15,11.107 0,0 -0.528,-4.043 -1.156,-11.107 -0.511,-7.064 -1.598,-17.148 -2.26,-29.256 -1.51,-24.213 -2.487,-56.514 -2.521,-88.801 0.116,-16.139 0.209,-32.289 0.72,-47.422 0.279,-7.563 0.552,-14.872 0.802,-21.82 -0.122,-3.224 1.092,-7.604 1.784,-11.09 1.342,-3.282 2.829,-6.327 4.247,-9.196 1.726,-2.638 3.358,-5.165 4.926,-7.564 1.784,-2.19 3.474,-4.258 5.054,-6.222 3.288,-3.788 6.21,-6.989 8.761,-9.487 5.042,-5.042 8.278,-7.517 8.278,-7.517 0,0 -2.524,3.224 -6.544,9.005 z"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
|
||||
|
||||
</g>
|
||||
<g
|
||||
id="g821"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g823"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g825"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g827"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g829"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g831"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g833"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g835"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g837"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g839"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g841"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g843"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g845"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g847"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g849"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1">
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#0c0000;stroke-width:1.66533339;stroke-opacity:1"
|
||||
d="M 440.92969 56.667969 A 66.428573 82.142858 16.845913 0 0 371.42188 118.32031 A 66.428573 82.142858 16.845913 0 0 411.19531 216.18945 A 66.428573 82.142858 16.845913 0 0 417.75781 217.64648 C 381.35143 302.41695 370.46475 410.50548 348.14648 499.98438 C 297.07737 687.66963 128.47878 622.66455 146.45508 716.38281 C 162.50962 800.08215 408.23439 883.99329 418.23438 885.42188 C 446.35062 889.43845 218.75133 784.15526 265.40039 726.04102 C 306.49074 674.8517 472.92361 721.17976 650.12695 656.71875 C 726.85809 628.34499 797.67407 580.21865 845.90625 519.00977 A 66.376657 87.827349 48.964508 0 0 927.6875 519.24805 A 66.376657 87.827349 48.964508 0 0 980.98047 413.88477 A 66.376657 87.827349 48.964508 0 0 907.36328 380.67383 C 911.18715 353.20036 910.57006 324.58905 904.71094 295.1582 C 874.19541 141.87518 734.80037 48.0882 582.23438 78.189453 C 572.33148 80.143182 562.48437 82.604632 552.73047 85.566406 C 533.33782 91.455119 516.21653 99.676893 501.02148 109.8418 A 66.428573 82.142858 16.845913 0 0 458.80469 58.953125 A 66.428573 82.142858 16.845913 0 0 440.92969 56.667969 z M 598.64062 188.20703 C 604.22194 188.22929 609.06312 189.70004 612.92773 192.57031 C 630.98057 205.9773 623.87627 246.11384 597.05859 282.2168 C 570.24164 318.31869 533.86885 336.71569 515.81836 323.30664 C 497.76711 309.89888 504.87302 269.76201 531.68945 233.66016 C 549.9558 209.06922 573.57677 191.68513 592.82031 188.66992 L 592.82227 188.66992 C 594.83831 188.35408 596.78019 188.19961 598.64062 188.20703 z M 778.42969 278.44141 C 784.01155 278.46343 788.85382 279.93226 792.71875 282.80273 C 810.7689 296.21155 803.66213 336.34605 776.8457 372.44727 C 750.02943 408.5489 713.65672 426.94663 695.60547 413.53906 C 677.55528 400.13024 684.66205 359.99578 711.47852 323.89453 C 729.74482 299.3036 753.36587 281.91757 772.60938 278.90234 C 774.62562 278.58637 776.56907 278.43406 778.42969 278.44141 z M 582.87695 399.91016 C 586.53338 399.95128 589.93604 400.53593 593.03711 401.66406 C 620.67041 411.71655 618.60959 461.69743 588.43555 513.29883 C 558.26146 564.90004 511.39926 598.58305 483.76562 588.53125 C 456.13229 578.47876 458.1931 528.49788 488.36719 476.89648 C 510.90103 438.36065 543.79364 408.38759 571.19336 401.41992 C 575.31072 400.37297 579.22053 399.86903 582.87695 399.91016 z "
|
||||
transform="matrix(0.26458333,0,0,0.26458333,0,26.06665)"
|
||||
id="path897" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 7.4 KiB |
|
@ -0,0 +1,156 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="1024"
|
||||
height="1024"
|
||||
viewBox="0 0 270.93333 270.93334"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
sodipodi:docname="flaschengeist-logo-white.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.7"
|
||||
inkscape:cx="427.27412"
|
||||
inkscape:cy="505.5186"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1015"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-26.06665)">
|
||||
<g
|
||||
id="g875"
|
||||
transform="matrix(0.04643093,-0.35277275,0.35277275,0.04643093,7.9696963,229.75997)"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
<g
|
||||
id="g819"
|
||||
transform="translate(-233.70212,301.68819)"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
<path
|
||||
id="path817"
|
||||
d="m 206.836,94.524 c 0,-17.132 0,-94.524 0,-94.524 h -12.723 -7.534 -12.717 c 0,0 0,77.392 0,94.524 0,17.132 -32.207,37.929 -32.207,62.346 0,24.411 0,201.009 0,207.236 0,6.229 4.166,16.615 13.501,16.615 6.355,0 22.012,0 31.435,0 4.45,0 7.534,0 7.534,0 9.423,0 25.073,0 31.429,0 9.342,0 13.513,-10.387 13.513,-16.615 0,-6.228 0,-182.826 0,-207.236 -0.001,-24.417 -32.231,-45.203 -32.231,-62.346 z m -25.857,27.757 c -2.085,2.847 -4.415,6.437 -6.947,10.579 -2.562,4.153 -4.99,8.993 -7.459,14.244 -0.941,2.684 -1.906,5.496 -2.713,8.313 -0.029,2.986 -0.976,5.188 -0.563,8.935 0.25,6.948 0.523,14.256 0.801,21.82 0.5,15.133 0.593,31.284 0.721,47.422 -0.035,32.287 -1.011,64.588 -2.521,88.801 -0.662,12.107 -1.748,22.191 -2.26,29.256 -0.627,7.064 -1.15,11.107 -1.15,11.107 0,0 -0.528,-4.043 -1.156,-11.107 -0.511,-7.064 -1.598,-17.148 -2.26,-29.256 -1.51,-24.213 -2.487,-56.514 -2.521,-88.801 0.116,-16.139 0.209,-32.289 0.72,-47.422 0.279,-7.563 0.552,-14.872 0.802,-21.82 -0.122,-3.224 1.092,-7.604 1.784,-11.09 1.342,-3.282 2.829,-6.327 4.247,-9.196 1.726,-2.638 3.358,-5.165 4.926,-7.564 1.784,-2.19 3.474,-4.258 5.054,-6.222 3.288,-3.788 6.21,-6.989 8.761,-9.487 5.042,-5.042 8.278,-7.517 8.278,-7.517 0,0 -2.524,3.224 -6.544,9.005 z"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-opacity:1" />
|
||||
|
||||
</g>
|
||||
<g
|
||||
id="g821"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g823"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g825"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g827"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g829"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g831"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g833"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g835"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g837"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g839"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g841"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g843"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g845"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g847"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
<g
|
||||
id="g849"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000d2;stroke-opacity:1">
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.44061947;stroke-opacity:1"
|
||||
d="m 154.04963,46.75413 c -2.62014,0.516924 -5.22545,1.168424 -7.80617,1.95206 -42.75163,12.981828 -43.91253,68.68501 -54.129684,109.64785 -13.512037,49.65839 -58.120549,32.45922 -53.364321,57.25551 4.247764,22.14545 69.262455,44.34715 71.908285,44.72513 7.43909,1.06272 -52.780019,-26.79368 -40.437456,-42.16974 10.871821,-13.54384 54.907216,-1.28617 101.792266,-18.34148 41.23972,-15.24969 76.0405,-52.05406 67.35884,-95.66274 -8.0739,-40.556134 -44.95534,-65.37088 -85.32176,-57.40659 z m 2.80071,29.231473 5.1e-4,-9.9e-5 c 2.13365,-0.334266 3.95652,0.01931 5.31987,1.031879 4.77648,3.547266 2.89647,14.166887 -4.19904,23.719127 -7.09532,9.55196 -16.7189,14.41932 -21.49476,10.87151 -4.77606,-3.54747 -2.89605,-14.166665 4.19913,-23.718615 4.83297,-6.506353 11.08277,-11.106027 16.17429,-11.903802 z m 47.56936,23.874148 c 2.13386,-0.334401 3.95691,0.01915 5.32037,1.031789 4.77577,3.54775 2.89554,14.16692 -4.19964,23.7187 -7.09514,9.55189 -16.7186,14.41945 -21.49466,10.87203 -4.77578,-3.54775 -2.89554,-14.16693 4.19965,-23.71872 4.83296,-6.50635 11.08277,-11.10602 16.17428,-11.903799 z M 151.12801,132.2755 c 2.17877,-0.55401 4.13861,-0.53197 5.77959,0.065 7.31131,2.65972 6.76636,15.88363 -1.21719,29.5365 -7.98356,13.65282 -20.38249,22.56458 -27.69389,19.90504 -7.31132,-2.65972 -6.76637,-15.88364 1.21719,-29.53651 5.96208,-10.19594 14.66479,-18.12654 21.9143,-19.97007 z"
|
||||
id="path897"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccsssccccccscccccccccccccccc" />
|
||||
<ellipse
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
|
||||
id="path962"
|
||||
cx="128.25729"
|
||||
cy="26.431171"
|
||||
rx="17.575893"
|
||||
ry="21.733631"
|
||||
transform="rotate(16.845913)" />
|
||||
<ellipse
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.29560357;stroke-opacity:1"
|
||||
id="path964"
|
||||
cx="245.22121"
|
||||
cy="-179.49768"
|
||||
rx="18.099041"
|
||||
ry="22.821976"
|
||||
transform="matrix(0.33166949,0.94339565,-0.88087771,0.47334392,0,0)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 7.2 KiB |
|
@ -0,0 +1,146 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="1024"
|
||||
height="1024"
|
||||
viewBox="0 0 270.93333 270.93334"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
sodipodi:docname="flaschengeist-logo.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.7"
|
||||
inkscape:cx="152.98841"
|
||||
inkscape:cy="505.5186"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1015"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-26.06665)">
|
||||
<circle
|
||||
id="path10"
|
||||
cx="135.46666"
|
||||
cy="161.53333"
|
||||
style="stroke-width:0.26506463;fill:#1976d2;fill-opacity:1"
|
||||
r="135.46666" />
|
||||
<g
|
||||
id="g875"
|
||||
transform="matrix(0.04643093,-0.35277275,0.35277275,0.04643093,7.9696963,229.75997)"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#1976d2;stroke-opacity:1">
|
||||
<g
|
||||
id="g819"
|
||||
transform="translate(-233.70212,301.68819)"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#1976d2;stroke-opacity:1">
|
||||
<path
|
||||
id="path817"
|
||||
d="m 206.836,94.524 c 0,-17.132 0,-94.524 0,-94.524 h -12.723 -7.534 -12.717 c 0,0 0,77.392 0,94.524 0,17.132 -32.207,37.929 -32.207,62.346 0,24.411 0,201.009 0,207.236 0,6.229 4.166,16.615 13.501,16.615 6.355,0 22.012,0 31.435,0 4.45,0 7.534,0 7.534,0 9.423,0 25.073,0 31.429,0 9.342,0 13.513,-10.387 13.513,-16.615 0,-6.228 0,-182.826 0,-207.236 -0.001,-24.417 -32.231,-45.203 -32.231,-62.346 z m -25.857,27.757 c -2.085,2.847 -4.415,6.437 -6.947,10.579 -2.562,4.153 -4.99,8.993 -7.459,14.244 -0.941,2.684 -1.906,5.496 -2.713,8.313 -0.029,2.986 -0.976,5.188 -0.563,8.935 0.25,6.948 0.523,14.256 0.801,21.82 0.5,15.133 0.593,31.284 0.721,47.422 -0.035,32.287 -1.011,64.588 -2.521,88.801 -0.662,12.107 -1.748,22.191 -2.26,29.256 -0.627,7.064 -1.15,11.107 -1.15,11.107 0,0 -0.528,-4.043 -1.156,-11.107 -0.511,-7.064 -1.598,-17.148 -2.26,-29.256 -1.51,-24.213 -2.487,-56.514 -2.521,-88.801 0.116,-16.139 0.209,-32.289 0.72,-47.422 0.279,-7.563 0.552,-14.872 0.802,-21.82 -0.122,-3.224 1.092,-7.604 1.784,-11.09 1.342,-3.282 2.829,-6.327 4.247,-9.196 1.726,-2.638 3.358,-5.165 4.926,-7.564 1.784,-2.19 3.474,-4.258 5.054,-6.222 3.288,-3.788 6.21,-6.989 8.761,-9.487 5.042,-5.042 8.278,-7.517 8.278,-7.517 0,0 -2.524,3.224 -6.544,9.005 z"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#1976d2;stroke-opacity:1" />
|
||||
</g>
|
||||
<g
|
||||
id="g821"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#1976d2;stroke-opacity:1" />
|
||||
<g
|
||||
id="g823"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#1976d2;stroke-opacity:1" />
|
||||
<g
|
||||
id="g825"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#1976d2;stroke-opacity:1" />
|
||||
<g
|
||||
id="g827"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#1976d2;stroke-opacity:1" />
|
||||
<g
|
||||
id="g829"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#1976d2;stroke-opacity:1" />
|
||||
<g
|
||||
id="g831"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#1976d2;stroke-opacity:1" />
|
||||
<g
|
||||
id="g833"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#1976d2;stroke-opacity:1" />
|
||||
<g
|
||||
id="g835"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#1976d2;stroke-opacity:1" />
|
||||
<g
|
||||
id="g837"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#1976d2;stroke-opacity:1" />
|
||||
<g
|
||||
id="g839"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#1976d2;stroke-opacity:1" />
|
||||
<g
|
||||
id="g841"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#1976d2;stroke-opacity:1" />
|
||||
<g
|
||||
id="g843"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#1976d2;stroke-opacity:1" />
|
||||
<g
|
||||
id="g845"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#1976d2;stroke-opacity:1" />
|
||||
<g
|
||||
id="g847"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#1976d2;stroke-opacity:1" />
|
||||
<g
|
||||
id="g849"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#1976d2;stroke-opacity:1" />
|
||||
</g>
|
||||
<path
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.44061947;stroke-opacity:1"
|
||||
d="m 154.04963,46.75413 c -2.62014,0.516924 -5.22545,1.168424 -7.80617,1.95206 -42.75163,12.981828 -43.91253,68.68501 -54.129684,109.64785 -13.512037,49.65839 -58.120549,32.45922 -53.364321,57.25551 4.247764,22.14545 69.262455,44.34715 71.908285,44.72513 7.43909,1.06272 -52.780019,-26.79368 -40.437456,-42.16974 10.871821,-13.54384 54.907216,-1.28617 101.792266,-18.34148 41.23972,-15.24969 76.0405,-52.05406 67.35884,-95.66274 -8.0739,-40.556134 -44.95534,-65.37088 -85.32176,-57.40659 z m 2.80071,29.231473 5.1e-4,-9.9e-5 c 2.13365,-0.334266 3.95652,0.01931 5.31987,1.031879 4.77648,3.547266 2.89647,14.166887 -4.19904,23.719127 -7.09532,9.55196 -16.7189,14.41932 -21.49476,10.87151 -4.77606,-3.54747 -2.89605,-14.166665 4.19913,-23.718615 4.83297,-6.506353 11.08277,-11.106027 16.17429,-11.903802 z m 47.56936,23.874148 c 2.13386,-0.334401 3.95691,0.01915 5.32037,1.031789 4.77577,3.54775 2.89554,14.16692 -4.19964,23.7187 -7.09514,9.55189 -16.7186,14.41945 -21.49466,10.87203 -4.77578,-3.54775 -2.89554,-14.16693 4.19965,-23.71872 4.83296,-6.50635 11.08277,-11.10602 16.17428,-11.903799 z M 151.12801,132.2755 c 2.17877,-0.55401 4.13861,-0.53197 5.77959,0.065 7.31131,2.65972 6.76636,15.88363 -1.21719,29.5365 -7.98356,13.65282 -20.38249,22.56458 -27.69389,19.90504 -7.31132,-2.65972 -6.76637,-15.88364 1.21719,-29.53651 5.96208,-10.19594 14.66479,-18.12654 21.9143,-19.97007 z"
|
||||
id="path897"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccsssccccccscccccccccccccccc" />
|
||||
<ellipse
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
|
||||
id="path962"
|
||||
cx="128.25729"
|
||||
cy="26.431171"
|
||||
rx="17.575893"
|
||||
ry="21.733631"
|
||||
transform="rotate(16.845913)" />
|
||||
<ellipse
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.29560357;stroke-opacity:1"
|
||||
id="path964"
|
||||
cx="245.22121"
|
||||
cy="-179.49768"
|
||||
rx="18.099041"
|
||||
ry="22.821976"
|
||||
transform="matrix(0.33166949,0.94339565,-0.88087771,0.47334392,0,0)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 7.3 KiB |
|
@ -15,10 +15,62 @@
|
|||
<allow-intent href="geo:*" />
|
||||
<platform name="android">
|
||||
<allow-intent href="market:*" />
|
||||
<icon density="ldpi" src="res/android/ldpi.png" />
|
||||
<icon density="mdpi" src="res/android/mdpi.png" />
|
||||
<icon density="hdpi" src="res/android/hdpi.png" />
|
||||
<icon density="xhdpi" src="res/android/xhdpi.png" />
|
||||
<icon density="xxhdpi" src="res/android/xxhdpi.png" />
|
||||
<icon density="xxxhdpi" src="res/android/xxxhdpi.png" />
|
||||
<splash density="land-ldpi" src="res/screen/android/splash-land-ldpi.png" />
|
||||
<splash density="port-ldpi" src="res/screen/android/splash-port-ldpi.png" />
|
||||
<splash density="land-mdpi" src="res/screen/android/splash-land-mdpi.png" />
|
||||
<splash density="port-mdpi" src="res/screen/android/splash-port-mdpi.png" />
|
||||
<splash density="land-hdpi" src="res/screen/android/splash-land-hdpi.png" />
|
||||
<splash density="port-hdpi" src="res/screen/android/splash-port-hdpi.png" />
|
||||
<splash density="land-xhdpi" src="res/screen/android/splash-land-xhdpi.png" />
|
||||
<splash density="port-xhdpi" src="res/screen/android/splash-port-xhdpi.png" />
|
||||
<splash density="land-xxhdpi" src="res/screen/android/splash-land-xxhdpi.png" />
|
||||
<splash density="port-xxhdpi" src="res/screen/android/splash-port-xxhdpi.png" />
|
||||
<splash density="land-xxxhdpi" src="res/screen/android/splash-land-xxxhdpi.png" />
|
||||
<splash density="port-xxxhdpi" src="res/screen/android/splash-port-xxxhdpi.png" />
|
||||
</platform>
|
||||
<platform name="ios">
|
||||
<allow-intent href="itms:*" />
|
||||
<allow-intent href="itms-apps:*" />
|
||||
<icon height="57" src="res/ios/icon.png" width="57" />
|
||||
<icon height="114" src="res/ios/icon@2x.png" width="114" />
|
||||
<icon height="40" src="res/ios/icon-20@2x.png" width="40" />
|
||||
<icon height="60" src="res/ios/icon-20@3x.png" width="60" />
|
||||
<icon height="29" src="res/ios/icon-29.png" width="29" />
|
||||
<icon height="58" src="res/ios/icon-29@2x.png" width="58" />
|
||||
<icon height="87" src="res/ios/icon-29@3x.png" width="87" />
|
||||
<icon height="80" src="res/ios/icon-40@2x.png" width="80" />
|
||||
<icon height="120" src="res/ios/icon-60@2x.png" width="120" />
|
||||
<icon height="180" src="res/ios/icon-60@3x.png" width="180" />
|
||||
<icon height="20" src="res/ios/icon-20.png" width="20" />
|
||||
<icon height="40" src="res/ios/icon-40.png" width="40" />
|
||||
<icon height="50" src="res/ios/icon-50.png" width="50" />
|
||||
<icon height="100" src="res/ios/icon-50@2x.png" width="100" />
|
||||
<icon height="72" src="res/ios/icon-72.png" width="72" />
|
||||
<icon height="144" src="res/ios/icon-72@2x.png" width="144" />
|
||||
<icon height="76" src="res/ios/icon-76.png" width="76" />
|
||||
<icon height="152" src="res/ios/icon-76@2x.png" width="152" />
|
||||
<icon height="167" src="res/ios/icon-83.5@2x.png" width="167" />
|
||||
<icon height="1024" src="res/ios/icon-1024.png" width="1024" />
|
||||
<icon height="48" src="res/ios/icon-24@2x.png" width="48" />
|
||||
<icon height="55" src="res/ios/icon-27.5@2x.png" width="55" />
|
||||
<icon height="88" src="res/ios/icon-44@2x.png" width="88" />
|
||||
<icon height="172" src="res/ios/icon-86@2x.png" width="172" />
|
||||
<icon height="196" src="res/ios/icon-98@2x.png" width="196" />
|
||||
<splash src="res/screen/ios/Default@2x~iphone~anyany.png" />
|
||||
<splash src="res/screen/ios/Default@2x~iphone~comany.png" />
|
||||
<splash src="res/screen/ios/Default@2x~iphone~comcom.png" />
|
||||
<splash src="res/screen/ios/Default@3x~iphone~anyany.png" />
|
||||
<splash src="res/screen/ios/Default@3x~iphone~anycom.png" />
|
||||
<splash src="res/screen/ios/Default@3x~iphone~comany.png" />
|
||||
<splash src="res/screen/ios/Default@2x~ipad~anyany.png" />
|
||||
<splash src="res/screen/ios/Default@2x~ipad~comany.png" />
|
||||
</platform>
|
||||
<allow-navigation href="about:*" />
|
||||
<preference name="SplashMaintainAspectRatio" value="true" />
|
||||
</widget>
|
||||
|
|
|
@ -13,15 +13,19 @@
|
|||
"author": "Apache Cordova Team",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"cordova-android": "^9.0.0",
|
||||
"cordova-ios": "^6.1.1",
|
||||
"cordova-plugin-splashscreen": "^6.0.0",
|
||||
"cordova-plugin-whitelist": "^1.3.4"
|
||||
},
|
||||
"cordova": {
|
||||
"plugins": {
|
||||
"cordova-plugin-whitelist": {}
|
||||
"cordova-plugin-whitelist": {},
|
||||
"cordova-plugin-splashscreen": {}
|
||||
},
|
||||
"platforms": [
|
||||
"ios"
|
||||
"ios",
|
||||
"android"
|
||||
]
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 411 B |
After Width: | Height: | Size: 715 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 866 B |
After Width: | Height: | Size: 1017 B |
After Width: | Height: | Size: 566 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 715 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 923 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 33 KiB |
|
@ -3,6 +3,8 @@ import { boot } from 'quasar/wrappers';
|
|||
import config from '../config';
|
||||
import { Store } from 'vuex';
|
||||
import { StateInterface } from 'src/store';
|
||||
import { LocalStorage } from 'quasar';
|
||||
import { Notify } from 'quasar';
|
||||
|
||||
declare module 'vue/types/vue' {
|
||||
interface Vue {
|
||||
|
@ -10,11 +12,29 @@ declare module 'vue/types/vue' {
|
|||
}
|
||||
}
|
||||
|
||||
export const setBaseUrl = (url: string) => {
|
||||
LocalStorage.set('baseURL', url);
|
||||
axios.defaults.baseURL = url;
|
||||
Notify.create({
|
||||
message: 'Serveraddresse gespeichert',
|
||||
position: 'bottom',
|
||||
caption: `${url}`,
|
||||
color: 'positive'
|
||||
});
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 5000);
|
||||
};
|
||||
|
||||
export default boot<Store<StateInterface>>(({ Vue, store, router }) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
Vue.prototype.$axios = axios;
|
||||
axios.defaults.baseURL = config.baseURL;
|
||||
|
||||
const baseURL = <string | undefined>LocalStorage.getItem('baseURL');
|
||||
if (baseURL) {
|
||||
axios.defaults.baseURL = baseURL;
|
||||
} else {
|
||||
axios.defaults.baseURL = config.baseURL;
|
||||
}
|
||||
/***
|
||||
* Intercept requests and insert Token if available
|
||||
*/
|
||||
|
|
|
@ -43,7 +43,7 @@ interface Props {
|
|||
label?: string;
|
||||
readonly: boolean;
|
||||
type: string;
|
||||
rules: Array<any>;
|
||||
rules: Array<string>;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
|
@ -63,7 +63,7 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
rules: {
|
||||
default: []
|
||||
default: () => { return [] }
|
||||
}
|
||||
},
|
||||
setup(props: Props, { emit }: { emit: any }) {
|
||||
|
|
|
@ -27,10 +27,11 @@ declare namespace FG {
|
|||
id: number;
|
||||
time: Date;
|
||||
amount: number;
|
||||
reversal?: this;
|
||||
reversal_id: number;
|
||||
sender_id?: string;
|
||||
receiver_id?: string;
|
||||
author_id?: string;
|
||||
original_id?: number;
|
||||
}
|
||||
interface Event {
|
||||
id: number;
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
|
||||
<q-toolbar-title>
|
||||
<router-link :to="{ name: 'dashboard' }" style="text-decoration: none; color: inherit">
|
||||
<q-avatar>
|
||||
<img src="logo.svg" />
|
||||
<q-avatar rounded>
|
||||
<img src="flaschengeist-logo-white.svg" />
|
||||
</q-avatar>
|
||||
<span class="gt-xs"> Flaschengeist </span>
|
||||
</router-link>
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
<q-header elevated>
|
||||
<q-toolbar>
|
||||
<q-toolbar-title>
|
||||
<q-avatar>
|
||||
<img src="logo.svg" />
|
||||
<q-avatar rounded>
|
||||
<img src="flaschengeist-logo-white.svg" />
|
||||
</q-avatar>
|
||||
<span class="gt-xs">
|
||||
Flaschengeist
|
||||
|
|
|
@ -36,6 +36,21 @@
|
|||
</div>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
<div class="row justify-end">
|
||||
<q-btn flat round icon="mdi-menu-down" class="cordova-only" @click="openServerSettings" />
|
||||
</div>
|
||||
<q-slide-transition class="cordova-only">
|
||||
<div v-show="visible">
|
||||
<q-separator />
|
||||
<q-card-section>
|
||||
<q-form ref="ServerSettingsForm" @submit="changeUrl" class="q-gutter-md">
|
||||
<div class="text-h6">Servereinstellung</div>
|
||||
<q-input filled label="Server" dense v-model="server" />
|
||||
<q-btn size="xs" dense color="primary" label="Speichern" type="submit" />
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
</div>
|
||||
</q-slide-transition>
|
||||
</q-card>
|
||||
</q-page>
|
||||
</template>
|
||||
|
@ -43,6 +58,7 @@
|
|||
<script lang="ts">
|
||||
import { defineComponent, ref } from '@vue/composition-api';
|
||||
import { Loading, Notify } from 'quasar';
|
||||
import { setBaseUrl } from 'boot/axios';
|
||||
|
||||
export default defineComponent({
|
||||
// name: 'PageName'
|
||||
|
@ -53,6 +69,18 @@ export default defineComponent({
|
|||
const userid = ref('');
|
||||
const password = ref('');
|
||||
const rules = [(val: string) => (val && val.length > 0) || 'Feld darf nicht leer sein!'];
|
||||
const server = ref<string | undefined>(root.$axios.defaults.baseURL);
|
||||
const visible = ref(false);
|
||||
|
||||
function openServerSettings() {
|
||||
visible.value = !visible.value;
|
||||
}
|
||||
|
||||
function changeUrl() {
|
||||
if (server.value) {
|
||||
setBaseUrl(server.value);
|
||||
}
|
||||
}
|
||||
|
||||
function doLogin() {
|
||||
Loading.show({
|
||||
|
@ -116,7 +144,17 @@ export default defineComponent({
|
|||
});
|
||||
}
|
||||
|
||||
return { userid, password, doLogin, doReset, rules };
|
||||
return {
|
||||
userid,
|
||||
password,
|
||||
doLogin,
|
||||
doReset,
|
||||
rules,
|
||||
server,
|
||||
changeUrl,
|
||||
visible,
|
||||
openServerSettings
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
>
|
||||
<div class="fit row justify-center content-center items-center">
|
||||
<q-img
|
||||
:src="$q.dark.isActive ? 'logo.svg' : 'logo-dark.svg'"
|
||||
:src="$q.dark.isActive ? 'flaschengeist-logo.svg' : 'flaschengeist-logo.svg'"
|
||||
class="col-12 q-ma-md"
|
||||
style="min-width: 200px; max-width: 400px"
|
||||
/>
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
<template>
|
||||
<q-card>
|
||||
<BalanceHeader @update:user="userUpdated" :showSelector="showSelector" @open-history="openHistory"/>
|
||||
<q-separator />
|
||||
|
||||
<q-card-section class="row q-col-gutter-md" v-if="shortCuts">
|
||||
<div :key="index" v-for="(shortcut, index) in shortCuts" class="col-4">
|
||||
<q-btn
|
||||
push
|
||||
v-if="shortcut"
|
||||
color="primary"
|
||||
style="width: 100%"
|
||||
:label="shortcut.toFixed(2).toString() + ' €'"
|
||||
@click="changeBalance(shortcut)"
|
||||
>
|
||||
<q-popup-proxy context-menu>
|
||||
<q-btn label="Entfernen" @click="removeShortcut(shortcut)" />
|
||||
</q-popup-proxy>
|
||||
<q-tooltip>Rechtsklick um Verknüpfung zu entfernen</q-tooltip>
|
||||
</q-btn>
|
||||
</div></q-card-section
|
||||
>
|
||||
<q-card-section class="row q-col-gutter-md items-center">
|
||||
<div class="col-sm-4 col-xs-12">
|
||||
<q-input
|
||||
v-model.number="amount"
|
||||
type="number"
|
||||
filled
|
||||
label="Eigener Betrag"
|
||||
step="0.1"
|
||||
min="0"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-sm-4 col-xs-6">
|
||||
<q-btn
|
||||
style="width: 100%"
|
||||
color="primary"
|
||||
label="Anschreiben"
|
||||
@click="changeBalance(amount * -1)"
|
||||
><q-tooltip>Rechtsklick um Betrag als Verknüpfung hinzuzufügen</q-tooltip>
|
||||
<q-popup-proxy context-menu v-model="showAddShortcut">
|
||||
<q-btn label="neue Verknüpfung" @click="addShortcut"></q-btn>
|
||||
</q-popup-proxy>
|
||||
</q-btn>
|
||||
</div>
|
||||
<div class="col-sm-4 col-xs-6">
|
||||
<q-btn
|
||||
v-if="canAddCredit"
|
||||
style="width: 100%"
|
||||
color="secondary"
|
||||
label="Gutschreiben"
|
||||
@click="changeBalance(amount)"
|
||||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, ref, defineComponent, onBeforeMount } from '@vue/composition-api';
|
||||
import { hasPermission } from 'src/utils/permission';
|
||||
import { StateInterfaceBalance } from '../store/balance';
|
||||
import { Store } from 'vuex';
|
||||
import BalanceHeader from '../components/BalanceHeader.vue';
|
||||
import PERMISSIONS from '../permissions';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'BalanceAdd',
|
||||
components: { BalanceHeader },
|
||||
setup(_, { root, emit }) {
|
||||
onBeforeMount(() => {
|
||||
void store.dispatch('balance/getShortcuts');
|
||||
if (store.state.balance.transactions.length == 0)
|
||||
// No transaction, load at most six since yesterday
|
||||
void store.dispatch('balance/getTransactions', {
|
||||
filter: { limit: 6, from: new Date(new Date().setDate(new Date().getDate() - 1)) }
|
||||
});
|
||||
});
|
||||
const store = <Store<StateInterfaceBalance>>root.$store;
|
||||
|
||||
const amount = ref<number>(0);
|
||||
const showAddShortcut = ref(false);
|
||||
const user = ref(store.state.user.currentUser);
|
||||
const shortCuts = ref(store.state.balance.shortcuts);
|
||||
|
||||
const canAddCredit = computed(() => hasPermission(PERMISSIONS.CREDIT, store));
|
||||
const showSelector = computed(
|
||||
() => hasPermission(PERMISSIONS.DEBIT, store) || hasPermission(PERMISSIONS.CREDIT, store)
|
||||
);
|
||||
|
||||
function addShortcut() {
|
||||
if (amount.value != 0) void store.dispatch('balance/addShortcut', amount.value * -1);
|
||||
}
|
||||
function removeShortcut(shortcut: number) {
|
||||
void store.dispatch('balance/removeShortcut', shortcut);
|
||||
}
|
||||
function userUpdated(selectedUser: FG.User) {
|
||||
user.value = selectedUser;
|
||||
}
|
||||
function changeBalance(amount: number) {
|
||||
store
|
||||
.dispatch('balance/changeBalance', { amount: amount, user: user.value?.userid })
|
||||
.catch(err => console.log(err));
|
||||
}
|
||||
|
||||
function openHistory() {
|
||||
emit('open-history')
|
||||
}
|
||||
|
||||
return {
|
||||
user,
|
||||
addShortcut,
|
||||
canAddCredit,
|
||||
removeShortcut,
|
||||
showAddShortcut,
|
||||
changeBalance,
|
||||
amount,
|
||||
showSelector,
|
||||
shortCuts,
|
||||
userUpdated,
|
||||
openHistory
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -1,12 +1,15 @@
|
|||
<template>
|
||||
<q-card-section class="fit row justify-left content-center items-center q-col-gutter-sm">
|
||||
<div class="text-h6 col-6">
|
||||
<div class="text-h6 col-5">
|
||||
Aktueller Stand: {{ balance.balance.toFixed(2) }} €
|
||||
<q-badge color="negative" align="top" v-if="isLocked"> gesperrt </q-badge>
|
||||
</div>
|
||||
<div v-if="showSelector" class="col-6">
|
||||
<UserSelector :user="user" @update:user="userUpdated" />
|
||||
</div>
|
||||
<div class="col-1 justify-end">
|
||||
<q-btn round flat icon="mdi-format-list-checks" @click="openHistory" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
</template>
|
||||
|
||||
|
@ -43,7 +46,11 @@ export default defineComponent({
|
|||
emit('update:user', selectedUser);
|
||||
}
|
||||
|
||||
return { user, balance, isLocked, userUpdated };
|
||||
function openHistory() {
|
||||
emit('open-history');
|
||||
}
|
||||
|
||||
return { user, balance, isLocked, userUpdated, openHistory };
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -1,39 +1,25 @@
|
|||
<template>
|
||||
<q-page padding class="fit row justify-left q-col-gutter-sm">
|
||||
<div class="col-12">
|
||||
<q-card>
|
||||
<BalanceHeader @update:user="senderUpdated" :showSelector="showSelector" />
|
||||
<q-separator />
|
||||
<q-card-section class="row q-col-gutter-md items-center">
|
||||
<div class="col-sm-4 col-xs-12">
|
||||
<q-input
|
||||
v-model.number="amount"
|
||||
type="number"
|
||||
filled
|
||||
label="Betrag"
|
||||
step="0.1"
|
||||
min="0"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-sm-4 col-xs-6">
|
||||
<UserSelector :user="receiver" @update:user="receiverUpdated" label="Empfänger" />
|
||||
</div>
|
||||
<div class="col-sm-4 col-xs-6">
|
||||
<q-btn
|
||||
style="width: 100%"
|
||||
color="primary"
|
||||
:disable="sendDisabled"
|
||||
label="Senden"
|
||||
@click="sendAmount"
|
||||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</div>
|
||||
<div v-for="(transaction, index) in transactions" v-bind:key="index" class="col-sm-4 col-xs-6">
|
||||
<Transaction :transaction.sync="transactions[index]" />
|
||||
</div>
|
||||
</q-page>
|
||||
<q-card>
|
||||
<BalanceHeader @update:user="senderUpdated" :showSelector="showSelector" @open-history="openHistory"/>
|
||||
<q-separator />
|
||||
<q-card-section class="row q-col-gutter-md items-center">
|
||||
<div class="col-sm-4 col-xs-12">
|
||||
<q-input v-model.number="amount" type="number" filled label="Betrag" step="0.1" min="0" />
|
||||
</div>
|
||||
<div class="col-sm-4 col-xs-6">
|
||||
<UserSelector :user="receiver" @update:user="receiverUpdated" label="Empfänger" />
|
||||
</div>
|
||||
<div class="col-sm-4 col-xs-6">
|
||||
<q-btn
|
||||
style="width: 100%"
|
||||
color="primary"
|
||||
:disable="sendDisabled"
|
||||
label="Senden"
|
||||
@click="sendAmount"
|
||||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -42,21 +28,19 @@ import { hasPermission } from 'src/utils/permission';
|
|||
import { StateInterfaceBalance } from '../store/balance';
|
||||
import { Store } from 'vuex';
|
||||
import UserSelector from 'src/plugins/user/components/UserSelector.vue';
|
||||
import Transaction from '../components/Transaction.vue';
|
||||
import BalanceHeader from '../components/BalanceHeader.vue';
|
||||
import PERMISSIONS from '../permissions';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'BalanceTransfer',
|
||||
components: { Transaction, BalanceHeader, UserSelector },
|
||||
setup(_, { root }) {
|
||||
components: { BalanceHeader, UserSelector },
|
||||
setup(_, { root, emit }) {
|
||||
const store: Store<StateInterfaceBalance> = <Store<StateInterfaceBalance>>root.$store;
|
||||
|
||||
const showSelector = computed(() => hasPermission(PERMISSIONS.SEND_OTHER, store));
|
||||
const sender = ref(store.state.user.currentUser);
|
||||
const receiver = ref<FG.User | undefined>(undefined);
|
||||
const amount = ref<number>(0);
|
||||
const transactions = computed(() => store.state.balance.transactions.slice().reverse());
|
||||
|
||||
const sendDisabled = computed(() => {
|
||||
return !(
|
||||
|
@ -85,16 +69,20 @@ export default defineComponent({
|
|||
.catch(err => console.log(err));
|
||||
}
|
||||
|
||||
function openHistory() {
|
||||
emit('open-history');
|
||||
}
|
||||
|
||||
return {
|
||||
sender,
|
||||
receiver,
|
||||
amount,
|
||||
sendAmount,
|
||||
transactions,
|
||||
showSelector,
|
||||
senderUpdated,
|
||||
receiverUpdated,
|
||||
sendDisabled
|
||||
sendDisabled,
|
||||
openHistory
|
||||
};
|
||||
}
|
||||
});
|
|
@ -1,29 +1,37 @@
|
|||
<template>
|
||||
<q-card v-bind:class="{ 'bg-grey': isReversed }">
|
||||
<q-card-section class="row items-start justify-between">
|
||||
<div class="col text-center">
|
||||
<div>
|
||||
<q-card flat square>
|
||||
<q-card-section class="row items-center justify-between" horizontal>
|
||||
<div class="col-5 text-left q-px-sm">
|
||||
<div
|
||||
v-bind:class="{ 'text-negative': isNegative() }"
|
||||
class="text-weight-bold"
|
||||
style="font-size: 2em"
|
||||
class="text-weight-bold text-h6"
|
||||
>
|
||||
<span v-if="isNegative()">-</span>{{ transaction.amount.toFixed(2) }} €
|
||||
</div>
|
||||
<div>{{ text }}</div>
|
||||
<div>{{ timeStr }}</div>
|
||||
<div class="text-caption">{{ text }}</div>
|
||||
<div class="text-caption">{{ timeStr }}</div>
|
||||
</div>
|
||||
<div class="col" style="text-align: right">
|
||||
<div class="col-5 q-px-sm text-center">
|
||||
<div class="text-subtitle1" v-if="isReversed">
|
||||
Storniert
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2 q-pr-sm" style="text-align: right">
|
||||
<q-btn
|
||||
color="negative"
|
||||
:color="isReversed ? 'positive' : 'negative'"
|
||||
aria-label="Reverse transaction"
|
||||
icon="mdi-trash-can"
|
||||
square
|
||||
:icon="!isReversed ? 'mdi-trash-can' : 'mdi-check-bold'"
|
||||
size="sm"
|
||||
round
|
||||
:disable="!canReverse"
|
||||
@click="reverse"
|
||||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
<q-separator />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -77,7 +85,9 @@ export default defineComponent({
|
|||
}
|
||||
};
|
||||
|
||||
const isReversed = computed(() => props.transaction.reversal != undefined);
|
||||
const isReversed = computed(
|
||||
() => props.transaction.reversal_id != undefined || props.transaction.original_id != undefined
|
||||
);
|
||||
|
||||
const canReverse = computed(
|
||||
() =>
|
||||
|
|
|
@ -1,121 +0,0 @@
|
|||
<template>
|
||||
<q-page padding class="fit row justify-left q-col-gutter-sm">
|
||||
<div class="col-12">
|
||||
<q-card>
|
||||
<BalanceHeader @update:user="userUpdated" :showSelector="showSelector" />
|
||||
<q-separator />
|
||||
|
||||
<q-card-section class="row q-col-gutter-md" v-if="shortCuts">
|
||||
<div :key="index" v-for="(shortcut, index) in shortCuts" class="col-4">
|
||||
<q-btn
|
||||
push
|
||||
v-if="shortcut"
|
||||
color="primary"
|
||||
style="width: 100%"
|
||||
:label="shortcut.toFixed(2).toString() + ' €'"
|
||||
@click="changeBalance(shortcut)"
|
||||
>
|
||||
<q-popup-proxy context-menu>
|
||||
<q-btn label="Entfernen" @click="removeShortcut(shortcut)" />
|
||||
</q-popup-proxy>
|
||||
<q-tooltip>Rechtsklick um Verknüpfung zu entfernen</q-tooltip>
|
||||
</q-btn>
|
||||
</div></q-card-section
|
||||
>
|
||||
<q-card-section class="row q-col-gutter-md items-center">
|
||||
<div class="col-sm-4 col-xs-12">
|
||||
<q-input
|
||||
v-model.number="amount"
|
||||
type="number"
|
||||
filled
|
||||
label="Eigener Betrag"
|
||||
step="0.1"
|
||||
min="0"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-sm-4 col-xs-6">
|
||||
<q-btn
|
||||
style="width: 100%"
|
||||
color="primary"
|
||||
label="Anschreiben"
|
||||
@click="changeBalance(amount * -1)"
|
||||
><q-tooltip>Rechtsklick um Betrag als Verknüpfung hinzuzufügen</q-tooltip>
|
||||
<q-popup-proxy context-menu v-model="showAddShortcut">
|
||||
<q-btn label="neue Verknüpfung" @click="addShortcut"></q-btn>
|
||||
</q-popup-proxy>
|
||||
</q-btn>
|
||||
</div>
|
||||
<div class="col-sm-4 col-xs-6">
|
||||
<q-btn
|
||||
style="width: 100%"
|
||||
color="secondary"
|
||||
label="Gutschreiben"
|
||||
@click="changeBalance(amount)"
|
||||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</div>
|
||||
<div v-for="(transaction, index) in transactions" v-bind:key="index" class="col-md-4 col-sm-6">
|
||||
<!-- TODO: In Vue3 use v-model:transaction="..." -->
|
||||
<Transaction :transaction.sync="transactions[index]" />
|
||||
</div>
|
||||
</q-page>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, ref, defineComponent, onBeforeMount } from '@vue/composition-api';
|
||||
import { hasPermission } from 'src/utils/permission';
|
||||
import { StateInterfaceBalance } from '../store/balance';
|
||||
import { Store } from 'vuex';
|
||||
import Transaction from '../components/Transaction.vue';
|
||||
import BalanceHeader from '../components/BalanceHeader.vue';
|
||||
import PERMISSIONS from '../permissions';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'BalanceAdd',
|
||||
components: { Transaction, BalanceHeader },
|
||||
setup(_, { root }) {
|
||||
onBeforeMount(() => void store.dispatch('balance/getShortcuts'));
|
||||
const store = <Store<StateInterfaceBalance>>root.$store;
|
||||
|
||||
const amount = ref<number>(0);
|
||||
const showAddShortcut = ref(false);
|
||||
const transactions = computed(() => store.state.balance.transactions.slice().reverse());
|
||||
const user = ref(store.state.user.currentUser);
|
||||
const shortCuts = ref(store.state.balance.shortcuts);
|
||||
|
||||
const showSelector = computed(
|
||||
() => hasPermission(PERMISSIONS.DEBIT, store) || hasPermission(PERMISSIONS.CREDIT, store)
|
||||
);
|
||||
|
||||
function addShortcut() {
|
||||
if (amount.value != 0) void store.dispatch('balance/addShortcut', amount.value * -1);
|
||||
}
|
||||
function removeShortcut(shortcut: number) {
|
||||
void store.dispatch('balance/removeShortcut', shortcut);
|
||||
}
|
||||
function userUpdated(selectedUser: FG.User) {
|
||||
user.value = selectedUser;
|
||||
}
|
||||
function changeBalance(amount: number) {
|
||||
store
|
||||
.dispatch('balance/changeBalance', { amount: amount, user: user.value?.userid })
|
||||
.catch(err => console.log(err));
|
||||
}
|
||||
|
||||
return {
|
||||
user,
|
||||
addShortcut,
|
||||
removeShortcut,
|
||||
showAddShortcut,
|
||||
changeBalance,
|
||||
transactions,
|
||||
amount,
|
||||
showSelector,
|
||||
shortCuts,
|
||||
userUpdated
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -11,25 +11,24 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
// TODO: Load all users / balances
|
||||
|
||||
// TODO: Fill usefull data
|
||||
|
||||
import { computed, defineComponent } from '@vue/composition-api';
|
||||
import { StateInterfaceBalance } from '../store/balance';
|
||||
import { ref, defineComponent, onMounted } from '@vue/composition-api';
|
||||
import { StateInterfaceBalance, BalancesResponse } from '../store/balance';
|
||||
import { Store } from 'vuex';
|
||||
export default defineComponent({
|
||||
// name: 'PageName'
|
||||
setup(_, { root }) {
|
||||
const store = <Store<StateInterfaceBalance>>root.$store;
|
||||
|
||||
const rows = computed(() => {
|
||||
const fo: Array<{ userid: string; balance: number }> = [];
|
||||
store.state.balance.balances.forEach((value, key) =>
|
||||
fo.push(Object.assign(value, { userid: key }))
|
||||
);
|
||||
return fo;
|
||||
});
|
||||
onMounted(
|
||||
() =>
|
||||
void store
|
||||
.dispatch('balance/getBalances')
|
||||
.then((balances: Array<BalancesResponse>) => rows.value.push(...balances))
|
||||
);
|
||||
|
||||
const rows = ref(new Array<BalancesResponse>());
|
||||
|
||||
const columns = [
|
||||
{
|
||||
|
@ -41,16 +40,22 @@ export default defineComponent({
|
|||
sortable: true
|
||||
},
|
||||
{
|
||||
name: 'balance',
|
||||
label: 'Kontostand',
|
||||
field: 'balance',
|
||||
name: 'credit',
|
||||
label: 'Haben',
|
||||
field: 'credit',
|
||||
format: (val: number) => val.toFixed(2)
|
||||
},
|
||||
{
|
||||
name: 'limit',
|
||||
label: 'Limit',
|
||||
field: 'limit',
|
||||
format: (val: number) => (val === null ? 'keins' : val)
|
||||
name: 'debit',
|
||||
label: 'Soll',
|
||||
field: 'debit',
|
||||
format: (val: number) => val.toFixed(2)
|
||||
},
|
||||
{
|
||||
name: 'balance',
|
||||
label: 'Kontostand',
|
||||
format: (_: undefined, row: { debit: number; credit: number }) =>
|
||||
(row.credit - row.debit).toFixed(2)
|
||||
}
|
||||
];
|
||||
return { rows, columns };
|
||||
|
|
|
@ -1,48 +1,118 @@
|
|||
<template>
|
||||
<div>
|
||||
<q-page padding v-if="checkMain">
|
||||
<q-card>
|
||||
<q-card-section>
|
||||
<q-list v-for="(mainRoute, index) in mainRoutes" :key="'mainRoute' + index">
|
||||
<essential-link
|
||||
v-for="(route, index2) in mainRoute.children"
|
||||
:key="'route' + index2"
|
||||
:title="route.title"
|
||||
:icon="route.icon"
|
||||
:link="route.name"
|
||||
:permissions="route.meta.permissions"
|
||||
/>
|
||||
</q-list>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
<q-tabs v-model="tab" v-if="$q.screen.gt.sm">
|
||||
<q-tab
|
||||
v-for="(tabindex, index) in tabs"
|
||||
:key="'tab' + index"
|
||||
:name="tabindex.name"
|
||||
:label="tabindex.label"
|
||||
/>
|
||||
</q-tabs>
|
||||
<div class="fit row justify-end" v-else>
|
||||
<q-btn flat round icon="mdi-menu" @click="showDrawer = !showDrawer; show = false" />
|
||||
</div>
|
||||
<q-drawer side="right" v-model="showDrawer" @click="showDrawer = !showDrawer" behavior="mobile">
|
||||
<q-list v-model="tab" v-if="!$q.screen.gt.sm && !show">
|
||||
<q-item
|
||||
v-for="(tabindex, index) in tabs"
|
||||
:key="'tab' + index"
|
||||
:active="tab == tabindex.name"
|
||||
clickable
|
||||
@click="tab = tabindex.name"
|
||||
>
|
||||
<q-item-label>{{ tabindex.label }}</q-item-label>
|
||||
</q-item>
|
||||
</q-list>
|
||||
<q-list v-if="show">
|
||||
<div
|
||||
v-for="(transaction, index) in transactions"
|
||||
v-bind:key="index"
|
||||
class="col-sm-12"
|
||||
>
|
||||
<!-- TODO: In Vue3 use v-model:transaction="..." -->
|
||||
<Transaction :transaction.sync="transactions[index]" />
|
||||
</div>
|
||||
</q-list>
|
||||
</q-drawer>
|
||||
<q-page padding class="fit row justify-left q-col-gutter-sm">
|
||||
<q-tab-panels
|
||||
v-model="tab"
|
||||
style="background-color: transparent"
|
||||
class="q-pa-none col-12"
|
||||
animated
|
||||
>
|
||||
<q-tab-panel name="add" class="q-px-xs">
|
||||
<BalanceAdd @open-history="showDrawer = !showDrawer; show = showDrawer"/>
|
||||
</q-tab-panel>
|
||||
<q-tab-panel name="transfer" class="q-px-xs">
|
||||
<BalanceTransfer @open-history="showDrawer = !showDrawer; show = showDrawer"/>
|
||||
</q-tab-panel>
|
||||
</q-tab-panels>
|
||||
</q-page>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent } from '@vue/composition-api';
|
||||
import EssentialLink from 'src/components/navigation/EssentialLink.vue';
|
||||
import mainRoutes from 'src/plugins/balance/routes';
|
||||
import { computed, defineComponent, ref, onMounted } from '@vue/composition-api';
|
||||
import { Store } from 'vuex';
|
||||
import { BalanceInterface } from 'src/plugins/balance/store/balance';
|
||||
import setLoadingBar from 'src/utils/loading';
|
||||
import { StateInterface } from 'src/store';
|
||||
import { hasPermissions, hasSomePermissions } from 'src/utils/permission';
|
||||
import PERMISSIONS from '../permissions';
|
||||
import { Screen } from 'quasar';
|
||||
import BalanceAdd from '../components/BalanceAdd.vue';
|
||||
import BalanceTransfer from '../components/BalanceTransfer.vue';
|
||||
import Transaction from '../components/Transaction.vue';
|
||||
import { StateInterfaceBalance } from '../store/balance';
|
||||
|
||||
export default defineComponent({
|
||||
// name: 'PageName'
|
||||
components: { EssentialLink },
|
||||
name: 'BalanceManage',
|
||||
components: { BalanceAdd, BalanceTransfer, Transaction },
|
||||
setup(_, { root }) {
|
||||
const store = <Store<StateInterface>>root.$store;
|
||||
const loading = computed(() => {
|
||||
return (<BalanceInterface>store.state.balance).loading > 0;
|
||||
});
|
||||
const checkMain = computed(() => {
|
||||
return root.$route.matched.length == 2;
|
||||
const store = <Store<StateInterfaceBalance>>root.$store;
|
||||
const now = new Date()
|
||||
onMounted(() => {
|
||||
void store.dispatch('balance/getTransactions', {filter: {from: new Date(now.getFullYear(), now.getMonth(), now.getDay())}})
|
||||
})
|
||||
const transactions = computed(() =>
|
||||
store.state.balance.transactions
|
||||
.filter(t => t.original_id == undefined)
|
||||
.sort((a, b) => (a.time >= b.time ? -1 : 1))
|
||||
);
|
||||
|
||||
const canAdd = () =>
|
||||
hasSomePermissions([PERMISSIONS.DEBIT, PERMISSIONS.CREDIT, PERMISSIONS.DEBIT_OWN], store);
|
||||
|
||||
interface Tab {
|
||||
name: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
const tabs: Tab[] = [
|
||||
...(canAdd() ? [{ name: 'add', label: 'Anschreiben' }] : []),
|
||||
...(hasSomePermissions([PERMISSIONS.SEND, PERMISSIONS.SEND_OTHER], store)
|
||||
? [{ name: 'transfer', label: 'Übertragen' }]
|
||||
: [])
|
||||
];
|
||||
|
||||
const drawer = ref<boolean>(false);
|
||||
|
||||
const showDrawer = computed({
|
||||
get: () => {
|
||||
return !Screen.gt.sm && drawer.value;
|
||||
},
|
||||
set: (val: boolean) => {
|
||||
drawer.value = val;
|
||||
}
|
||||
});
|
||||
|
||||
setLoadingBar(loading);
|
||||
|
||||
return { checkMain, mainRoutes };
|
||||
const tab = ref<string>(canAdd() ? 'add' : 'transfer');
|
||||
const show = ref<boolean>(false);
|
||||
return {
|
||||
showDrawer,
|
||||
tab,
|
||||
tabs,
|
||||
transactions,
|
||||
show
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
<template>
|
||||
<q-page padding>
|
||||
<q-card>
|
||||
<q-card-section class="text-center">
|
||||
<div class="text-h4">Aktueller Stand</div>
|
||||
<div style="font-size: 2em">{{ balance.toFixed(2) }} €</div>
|
||||
</q-card-section>
|
||||
<q-separator />
|
||||
<q-card-section>
|
||||
<q-table
|
||||
title="Buchungen"
|
||||
:data="data"
|
||||
:columns="columns"
|
||||
row-key="id"
|
||||
:pagination.sync="pagination"
|
||||
:loading="loading"
|
||||
@request="onRequest"
|
||||
binary-state-sort
|
||||
>
|
||||
<template v-slot:top>
|
||||
<q-toggle v-model="showCancelled" label="Stornierte einblenden" />
|
||||
</template>
|
||||
<template v-slot:body-cell="props">
|
||||
<q-td :props="props" v-bind:class="{ 'bg-grey': props.row.reversal_id != null }">
|
||||
{{ props.value }}
|
||||
</q-td>
|
||||
</template>
|
||||
</q-table>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-page>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, onMounted, ref } from '@vue/composition-api';
|
||||
import { StateInterfaceBalance, TransactionsResponse } from '../store/balance';
|
||||
import { Store } from 'vuex';
|
||||
import { formatDateTime } from 'src/utils/datetime';
|
||||
|
||||
export default defineComponent({
|
||||
// name: 'PageName'
|
||||
setup(_, { root }) {
|
||||
const store = <Store<StateInterfaceBalance>>root.$store;
|
||||
|
||||
onMounted(() => {
|
||||
void store.dispatch('balance/getBalance');
|
||||
void store.dispatch('user/getUsers').then(() =>
|
||||
onRequest({
|
||||
pagination: pagination.value,
|
||||
filter: undefined
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
const showCancelled = ref(false);
|
||||
const data = ref<FG.Transaction[]>([]);
|
||||
const loading = ref(false);
|
||||
const pagination = ref({
|
||||
sortBy: 'time',
|
||||
descending: false,
|
||||
page: 1,
|
||||
rowsPerPage: 3,
|
||||
rowsNumber: 10
|
||||
});
|
||||
|
||||
interface PaginationInterface {
|
||||
sortBy: string;
|
||||
descending: boolean;
|
||||
page: number;
|
||||
rowsPerPage: number;
|
||||
rowsNumber: number;
|
||||
}
|
||||
|
||||
function onRequest(props: { pagination: PaginationInterface; filter?: string }) {
|
||||
const { page, rowsPerPage, sortBy, descending } = props.pagination;
|
||||
|
||||
loading.value = true;
|
||||
// get all rows if "All" (0) is selected
|
||||
const fetchCount = rowsPerPage === 0 ? pagination.value.rowsNumber : rowsPerPage;
|
||||
// calculate starting row of data
|
||||
const startRow = (page - 1) * rowsPerPage;
|
||||
store
|
||||
.dispatch('balance/getTransactions', {
|
||||
filter: {
|
||||
offset: startRow,
|
||||
limit: fetchCount,
|
||||
showCancelled: showCancelled.value,
|
||||
showReversals: false
|
||||
}
|
||||
})
|
||||
.then((result: TransactionsResponse) => {
|
||||
// clear out existing data and add new
|
||||
data.value.splice(0, data.value.length, ...result.transactions);
|
||||
// don't forget to update local pagination object
|
||||
pagination.value.page = page;
|
||||
pagination.value.rowsPerPage = rowsPerPage;
|
||||
pagination.value.sortBy = sortBy;
|
||||
pagination.value.descending = descending;
|
||||
if (result.count) pagination.value.rowsNumber = result.count;
|
||||
})
|
||||
.finally(() => (loading.value = false));
|
||||
}
|
||||
|
||||
const balance = computed(
|
||||
() =>
|
||||
store.state.balance.balances.get((<FG.User>store.state.user.currentUser).userid)?.balance ||
|
||||
NaN
|
||||
);
|
||||
|
||||
const columns = [
|
||||
{
|
||||
name: 'time',
|
||||
label: 'Datum',
|
||||
field: 'time',
|
||||
required: true,
|
||||
sortable: true,
|
||||
format: (val: Date) => formatDateTime(new Date(val), true, true, true)
|
||||
},
|
||||
{
|
||||
name: 'text',
|
||||
label: 'Text',
|
||||
format: (_: undefined, row: FG.Transaction) => {
|
||||
if (row.sender_id == null) return 'Gutschrift';
|
||||
else {
|
||||
if (row.receiver_id == null) return 'Angeschrieben';
|
||||
else {
|
||||
if (row.receiver_id === store.state.user.currentUser?.userid) return 'Bekommen von X';
|
||||
else return 'Gesendet an X';
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'amount',
|
||||
label: 'Betrag',
|
||||
field: 'amount',
|
||||
format: (val: number) => `${val.toFixed(2)}€`
|
||||
},
|
||||
{
|
||||
name: 'author_id',
|
||||
label: 'Benutzer',
|
||||
field: 'author_id',
|
||||
format: (val: string) => {
|
||||
const user = store.state.user.users.filter(x => x.userid == val);
|
||||
if (user.length > 0) return user[0].display_name;
|
||||
else return val;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
return { data, pagination, onRequest, loading, balance, columns, showCancelled };
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -7,32 +7,32 @@ const mainRoutes: FG_Plugin.PluginRouteConfig[] = [
|
|||
icon: 'mdi-cash-100',
|
||||
path: 'balance',
|
||||
name: 'balance',
|
||||
redirect: { name: 'balance-add' },
|
||||
redirect: { name: 'balance-view' },
|
||||
meta: { permissions: ['user'] },
|
||||
children: [
|
||||
{
|
||||
title: 'Anschreiben',
|
||||
title: 'Übersicht',
|
||||
icon: 'mdi-cash-plus',
|
||||
path: 'add',
|
||||
name: 'balance-add',
|
||||
shortcut: true,
|
||||
meta: { permissions: [permissions.DEBIT_OWN, permissions.SHOW] },
|
||||
component: () => import('../pages/Add.vue')
|
||||
path: 'overview',
|
||||
name: 'balance-view',
|
||||
meta: { permissions: [permissions.SHOW] },
|
||||
component: () => import('../pages/Overview.vue')
|
||||
},
|
||||
{
|
||||
title: 'Übertragen',
|
||||
icon: 'mdi-cash-refund',
|
||||
path: 'transfer',
|
||||
name: 'balance-transfer',
|
||||
meta: { permissions: [permissions.SEND] },
|
||||
component: () => import('../pages/Transfer.vue')
|
||||
title: 'Buchen',
|
||||
icon: 'mdi-cash-plus',
|
||||
path: 'change',
|
||||
name: 'balance-change',
|
||||
shortcut: true,
|
||||
meta: { permissions: [permissions.DEBIT_OWN, permissions.SHOW] },
|
||||
component: () => import('../pages/MainPage.vue')
|
||||
},
|
||||
{
|
||||
title: 'Verwaltung',
|
||||
icon: 'mdi-account-cash',
|
||||
path: 'admin',
|
||||
name: 'balance-admin',
|
||||
meta: { permissions: [permissions.DEBIT_OWN, permissions.SHOW] },
|
||||
meta: { permissions: [permissions.SET_LIMIT, permissions.SHOW_OTHER] },
|
||||
component: () => import('../pages/Admin.vue')
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Module, MutationTree, ActionTree, GetterTree } from 'vuex';
|
||||
import { StateInterface } from 'src/store';
|
||||
import store, { StateInterface } from 'src/store';
|
||||
import { axios } from 'src/boot/axios';
|
||||
import { AxiosResponse } from 'axios';
|
||||
|
||||
|
@ -9,6 +9,15 @@ interface BalanceResponse {
|
|||
debit: number;
|
||||
}
|
||||
|
||||
export interface BalancesResponse extends BalanceResponse {
|
||||
userid: string;
|
||||
}
|
||||
|
||||
export interface TransactionsResponse {
|
||||
transactions: Array<FG.Transaction>;
|
||||
count?: number;
|
||||
}
|
||||
|
||||
export interface UserBalance extends BalanceResponse {
|
||||
limit: number | null;
|
||||
}
|
||||
|
@ -31,6 +40,10 @@ const state: BalanceInterface = {
|
|||
loading: 0
|
||||
};
|
||||
|
||||
function fixTransaction(t: FG.Transaction) {
|
||||
t.time = new Date(t.time);
|
||||
}
|
||||
|
||||
const mutations: MutationTree<BalanceInterface> = {
|
||||
setBalance(state, data: { userid: string; balance: BalanceResponse }) {
|
||||
state.balances.set(
|
||||
|
@ -59,9 +72,13 @@ const mutations: MutationTree<BalanceInterface> = {
|
|||
addTransaction(state, data: FG.Transaction) {
|
||||
state.transactions.push(data);
|
||||
},
|
||||
addTransactions(state, data: [FG.Transaction]) {
|
||||
state.transactions.push(...data);
|
||||
state.transactions.sort((a, b) => (a.time <= b.time ? -1 : 1));
|
||||
},
|
||||
reverseTransaction(state, data: { transaction: FG.Transaction; reversal: FG.Transaction }) {
|
||||
const idx = state.transactions.findIndex(value => value.id === data.transaction.id);
|
||||
data.transaction.reversal = data.reversal;
|
||||
data.transaction.reversal_id = data.reversal.id;
|
||||
if (idx > -1) state.transactions[idx] = data.transaction;
|
||||
else state.transactions.push(data.transaction);
|
||||
}
|
||||
|
@ -70,7 +87,7 @@ const mutations: MutationTree<BalanceInterface> = {
|
|||
const actions: ActionTree<BalanceInterface, StateInterface> = {
|
||||
addShortcut({ commit, state, rootState }, shortcut) {
|
||||
const sc = [...state.shortcuts, shortcut];
|
||||
sc.sort().reverse();
|
||||
sc.sort();
|
||||
|
||||
const user = <FG.User>rootState.user.currentUser;
|
||||
return axios.put(`/users/${user.userid}/balance/shortcuts`, sc).then(() => {
|
||||
|
@ -109,6 +126,37 @@ const actions: ActionTree<BalanceInterface, StateInterface> = {
|
|||
})
|
||||
.finally(() => commit('setLoading', false));
|
||||
},
|
||||
getBalances() {
|
||||
return axios.get('/balance').then(({ data }: AxiosResponse<Array<BalancesResponse>>) => {
|
||||
return data;
|
||||
});
|
||||
},
|
||||
getTransactions(
|
||||
{ commit, rootState },
|
||||
payload: {
|
||||
userid?: string;
|
||||
filter?: {
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
from?: Date;
|
||||
to?: Date;
|
||||
showReversals?: boolean;
|
||||
showCancelled?: boolean;
|
||||
};
|
||||
}
|
||||
) {
|
||||
commit('setLoading');
|
||||
if (!payload.userid) payload.userid = (<FG.User>rootState.user.currentUser).userid;
|
||||
if (!payload.filter) payload.filter = { limit: 10 };
|
||||
return axios
|
||||
.get(`/users/${payload.userid}/balance/transactions`, { params: payload.filter || {} })
|
||||
.then(({ data }: AxiosResponse<TransactionsResponse>) => {
|
||||
data.transactions.forEach(t => fixTransaction(t));
|
||||
commit('addTransactions', data.transactions);
|
||||
return data;
|
||||
})
|
||||
.finally(() => commit('setLoading', false));
|
||||
},
|
||||
getLimit({ rootState, commit }) {
|
||||
commit('setLoading');
|
||||
axios
|
||||
|
@ -125,19 +173,27 @@ const actions: ActionTree<BalanceInterface, StateInterface> = {
|
|||
revert({ dispatch, commit }, transaction: FG.Transaction) {
|
||||
return axios
|
||||
.delete(`/balance/${transaction.id}`)
|
||||
.then((response: AxiosResponse<FG.Transaction>) => {
|
||||
commit('reverseTransaction', { transaction: transaction, reversal: response.data });
|
||||
.then(({ data }: AxiosResponse<FG.Transaction>) => {
|
||||
fixTransaction(data);
|
||||
commit('reverseTransaction', { transaction: transaction, reversal: data });
|
||||
dispatch('getBalance').catch(err => console.warn(err));
|
||||
});
|
||||
},
|
||||
changeBalance({ dispatch, commit }, data: { amount: number; user: string; sender?: string }) {
|
||||
changeBalance(
|
||||
{ dispatch, commit, rootState },
|
||||
data: { amount: number; user: string; sender?: string }
|
||||
) {
|
||||
commit('setLoading');
|
||||
return axios
|
||||
.put(`/users/${data.user}/balance`, data)
|
||||
.then((response: AxiosResponse<FG.Transaction>) => {
|
||||
const transaction = response.data;
|
||||
transaction.time = new Date(transaction.time);
|
||||
commit('addTransaction', transaction);
|
||||
fixTransaction(transaction);
|
||||
if (
|
||||
data.user == rootState.user.currentUser?.userid ||
|
||||
data.sender === rootState.user.currentUser?.userid
|
||||
)
|
||||
commit('addTransaction', transaction);
|
||||
commit(state.balances.has(data.user) ? 'changeBalance' : 'setBalance', {
|
||||
userid: data.user,
|
||||
amount: data.amount
|
||||
|
@ -152,6 +208,7 @@ const actions: ActionTree<BalanceInterface, StateInterface> = {
|
|||
.catch(err => {
|
||||
console.debug(err);
|
||||
// Maybe Balance changed
|
||||
void dispatch('getTransactions', {});
|
||||
return dispatch('getBalance', data.sender ? data.sender : data.user);
|
||||
})
|
||||
.finally(() => commit('setLoading', false));
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<q-card>
|
||||
<q-form @submit="save" @reset="reset">
|
||||
<q-card-section class="fit row justify-start content-center items-center">
|
||||
<q-card-section class="fit ">
|
||||
<q-card-section class="fit">
|
||||
<div class="text-h6">Veranstaltung erstellen</div>
|
||||
</q-card-section>
|
||||
<q-select
|
||||
|
@ -27,7 +27,7 @@
|
|||
:rules="[noValidDate, notEmpty]"
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-section class="fit justify-start content-center items-center">
|
||||
<q-card-section class="fit justify-start content-center items-center">
|
||||
<q-input
|
||||
class="col-xs-12 col-sm-6 q-pa-sm"
|
||||
label="Beschreibung"
|
||||
|
@ -45,12 +45,12 @@
|
|||
<job
|
||||
:job="job"
|
||||
:jobCanDelete="jobDeleteDisabled"
|
||||
@setStart="setStart"
|
||||
@setRequired="setRequired"
|
||||
@setEnd="setEnd"
|
||||
@setComment="setComment"
|
||||
@setJobType="setJobType"
|
||||
@removeJob="removeJob(index)"
|
||||
@set-start="setStart"
|
||||
@set-required="setRequired"
|
||||
@set-end="setEnd"
|
||||
@set-comment="setComment"
|
||||
@set-job-type="setJobType"
|
||||
@remove-job="removeJob(index)"
|
||||
/>
|
||||
</q-card>
|
||||
</q-card-section>
|
||||
|
@ -149,7 +149,7 @@ export default defineComponent({
|
|||
event.value.id = NaN;
|
||||
event.value.start = new Date();
|
||||
event.value.description = '';
|
||||
delete event.value['type'];
|
||||
event.value.type = {id: -1, name: ''};
|
||||
event.value.jobs = [Object.assign({}, newJob.value)];
|
||||
}
|
||||
function notEmpty(val: string) {
|
||||
|
|
|
@ -89,33 +89,33 @@ export default defineComponent({
|
|||
|
||||
function setStart(value: Date) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
emit('setStart', { job: props.job, value });
|
||||
emit('set-start', { job: props.job, value });
|
||||
}
|
||||
|
||||
function setEnd(value: Date) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
emit('setEnd', { job: props.job, value });
|
||||
emit('set-end', { job: props.job, value });
|
||||
}
|
||||
|
||||
function setComment(value: string) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
emit('setComment', { job: props.job, value });
|
||||
emit('set-comment', { job: props.job, value });
|
||||
}
|
||||
|
||||
function setJobType(value: FG.JobType) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
console.log('setJobType', value);
|
||||
emit('setJobType', { job: props.job, value });
|
||||
emit('set-job-type', { job: props.job, value });
|
||||
}
|
||||
|
||||
function setRequired(value: number) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
emit('setRequired', { job: props.job, value });
|
||||
emit('set-required', { job: props.job, value });
|
||||
}
|
||||
|
||||
function removeJob() {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
emit('removeJob');
|
||||
emit('remove-job');
|
||||
}
|
||||
|
||||
function notEmpty(val: string) {
|
||||
|
|
|
@ -1,25 +1,5 @@
|
|||
import { FG_Plugin } from 'src/plugins';
|
||||
|
||||
/*const permissions = {
|
||||
// Show own and others balance
|
||||
SHOW: 'balance_show',
|
||||
SHOW_OTHER: 'balance_show_others',
|
||||
// Credit balance (give)
|
||||
CREDIT: 'balance_credit',
|
||||
// Debit balance (take)
|
||||
DEBIT: 'balance_debit',
|
||||
// Debit own balance only
|
||||
DEBIT_OWN: 'balance_debit_own',
|
||||
// Send from to other
|
||||
SEND: 'balance_send',
|
||||
// Send from other to another
|
||||
SEND_OTHER: 'balance_send_others',
|
||||
// Can set limit for users
|
||||
SET_LIMIT: 'balance_set_limit',
|
||||
//Allow sending / sub while exceeding the set limit
|
||||
EXCEED_LIMIT: 'balance_exceed_limit'
|
||||
};*/
|
||||
|
||||
const mainRoutes: FG_Plugin.PluginRouteConfig[] = [
|
||||
{
|
||||
title: 'Dienste',
|
||||
|
|
|
@ -31,12 +31,7 @@
|
|||
label="Zeit"
|
||||
filled
|
||||
/>
|
||||
<q-select
|
||||
class="col-xs-12 col-sm-6 q-px-sm"
|
||||
:options="options"
|
||||
v-model="option"
|
||||
filled
|
||||
/>
|
||||
<q-select class="col-xs-12 col-sm-6 q-px-sm" :options="options" v-model="option" filled />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-actions align="right" v-if="!isEdit">
|
||||
|
@ -59,10 +54,10 @@ export default defineComponent({
|
|||
name: 'Sessions',
|
||||
props: {
|
||||
session: {
|
||||
required: true,
|
||||
},
|
||||
required: true
|
||||
}
|
||||
},
|
||||
setup(props: {session: FG.Session}, { root }) {
|
||||
setup(props: { session: FG.Session }, { root }) {
|
||||
const store = <Store<StateInterface>>root.$store;
|
||||
const options = ref(['Minuten', 'Stunden', 'Tage']);
|
||||
const option = ref<string>(options.value[0]);
|
||||
|
@ -92,7 +87,7 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
function deleteSession(token: string) {
|
||||
store.dispatch('session/deleteSession', token).catch((error) => {
|
||||
store.dispatch('session/deleteSession', token).catch(error => {
|
||||
console.warn(error);
|
||||
});
|
||||
}
|
||||
|
@ -113,7 +108,7 @@ export default defineComponent({
|
|||
return (lifetime.value / (60 * 60 * 24)).toFixed(2);
|
||||
}
|
||||
},
|
||||
set: (val) => {
|
||||
set: val => {
|
||||
if (val) {
|
||||
switch (option.value) {
|
||||
case options.value[0]:
|
||||
|
@ -127,7 +122,7 @@ export default defineComponent({
|
|||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
function edit(value: boolean) {
|
||||
|
@ -139,11 +134,8 @@ export default defineComponent({
|
|||
console.log(lifetime.value);
|
||||
isEdit.value = false;
|
||||
void store
|
||||
.dispatch(
|
||||
'session/updateSession',
|
||||
{lifetime: lifetime.value, token: props.session.token}
|
||||
)
|
||||
.catch((error) => {
|
||||
.dispatch('session/updateSession', { lifetime: lifetime.value, token: props.session.token })
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
@ -159,8 +151,8 @@ export default defineComponent({
|
|||
option,
|
||||
lifetime,
|
||||
computedLifetime,
|
||||
save,
|
||||
save
|
||||
};
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -25,7 +25,7 @@ function loadCurrentSession() {
|
|||
const state: SessionInterface = {
|
||||
sessions: [],
|
||||
currentSession: loadCurrentSession() || undefined,
|
||||
loading: false,
|
||||
loading: false
|
||||
};
|
||||
|
||||
const mutations: MutationTree<SessionInterface> = {
|
||||
|
@ -44,11 +44,11 @@ const mutations: MutationTree<SessionInterface> = {
|
|||
state.loading = value;
|
||||
},
|
||||
updateSession(state, session: FG.Session) {
|
||||
const index = state.sessions.findIndex((x) => x.token == session.token);
|
||||
const index = state.sessions.findIndex(x => x.token == session.token);
|
||||
if (index > -1) {
|
||||
state.sessions[index] = session;
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
const actions: ActionTree<SessionInterface, StateInterface> = {
|
||||
|
@ -65,7 +65,7 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
|||
commit('setCurrentSession', response.data.session);
|
||||
commit('user/setCurrentUser', response.data.user, { root: true });
|
||||
commit('user/setCurrentPermissions', response.data.permissions, {
|
||||
root: true,
|
||||
root: true
|
||||
});
|
||||
})
|
||||
.catch((error: AxiosError) => {
|
||||
|
@ -78,7 +78,7 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
|||
*/
|
||||
logout({ dispatch, rootState }) {
|
||||
if (rootState.session.currentSession) {
|
||||
dispatch('deleteSession', rootState.session.currentSession.token).catch((error) => {
|
||||
dispatch('deleteSession', rootState.session.currentSession.token).catch(error => {
|
||||
console.log(error);
|
||||
void dispatch('clearCurrent', false);
|
||||
});
|
||||
|
@ -97,7 +97,7 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
|||
if (token === rootState.session.currentSession?.token) {
|
||||
void dispatch('clearCurrent', false);
|
||||
} else {
|
||||
dispatch('getSessions').catch((error) => {
|
||||
dispatch('getSessions').catch(error => {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
|||
void Router.push({
|
||||
name: 'login',
|
||||
query: redirect ? { redirect: Router.currentRoute.fullPath } : {},
|
||||
params: { logout: 'true' },
|
||||
params: { logout: 'true' }
|
||||
}).then(() => {
|
||||
commit('clearCurrentSession');
|
||||
commit('user/clearCurrentUser', null, { root: true });
|
||||
|
@ -132,7 +132,7 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
|||
axios
|
||||
.get('/auth')
|
||||
.then((response: AxiosResponse<FG.Session[]>) => {
|
||||
response.data.forEach((session) => {
|
||||
response.data.forEach(session => {
|
||||
session.expires = new Date(session.expires);
|
||||
});
|
||||
commit('setSessions', response.data);
|
||||
|
@ -143,7 +143,7 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
|||
commit('setCurrentSession', currentSession);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
.catch(error => {
|
||||
throw error;
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -160,7 +160,7 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
|||
commit('setCurrentSession', response.data);
|
||||
}
|
||||
})
|
||||
.catch((err) => console.log(err))
|
||||
.catch(err => console.log(err))
|
||||
.finally(() => {
|
||||
commit('setLoading', false);
|
||||
});
|
||||
|
@ -173,7 +173,7 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
|||
return axios.post('/auth/reset', data).catch((error: AxiosError) => {
|
||||
return Promise.reject(error.response);
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
const getters: GetterTree<SessionInterface, StateInterface> = {
|
||||
|
@ -185,7 +185,7 @@ const getters: GetterTree<SessionInterface, StateInterface> = {
|
|||
},
|
||||
loading(state) {
|
||||
return state.loading;
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
const sessions: Module<SessionInterface, StateInterface> = {
|
||||
|
@ -193,7 +193,7 @@ const sessions: Module<SessionInterface, StateInterface> = {
|
|||
state,
|
||||
mutations,
|
||||
actions,
|
||||
getters,
|
||||
getters
|
||||
};
|
||||
|
||||
export default sessions;
|
||||
|
|
|
@ -9,3 +9,8 @@ export function hasPermissions(needed: string[], store: Store<StateInterface>) {
|
|||
const permissions = store.state.user.currentPermissions;
|
||||
return needed.every(value => permissions.includes(value));
|
||||
}
|
||||
|
||||
export function hasSomePermissions(needed: string[], store: Store<StateInterface>) {
|
||||
const permissions = store.state.user.currentPermissions;
|
||||
return needed.some(value => permissions.includes(value));
|
||||
}
|
||||
|
|