diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..f14788c --- /dev/null +++ b/.prettierrc @@ -0,0 +1,8 @@ +{ + "tabWidth": 2, + "useTabs": false, + "singleQuote": true, + "arrowParens": "always", + "printWidth": 80, + "trailingComma": "es5" +} diff --git a/CHANGELOG.md b/CHANGELOG.md index e6df0e5..3101629 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +### v1.6.3 (2021-08-09) +- Added support for custom SVG icons ([#73](https://github.com/pawelmalak/flame/issues/73)) +- Added Deezer and Tidal to search queries + ### v1.6.2 (2021-08-06) - Fixed changelog link - Added support for Docker API ([#14](https://github.com/pawelmalak/flame/issues/14)) diff --git a/README.md b/README.md index c15bf65..ef01382 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ services: container_name: flame volumes: - :/app/data - - /var/run/docker.sock:/var/sock/docker.sock # optional but required for Docker integration feature + - /var/run/docker.sock:/var/run/docker.sock # optional but required for Docker integration feature ports: - 5005:5005 restart: unless-stopped @@ -174,10 +174,4 @@ And you must have activated the Docker sync option in the settings panel. > This is an experimental feature. Its behaviour might change in the future. > -> Follow instructions from wiki: [Custom CSS](https://github.com/pawelmalak/flame/wiki/Custom-CSS) - -## Support - -If you want to support development of Flame and my upcoming self-hosted and open source projects you can use the following link: - -[![PayPal Badge](https://img.shields.io/badge/PayPal-00457C?style=for-the-badge&logo=paypal&logoColor=white)](https://www.paypal.com/paypalme/pawelmalak) +> Follow instructions from wiki: [Custom CSS](https://github.com/pawelmalak/flame/wiki/Custom-CSS) \ No newline at end of file diff --git a/api.js b/api.js index a720fe2..1c2d863 100644 --- a/api.js +++ b/api.js @@ -9,8 +9,7 @@ api.use(express.static(join(__dirname, 'public'))); api.use('/uploads', express.static(join(__dirname, 'data/uploads'))); api.get(/^\/(?!api)/, (req, res) => { res.sendFile(join(__dirname, 'public/index.html')); -}) - +}); // Body parser api.use(express.json()); @@ -25,4 +24,4 @@ api.use('/api/bookmarks', require('./routes/bookmark')); // Custom error handler api.use(errorHandler); -module.exports = api; \ No newline at end of file +module.exports = api; diff --git a/client/.env b/client/.env index 0c25886..3ab31e3 100644 --- a/client/.env +++ b/client/.env @@ -1 +1 @@ -REACT_APP_VERSION=1.6.2 \ No newline at end of file +REACT_APP_VERSION=1.6.3 \ No newline at end of file diff --git a/client/package-lock.json b/client/package-lock.json index 66b371f..2717839 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -6462,6 +6462,14 @@ } } }, + "external-svg-loader": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/external-svg-loader/-/external-svg-loader-1.3.4.tgz", + "integrity": "sha512-73h7/rYYA4KnIV74M/0r6zHWPLuY/8QHnwKymwh+46tbQAZ0ZtoN98TJZI+CUYTfP2nXgqslCgSsxcr7eOw45w==", + "requires": { + "idb-keyval": "^3.2.0" + } + }, "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", @@ -7527,6 +7535,11 @@ "postcss": "^7.0.14" } }, + "idb-keyval": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-3.2.0.tgz", + "integrity": "sha512-slx8Q6oywCCSfKgPgL0sEsXtPVnSbTLWpyiDcu6msHOyKOLari1TD1qocXVCft80umnkk3/Qqh3lwoFt8T/BPQ==" + }, "identity-obj-proxy": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", @@ -12100,6 +12113,12 @@ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" }, + "prettier": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz", + "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==", + "dev": true + }, "pretty-bytes": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", diff --git a/client/package.json b/client/package.json index 832d079..6e05667 100644 --- a/client/package.json +++ b/client/package.json @@ -16,6 +16,7 @@ "@types/react-redux": "^7.1.16", "@types/react-router-dom": "^5.1.7", "axios": "^0.21.1", + "external-svg-loader": "^1.3.4", "http-proxy-middleware": "^2.0.0", "react": "^17.0.2", "react-beautiful-dnd": "^13.1.0", @@ -53,5 +54,8 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "prettier": "^2.3.2" } } diff --git a/client/src/App.tsx b/client/src/App.tsx index 157206e..05db805 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,5 +1,6 @@ import { BrowserRouter, Route, Switch } from 'react-router-dom'; import { getConfig, setTheme } from './store/actions'; +import 'external-svg-loader'; // Redux import { store } from './store/store'; @@ -40,6 +41,6 @@ const App = (): JSX.Element => { ); -} +}; -export default App; \ No newline at end of file +export default App; diff --git a/client/src/components/Apps/AppCard/AppCard.module.css b/client/src/components/Apps/AppCard/AppCard.module.css index 768ef8e..d6b13a8 100644 --- a/client/src/components/Apps/AppCard/AppCard.module.css +++ b/client/src/components/Apps/AppCard/AppCard.module.css @@ -33,11 +33,11 @@ .AppCard { padding: 2px; border-radius: 4px; - transition: all 0.10s; + transition: all 0.1s; } .AppCard:hover { - background-color: rgba(0,0,0,0.2); + background-color: rgba(0, 0, 0, 0.2); } } @@ -47,4 +47,4 @@ margin-top: 2px; margin-left: 2px; object-fit: contain; -} \ No newline at end of file +} diff --git a/client/src/components/Apps/AppCard/AppCard.tsx b/client/src/components/Apps/AppCard/AppCard.tsx index 79ad3d8..172a680 100644 --- a/client/src/components/Apps/AppCard/AppCard.tsx +++ b/client/src/components/Apps/AppCard/AppCard.tsx @@ -13,6 +13,31 @@ interface ComponentProps { const AppCard = (props: ComponentProps): JSX.Element => { const [displayUrl, redirectUrl] = urlParser(props.app.url); + let iconEl: JSX.Element; + const { icon } = props.app; + + if (/.(jpeg|jpg|png)$/i.test(icon)) { + iconEl = ( + {`${props.app.name} + ); + } else if (/.(svg)$/i.test(icon)) { + iconEl = ( +
+ +
+ ); + } else { + iconEl = ; + } + return ( { rel='noreferrer' className={classes.AppCard} > -
- {(/.(jpeg|jpg|png)$/i).test(props.app.icon) - ? {`${props.app.name} - : - } -
+
{iconEl}
{props.app.name}
{displayUrl}
- ) -} + ); +}; -export default AppCard; \ No newline at end of file +export default AppCard; diff --git a/client/src/components/Apps/AppForm/AppForm.tsx b/client/src/components/Apps/AppForm/AppForm.tsx index 72d8db2..5d05f0a 100644 --- a/client/src/components/Apps/AppForm/AppForm.tsx +++ b/client/src/components/Apps/AppForm/AppForm.tsx @@ -31,28 +31,28 @@ const AppForm = (props: ComponentProps): JSX.Element => { name: props.app.name, url: props.app.url, icon: props.app.icon - }) + }); } else { setFormData({ name: '', url: '', icon: '' - }) + }); } - }, [props.app]) + }, [props.app]); const inputChangeHandler = (e: ChangeEvent): void => { setFormData({ ...formData, [e.target.name]: e.target.value - }) - } + }); + }; const fileChangeHandler = (e: ChangeEvent): void => { if (e.target.files) { setCustomIcon(e.target.files[0]); } - } + }; const formSubmitHandler = (e: SyntheticEvent): void => { e.preventDefault(); @@ -66,7 +66,7 @@ const AppForm = (props: ComponentProps): JSX.Element => { data.append('url', formData.url); return data; - } + }; if (!props.app) { if (customIcon) { @@ -89,10 +89,10 @@ const AppForm = (props: ComponentProps): JSX.Element => { name: '', url: '', icon: '' - }) + }); setCustomIcon(null); - } + }; return ( { placeholder='Bookstack' required value={formData.name} - onChange={(e) => inputChangeHandler(e)} + onChange={e => inputChangeHandler(e)} /> @@ -120,7 +120,7 @@ const AppForm = (props: ComponentProps): JSX.Element => { placeholder='bookstack.example.com' required value={formData.url} - onChange={(e) => inputChangeHandler(e)} + onChange={e => inputChangeHandler(e)} /> { target='_blank' rel='noreferrer' > - {' '}Check supported URL formats + {' '} + Check supported URL formats - {!useCustomIcon + {!useCustomIcon ? ( // use mdi icon - ? ( - - inputChangeHandler(e)} - /> - - Use icon name from MDI. - - {' '}Click here for reference - - - toggleUseCustomIcon(!useCustomIcon)} - className={classes.Switch}> - Switch to custom icon upload - - ) + + + inputChangeHandler(e)} + /> + + Use icon name from MDI. + + {' '} + Click here for reference + + + toggleUseCustomIcon(!useCustomIcon)} + className={classes.Switch} + > + Switch to custom icon upload + + + ) : ( // upload custom icon - : ( - - fileChangeHandler(e)} - accept='.jpg,.jpeg,.png' - /> - toggleUseCustomIcon(!useCustomIcon)} - className={classes.Switch}> - Switch to MDI - - ) - } - {!props.app - ? - : - } + + + fileChangeHandler(e)} + accept='.jpg,.jpeg,.png,.svg' + /> + toggleUseCustomIcon(!useCustomIcon)} + className={classes.Switch} + > + Switch to MDI + + + )} + {!props.app ? ( + + ) : ( + + )} - ) -} + ); +}; -export default connect(null, { addApp, updateApp })(AppForm); \ No newline at end of file +export default connect(null, { addApp, updateApp })(AppForm); diff --git a/client/src/components/Bookmarks/BookmarkCard/BookmarkCard.module.css b/client/src/components/Bookmarks/BookmarkCard/BookmarkCard.module.css index b21ed42..ec5cbfd 100644 --- a/client/src/components/Bookmarks/BookmarkCard/BookmarkCard.module.css +++ b/client/src/components/Bookmarks/BookmarkCard/BookmarkCard.module.css @@ -32,4 +32,14 @@ display: flex; margin-top: 3px; margin-right: 2px; -} \ No newline at end of file + justify-content: center; + align-items: center; +} + +.BookmarkIconSvg { + width: 80%; + height: 80%; + margin-top: 2px; + margin-left: 2px; + object-fit: contain; +} diff --git a/client/src/components/Bookmarks/BookmarkCard/BookmarkCard.tsx b/client/src/components/Bookmarks/BookmarkCard/BookmarkCard.tsx index fe2198b..d3c0b2d 100644 --- a/client/src/components/Bookmarks/BookmarkCard/BookmarkCard.tsx +++ b/client/src/components/Bookmarks/BookmarkCard/BookmarkCard.tsx @@ -16,31 +16,52 @@ const BookmarkCard = (props: ComponentProps): JSX.Element => { {props.category.bookmarks.map((bookmark: Bookmark) => { const redirectUrl = urlParser(bookmark.url)[1]; + let iconEl: JSX.Element; + const { icon, name } = bookmark; + + if (/.(jpeg|jpg|png)$/i.test(icon)) { + iconEl = ( +
+ {`${name} +
+ ); + } else if (/.(svg)$/i.test(icon)) { + iconEl = ( +
+ +
+ ); + } else { + iconEl = ( +
+ +
+ ); + } + return ( - {bookmark.icon && ( -
- {(/.(jpeg|jpg|png)$/i).test(bookmark.icon) - ? {`${bookmark.name} - : - } -
- )} + key={`bookmark-${bookmark.id}`} + > + {icon && iconEl} {bookmark.name}
- ) + ); })} - ) -} + ); +}; -export default BookmarkCard; \ No newline at end of file +export default BookmarkCard; diff --git a/client/src/components/Bookmarks/BookmarkForm/BookmarkForm.tsx b/client/src/components/Bookmarks/BookmarkForm/BookmarkForm.tsx index 67059ae..10d6de2 100644 --- a/client/src/components/Bookmarks/BookmarkForm/BookmarkForm.tsx +++ b/client/src/components/Bookmarks/BookmarkForm/BookmarkForm.tsx @@ -1,11 +1,31 @@ -import { useState, SyntheticEvent, Fragment, ChangeEvent, useEffect } from 'react'; +import { + useState, + SyntheticEvent, + Fragment, + ChangeEvent, + useEffect +} from 'react'; import { connect } from 'react-redux'; import ModalForm from '../../UI/Forms/ModalForm/ModalForm'; import InputGroup from '../../UI/Forms/InputGroup/InputGroup'; -import { Bookmark, Category, GlobalState, NewBookmark, NewCategory, NewNotification } from '../../../interfaces'; +import { + Bookmark, + Category, + GlobalState, + NewBookmark, + NewCategory, + NewNotification +} from '../../../interfaces'; import { ContentType } from '../Bookmarks'; -import { getCategories, addCategory, addBookmark, updateCategory, updateBookmark, createNotification } from '../../../store/actions'; +import { + getCategories, + addCategory, + addBookmark, + updateCategory, + updateBookmark, + createNotification +} from '../../../store/actions'; import Button from '../../UI/Buttons/Button/Button'; import classes from './BookmarkForm.module.css'; @@ -22,8 +42,8 @@ interface ComponentProps { id: number, formData: NewBookmark | FormData, category: { - prev: number, - curr: number + prev: number; + curr: number; } ) => void; createNotification: (notification: NewNotification) => void; @@ -34,14 +54,14 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => { const [customIcon, setCustomIcon] = useState(null); const [categoryName, setCategoryName] = useState({ name: '' - }) + }); const [formData, setFormData] = useState({ name: '', url: '', categoryId: -1, icon: '' - }) + }); // Load category data if provided for editing useEffect(() => { @@ -50,7 +70,7 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => { } else { setCategoryName({ name: '' }); } - }, [props.category]) + }, [props.category]); // Load bookmark data if provided for editing useEffect(() => { @@ -60,16 +80,16 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => { url: props.bookmark.url, categoryId: props.bookmark.categoryId, icon: props.bookmark.icon - }) + }); } else { setFormData({ name: '', url: '', categoryId: -1, icon: '' - }) + }); } - }, [props.bookmark]) + }, [props.bookmark]); const formSubmitHandler = (e: SyntheticEvent): void => { e.preventDefault(); @@ -84,7 +104,7 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => { data.append('categoryId', `${formData.categoryId}`); return data; - } + }; if (!props.category && !props.bookmark) { // Add new @@ -98,7 +118,7 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => { props.createNotification({ title: 'Error', message: 'Please select category' - }) + }); return; } @@ -108,15 +128,15 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => { } else { props.addBookmark(formData); } - + setFormData({ name: '', url: '', categoryId: formData.categoryId, icon: '' - }) + }); - setCustomIcon(null) + setCustomIcon(null); } } else { // Update @@ -128,23 +148,15 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => { // Update bookmark if (customIcon) { const data = createFormData(); - props.updateBookmark( - props.bookmark.id, - data, - { - prev: props.bookmark.categoryId, - curr: formData.categoryId - } - ) + props.updateBookmark(props.bookmark.id, data, { + prev: props.bookmark.categoryId, + curr: formData.categoryId + }); } else { - props.updateBookmark( - props.bookmark.id, - formData, - { - prev: props.bookmark.categoryId, - curr: formData.categoryId - } - ); + props.updateBookmark(props.bookmark.id, formData, { + prev: props.bookmark.categoryId, + curr: formData.categoryId + }); } setFormData({ @@ -152,36 +164,36 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => { url: '', categoryId: -1, icon: '' - }) + }); - setCustomIcon(null) + setCustomIcon(null); } props.modalHandler(); } - } + }; const inputChangeHandler = (e: ChangeEvent): void => { setFormData({ ...formData, [e.target.name]: e.target.value - }) - } + }); + }; const selectChangeHandler = (e: ChangeEvent): void => { setFormData({ ...formData, categoryId: parseInt(e.target.value) - }) - } + }); + }; const fileChangeHandler = (e: ChangeEvent): void => { if (e.target.files) { setCustomIcon(e.target.files[0]); } - } + }; - let button = + let button = ; if (!props.category && !props.bookmark) { if (props.contentType === ContentType.category) { @@ -190,9 +202,9 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => { button = ; } } else if (props.category) { - button = + button = ; } else if (props.bookmark) { - button = + button = ; } return ( @@ -200,136 +212,133 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => { modalHandler={props.modalHandler} formHandler={formSubmitHandler} > - {props.contentType === ContentType.category - ? ( - + {props.contentType === ContentType.category ? ( + + + + setCategoryName({ name: e.target.value })} + /> + + + ) : ( + + + + inputChangeHandler(e)} + /> + + + + inputChangeHandler(e)} + /> + + + {' '} + Check supported URL formats + + + + + + + + {!useCustomIcon ? ( + // mdi - + setCategoryName({ name: e.target.value })} - /> - - - ) - : ( - - - - inputChangeHandler(e)} - /> - - - - inputChangeHandler(e)} + name='icon' + id='icon' + placeholder='book-open-outline' + value={formData.icon} + onChange={e => inputChangeHandler(e)} /> - - {' '}Check supported URL formats + Use icon name from MDI. + + {' '} + Click here for reference - - - - + Switch to custom icon upload + - {!useCustomIcon - // mdi - ? ( - - inputChangeHandler(e)} - /> - - Use icon name from MDI. - - {' '}Click here for reference - - - toggleUseCustomIcon(!useCustomIcon)} - className={classes.Switch}> - Switch to custom icon upload - - ) - // custom - : ( - - fileChangeHandler(e)} - accept='.jpg,.jpeg,.png' - /> - toggleUseCustomIcon(!useCustomIcon)} - className={classes.Switch}> - Switch to MDI - - ) - } - - ) - } + ) : ( + // custom + + + fileChangeHandler(e)} + accept='.jpg,.jpeg,.png,.svg' + /> + toggleUseCustomIcon(!useCustomIcon)} + className={classes.Switch} + > + Switch to MDI + + + )} + + )} {button} - ) -} + ); +}; const mapStateToProps = (state: GlobalState) => { return { categories: state.bookmark.categories - } -} + }; +}; const dispatchMap = { getCategories, @@ -338,6 +347,6 @@ const dispatchMap = { updateCategory, updateBookmark, createNotification -} +}; -export default connect(mapStateToProps, dispatchMap)(BookmarkForm); \ No newline at end of file +export default connect(mapStateToProps, dispatchMap)(BookmarkForm); diff --git a/client/src/utility/searchQueries.json b/client/src/utility/searchQueries.json index 6e23503..e154245 100644 --- a/client/src/utility/searchQueries.json +++ b/client/src/utility/searchQueries.json @@ -1,14 +1,9 @@ { "queries": [ { - "name": "Google", - "prefix": "g", - "template": "https://www.google.com/search?q=" - }, - { - "name": "DuckDuckGo", - "prefix": "d", - "template": "https://duckduckgo.com/?q=" + "name": "Deezer", + "prefix": "dz", + "template": "https://www.deezer.com/search/" }, { "name": "Disroot", @@ -16,14 +11,14 @@ "template": "http://search.disroot.org/search?q=" }, { - "name": "YouTube", - "prefix": "yt", - "template": "https://www.youtube.com/results?search_query=" + "name": "DuckDuckGo", + "prefix": "d", + "template": "https://duckduckgo.com/?q=" }, { - "name": "Reddit", - "prefix": "r", - "template": "https://www.reddit.com/search?q=" + "name": "Google", + "prefix": "g", + "template": "https://www.google.com/search?q=" }, { "name": "IMDb", @@ -31,14 +26,29 @@ "template": "https://www.imdb.com/find?q=" }, { - "name": "The Movie Database", - "prefix": "mv", - "template": "https://www.themoviedb.org/search?query=" + "name": "Reddit", + "prefix": "r", + "template": "https://www.reddit.com/search?q=" }, { "name": "Spotify", "prefix": "sp", "template": "https://open.spotify.com/search/" + }, + { + "name": "The Movie Database", + "prefix": "mv", + "template": "https://www.themoviedb.org/search?query=" + }, + { + "name": "Tidal", + "prefix": "td", + "template": "https://listen.tidal.com/search?q=" + }, + { + "name": "YouTube", + "prefix": "yt", + "template": "https://www.youtube.com/results?search_query=" } ] -} \ No newline at end of file +} diff --git a/client/utils/dev/cli-searchQueries.js b/client/utils/dev/cli-searchQueries.js new file mode 100644 index 0000000..c431b32 --- /dev/null +++ b/client/utils/dev/cli-searchQueries.js @@ -0,0 +1,57 @@ +const queries = require('../../src/utility/searchQueries.json'); +const fs = require('fs'); +const prettier = require('prettier'); + +/** + * @description CLI tool for adding new search engines/providers. It will ensure that prefix is unique and that all entries are sorted alphabetically + * @argumens name prefix template + * @example node cli-searchQueries.js "DuckDuckGo" "d" "https://duckduckgo.com/?q=" + */ + +// Get arguments +const args = process.argv.slice(2); + +// Check arguments +if (args.length < 3) { + return console.log('Missing arguments'); +} else if (args.length > 3) { + return console.log('Too many arguments provided'); +} + +// Construct new query object +const newQuery = { + name: args[0], + prefix: args[1], + template: args[2], +}; + +// Get old queries +let rawQueries = queries.queries; +let parsedQueries = ''; + +// Check if prefix is unique +const isUnique = !rawQueries.find((query) => query.prefix == newQuery.prefix); + +if (!isUnique) { + return console.log('Prefix already exists'); +} + +// Add new query +rawQueries.push(newQuery); + +// Sort alphabetically +rawQueries = rawQueries.sort((a, b) => { + const _a = a.name.toLowerCase(); + const _b = b.name.toLowerCase(); + + if (_a < _b) return -1; + if (_a > _b) return 1; + return 0; +}); + +// Format JSON +parsedQueries = JSON.stringify(queries); +parsedQueries = prettier.format(parsedQueries, { parser: 'json' }); + +// Save file +fs.writeFileSync('../../src/utility/searchQueries.json', parsedQueries); diff --git a/controllers/apps.js b/controllers/apps.js index e4fa1bc..ab59f2c 100644 --- a/controllers/apps.js +++ b/controllers/apps.js @@ -126,8 +126,16 @@ exports.getApps = asyncWrapper(async (req, res, next) => { }); } - // Set header to fetch containers info every time - res.status(200).setHeader('Cache-Control', 'no-store').json({ + if (process.env.NODE_ENV === 'production') { + // Set header to fetch containers info every time + res.status(200).setHeader('Cache-Control', 'no-store').json({ + success: true, + data: apps + }); + return; + } + + res.status(200).json({ success: true, data: apps }); diff --git a/db.js b/db.js index 9761efe..f9cbcfd 100644 --- a/db.js +++ b/db.js @@ -6,15 +6,15 @@ const sequelize = new Sequelize({ dialect: 'sqlite', storage: './data/db.sqlite', logging: false -}) +}); const connectDB = async () => { try { await sequelize.authenticate(); logger.log('Connected to database'); - + const syncModels = true; - + if (syncModels) { logger.log('Starting model synchronization'); await sequelize.sync({ alter: true }); @@ -24,9 +24,9 @@ const connectDB = async () => { logger.log(`Unable to connect to the database: ${error.message}`, 'ERROR'); process.exit(1); } -} +}; module.exports = { connectDB, sequelize -} \ No newline at end of file +}; diff --git a/middleware/multer.js b/middleware/multer.js index b1314a9..bd493f5 100644 --- a/middleware/multer.js +++ b/middleware/multer.js @@ -12,9 +12,9 @@ const storage = multer.diskStorage({ filename: (req, file, cb) => { cb(null, Date.now() + '--' + file.originalname); } -}) +}); -const supportedTypes = ['jpg', 'jpeg', 'png']; +const supportedTypes = ['jpg', 'jpeg', 'png', 'svg', 'svg+xml']; const fileFilter = (req, file, cb) => { if (supportedTypes.includes(file.mimetype.split('/')[1])) { @@ -22,8 +22,8 @@ const fileFilter = (req, file, cb) => { } else { cb(null, false); } -} +}; const upload = multer({ storage, fileFilter }); -module.exports = upload.single('icon'); \ No newline at end of file +module.exports = upload.single('icon');