├── .gitignore
├── LICENSE
├── README.md
├── client
├── .gitignore
├── .vscode
│ └── extensions.json
├── README.md
├── index.html
├── package-lock.json
├── package.json
├── public
│ └── favicon.ico
├── src
│ ├── App.vue
│ ├── assets
│ │ └── logo.svg
│ ├── components
│ │ ├── Alert.vue
│ │ ├── Books.vue
│ │ ├── HelloWorld.vue
│ │ └── Ping.vue
│ ├── main.js
│ └── router
│ │ └── index.js
└── vite.config.js
└── server
├── app.py
└── requirements.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | /dist/
4 | env/
5 | __pycache__
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 TestDriven.io
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Developing a Single Page App with Flask and Vue.js
2 |
3 | ### Want to learn how to build this?
4 |
5 |
6 |
7 | ## Want to use this project?
8 |
9 | 1. Fork/Clone
10 |
11 | 1. Run the server-side Flask app in one terminal window:
12 |
13 | ```sh
14 | $ cd server
15 | $ python3 -m venv env
16 | $ source env/bin/activate
17 | (env)$ pip install -r requirements.txt
18 | (env)$ flask run --port=5001 --debug
19 | ```
20 |
21 |
22 |
23 | 1. Run the client-side Vue app in a different terminal window:
24 |
25 | ```sh
26 | $ cd client
27 | $ npm install
28 | $ npm run dev
29 | ```
30 |
31 |
32 |
--------------------------------------------------------------------------------
/client/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | .DS_Store
12 | dist
13 | dist-ssr
14 | coverage
15 | *.local
16 |
17 | /cypress/videos/
18 | /cypress/screenshots/
19 |
20 | # Editor directories and files
21 | .vscode/*
22 | !.vscode/extensions.json
23 | .idea
24 | *.suo
25 | *.ntvs*
26 | *.njsproj
27 | *.sln
28 | *.sw?
29 |
--------------------------------------------------------------------------------
/client/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
3 | }
4 |
--------------------------------------------------------------------------------
/client/README.md:
--------------------------------------------------------------------------------
1 | # client
2 |
3 | This template should help get you started developing with Vue 3 in Vite.
4 |
5 | ## Recommended IDE Setup
6 |
7 | [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
8 |
9 | ## Customize configuration
10 |
11 | See [Vite Configuration Reference](https://vitejs.dev/config/).
12 |
13 | ## Project Setup
14 |
15 | ```sh
16 | npm install
17 | ```
18 |
19 | ### Compile and Hot-Reload for Development
20 |
21 | ```sh
22 | npm run dev
23 | ```
24 |
25 | ### Compile and Minify for Production
26 |
27 | ```sh
28 | npm run build
29 | ```
30 |
--------------------------------------------------------------------------------
/client/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/client/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "client",
3 | "version": "0.0.0",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "client",
9 | "version": "0.0.0",
10 | "dependencies": {
11 | "axios": "^1.3.6",
12 | "bootstrap": "^5.2.3",
13 | "vue": "^3.2.47",
14 | "vue-router": "^4.1.6"
15 | },
16 | "devDependencies": {
17 | "@vitejs/plugin-vue": "^4.0.0",
18 | "vite": "^4.1.4"
19 | }
20 | },
21 | "node_modules/@babel/parser": {
22 | "version": "7.21.4",
23 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz",
24 | "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==",
25 | "bin": {
26 | "parser": "bin/babel-parser.js"
27 | },
28 | "engines": {
29 | "node": ">=6.0.0"
30 | }
31 | },
32 | "node_modules/@esbuild/android-arm": {
33 | "version": "0.17.17",
34 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.17.tgz",
35 | "integrity": "sha512-E6VAZwN7diCa3labs0GYvhEPL2M94WLF8A+czO8hfjREXxba8Ng7nM5VxV+9ihNXIY1iQO1XxUU4P7hbqbICxg==",
36 | "cpu": [
37 | "arm"
38 | ],
39 | "dev": true,
40 | "optional": true,
41 | "os": [
42 | "android"
43 | ],
44 | "engines": {
45 | "node": ">=12"
46 | }
47 | },
48 | "node_modules/@esbuild/android-arm64": {
49 | "version": "0.17.17",
50 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.17.tgz",
51 | "integrity": "sha512-jaJ5IlmaDLFPNttv0ofcwy/cfeY4bh/n705Tgh+eLObbGtQBK3EPAu+CzL95JVE4nFAliyrnEu0d32Q5foavqg==",
52 | "cpu": [
53 | "arm64"
54 | ],
55 | "dev": true,
56 | "optional": true,
57 | "os": [
58 | "android"
59 | ],
60 | "engines": {
61 | "node": ">=12"
62 | }
63 | },
64 | "node_modules/@esbuild/android-x64": {
65 | "version": "0.17.17",
66 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.17.tgz",
67 | "integrity": "sha512-446zpfJ3nioMC7ASvJB1pszHVskkw4u/9Eu8s5yvvsSDTzYh4p4ZIRj0DznSl3FBF0Z/mZfrKXTtt0QCoFmoHA==",
68 | "cpu": [
69 | "x64"
70 | ],
71 | "dev": true,
72 | "optional": true,
73 | "os": [
74 | "android"
75 | ],
76 | "engines": {
77 | "node": ">=12"
78 | }
79 | },
80 | "node_modules/@esbuild/darwin-arm64": {
81 | "version": "0.17.17",
82 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.17.tgz",
83 | "integrity": "sha512-m/gwyiBwH3jqfUabtq3GH31otL/0sE0l34XKpSIqR7NjQ/XHQ3lpmQHLHbG8AHTGCw8Ao059GvV08MS0bhFIJQ==",
84 | "cpu": [
85 | "arm64"
86 | ],
87 | "dev": true,
88 | "optional": true,
89 | "os": [
90 | "darwin"
91 | ],
92 | "engines": {
93 | "node": ">=12"
94 | }
95 | },
96 | "node_modules/@esbuild/darwin-x64": {
97 | "version": "0.17.17",
98 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.17.tgz",
99 | "integrity": "sha512-4utIrsX9IykrqYaXR8ob9Ha2hAY2qLc6ohJ8c0CN1DR8yWeMrTgYFjgdeQ9LIoTOfLetXjuCu5TRPHT9yKYJVg==",
100 | "cpu": [
101 | "x64"
102 | ],
103 | "dev": true,
104 | "optional": true,
105 | "os": [
106 | "darwin"
107 | ],
108 | "engines": {
109 | "node": ">=12"
110 | }
111 | },
112 | "node_modules/@esbuild/freebsd-arm64": {
113 | "version": "0.17.17",
114 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.17.tgz",
115 | "integrity": "sha512-4PxjQII/9ppOrpEwzQ1b0pXCsFLqy77i0GaHodrmzH9zq2/NEhHMAMJkJ635Ns4fyJPFOlHMz4AsklIyRqFZWA==",
116 | "cpu": [
117 | "arm64"
118 | ],
119 | "dev": true,
120 | "optional": true,
121 | "os": [
122 | "freebsd"
123 | ],
124 | "engines": {
125 | "node": ">=12"
126 | }
127 | },
128 | "node_modules/@esbuild/freebsd-x64": {
129 | "version": "0.17.17",
130 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.17.tgz",
131 | "integrity": "sha512-lQRS+4sW5S3P1sv0z2Ym807qMDfkmdhUYX30GRBURtLTrJOPDpoU0kI6pVz1hz3U0+YQ0tXGS9YWveQjUewAJw==",
132 | "cpu": [
133 | "x64"
134 | ],
135 | "dev": true,
136 | "optional": true,
137 | "os": [
138 | "freebsd"
139 | ],
140 | "engines": {
141 | "node": ">=12"
142 | }
143 | },
144 | "node_modules/@esbuild/linux-arm": {
145 | "version": "0.17.17",
146 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.17.tgz",
147 | "integrity": "sha512-biDs7bjGdOdcmIk6xU426VgdRUpGg39Yz6sT9Xp23aq+IEHDb/u5cbmu/pAANpDB4rZpY/2USPhCA+w9t3roQg==",
148 | "cpu": [
149 | "arm"
150 | ],
151 | "dev": true,
152 | "optional": true,
153 | "os": [
154 | "linux"
155 | ],
156 | "engines": {
157 | "node": ">=12"
158 | }
159 | },
160 | "node_modules/@esbuild/linux-arm64": {
161 | "version": "0.17.17",
162 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.17.tgz",
163 | "integrity": "sha512-2+pwLx0whKY1/Vqt8lyzStyda1v0qjJ5INWIe+d8+1onqQxHLLi3yr5bAa4gvbzhZqBztifYEu8hh1La5+7sUw==",
164 | "cpu": [
165 | "arm64"
166 | ],
167 | "dev": true,
168 | "optional": true,
169 | "os": [
170 | "linux"
171 | ],
172 | "engines": {
173 | "node": ">=12"
174 | }
175 | },
176 | "node_modules/@esbuild/linux-ia32": {
177 | "version": "0.17.17",
178 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.17.tgz",
179 | "integrity": "sha512-IBTTv8X60dYo6P2t23sSUYym8fGfMAiuv7PzJ+0LcdAndZRzvke+wTVxJeCq4WgjppkOpndL04gMZIFvwoU34Q==",
180 | "cpu": [
181 | "ia32"
182 | ],
183 | "dev": true,
184 | "optional": true,
185 | "os": [
186 | "linux"
187 | ],
188 | "engines": {
189 | "node": ">=12"
190 | }
191 | },
192 | "node_modules/@esbuild/linux-loong64": {
193 | "version": "0.17.17",
194 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.17.tgz",
195 | "integrity": "sha512-WVMBtcDpATjaGfWfp6u9dANIqmU9r37SY8wgAivuKmgKHE+bWSuv0qXEFt/p3qXQYxJIGXQQv6hHcm7iWhWjiw==",
196 | "cpu": [
197 | "loong64"
198 | ],
199 | "dev": true,
200 | "optional": true,
201 | "os": [
202 | "linux"
203 | ],
204 | "engines": {
205 | "node": ">=12"
206 | }
207 | },
208 | "node_modules/@esbuild/linux-mips64el": {
209 | "version": "0.17.17",
210 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.17.tgz",
211 | "integrity": "sha512-2kYCGh8589ZYnY031FgMLy0kmE4VoGdvfJkxLdxP4HJvWNXpyLhjOvxVsYjYZ6awqY4bgLR9tpdYyStgZZhi2A==",
212 | "cpu": [
213 | "mips64el"
214 | ],
215 | "dev": true,
216 | "optional": true,
217 | "os": [
218 | "linux"
219 | ],
220 | "engines": {
221 | "node": ">=12"
222 | }
223 | },
224 | "node_modules/@esbuild/linux-ppc64": {
225 | "version": "0.17.17",
226 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.17.tgz",
227 | "integrity": "sha512-KIdG5jdAEeAKogfyMTcszRxy3OPbZhq0PPsW4iKKcdlbk3YE4miKznxV2YOSmiK/hfOZ+lqHri3v8eecT2ATwQ==",
228 | "cpu": [
229 | "ppc64"
230 | ],
231 | "dev": true,
232 | "optional": true,
233 | "os": [
234 | "linux"
235 | ],
236 | "engines": {
237 | "node": ">=12"
238 | }
239 | },
240 | "node_modules/@esbuild/linux-riscv64": {
241 | "version": "0.17.17",
242 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.17.tgz",
243 | "integrity": "sha512-Cj6uWLBR5LWhcD/2Lkfg2NrkVsNb2sFM5aVEfumKB2vYetkA/9Uyc1jVoxLZ0a38sUhFk4JOVKH0aVdPbjZQeA==",
244 | "cpu": [
245 | "riscv64"
246 | ],
247 | "dev": true,
248 | "optional": true,
249 | "os": [
250 | "linux"
251 | ],
252 | "engines": {
253 | "node": ">=12"
254 | }
255 | },
256 | "node_modules/@esbuild/linux-s390x": {
257 | "version": "0.17.17",
258 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.17.tgz",
259 | "integrity": "sha512-lK+SffWIr0XsFf7E0srBjhpkdFVJf3HEgXCwzkm69kNbRar8MhezFpkIwpk0qo2IOQL4JE4mJPJI8AbRPLbuOQ==",
260 | "cpu": [
261 | "s390x"
262 | ],
263 | "dev": true,
264 | "optional": true,
265 | "os": [
266 | "linux"
267 | ],
268 | "engines": {
269 | "node": ">=12"
270 | }
271 | },
272 | "node_modules/@esbuild/linux-x64": {
273 | "version": "0.17.17",
274 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.17.tgz",
275 | "integrity": "sha512-XcSGTQcWFQS2jx3lZtQi7cQmDYLrpLRyz1Ns1DzZCtn898cWfm5Icx/DEWNcTU+T+tyPV89RQtDnI7qL2PObPg==",
276 | "cpu": [
277 | "x64"
278 | ],
279 | "dev": true,
280 | "optional": true,
281 | "os": [
282 | "linux"
283 | ],
284 | "engines": {
285 | "node": ">=12"
286 | }
287 | },
288 | "node_modules/@esbuild/netbsd-x64": {
289 | "version": "0.17.17",
290 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.17.tgz",
291 | "integrity": "sha512-RNLCDmLP5kCWAJR+ItLM3cHxzXRTe4N00TQyQiimq+lyqVqZWGPAvcyfUBM0isE79eEZhIuGN09rAz8EL5KdLA==",
292 | "cpu": [
293 | "x64"
294 | ],
295 | "dev": true,
296 | "optional": true,
297 | "os": [
298 | "netbsd"
299 | ],
300 | "engines": {
301 | "node": ">=12"
302 | }
303 | },
304 | "node_modules/@esbuild/openbsd-x64": {
305 | "version": "0.17.17",
306 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.17.tgz",
307 | "integrity": "sha512-PAXswI5+cQq3Pann7FNdcpSUrhrql3wKjj3gVkmuz6OHhqqYxKvi6GgRBoaHjaG22HV/ZZEgF9TlS+9ftHVigA==",
308 | "cpu": [
309 | "x64"
310 | ],
311 | "dev": true,
312 | "optional": true,
313 | "os": [
314 | "openbsd"
315 | ],
316 | "engines": {
317 | "node": ">=12"
318 | }
319 | },
320 | "node_modules/@esbuild/sunos-x64": {
321 | "version": "0.17.17",
322 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.17.tgz",
323 | "integrity": "sha512-V63egsWKnx/4V0FMYkr9NXWrKTB5qFftKGKuZKFIrAkO/7EWLFnbBZNM1CvJ6Sis+XBdPws2YQSHF1Gqf1oj/Q==",
324 | "cpu": [
325 | "x64"
326 | ],
327 | "dev": true,
328 | "optional": true,
329 | "os": [
330 | "sunos"
331 | ],
332 | "engines": {
333 | "node": ">=12"
334 | }
335 | },
336 | "node_modules/@esbuild/win32-arm64": {
337 | "version": "0.17.17",
338 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.17.tgz",
339 | "integrity": "sha512-YtUXLdVnd6YBSYlZODjWzH+KzbaubV0YVd6UxSfoFfa5PtNJNaW+1i+Hcmjpg2nEe0YXUCNF5bkKy1NnBv1y7Q==",
340 | "cpu": [
341 | "arm64"
342 | ],
343 | "dev": true,
344 | "optional": true,
345 | "os": [
346 | "win32"
347 | ],
348 | "engines": {
349 | "node": ">=12"
350 | }
351 | },
352 | "node_modules/@esbuild/win32-ia32": {
353 | "version": "0.17.17",
354 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.17.tgz",
355 | "integrity": "sha512-yczSLRbDdReCO74Yfc5tKG0izzm+lPMYyO1fFTcn0QNwnKmc3K+HdxZWLGKg4pZVte7XVgcFku7TIZNbWEJdeQ==",
356 | "cpu": [
357 | "ia32"
358 | ],
359 | "dev": true,
360 | "optional": true,
361 | "os": [
362 | "win32"
363 | ],
364 | "engines": {
365 | "node": ">=12"
366 | }
367 | },
368 | "node_modules/@esbuild/win32-x64": {
369 | "version": "0.17.17",
370 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.17.tgz",
371 | "integrity": "sha512-FNZw7H3aqhF9OyRQbDDnzUApDXfC1N6fgBhkqEO2jvYCJ+DxMTfZVqg3AX0R1khg1wHTBRD5SdcibSJ+XF6bFg==",
372 | "cpu": [
373 | "x64"
374 | ],
375 | "dev": true,
376 | "optional": true,
377 | "os": [
378 | "win32"
379 | ],
380 | "engines": {
381 | "node": ">=12"
382 | }
383 | },
384 | "node_modules/@popperjs/core": {
385 | "version": "2.11.7",
386 | "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.7.tgz",
387 | "integrity": "sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==",
388 | "peer": true,
389 | "funding": {
390 | "type": "opencollective",
391 | "url": "https://opencollective.com/popperjs"
392 | }
393 | },
394 | "node_modules/@vitejs/plugin-vue": {
395 | "version": "4.1.0",
396 | "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.1.0.tgz",
397 | "integrity": "sha512-++9JOAFdcXI3lyer9UKUV4rfoQ3T1RN8yDqoCLar86s0xQct5yblxAE+yWgRnU5/0FOlVCpTZpYSBV/bGWrSrQ==",
398 | "dev": true,
399 | "engines": {
400 | "node": "^14.18.0 || >=16.0.0"
401 | },
402 | "peerDependencies": {
403 | "vite": "^4.0.0",
404 | "vue": "^3.2.25"
405 | }
406 | },
407 | "node_modules/@vue/compiler-core": {
408 | "version": "3.2.47",
409 | "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.47.tgz",
410 | "integrity": "sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==",
411 | "dependencies": {
412 | "@babel/parser": "^7.16.4",
413 | "@vue/shared": "3.2.47",
414 | "estree-walker": "^2.0.2",
415 | "source-map": "^0.6.1"
416 | }
417 | },
418 | "node_modules/@vue/compiler-dom": {
419 | "version": "3.2.47",
420 | "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.47.tgz",
421 | "integrity": "sha512-dBBnEHEPoftUiS03a4ggEig74J2YBZ2UIeyfpcRM2tavgMWo4bsEfgCGsu+uJIL/vax9S+JztH8NmQerUo7shQ==",
422 | "dependencies": {
423 | "@vue/compiler-core": "3.2.47",
424 | "@vue/shared": "3.2.47"
425 | }
426 | },
427 | "node_modules/@vue/compiler-sfc": {
428 | "version": "3.2.47",
429 | "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.47.tgz",
430 | "integrity": "sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ==",
431 | "dependencies": {
432 | "@babel/parser": "^7.16.4",
433 | "@vue/compiler-core": "3.2.47",
434 | "@vue/compiler-dom": "3.2.47",
435 | "@vue/compiler-ssr": "3.2.47",
436 | "@vue/reactivity-transform": "3.2.47",
437 | "@vue/shared": "3.2.47",
438 | "estree-walker": "^2.0.2",
439 | "magic-string": "^0.25.7",
440 | "postcss": "^8.1.10",
441 | "source-map": "^0.6.1"
442 | }
443 | },
444 | "node_modules/@vue/compiler-ssr": {
445 | "version": "3.2.47",
446 | "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.47.tgz",
447 | "integrity": "sha512-wVXC+gszhulcMD8wpxMsqSOpvDZ6xKXSVWkf50Guf/S+28hTAXPDYRTbLQ3EDkOP5Xz/+SY37YiwDquKbJOgZw==",
448 | "dependencies": {
449 | "@vue/compiler-dom": "3.2.47",
450 | "@vue/shared": "3.2.47"
451 | }
452 | },
453 | "node_modules/@vue/devtools-api": {
454 | "version": "6.5.0",
455 | "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.5.0.tgz",
456 | "integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q=="
457 | },
458 | "node_modules/@vue/reactivity": {
459 | "version": "3.2.47",
460 | "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.47.tgz",
461 | "integrity": "sha512-7khqQ/75oyyg+N/e+iwV6lpy1f5wq759NdlS1fpAhFXa8VeAIKGgk2E/C4VF59lx5b+Ezs5fpp/5WsRYXQiKxQ==",
462 | "dependencies": {
463 | "@vue/shared": "3.2.47"
464 | }
465 | },
466 | "node_modules/@vue/reactivity-transform": {
467 | "version": "3.2.47",
468 | "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.47.tgz",
469 | "integrity": "sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==",
470 | "dependencies": {
471 | "@babel/parser": "^7.16.4",
472 | "@vue/compiler-core": "3.2.47",
473 | "@vue/shared": "3.2.47",
474 | "estree-walker": "^2.0.2",
475 | "magic-string": "^0.25.7"
476 | }
477 | },
478 | "node_modules/@vue/runtime-core": {
479 | "version": "3.2.47",
480 | "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.47.tgz",
481 | "integrity": "sha512-RZxbLQIRB/K0ev0K9FXhNbBzT32H9iRtYbaXb0ZIz2usLms/D55dJR2t6cIEUn6vyhS3ALNvNthI+Q95C+NOpA==",
482 | "dependencies": {
483 | "@vue/reactivity": "3.2.47",
484 | "@vue/shared": "3.2.47"
485 | }
486 | },
487 | "node_modules/@vue/runtime-dom": {
488 | "version": "3.2.47",
489 | "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.47.tgz",
490 | "integrity": "sha512-ArXrFTjS6TsDei4qwNvgrdmHtD930KgSKGhS5M+j8QxXrDJYLqYw4RRcDy1bz1m1wMmb6j+zGLifdVHtkXA7gA==",
491 | "dependencies": {
492 | "@vue/runtime-core": "3.2.47",
493 | "@vue/shared": "3.2.47",
494 | "csstype": "^2.6.8"
495 | }
496 | },
497 | "node_modules/@vue/server-renderer": {
498 | "version": "3.2.47",
499 | "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.47.tgz",
500 | "integrity": "sha512-dN9gc1i8EvmP9RCzvneONXsKfBRgqFeFZLurmHOveL7oH6HiFXJw5OGu294n1nHc/HMgTy6LulU/tv5/A7f/LA==",
501 | "dependencies": {
502 | "@vue/compiler-ssr": "3.2.47",
503 | "@vue/shared": "3.2.47"
504 | },
505 | "peerDependencies": {
506 | "vue": "3.2.47"
507 | }
508 | },
509 | "node_modules/@vue/shared": {
510 | "version": "3.2.47",
511 | "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.47.tgz",
512 | "integrity": "sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ=="
513 | },
514 | "node_modules/asynckit": {
515 | "version": "0.4.0",
516 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
517 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
518 | },
519 | "node_modules/axios": {
520 | "version": "1.3.6",
521 | "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.6.tgz",
522 | "integrity": "sha512-PEcdkk7JcdPiMDkvM4K6ZBRYq9keuVJsToxm2zQIM70Qqo2WHTdJZMXcG9X+RmRp2VPNUQC8W1RAGbgt6b1yMg==",
523 | "dependencies": {
524 | "follow-redirects": "^1.15.0",
525 | "form-data": "^4.0.0",
526 | "proxy-from-env": "^1.1.0"
527 | }
528 | },
529 | "node_modules/bootstrap": {
530 | "version": "5.2.3",
531 | "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.3.tgz",
532 | "integrity": "sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ==",
533 | "funding": [
534 | {
535 | "type": "github",
536 | "url": "https://github.com/sponsors/twbs"
537 | },
538 | {
539 | "type": "opencollective",
540 | "url": "https://opencollective.com/bootstrap"
541 | }
542 | ],
543 | "peerDependencies": {
544 | "@popperjs/core": "^2.11.6"
545 | }
546 | },
547 | "node_modules/combined-stream": {
548 | "version": "1.0.8",
549 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
550 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
551 | "dependencies": {
552 | "delayed-stream": "~1.0.0"
553 | },
554 | "engines": {
555 | "node": ">= 0.8"
556 | }
557 | },
558 | "node_modules/csstype": {
559 | "version": "2.6.21",
560 | "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz",
561 | "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w=="
562 | },
563 | "node_modules/delayed-stream": {
564 | "version": "1.0.0",
565 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
566 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
567 | "engines": {
568 | "node": ">=0.4.0"
569 | }
570 | },
571 | "node_modules/esbuild": {
572 | "version": "0.17.17",
573 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.17.tgz",
574 | "integrity": "sha512-/jUywtAymR8jR4qsa2RujlAF7Krpt5VWi72Q2yuLD4e/hvtNcFQ0I1j8m/bxq238pf3/0KO5yuXNpuLx8BE1KA==",
575 | "dev": true,
576 | "hasInstallScript": true,
577 | "bin": {
578 | "esbuild": "bin/esbuild"
579 | },
580 | "engines": {
581 | "node": ">=12"
582 | },
583 | "optionalDependencies": {
584 | "@esbuild/android-arm": "0.17.17",
585 | "@esbuild/android-arm64": "0.17.17",
586 | "@esbuild/android-x64": "0.17.17",
587 | "@esbuild/darwin-arm64": "0.17.17",
588 | "@esbuild/darwin-x64": "0.17.17",
589 | "@esbuild/freebsd-arm64": "0.17.17",
590 | "@esbuild/freebsd-x64": "0.17.17",
591 | "@esbuild/linux-arm": "0.17.17",
592 | "@esbuild/linux-arm64": "0.17.17",
593 | "@esbuild/linux-ia32": "0.17.17",
594 | "@esbuild/linux-loong64": "0.17.17",
595 | "@esbuild/linux-mips64el": "0.17.17",
596 | "@esbuild/linux-ppc64": "0.17.17",
597 | "@esbuild/linux-riscv64": "0.17.17",
598 | "@esbuild/linux-s390x": "0.17.17",
599 | "@esbuild/linux-x64": "0.17.17",
600 | "@esbuild/netbsd-x64": "0.17.17",
601 | "@esbuild/openbsd-x64": "0.17.17",
602 | "@esbuild/sunos-x64": "0.17.17",
603 | "@esbuild/win32-arm64": "0.17.17",
604 | "@esbuild/win32-ia32": "0.17.17",
605 | "@esbuild/win32-x64": "0.17.17"
606 | }
607 | },
608 | "node_modules/estree-walker": {
609 | "version": "2.0.2",
610 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
611 | "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
612 | },
613 | "node_modules/follow-redirects": {
614 | "version": "1.15.2",
615 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
616 | "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
617 | "funding": [
618 | {
619 | "type": "individual",
620 | "url": "https://github.com/sponsors/RubenVerborgh"
621 | }
622 | ],
623 | "engines": {
624 | "node": ">=4.0"
625 | },
626 | "peerDependenciesMeta": {
627 | "debug": {
628 | "optional": true
629 | }
630 | }
631 | },
632 | "node_modules/form-data": {
633 | "version": "4.0.0",
634 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
635 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
636 | "dependencies": {
637 | "asynckit": "^0.4.0",
638 | "combined-stream": "^1.0.8",
639 | "mime-types": "^2.1.12"
640 | },
641 | "engines": {
642 | "node": ">= 6"
643 | }
644 | },
645 | "node_modules/fsevents": {
646 | "version": "2.3.2",
647 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
648 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
649 | "dev": true,
650 | "hasInstallScript": true,
651 | "optional": true,
652 | "os": [
653 | "darwin"
654 | ],
655 | "engines": {
656 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
657 | }
658 | },
659 | "node_modules/magic-string": {
660 | "version": "0.25.9",
661 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
662 | "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==",
663 | "dependencies": {
664 | "sourcemap-codec": "^1.4.8"
665 | }
666 | },
667 | "node_modules/mime-db": {
668 | "version": "1.52.0",
669 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
670 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
671 | "engines": {
672 | "node": ">= 0.6"
673 | }
674 | },
675 | "node_modules/mime-types": {
676 | "version": "2.1.35",
677 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
678 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
679 | "dependencies": {
680 | "mime-db": "1.52.0"
681 | },
682 | "engines": {
683 | "node": ">= 0.6"
684 | }
685 | },
686 | "node_modules/nanoid": {
687 | "version": "3.3.6",
688 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
689 | "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
690 | "funding": [
691 | {
692 | "type": "github",
693 | "url": "https://github.com/sponsors/ai"
694 | }
695 | ],
696 | "bin": {
697 | "nanoid": "bin/nanoid.cjs"
698 | },
699 | "engines": {
700 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
701 | }
702 | },
703 | "node_modules/picocolors": {
704 | "version": "1.0.0",
705 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
706 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
707 | },
708 | "node_modules/postcss": {
709 | "version": "8.4.23",
710 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz",
711 | "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==",
712 | "funding": [
713 | {
714 | "type": "opencollective",
715 | "url": "https://opencollective.com/postcss/"
716 | },
717 | {
718 | "type": "tidelift",
719 | "url": "https://tidelift.com/funding/github/npm/postcss"
720 | },
721 | {
722 | "type": "github",
723 | "url": "https://github.com/sponsors/ai"
724 | }
725 | ],
726 | "dependencies": {
727 | "nanoid": "^3.3.6",
728 | "picocolors": "^1.0.0",
729 | "source-map-js": "^1.0.2"
730 | },
731 | "engines": {
732 | "node": "^10 || ^12 || >=14"
733 | }
734 | },
735 | "node_modules/proxy-from-env": {
736 | "version": "1.1.0",
737 | "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
738 | "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
739 | },
740 | "node_modules/rollup": {
741 | "version": "3.20.7",
742 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.7.tgz",
743 | "integrity": "sha512-P7E2zezKSLhWnTz46XxjSmInrbOCiul1yf+kJccMxT56vxjHwCbDfoLbiqFgu+WQoo9ij2PkraYaBstgB2prBA==",
744 | "dev": true,
745 | "bin": {
746 | "rollup": "dist/bin/rollup"
747 | },
748 | "engines": {
749 | "node": ">=14.18.0",
750 | "npm": ">=8.0.0"
751 | },
752 | "optionalDependencies": {
753 | "fsevents": "~2.3.2"
754 | }
755 | },
756 | "node_modules/source-map": {
757 | "version": "0.6.1",
758 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
759 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
760 | "engines": {
761 | "node": ">=0.10.0"
762 | }
763 | },
764 | "node_modules/source-map-js": {
765 | "version": "1.0.2",
766 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
767 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
768 | "engines": {
769 | "node": ">=0.10.0"
770 | }
771 | },
772 | "node_modules/sourcemap-codec": {
773 | "version": "1.4.8",
774 | "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
775 | "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
776 | "deprecated": "Please use @jridgewell/sourcemap-codec instead"
777 | },
778 | "node_modules/vite": {
779 | "version": "4.3.1",
780 | "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.1.tgz",
781 | "integrity": "sha512-EPmfPLAI79Z/RofuMvkIS0Yr091T2ReUoXQqc5ppBX/sjFRhHKiPPF/R46cTdoci/XgeQpB23diiJxq5w30vdg==",
782 | "dev": true,
783 | "dependencies": {
784 | "esbuild": "^0.17.5",
785 | "postcss": "^8.4.21",
786 | "rollup": "^3.20.2"
787 | },
788 | "bin": {
789 | "vite": "bin/vite.js"
790 | },
791 | "engines": {
792 | "node": "^14.18.0 || >=16.0.0"
793 | },
794 | "optionalDependencies": {
795 | "fsevents": "~2.3.2"
796 | },
797 | "peerDependencies": {
798 | "@types/node": ">= 14",
799 | "less": "*",
800 | "sass": "*",
801 | "stylus": "*",
802 | "sugarss": "*",
803 | "terser": "^5.4.0"
804 | },
805 | "peerDependenciesMeta": {
806 | "@types/node": {
807 | "optional": true
808 | },
809 | "less": {
810 | "optional": true
811 | },
812 | "sass": {
813 | "optional": true
814 | },
815 | "stylus": {
816 | "optional": true
817 | },
818 | "sugarss": {
819 | "optional": true
820 | },
821 | "terser": {
822 | "optional": true
823 | }
824 | }
825 | },
826 | "node_modules/vue": {
827 | "version": "3.2.47",
828 | "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.47.tgz",
829 | "integrity": "sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ==",
830 | "dependencies": {
831 | "@vue/compiler-dom": "3.2.47",
832 | "@vue/compiler-sfc": "3.2.47",
833 | "@vue/runtime-dom": "3.2.47",
834 | "@vue/server-renderer": "3.2.47",
835 | "@vue/shared": "3.2.47"
836 | }
837 | },
838 | "node_modules/vue-router": {
839 | "version": "4.1.6",
840 | "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.6.tgz",
841 | "integrity": "sha512-DYWYwsG6xNPmLq/FmZn8Ip+qrhFEzA14EI12MsMgVxvHFDYvlr4NXpVF5hrRH1wVcDP8fGi5F4rxuJSl8/r+EQ==",
842 | "dependencies": {
843 | "@vue/devtools-api": "^6.4.5"
844 | },
845 | "funding": {
846 | "url": "https://github.com/sponsors/posva"
847 | },
848 | "peerDependencies": {
849 | "vue": "^3.2.0"
850 | }
851 | }
852 | }
853 | }
854 |
--------------------------------------------------------------------------------
/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "client",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "vite",
7 | "build": "vite build",
8 | "preview": "vite preview"
9 | },
10 | "dependencies": {
11 | "axios": "^1.3.6",
12 | "bootstrap": "^5.2.3",
13 | "vue": "^3.2.47",
14 | "vue-router": "^4.1.6"
15 | },
16 | "devDependencies": {
17 | "@vitejs/plugin-vue": "^4.0.0",
18 | "vite": "^4.1.4"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/client/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fumatecdev/vue.js_flask/5452ead85dc9760d7943f9bc727b68a57d5436b3/client/public/favicon.ico
--------------------------------------------------------------------------------
/client/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
14 |
--------------------------------------------------------------------------------
/client/src/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/client/src/components/Alert.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ message }}
4 |
5 |
6 |
7 |
8 |
13 |
--------------------------------------------------------------------------------
/client/src/components/Books.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
Books
6 |
7 |
8 |
14 |
15 |
16 |
17 |
18 | Title |
19 | Author |
20 | Read? |
21 | |
22 |
23 |
24 |
25 |
26 | {{ book.title }} |
27 | {{ book.author }} |
28 |
29 | Yes
30 | No
31 | |
32 |
33 |
34 |
40 |
46 |
47 | |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
121 |
122 |
123 |
124 |
190 |
191 |
192 |
193 |
194 |
345 |
--------------------------------------------------------------------------------
/client/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
{{ msg }}
13 |
14 | You’ve successfully created a project with
15 | Vite +
16 | Vue 3.
17 |
18 |
19 |
20 |
21 |
44 |
--------------------------------------------------------------------------------
/client/src/components/Ping.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
35 |
--------------------------------------------------------------------------------
/client/src/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './App.vue'
3 | import router from './router'
4 | import 'bootstrap/dist/css/bootstrap.css'
5 |
6 | const app = createApp(App)
7 |
8 | app.use(router)
9 |
10 | app.mount('#app')
11 |
--------------------------------------------------------------------------------
/client/src/router/index.js:
--------------------------------------------------------------------------------
1 | import { createRouter, createWebHistory } from 'vue-router'
2 | import Books from '../components/Books.vue'
3 | import Ping from '../components/Ping.vue'
4 |
5 | const router = createRouter({
6 | history: createWebHistory(import.meta.env.BASE_URL),
7 | routes: [
8 | {
9 | path: '/',
10 | name: 'Books',
11 | component: Books,
12 | },
13 | {
14 | path: '/ping',
15 | name: 'ping',
16 | component: Ping
17 | },
18 | ]
19 | })
20 |
21 | export default router
22 |
--------------------------------------------------------------------------------
/client/vite.config.js:
--------------------------------------------------------------------------------
1 | import { fileURLToPath, URL } from 'node:url'
2 |
3 | import { defineConfig } from 'vite'
4 | import vue from '@vitejs/plugin-vue'
5 |
6 | // https://vitejs.dev/config/
7 | export default defineConfig({
8 | plugins: [vue()],
9 | resolve: {
10 | alias: {
11 | '@': fileURLToPath(new URL('./src', import.meta.url))
12 | }
13 | }
14 | })
15 |
--------------------------------------------------------------------------------
/server/app.py:
--------------------------------------------------------------------------------
1 | import uuid
2 |
3 | from flask import Flask, jsonify, request
4 | from flask_cors import CORS
5 |
6 |
7 | BOOKS = [
8 | {
9 | 'id': uuid.uuid4().hex,
10 | 'title': 'On the Road',
11 | 'author': 'Jack Kerouac',
12 | 'read': True
13 | },
14 | {
15 | 'id': uuid.uuid4().hex,
16 | 'title': 'Harry Potter and the Philosopher\'s Stone',
17 | 'author': 'J. K. Rowling',
18 | 'read': False
19 | },
20 | {
21 | 'id': uuid.uuid4().hex,
22 | 'title': 'Green Eggs and Ham',
23 | 'author': 'Dr. Seuss',
24 | 'read': True
25 | }
26 | ]
27 |
28 | # instantiate the app
29 | app = Flask(__name__)
30 | app.config.from_object(__name__)
31 |
32 | # enable CORS
33 | CORS(app, resources={r'/*': {'origins': '*'}})
34 |
35 |
36 | def remove_book(book_id):
37 | for book in BOOKS:
38 | if book['id'] == book_id:
39 | BOOKS.remove(book)
40 | return True
41 | return False
42 |
43 |
44 | # sanity check route
45 | @app.route('/ping', methods=['GET'])
46 | def ping_pong():
47 | return jsonify('pong!')
48 |
49 |
50 | @app.route('/books', methods=['GET', 'POST'])
51 | def all_books():
52 | response_object = {'status': 'success'}
53 | if request.method == 'POST':
54 | post_data = request.get_json()
55 | BOOKS.append({
56 | 'id': uuid.uuid4().hex,
57 | 'title': post_data.get('title'),
58 | 'author': post_data.get('author'),
59 | 'read': post_data.get('read')
60 | })
61 | response_object['message'] = 'Book added!'
62 | else:
63 | response_object['books'] = BOOKS
64 | return jsonify(response_object)
65 |
66 |
67 | @app.route('/books/', methods=['PUT', 'DELETE'])
68 | def single_book(book_id):
69 | response_object = {'status': 'success'}
70 | if request.method == 'PUT':
71 | post_data = request.get_json()
72 | remove_book(book_id)
73 | BOOKS.append({
74 | 'id': uuid.uuid4().hex,
75 | 'title': post_data.get('title'),
76 | 'author': post_data.get('author'),
77 | 'read': post_data.get('read')
78 | })
79 | response_object['message'] = 'Book updated!'
80 | if request.method == 'DELETE':
81 | remove_book(book_id)
82 | response_object['message'] = 'Book removed!'
83 | return jsonify(response_object)
84 |
85 |
86 | if __name__ == '__main__':
87 | app.run()
88 |
--------------------------------------------------------------------------------
/server/requirements.txt:
--------------------------------------------------------------------------------
1 | Flask==2.2.3
2 | Flask-Cors==3.0.10
3 |
--------------------------------------------------------------------------------