mirror of
https://github.com/pawelmalak/flame.git
synced 2025-07-21 20:39:36 +02:00
Case-insensitive sorting. App version checking
This commit is contained in:
parent
e884c84aa8
commit
9a1ec76ffd
15 changed files with 104 additions and 11 deletions
0
._env
0
._env
2
.env
Normal file
2
.env
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
PORT=5005
|
||||||
|
NODE_ENV=development
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,2 @@
|
||||||
node_modules/
|
node_modules/
|
||||||
data/
|
data/
|
||||||
.env
|
|
1
client/.env
Normal file
1
client/.env
Normal file
|
@ -0,0 +1 @@
|
||||||
|
REACT_APP_VERSION=1.3.2
|
|
@ -5,6 +5,10 @@ import { getConfig, setTheme } from './store/actions';
|
||||||
import { store } from './store/store';
|
import { store } from './store/store';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
|
|
||||||
|
// Utils
|
||||||
|
import { checkVersion } from './utility';
|
||||||
|
|
||||||
|
// Routes
|
||||||
import Home from './components/Home/Home';
|
import Home from './components/Home/Home';
|
||||||
import Apps from './components/Apps/Apps';
|
import Apps from './components/Apps/Apps';
|
||||||
import Settings from './components/Settings/Settings';
|
import Settings from './components/Settings/Settings';
|
||||||
|
@ -14,10 +18,14 @@ import NotificationCenter from './components/NotificationCenter/NotificationCent
|
||||||
// Get config pairs from database
|
// Get config pairs from database
|
||||||
store.dispatch<any>(getConfig());
|
store.dispatch<any>(getConfig());
|
||||||
|
|
||||||
|
// Set theme
|
||||||
if (localStorage.theme) {
|
if (localStorage.theme) {
|
||||||
store.dispatch<any>(setTheme(localStorage.theme));
|
store.dispatch<any>(setTheme(localStorage.theme));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for updates
|
||||||
|
checkVersion();
|
||||||
|
|
||||||
const App = (): JSX.Element => {
|
const App = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
.AppVersion {
|
||||||
|
color: var(--color-primary);
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.AppVersion a {
|
||||||
|
color: var(--color-accent);
|
||||||
|
}
|
25
client/src/components/Settings/AppDetails/AppDetails.tsx
Normal file
25
client/src/components/Settings/AppDetails/AppDetails.tsx
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { Fragment } from 'react';
|
||||||
|
|
||||||
|
import classes from './AppDetails.module.css';
|
||||||
|
import Button from '../../UI/Buttons/Button/Button';
|
||||||
|
import { checkVersion } from '../../../utility';
|
||||||
|
|
||||||
|
const AppDetails = (): JSX.Element => {
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<p className={classes.AppVersion}>
|
||||||
|
<a
|
||||||
|
href='https://github.com/pawelmalak/flame'
|
||||||
|
target='_blank'
|
||||||
|
rel='noreferrer'>
|
||||||
|
Flame
|
||||||
|
</a>
|
||||||
|
{' '}
|
||||||
|
version {process.env.REACT_APP_VERSION}
|
||||||
|
</p>
|
||||||
|
<Button click={() => checkVersion(true)}>Check for updates</Button>
|
||||||
|
</Fragment>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AppDetails;
|
|
@ -1,12 +1,14 @@
|
||||||
import { NavLink, Link, Switch, Route, withRouter } from 'react-router-dom';
|
import { NavLink, Link, Switch, Route } from 'react-router-dom';
|
||||||
|
|
||||||
import classes from './Settings.module.css';
|
import classes from './Settings.module.css';
|
||||||
|
|
||||||
import { Container } from '../UI/Layout/Layout';
|
import { Container } from '../UI/Layout/Layout';
|
||||||
import Headline from '../UI/Headlines/Headline/Headline';
|
import Headline from '../UI/Headlines/Headline/Headline';
|
||||||
|
|
||||||
import Themer from '../Themer/Themer';
|
import Themer from '../Themer/Themer';
|
||||||
import WeatherSettings from './WeatherSettings/WeatherSettings';
|
import WeatherSettings from './WeatherSettings/WeatherSettings';
|
||||||
import OtherSettings from './OtherSettings/OtherSettings';
|
import OtherSettings from './OtherSettings/OtherSettings';
|
||||||
|
import AppDetails from './AppDetails/AppDetails';
|
||||||
|
|
||||||
const Settings = (): JSX.Element => {
|
const Settings = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
|
@ -38,12 +40,20 @@ const Settings = (): JSX.Element => {
|
||||||
to='/settings/other'>
|
to='/settings/other'>
|
||||||
Other
|
Other
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
<NavLink
|
||||||
|
className={classes.SettingsNavLink}
|
||||||
|
activeClassName={classes.SettingsNavLinkActive}
|
||||||
|
exact
|
||||||
|
to='/settings/app'>
|
||||||
|
App
|
||||||
|
</NavLink>
|
||||||
</nav>
|
</nav>
|
||||||
<section className={classes.SettingsContent}>
|
<section className={classes.SettingsContent}>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path='/settings' component={Themer} />
|
<Route exact path='/settings' component={Themer} />
|
||||||
<Route path='/settings/weather' component={WeatherSettings} />
|
<Route path='/settings/weather' component={WeatherSettings} />
|
||||||
<Route path='/settings/other' component={OtherSettings} />
|
<Route path='/settings/other' component={OtherSettings} />
|
||||||
|
<Route path='/settings/app' component={AppDetails} />
|
||||||
</Switch>
|
</Switch>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
@ -51,4 +61,4 @@ const Settings = (): JSX.Element => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withRouter(Settings);
|
export default Settings;
|
|
@ -6,8 +6,7 @@
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Button:hover,
|
.Button:hover {
|
||||||
.Button:focus {
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: var(--color-accent);
|
background-color: var(--color-accent);
|
||||||
color: var(--color-background);
|
color: var(--color-background);
|
||||||
|
|
|
@ -2,10 +2,20 @@ import classes from './Button.module.css';
|
||||||
|
|
||||||
interface ComponentProps {
|
interface ComponentProps {
|
||||||
children: string;
|
children: string;
|
||||||
|
click?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Button = (props: ComponentProps): JSX.Element => {
|
const Button = (props: ComponentProps): JSX.Element => {
|
||||||
return <button className={classes.Button}>{props.children}</button>
|
const {
|
||||||
|
children,
|
||||||
|
click
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button className={classes.Button} onClick={click ? click : () => {}} >
|
||||||
|
{children}
|
||||||
|
</button>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Button;
|
export default Button;
|
27
client/src/utility/checkVersion.ts
Normal file
27
client/src/utility/checkVersion.ts
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import axios from 'axios';
|
||||||
|
import { store } from '../store/store';
|
||||||
|
import { createNotification } from '../store/actions';
|
||||||
|
|
||||||
|
export const checkVersion = async (isForced: boolean = false) => {
|
||||||
|
try {
|
||||||
|
const res = await axios.get<string>('https://raw.githubusercontent.com/pawelmalak/flame/master/client/.env');
|
||||||
|
|
||||||
|
const githubVersion = res.data
|
||||||
|
.split('\n')
|
||||||
|
.map(pair => pair.split('='))[0][1];
|
||||||
|
|
||||||
|
if (githubVersion !== process.env.REACT_APP_VERSION) {
|
||||||
|
store.dispatch<any>(createNotification({
|
||||||
|
title: 'Info',
|
||||||
|
message: 'New version is available!'
|
||||||
|
}))
|
||||||
|
} else if (isForced) {
|
||||||
|
store.dispatch<any>(createNotification({
|
||||||
|
title: 'Info',
|
||||||
|
message: 'You are using the latest version!'
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
export * from './iconParser';
|
export * from './iconParser';
|
||||||
export * from './urlParser';
|
export * from './urlParser';
|
||||||
export * from './searchConfig';
|
export * from './searchConfig';
|
||||||
|
export * from './checkVersion';
|
|
@ -2,6 +2,7 @@ const asyncWrapper = require('../middleware/asyncWrapper');
|
||||||
const ErrorResponse = require('../utils/ErrorResponse');
|
const ErrorResponse = require('../utils/ErrorResponse');
|
||||||
const App = require('../models/App');
|
const App = require('../models/App');
|
||||||
const Config = require('../models/Config');
|
const Config = require('../models/Config');
|
||||||
|
const { Sequelize } = require('sequelize');
|
||||||
|
|
||||||
// @desc Create new app
|
// @desc Create new app
|
||||||
// @route POST /api/apps
|
// @route POST /api/apps
|
||||||
|
@ -36,7 +37,7 @@ exports.createApp = asyncWrapper(async (req, res, next) => {
|
||||||
// @access Public
|
// @access Public
|
||||||
exports.getApps = asyncWrapper(async (req, res, next) => {
|
exports.getApps = asyncWrapper(async (req, res, next) => {
|
||||||
const apps = await App.findAll({
|
const apps = await App.findAll({
|
||||||
order: [['name', 'ASC']]
|
order: [[ Sequelize.fn('lower', Sequelize.col('name')), 'ASC' ]]
|
||||||
});
|
});
|
||||||
|
|
||||||
res.status(200).json({
|
res.status(200).json({
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
const asyncWrapper = require('../middleware/asyncWrapper');
|
const asyncWrapper = require('../middleware/asyncWrapper');
|
||||||
const ErrorResponse = require('../utils/ErrorResponse');
|
const ErrorResponse = require('../utils/ErrorResponse');
|
||||||
const Bookmark = require('../models/Bookmark');
|
const Bookmark = require('../models/Bookmark');
|
||||||
|
const { Sequelize } = require('sequelize');
|
||||||
|
|
||||||
// @desc Create new bookmark
|
// @desc Create new bookmark
|
||||||
// @route POST /api/bookmarks
|
// @route POST /api/bookmarks
|
||||||
|
@ -19,7 +20,7 @@ exports.createBookmark = asyncWrapper(async (req, res, next) => {
|
||||||
// @access Public
|
// @access Public
|
||||||
exports.getBookmarks = asyncWrapper(async (req, res, next) => {
|
exports.getBookmarks = asyncWrapper(async (req, res, next) => {
|
||||||
const bookmarks = await Bookmark.findAll({
|
const bookmarks = await Bookmark.findAll({
|
||||||
order: [['name', 'ASC']]
|
order: [[ Sequelize.fn('lower', Sequelize.col('name')), 'ASC' ]]
|
||||||
});
|
});
|
||||||
|
|
||||||
res.status(200).json({
|
res.status(200).json({
|
||||||
|
|
|
@ -3,6 +3,7 @@ const ErrorResponse = require('../utils/ErrorResponse');
|
||||||
const Category = require('../models/Category');
|
const Category = require('../models/Category');
|
||||||
const Bookmark = require('../models/Bookmark');
|
const Bookmark = require('../models/Bookmark');
|
||||||
const Config = require('../models/Config');
|
const Config = require('../models/Config');
|
||||||
|
const { Sequelize } = require('sequelize')
|
||||||
|
|
||||||
// @desc Create new category
|
// @desc Create new category
|
||||||
// @route POST /api/categories
|
// @route POST /api/categories
|
||||||
|
@ -41,7 +42,7 @@ exports.getCategories = asyncWrapper(async (req, res, next) => {
|
||||||
model: Bookmark,
|
model: Bookmark,
|
||||||
as: 'bookmarks'
|
as: 'bookmarks'
|
||||||
}],
|
}],
|
||||||
order: [['name', 'ASC']]
|
order: [[ Sequelize.fn('lower', Sequelize.col('Category.name')), 'ASC' ]]
|
||||||
});
|
});
|
||||||
|
|
||||||
res.status(200).json({
|
res.status(200).json({
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue