From 8c54988023678c4a606acbbc13c95d72694b2d57 Mon Sep 17 00:00:00 2001 From: Torsten Schulz Date: Mon, 17 Jun 2024 23:34:31 +0200 Subject: [PATCH] Added multiple features --- controllers/imageController.js | 95 +++++++ controllers/menuDataController.js | 11 +- controllers/userController.js | 60 +++++ controllers/worshipController.js | 11 +- .../20240617191416-create-images-table.js | 35 +++ .../20240617192740-create-images-table.js | 15 ++ models/Image.js | 36 +++ package-lock.json | 238 +++++++++++++----- package.json | 4 +- .../44390f72-e407-4796-8cc7-a5253dae4ebd.jpg | Bin 0 -> 38714 bytes routes/image.js | 12 + routes/users.js | 12 + server.js | 5 +- src/assets/icons/Bold_Italic_Underline.png | Bin 0 -> 1822 bytes src/assets/icons/format_list_bulleted.png | Bin 0 -> 962 bytes src/assets/icons/format_list_numbered.png | Bin 0 -> 1081 bytes src/assets/icons/image.png | Bin 0 -> 1632 bytes src/assets/icons/strikethrough.png | Bin 0 -> 1869 bytes src/assets/icons/table.png | Bin 0 -> 1433 bytes src/common/components/FooterComponent.vue | 2 +- src/common/components/HeaderComponent.vue | 13 +- src/components/WorshipDialog.vue | 37 ++- src/components/WorshipRender.vue | 2 +- src/content/admin/AdminWorshipService.vue | 12 - src/content/admin/EditPagesComponent.vue | 43 +++- src/content/admin/ImageUpload.vue | 134 ++++++++++ src/content/admin/IndexContent.vue | 78 ++++-- src/content/admin/MenuManagement.vue | 75 ++++-- src/content/admin/UserAdministration.vue | 153 +++++++++++ ...Password.vue => ForgotPasswordContent.vue} | 0 .../{LoginComponent.vue => LoginContent.vue} | 2 +- ...isterComponent.vue => RegisterContent.vue} | 0 ...sWorshipContent.vue => BonamesContent.vue} | 0 src/content/worship/NeighborhoodContent.vue | 24 ++ src/icons.js | 8 + src/router.js | 24 +- src/utils/strings.js | 8 + utils/fetchMenuData.js | 2 +- 38 files changed, 1006 insertions(+), 145 deletions(-) create mode 100644 controllers/imageController.js create mode 100644 controllers/userController.js create mode 100644 migrations/20240617191416-create-images-table.js create mode 100644 migrations/20240617192740-create-images-table.js create mode 100644 models/Image.js create mode 100644 public/images/uploads/44390f72-e407-4796-8cc7-a5253dae4ebd.jpg create mode 100644 routes/image.js create mode 100644 routes/users.js create mode 100644 src/assets/icons/Bold_Italic_Underline.png create mode 100644 src/assets/icons/format_list_bulleted.png create mode 100644 src/assets/icons/format_list_numbered.png create mode 100644 src/assets/icons/image.png create mode 100644 src/assets/icons/strikethrough.png create mode 100644 src/assets/icons/table.png delete mode 100644 src/content/admin/AdminWorshipService.vue create mode 100644 src/content/admin/ImageUpload.vue create mode 100644 src/content/admin/UserAdministration.vue rename src/content/authentication/{ForgotPassword.vue => ForgotPasswordContent.vue} (100%) rename src/content/authentication/{LoginComponent.vue => LoginContent.vue} (98%) rename src/content/authentication/{RegisterComponent.vue => RegisterContent.vue} (100%) rename src/content/worship/{BonamesWorshipContent.vue => BonamesContent.vue} (100%) create mode 100644 src/content/worship/NeighborhoodContent.vue create mode 100644 src/icons.js diff --git a/controllers/imageController.js b/controllers/imageController.js new file mode 100644 index 0000000..5667f4b --- /dev/null +++ b/controllers/imageController.js @@ -0,0 +1,95 @@ +const { Image } = require('../models'); +const { v4: uuidv4 } = require('uuid'); +const multer = require('multer'); +const path = require('path'); + +const storage = multer.diskStorage({ + destination: (req, file, cb) => { + cb(null, 'public/images/uploads'); + }, + filename: (req, file, cb) => { + const uniqueSuffix = `${uuidv4()}${path.extname(file.originalname)}`; + cb(null, uniqueSuffix); + } +}); + +const upload = multer({ storage }); + +exports.uploadImage = upload.single('image'); + +exports.saveImageDetails = async (req, res) => { + try { + const { title, description, pageId } = req.body; + const filename = req.file.filename; + const newImage = await Image.create({ + id: uuidv4(), + filename, + title, + description, + pageId: pageId || null + }); + res.status(201).json(newImage); + } catch (error) { + console.error('Fehler beim Speichern des Bildes:', error); + res.status(500).send('Fehler beim Speichern des Bildes'); + } +}; + +exports.getImages = async (req, res) => { + try { + const images = await Image.findAll(); + res.status(200).json(images); + } catch (error) { + console.error('Fehler beim Abrufen der Bilder:', error); + res.status(500).send('Fehler beim Abrufen der Bilder'); + } +}; + +exports.getImagesByPage = async (req, res) => { + try { + const { pageId } = req.params; + const images = await Image.findAll({ where: { pageId } }); + res.status(200).json(images); + } catch (error) { + console.error('Fehler beim Abrufen der Bilder:', error); + res.status(500).send('Fehler beim Abrufen der Bilder'); + } +}; + +exports.getImageById = async (req, res) => { + try { + const { id } = req.params; + const image = await Image.findByPk(id); + if (image) { + res.status(200).json(image); + } else { + res.status(404).send('Bild nicht gefunden'); + } + } catch (error) { + console.error('Fehler beim Abrufen des Bildes:', error); + res.status(500).send('Fehler beim Abrufen des Bildes'); + } +}; + +exports.updateImage = async (req, res) => { + try { + const { id } = req.params; + const { title, description } = req.body; + + const image = await Image.findByPk(id); + + if (!image) { + return res.status(404).json({ error: 'Bild nicht gefunden' }); + } + + image.title = title; + image.description = description; + + await image.save(); + + res.json(image); + } catch (error) { + console.error('Fehler beim Aktualisieren des Bildes:', error); + res.status(500).json({ error: 'Fehler beim Aktualisieren des Bildes' }); + } +}; \ No newline at end of file diff --git a/controllers/menuDataController.js b/controllers/menuDataController.js index 6012bf7..33c5407 100644 --- a/controllers/menuDataController.js +++ b/controllers/menuDataController.js @@ -1,4 +1,4 @@ -const { MenuItem } = require('../models'); // Stellen Sie sicher, dass das Modell korrekt importiert wird +const { MenuItem } = require('../models'); const fetchMenuData = require('../utils/fetchMenuData'); exports.getMenuData = async (req, res) => { @@ -13,8 +13,15 @@ exports.getMenuData = async (req, res) => { exports.saveMenuData = async (req, res) => { try { const menuData = req.body; + const adjustedMenuData = menuData.map(item => { + item.parent_id = item.parent_id < 0 ? null : item.parent_id; + return item; + }) + .sort((a, b) => (a.parent_id === null ? -1 : 1) - (b.parent_id === null ? -1 : 1)); await MenuItem.destroy({ where: {} }); - await MenuItem.bulkCreate(menuData, { include: [{ model: MenuItem, as: 'submenu' }] }); + for (const item of adjustedMenuData) { + await MenuItem.create(item); + } res.status(200).send('Menü-Daten erfolgreich gespeichert'); } catch (error) { console.error('Fehler beim Speichern der Menü-Daten:', error); diff --git a/controllers/userController.js b/controllers/userController.js new file mode 100644 index 0000000..8ce9dea --- /dev/null +++ b/controllers/userController.js @@ -0,0 +1,60 @@ +const { User } = require('../models'); + +exports.getAllUsers = async (req, res) => { + try { + const users = await User.findAll(); + res.status(200).json(users); + } catch (error) { + res.status(500).json({ message: 'Error fetching users' }); + } +}; + +exports.getUserById = async (req, res) => { + try { + const user = await User.findByPk(req.params.id); + if (user) { + res.status(200).json(user); + } else { + res.status(404).json({ message: 'User not found' }); + } + } catch (error) { + res.status(500).json({ message: 'Error fetching user' }); + } +}; + +exports.createUser = async (req, res) => { + try { + const user = await User.create(req.body); + res.status(201).json(user); + } catch (error) { + res.status(500).json({ message: 'Error creating user' }); + } +}; + +exports.updateUser = async (req, res) => { + try { + const user = await User.findByPk(req.params.id); + if (user) { + await user.update(req.body); + res.status(200).json(user); + } else { + res.status(404).json({ message: 'User not found' }); + } + } catch (error) { + res.status(500).json({ message: 'Error updating user' }); + } +}; + +exports.deleteUser = async (req, res) => { + try { + const user = await User.findByPk(req.params.id); + if (user) { + await user.destroy(); + res.status(200).json({ message: 'User deleted successfully' }); + } else { + res.status(404).json({ message: 'User not found' }); + } + } catch (error) { + res.status(500).json({ message: 'Error deleting user' }); + } +}; diff --git a/controllers/worshipController.js b/controllers/worshipController.js index d11c950..4ded946 100644 --- a/controllers/worshipController.js +++ b/controllers/worshipController.js @@ -1,4 +1,4 @@ -const { Worship, EventPlace } = require('../models'); +const { Worship, EventPlace, Sequelize } = require('../models'); const { Op } = require('sequelize'); // Importieren Sie die Operatoren von Sequelize exports.getAllWorships = async (req, res) => { @@ -53,7 +53,14 @@ exports.getFilteredWorships = async (req, res) => { const where = {}; if (location && location !== '-1') { - where.eventPlaceId = location; + if (location.includes('|')) { + const locationsArray = location.split('|'); + where.eventPlaceId = { + [Sequelize.Op.in]: locationsArray + } + } else { + where.eventPlaceId = location; + } } where.date = { diff --git a/migrations/20240617191416-create-images-table.js b/migrations/20240617191416-create-images-table.js new file mode 100644 index 0000000..478fa99 --- /dev/null +++ b/migrations/20240617191416-create-images-table.js @@ -0,0 +1,35 @@ +'use strict'; + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.createTable('images', { + id: { + allowNull: false, + primaryKey: true, + type: Sequelize.UUID, + defaultValue: Sequelize.UUIDV4 + }, + filename: { + type: Sequelize.STRING, + allowNull: false + }, + title: { + type: Sequelize.STRING, + allowNull: true + }, + description: { + type: Sequelize.TEXT, + allowNull: true + }, + uploadDate: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.NOW + } + }); + }, + + down: async (queryInterface, Sequelize) => { + await queryInterface.dropTable('images'); + } +}; diff --git a/migrations/20240617192740-create-images-table.js b/migrations/20240617192740-create-images-table.js new file mode 100644 index 0000000..df137c8 --- /dev/null +++ b/migrations/20240617192740-create-images-table.js @@ -0,0 +1,15 @@ +'use strict'; + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up (queryInterface, Sequelize) { + await queryInterface.addColumn('images', 'pageId', { + type: Sequelize.INTEGER, + allowNull: true, + }); + }, + + async down (queryInterface, Sequelize) { + await queryInterface.removeColumn('images', 'pageId'); + } +}; diff --git a/models/Image.js b/models/Image.js new file mode 100644 index 0000000..3318bad --- /dev/null +++ b/models/Image.js @@ -0,0 +1,36 @@ +const { DataTypes } = require('sequelize'); + +module.exports = (sequelize) => { + const Image = sequelize.define('Image', { + id: { + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + primaryKey: true + }, + filename: { + type: DataTypes.STRING, + allowNull: false + }, + title: { + type: DataTypes.STRING, + allowNull: true + }, + description: { + type: DataTypes.TEXT, + allowNull: true + }, + uploadDate: { + type: DataTypes.DATE, + defaultValue: DataTypes.NOW + }, + pageId: { + type: DataTypes.UUID, + allowNull: true + } + }, { + tableName: 'images', + timestamps: false + }); + + return Image; +}; diff --git a/package-lock.json b/package-lock.json index cac17e8..75abc4c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "miriamgemeinde", "version": "0.1.0", "dependencies": { + "@iconoir/vue": "^7.7.0", "@tiptap/extension-bold": "^2.4.0", "@tiptap/extension-bullet-list": "^2.4.0", "@tiptap/extension-heading": "^2.4.0", @@ -21,7 +22,6 @@ "@tiptap/extension-underline": "^2.4.0", "@tiptap/starter-kit": "^2.4.0", "@tiptap/vue-3": "^2.4.0", - "@vueup/vue-quill": "^1.2.0", "axios": "^1.7.2", "bcryptjs": "^2.4.3", "body-parser": "^1.20.2", @@ -32,10 +32,12 @@ "dotenv": "^16.4.5", "express": "^4.19.2", "jsonwebtoken": "^9.0.2", + "multer": "^1.4.5-lts.1", "mysql2": "^3.10.1", "nodemon": "^3.1.3", "sequelize": "^6.37.3", "sequelize-cli": "^6.6.2", + "uuid": "^10.0.0", "vm-browserify": "^1.1.2", "vue": "^3.2.13", "vue-multiselect": "^3.0.0", @@ -1958,6 +1960,52 @@ "deprecated": "Use @eslint/object-schema instead", "dev": true }, + "node_modules/@iconoir/vue": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@iconoir/vue/-/vue-7.7.0.tgz", + "integrity": "sha512-EvJK80DUGpCFd2MZsC5K6duv/h4zafruBSQYV9F5b+kJOrdWNCHxEHpwbUwjsI35GpSzMD0N2jAR86s3YTsMmw==", + "dependencies": { + "vue-demi": "^0.14.6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/iconoir" + }, + "peerDependencies": { + "@vue/composition-api": ">=1.0.0-rc.1", + "vue": "^2.6.11 || >=3.0.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@iconoir/vue/node_modules/vue-demi": { + "version": "0.14.8", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.8.tgz", + "integrity": "sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -3741,18 +3789,6 @@ "integrity": "sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==", "dev": true }, - "node_modules/@vueup/vue-quill": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@vueup/vue-quill/-/vue-quill-1.2.0.tgz", - "integrity": "sha512-kd5QPSHMDpycklojPXno2Kw2JSiKMYduKYQckTm1RJoVDA557MnyUXgcuuDpry4HY/Rny9nGNcK+m3AHk94wag==", - "dependencies": { - "quill": "^1.3.7", - "quill-delta": "^4.2.2" - }, - "peerDependencies": { - "vue": "^3.2.41" - } - }, "node_modules/@webassemblyjs/ast": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", @@ -4114,6 +4150,11 @@ "node": ">= 8" } }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, "node_modules/arch": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", @@ -4657,8 +4698,7 @@ "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "node_modules/buffer-xor": { "version": "1.0.3", @@ -4666,6 +4706,17 @@ "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", "dev": true }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -5143,6 +5194,47 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/config-chain": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", @@ -5280,8 +5372,7 @@ "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, "node_modules/cors": { "version": "2.8.5", @@ -7158,11 +7249,6 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==" - }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -8373,8 +8459,7 @@ "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, "node_modules/isexe": { "version": "2.0.0", @@ -8822,11 +8907,6 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" - }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -8849,11 +8929,6 @@ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" - }, "node_modules/lodash.isinteger": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", @@ -9463,7 +9538,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -9490,7 +9564,6 @@ "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, "dependencies": { "minimist": "^1.2.6" }, @@ -9537,6 +9610,23 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/multicast-dns": { "version": "7.2.5", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", @@ -10995,8 +11085,7 @@ "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "node_modules/progress": { "version": "2.0.3", @@ -11358,16 +11447,6 @@ "quill-delta": "^3.6.2" } }, - "node_modules/quill-delta": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-4.2.2.tgz", - "integrity": "sha512-qjbn82b/yJzOjstBgkhtBjN2TNK+ZHP/BgUQO+j6bRhWQQdmj2lH6hXG7+nwwLF41Xgn//7/83lxs9n2BkTtTg==", - "dependencies": { - "fast-diff": "1.2.0", - "lodash.clonedeep": "^4.5.0", - "lodash.isequal": "^4.5.0" - } - }, "node_modules/quill/node_modules/fast-diff": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz", @@ -11972,6 +12051,14 @@ "node": ">=10" } }, + "node_modules/sequelize/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", @@ -12290,6 +12377,15 @@ "websocket-driver": "^0.7.4" } }, + "node_modules/sockjs/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -12436,6 +12532,14 @@ "readable-stream": "^3.5.0" } }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -12939,6 +13043,11 @@ "node": ">= 0.6" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, "node_modules/uc.micro": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", @@ -13064,8 +13173,7 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/utila": { "version": "0.4.0", @@ -13082,9 +13190,13 @@ } }, "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } @@ -13752,9 +13864,9 @@ } }, "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", - "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, "engines": { "node": ">=10.0.0" @@ -13995,9 +14107,9 @@ "dev": true }, "node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "dev": true, "engines": { "node": ">=8.3.0" @@ -14015,6 +14127,14 @@ } } }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index e5f95d5..0118f12 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "lint": "vue-cli-service lint" }, "dependencies": { + "@iconoir/vue": "^7.7.0", "@tiptap/extension-bold": "^2.4.0", "@tiptap/extension-bullet-list": "^2.4.0", "@tiptap/extension-heading": "^2.4.0", @@ -21,7 +22,6 @@ "@tiptap/extension-underline": "^2.4.0", "@tiptap/starter-kit": "^2.4.0", "@tiptap/vue-3": "^2.4.0", - "@vueup/vue-quill": "^1.2.0", "axios": "^1.7.2", "bcryptjs": "^2.4.3", "body-parser": "^1.20.2", @@ -32,10 +32,12 @@ "dotenv": "^16.4.5", "express": "^4.19.2", "jsonwebtoken": "^9.0.2", + "multer": "^1.4.5-lts.1", "mysql2": "^3.10.1", "nodemon": "^3.1.3", "sequelize": "^6.37.3", "sequelize-cli": "^6.6.2", + "uuid": "^10.0.0", "vm-browserify": "^1.1.2", "vue": "^3.2.13", "vue-multiselect": "^3.0.0", diff --git a/public/images/uploads/44390f72-e407-4796-8cc7-a5253dae4ebd.jpg b/public/images/uploads/44390f72-e407-4796-8cc7-a5253dae4ebd.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0295635a08094ae00465042f2f78195eb49c77cf GIT binary patch literal 38714 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 literal 0 HcmV?d00001 diff --git a/routes/image.js b/routes/image.js new file mode 100644 index 0000000..65b1df0 --- /dev/null +++ b/routes/image.js @@ -0,0 +1,12 @@ +const express = require('express'); +const router = express.Router(); +const { uploadImage, saveImageDetails, getImages, getImagesByPage, getImageById, updateImage } = require('../controllers/imageController'); +const authMiddleware = require('../middleware/authMiddleware') + +router.post('/', authMiddleware, uploadImage, saveImageDetails); +router.get('/', authMiddleware, getImages); +router.get('/page/:pageId', getImagesByPage); +router.get('/:id', getImageById); +router.put('/:id', authMiddleware, updateImage); + +module.exports = router; diff --git a/routes/users.js b/routes/users.js new file mode 100644 index 0000000..3dcd57c --- /dev/null +++ b/routes/users.js @@ -0,0 +1,12 @@ +const express = require('express'); +const router = express.Router(); +const { getAllUsers, createUser, updateUser, deleteUser, getUserById } = require('../controllers/userController'); +const authMiddleware = require('../middleware/authMiddleware'); + +router.get('/', authMiddleware, getAllUsers); +router.get('/:id', authMiddleware, getUserById); +router.post('/', authMiddleware, createUser); +router.put('/:id', authMiddleware, updateUser); +router.delete('/:id', authMiddleware, deleteUser); + +module.exports = router; diff --git a/server.js b/server.js index 05676c4..1fbfd5f 100644 --- a/server.js +++ b/server.js @@ -12,6 +12,8 @@ const eventRouter = require('./routes/event'); const menuDataRouter = require('./routes/menuData'); const worshipRouter = require('./routes/worships'); const pageRoutes = require('./routes/pages'); +const userRoutes = require('./routes/users'); +const imageRoutes = require('./routes/image'); const app = express(); const PORT = 3000; @@ -29,7 +31,8 @@ app.use('/api/events', eventRouter); app.use('/api/menu-data', menuDataRouter); app.use('/api/worships', worshipRouter); app.use('/api/page-content', pageRoutes); - +app.use('/api/users', userRoutes); +app.use('/api/image', imageRoutes); sequelize.sync().then(() => { app.listen(PORT, () => { console.log(`Server läuft auf Port ${PORT}`); diff --git a/src/assets/icons/Bold_Italic_Underline.png b/src/assets/icons/Bold_Italic_Underline.png new file mode 100644 index 0000000000000000000000000000000000000000..80adbbf0e8a2cad45289457e090902f7a528547d GIT binary patch literal 1822 zcmb7_YdjMQ1I9;-nK_u(TVtiUHRMuqi(F;MWXvOpr~5_ z>^Ti^jGw^x$=(F`2Ow5X%maHQ;jezl$8DuiLD$b`m4`-j6mLE&I_404<#4vEt*u%y z?EsAclrWr#X;5X7EE0jE=>aKEO2JMj3gXmTxEl?s3=#2Ns6^$+_<}(CSosnP$lCH( zlWG|?^l?%4Tc?Le1Y1TXFkKTZAxn+di*)^e7iLKRk7IqhI?d$o_wIZiy?7t*vpR9$ZT_5C2#AZI*k5iK}Ucdv0j^_5F#nA|Ea?w8zaA z;s=|=HV)or5r^SXIv&D}=0CoXL1hVr+6=iyrLOea3*1)8B9ZrJ~5 z-w+3`3QzVNG-$z*nrMKb7i1>}3s4}2PTbV_n=c|Af)Hu%= zWTnG-=OU!}cQrwi46G+nCWIR%Z-^M167Xo*fO zFsTD|;}yg+H1O7l7GXUdoSYqy!S5lCH}y>%I92QH>c;K92JS8hTx$4^SP?HC2c)I; zDqr6AX|3VOf=yWN734z-6KG)!!!N1`%=7GF>KR(EOnHmZ_Fbnb*U+hoU$$frVOFPD&RsIj^q`sl^Cg>D;21uIjw zr6(5Q)^J3f)+5ljRLcwCgAP+cdL=b%?(LV9J6ClmlmO2oUX%KhBKxx)q-SlLd38T^ zLc)C|U`OfGvj&ziDdr36fpk8T8P0Lf_`Pf7TjI$AZT zEJ5rqT;uW$}G!YJb;096xunN_d*BIL5L)ac`_;%u19xBt+RYo4*>&W!|^AXPIUYbvN) z$h&wI)oHn&f(6I^GW$p!O^AMbu=%``PjW)(*|w;o4R5^o4$6VXcKH?vPCI@i19KJj z-paEk8WA-a!i-azA81aT5~^{dE{#r%P;YFn)IRZ)K)_C_|C=#f5U7p3Im5@R1k%G= z%k{I#bIwH%IcH`kZno#?*7@}=qWTH)Q;k@I0o%N>!YkD1(LuGY&ZiZ)l04s5Yh5nR zJ()y7->0AJ3~pY+xZ_O5Y75?MA%h-|nf=`1s%+R_Sd~8Q7ZrT6Q}n5A|CzqPy}t6T z>r6MVd$+t{Gj9>ZpYhRhMP~L!kRiGGBZ=S8S%=UL~|E zJ20#|Oqq*4875fMSjGuQTU$<{LR@LMN-zIROFzZ7B|=2TT(M&gpFAlSW%m1*cMVGC zNeHgDsKk-t~SVHc@{TtuAB{0q)E26uy7^~pVmajnc!0-ugkH$-0 zy0j?m$}MUbUh200ey7zCwQBnhGuAm0(eg0ua0h9%z1p>CooxHO2X6pATyLG-`7660 zQWS?t1dvyDONCC`VSbN|?vo55<@BJ+kR;m7j>m5!owW`cK6A&|k7@d0?DDgCH}2Xx zT;q&GjizUl^N(r&PlUk+?MY{K7JvP|%oh3KJ%Am?5nYEOJop=c7+RnJ literal 0 HcmV?d00001 diff --git a/src/assets/icons/format_list_bulleted.png b/src/assets/icons/format_list_bulleted.png new file mode 100644 index 0000000000000000000000000000000000000000..020466b5d4d551d54fb5408cb50a409282c98fc7 GIT binary patch literal 962 zcmeAS@N?(olHy`uVBq!ia0vp^DIm>_bTr^hIuY~80Rspf8ckDjo;xYt8Cdc=?6|?XQs>$S!Lmzdr9TT z!9Tm+s8q)9yZ`(7)1~*XNZAGPMQECK7%~X%=44<7w`XVf5+Lkai?akb_$EW>-+r8wyn!7XKpoqcgA9Kab?}dhZz+GW%_po z1m^NA+5D;Mdh?B0tM2YxeDUYe)%A{<+ppa&OOfL|vwsy!x|m)OzmNZp-@e6^va9)`gVoxvy4g~@4GoUv&iPqlapN|F$5O7&xOM9|Ez;Zm9=s>q z@Pfhet3%!ULwQY!CzDQg#btV%t@#%a9})E>+CqA3?9+ws~t^ z)Wa7kHGQRD3+?}$(~_C{rl7>g{@07|6K?AX@`?Zb{&?<`{la|DraPYRWR7&$uyGGF zgXa6pYaI+HH?6NpZ^?PRHD*O*2kN&$9r((H7pNjdsZ?7{rvwEkL90E3h>RGQ&Un@Eb}jL z9ZS>x<0qJc;`o%AT;9kra5x;15t!`U%HVQ_(aHq)$ literal 0 HcmV?d00001 diff --git a/src/assets/icons/format_list_numbered.png b/src/assets/icons/format_list_numbered.png new file mode 100644 index 0000000000000000000000000000000000000000..54b663ef3d503151623ebafca7987c7b0b1a2739 GIT binary patch literal 1081 zcmV-91jhS`P)=#D6oz-L844PF16)E}pfLx)O=3!p5Kcfi0pSGX27x2cVW)67K#Ws3P?{Sg1r0Oy zA^~!&7e8+*B!GRYk*K41p*+2nd8glqsMr9A*fC zC{sXLILr_NQKo>haF`(kqD%p0;V?r8M41B0!eNFGh%yC~g~JS~8j!TPpW2Cev@UL! zn496~Y^ZErl?}(6A+6@Yxi$91S|G-K9gKSI$||5NZ~`F^WeO+@Cm=&QC&svR9=Ed% zYt7@?XSc;E%U73_X|#1X&LlsFKfa6+2VNk{&RTm1$JW|+F+hBE37LTAvCg^ogR9;# z5+i{iYJp=31QbkqIDtqj4EiS!P%!D?1R||4=$}A9!K8;1h_u3>|H=T#7lvk%)WP{x zarn3r3&ScZTUN|>vM?-ba#h?9fheN}14*B}Y-DrD|Nd>smcAOxaJ0cGJZLkL8f0?NW+hExp*+K|A;xj4e!3_%+bw&_BNo5KCFCJ<#j38Z>J zmKx=X6R2l>zt0L^IrI7As{3lwJkh$OOtau{N@)6YJ)XWwP@<8u1zcY8QK zzupuzT9<+qP&TlXCx){*xAr=xSxf2Rtp@I9GO48@Psj*l{gLCXA*)PVPdi7pWMhifFen5P2_$W_>&e3hePiwXJ&~9dIe|n1+4k~w z-EIja0!XXbIms@?-V_&qZkT1u%C&|w=5jFV9{CoAY?NEAkoU3|J(^=qWnmTQevcv$ zWqb*wYCzz|Xg1D8A@*iSly@4#3J?e^nXCbU$m$DwClFXNSpx!*)fe_oAh2Yz1_UCj zFYMh51Z_xQqa4hjVBiJ9ds%S;qt*n1DkeOhK!gQG-3I{K*eI9puh1+Pa{C>vOX#Gu zj4!=WE}wYzti7EiE^nCoyM+Kj>yj3M(Kt$Nl$!-dAnP%e0%Z9&7nj3fhTJMbAm}+o zcszj!3yiua5L7YY@udJ+o&$^e9T#;12~R7L4Ef(ESA0uqF(&8gXp1S_I1#RawvoI4 zMLBd47joIFO*KvN1l&5={QpC?S%+v6KwB&XqKt?a2z!*5Lhx< z0|JrN7xqpduw=3Z1R|?1?43Yh$z%-(L{?weJAuHG$r=!dtiG^!0)ZuyH6RdKePQne z0!t=qKp?XE!rlo4mQ2=wKxFlWy%Pv5nXJJdsx^3nWb{0900000NkvXXu0mjfJ15tF literal 0 HcmV?d00001 diff --git a/src/assets/icons/image.png b/src/assets/icons/image.png new file mode 100644 index 0000000000000000000000000000000000000000..3b074a4ae4e55a805ada37a21cb7a133582f0166 GIT binary patch literal 1632 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 literal 0 HcmV?d00001 diff --git a/src/assets/icons/table.png b/src/assets/icons/table.png new file mode 100644 index 0000000000000000000000000000000000000000..d7ab2d25d054c3eb07b05a41a950ef2da1189cad GIT binary patch literal 1433 zcmb`HX*kpg0LK60XoeCI(X2HrWhIhh#+5N)4onP|b$Nr1gUP(tMulVIKHhKm!-xOO-8PxZ`bZq*wa#PH`E7}Oj zAg;^cKOvztuBZj%j3lh@V7CU)0ckxVi&3_#yw-E8!@)G{p` zG+169*p0Yz`PZ{Q(jVLM9LmvH>pu11k^C)i6W16fUdZFqyK3TRr-C0_@h^{^1l6Ld z;bxo6jCE_r^zi^kI8>fnn>bB7=D$C!=IG@o>I?OH`Lj{u?A&Q$wG*WGR(82(#;HL; zzDE7ZlgG^WT!UhJjv%4&0Ws=}8Z6rb!W)3A!XrpxxSJJq&1nj_XuJ+EEw4Aca<< zRwkgOWo!dsf2>!ml~Op6yptg)xXwa7hNU{YFh6ckAUUvg@4bYlLo5739?e&c_FlgN%N_A0OC#O>-=j7#8#!J zsIwt50y#;TS841!zz#zXRt0ACbf{n$3KiOc0GWGBaG@^4!D`2P>%DN>g^)6FM_&cx zNN?vRm_R<#P>^z;*N_`+-58JRjeeAFYK^&|NrNWhC~g;b-ZA=gP2Yp#)`mS7n|rE4 zQKq#0U%Der$wtw%t0VZC#U?u&#IA^l@ZpY@wVc5SD?G6G!tEyo7g}F z&9RK#vKEmS8-u2o&h0dZ$->=IrJp2Hw9(?A`33>EH0&z8f{spUQ6|4S7>uEZV!T(z zx^7RdDCq^ZOq7nISgET!(4tOMxh;I+gGdw~)H2aTSRCD`UNUgv@y&`66;D<8AzKZD zYVoRGPzL_HGb5iqaaKBico^)b$ufxILE*HSs