Pushed version 1.6.2. Small formatting fixes

This commit is contained in:
unknown 2021-08-06 10:36:05 +02:00
parent 1962af01e6
commit a01661d0d5
6 changed files with 123 additions and 78 deletions

1
.prettierignore Normal file
View File

@ -0,0 +1 @@
*.md

View File

@ -1,3 +1,7 @@
### v1.6.2 (2021-08-06)
- Fixed changelog link
- Added support for Docker API ([#14](https://github.com/pawelmalak/flame/issues/14))
### v1.6.1 (2021-07-28)
- Added option to upload custom icons for bookmarks ([#52](https://github.com/pawelmalak/flame/issues/52))
- Fixed custom icons not updating ([#58](https://github.com/pawelmalak/flame/issues/58))

View File

@ -1 +1 @@
REACT_APP_VERSION=1.6.1
REACT_APP_VERSION=1.6.2

View File

@ -2,10 +2,20 @@ import { useState, useEffect, ChangeEvent, FormEvent } from 'react';
// Redux
import { connect } from 'react-redux';
import { createNotification, updateConfig, sortApps, sortCategories } from '../../../store/actions';
import {
createNotification,
updateConfig,
sortApps,
sortCategories
} from '../../../store/actions';
// Typescript
import { GlobalState, NewNotification, Query, SettingsForm } from '../../../interfaces';
import {
GlobalState,
NewNotification,
Query,
SettingsForm
} from '../../../interfaces';
// UI
import InputGroup from '../../UI/Forms/InputGroup/InputGroup';
@ -41,9 +51,9 @@ const OtherSettings = (props: ComponentProps): JSX.Element => {
appsSameTab: 0,
bookmarksSameTab: 0,
searchSameTab: 0,
dockerApps:1,
dockerApps: 1,
unpinStoppedApps: 1
})
});
// Get config
useEffect(() => {
@ -60,9 +70,9 @@ const OtherSettings = (props: ComponentProps): JSX.Element => {
appsSameTab: searchConfig('appsSameTab', 0),
bookmarksSameTab: searchConfig('bookmarksSameTab', 0),
searchSameTab: searchConfig('searchSameTab', 0),
dockerApps: searchConfig('dockerApps', 1),
unpinStoppedApps: searchConfig('unpinStoppedApps', 1)
})
dockerApps: searchConfig('dockerApps', 0),
unpinStoppedApps: searchConfig('unpinStoppedApps', 0)
});
}, [props.loading]);
// Form handler
@ -78,10 +88,13 @@ const OtherSettings = (props: ComponentProps): JSX.Element => {
// Sort apps and categories with new settings
props.sortApps();
props.sortCategories();
}
};
// Input handler
const inputChangeHandler = (e: ChangeEvent<HTMLInputElement | HTMLSelectElement>, isNumber?: boolean) => {
const inputChangeHandler = (
e: ChangeEvent<HTMLInputElement | HTMLSelectElement>,
isNumber?: boolean
) => {
let value: string | number = e.target.value;
if (isNumber) {
@ -91,11 +104,11 @@ const OtherSettings = (props: ComponentProps): JSX.Element => {
setFormData({
...formData,
[e.target.name]: value
})
}
});
};
return (
<form onSubmit={(e) => formSubmitHandler(e)}>
<form onSubmit={e => formSubmitHandler(e)}>
{/* OTHER OPTIONS */}
<h2 className={classes.SettingsSection}>Miscellaneous</h2>
<InputGroup>
@ -106,31 +119,35 @@ const OtherSettings = (props: ComponentProps): JSX.Element => {
name='customTitle'
placeholder='Flame'
value={formData.customTitle}
onChange={(e) => inputChangeHandler(e)}
onChange={e => inputChangeHandler(e)}
/>
</InputGroup>
{/* BEAHVIOR OPTIONS */}
<h2 className={classes.SettingsSection}>App Behavior</h2>
<InputGroup>
<label htmlFor='pinAppsByDefault'>Pin new applications by default</label>
<label htmlFor='pinAppsByDefault'>
Pin new applications by default
</label>
<select
id='pinAppsByDefault'
name='pinAppsByDefault'
value={formData.pinAppsByDefault}
onChange={(e) => inputChangeHandler(e, true)}
onChange={e => inputChangeHandler(e, true)}
>
<option value={1}>True</option>
<option value={0}>False</option>
</select>
</InputGroup>
<InputGroup>
<label htmlFor='pinCategoriesByDefault'>Pin new categories by default</label>
<label htmlFor='pinCategoriesByDefault'>
Pin new categories by default
</label>
<select
id='pinCategoriesByDefault'
name='pinCategoriesByDefault'
value={formData.pinCategoriesByDefault}
onChange={(e) => inputChangeHandler(e, true)}
onChange={e => inputChangeHandler(e, true)}
>
<option value={1}>True</option>
<option value={0}>False</option>
@ -142,7 +159,7 @@ const OtherSettings = (props: ComponentProps): JSX.Element => {
id='useOrdering'
name='useOrdering'
value={formData.useOrdering}
onChange={(e) => inputChangeHandler(e)}
onChange={e => inputChangeHandler(e)}
>
<option value='createdAt'>By creation date</option>
<option value='name'>Alphabetical order</option>
@ -155,18 +172,22 @@ const OtherSettings = (props: ComponentProps): JSX.Element => {
id='defaultSearchProvider'
name='defaultSearchProvider'
value={formData.defaultSearchProvider}
onChange={(e) => inputChangeHandler(e)}
onChange={e => inputChangeHandler(e)}
>
{queries.map((query: Query) => (<option value={query.prefix}>{query.name}</option>))}
{queries.map((query: Query) => (
<option value={query.prefix}>{query.name}</option>
))}
</select>
</InputGroup>
<InputGroup>
<label htmlFor='searchSameTab'>Open search results in the same tab</label>
<label htmlFor='searchSameTab'>
Open search results in the same tab
</label>
<select
id='searchSameTab'
name='searchSameTab'
value={formData.searchSameTab}
onChange={(e) => inputChangeHandler(e, true)}
onChange={e => inputChangeHandler(e, true)}
>
<option value={1}>True</option>
<option value={0}>False</option>
@ -178,7 +199,7 @@ const OtherSettings = (props: ComponentProps): JSX.Element => {
id='appsSameTab'
name='appsSameTab'
value={formData.appsSameTab}
onChange={(e) => inputChangeHandler(e, true)}
onChange={e => inputChangeHandler(e, true)}
>
<option value={1}>True</option>
<option value={0}>False</option>
@ -190,7 +211,7 @@ const OtherSettings = (props: ComponentProps): JSX.Element => {
id='bookmarksSameTab'
name='bookmarksSameTab'
value={formData.bookmarksSameTab}
onChange={(e) => inputChangeHandler(e, true)}
onChange={e => inputChangeHandler(e, true)}
>
<option value={1}>True</option>
<option value={0}>False</option>
@ -205,7 +226,7 @@ const OtherSettings = (props: ComponentProps): JSX.Element => {
id='hideSearch'
name='hideSearch'
value={formData.hideSearch}
onChange={(e) => inputChangeHandler(e, true)}
onChange={e => inputChangeHandler(e, true)}
>
<option value={1}>True</option>
<option value={0}>False</option>
@ -217,7 +238,7 @@ const OtherSettings = (props: ComponentProps): JSX.Element => {
id='hideHeader'
name='hideHeader'
value={formData.hideHeader}
onChange={(e) => inputChangeHandler(e, true)}
onChange={e => inputChangeHandler(e, true)}
>
<option value={1}>True</option>
<option value={0}>False</option>
@ -229,7 +250,7 @@ const OtherSettings = (props: ComponentProps): JSX.Element => {
id='hideApps'
name='hideApps'
value={formData.hideApps}
onChange={(e) => inputChangeHandler(e, true)}
onChange={e => inputChangeHandler(e, true)}
>
<option value={1}>True</option>
<option value={0}>False</option>
@ -241,12 +262,14 @@ const OtherSettings = (props: ComponentProps): JSX.Element => {
id='hideCategories'
name='hideCategories'
value={formData.hideCategories}
onChange={(e) => inputChangeHandler(e, true)}
onChange={e => inputChangeHandler(e, true)}
>
<option value={1}>True</option>
<option value={0}>False</option>
</select>
</InputGroup>
{/* DOCKER SETTINGS */}
<h2 className={classes.SettingsSection}>Docker</h2>
<InputGroup>
<label htmlFor='dockerApps'>Use Docker API</label>
@ -254,40 +277,42 @@ const OtherSettings = (props: ComponentProps): JSX.Element => {
id='dockerApps'
name='dockerApps'
value={formData.dockerApps}
onChange={(e) => inputChangeHandler(e, true)}
onChange={e => inputChangeHandler(e, true)}
>
<option value={1}>True</option>
<option value={0}>False</option>
</select>
</InputGroup>
<InputGroup>
<label htmlFor='unpinStoppedApps'>Unpin stopped containers / other apps</label>
<label htmlFor='unpinStoppedApps'>
Unpin stopped containers / other apps
</label>
<select
id='unpinStoppedApps'
name='unpinStoppedApps'
value={formData.unpinStoppedApps}
onChange={(e) => inputChangeHandler(e, true)}
onChange={e => inputChangeHandler(e, true)}
>
<option value={1}>True</option>
<option value={0}>False</option>
</select>
</InputGroup>
<Button>Save changes</Button>
<Button>Save changes</Button>
</form>
)
}
);
};
const mapStateToProps = (state: GlobalState) => {
return {
loading: state.config.loading
}
}
};
};
const actions = {
createNotification,
updateConfig,
sortApps,
sortCategories
}
};
export default connect(mapStateToProps, actions)(OtherSettings);

View File

@ -28,7 +28,7 @@ exports.createApp = asyncWrapper(async (req, res, next) => {
app = await App.create({
..._body,
isPinned: true
})
});
} else {
app = await App.create(req.body);
}
@ -37,8 +37,8 @@ exports.createApp = asyncWrapper(async (req, res, next) => {
res.status(201).json({
success: true,
data: app
})
})
});
});
// @desc Get all apps
// @route GET /api/apps
@ -58,37 +58,45 @@ exports.getApps = asyncWrapper(async (req, res, next) => {
const orderType = useOrdering ? useOrdering.value : 'createdAt';
let apps;
if (useDockerApi && useDockerApi.value==1) {
if (useDockerApi && useDockerApi.value == 1) {
let containers = null;
try {
let {data} = await axios.get('http://localhost/containers/json?{"status":["running"]}', {
socketPath: '/var/run/docker.sock'
});
containers = data;
} catch{logger.log("Can't connect to the docker socket","ERROR")}
let { data } = await axios.get(
'http://localhost/containers/json?{"status":["running"]}',
{
socketPath: '/var/run/docker.sock'
}
);
containers = data;
} catch {
logger.log("Can't connect to the docker socket", 'ERROR');
}
if (containers) {
apps = await App.findAll({
order: [[ orderType, 'ASC' ]]
order: [[orderType, 'ASC']]
});
containers = containers.filter((e) => Object.keys(e.Labels).length !== 0);
containers = containers.filter(e => Object.keys(e.Labels).length !== 0);
const dockerApps = [];
for (const container of containers) {
const labels = container.Labels;
if ('flame.name' in labels && 'flame.url' in labels && /^app/.test(labels['flame.type'])) {
if (
'flame.name' in labels &&
'flame.url' in labels &&
/^app/.test(labels['flame.type'])
) {
dockerApps.push({
name: labels['flame.name'],
url: labels['flame.url'],
icon: labels['flame.icon'] || 'docker'
})
});
}
}
if (unpinStoppedApps && unpinStoppedApps.value==1) {
if (unpinStoppedApps && unpinStoppedApps.value == 1) {
for (const app of apps) {
await app.update({ isPinned: false });
}
@ -97,12 +105,12 @@ exports.getApps = asyncWrapper(async (req, res, next) => {
for (const item of dockerApps) {
if (apps.some(app => app.name === item.name)) {
const app = apps.filter(e => e.name === item.name)[0];
await app.update({ ...item,isPinned: true });
await app.update({ ...item, isPinned: true });
} else {
await App.create({
...item,
isPinned: true
})
});
}
}
}
@ -110,20 +118,20 @@ exports.getApps = asyncWrapper(async (req, res, next) => {
if (orderType == 'name') {
apps = await App.findAll({
order: [[ Sequelize.fn('lower', Sequelize.col('name')), 'ASC' ]]
order: [[Sequelize.fn('lower', Sequelize.col('name')), 'ASC']]
});
} else {
apps = await App.findAll({
order: [[ orderType, 'ASC' ]]
order: [[orderType, 'ASC']]
});
}
// Set header to fetch containers info every time
res.status(200).setHeader('Cache-Control','no-store').json({
res.status(200).setHeader('Cache-Control', 'no-store').json({
success: true,
data: apps
})
})
});
});
// @desc Get single app
// @route GET /api/apps/:id
@ -134,14 +142,16 @@ exports.getApp = asyncWrapper(async (req, res, next) => {
});
if (!app) {
return next(new ErrorResponse(`App with id of ${req.params.id} was not found`, 404));
return next(
new ErrorResponse(`App with id of ${req.params.id} was not found`, 404)
);
}
res.status(200).json({
success: true,
data: app
})
})
});
});
// @desc Update app
// @route PUT /api/apps/:id
@ -152,7 +162,9 @@ exports.updateApp = asyncWrapper(async (req, res, next) => {
});
if (!app) {
return next(new ErrorResponse(`App with id of ${req.params.id} was not found`, 404));
return next(
new ErrorResponse(`App with id of ${req.params.id} was not found`, 404)
);
}
let _body = { ...req.body };
@ -166,8 +178,8 @@ exports.updateApp = asyncWrapper(async (req, res, next) => {
res.status(200).json({
success: true,
data: app
})
})
});
});
// @desc Delete app
// @route DELETE /api/apps/:id
@ -175,26 +187,29 @@ exports.updateApp = asyncWrapper(async (req, res, next) => {
exports.deleteApp = asyncWrapper(async (req, res, next) => {
await App.destroy({
where: { id: req.params.id }
})
});
res.status(200).json({
success: true,
data: {}
})
})
});
});
// @desc Reorder apps
// @route PUT /api/apps/0/reorder
// @access Public
exports.reorderApps = asyncWrapper(async (req, res, next) => {
req.body.apps.forEach(async ({ id, orderId }) => {
await App.update({ orderId }, {
where: { id }
})
})
await App.update(
{ orderId },
{
where: { id }
}
);
});
res.status(200).json({
success: true,
data: {}
})
})
});
});

View File

@ -66,11 +66,11 @@
},
{
"key": "dockerApps",
"value": true
"value": false
},
{
"key": "unpinStoppedApps",
"value": true
"value": false
}
]
}