mirror of
https://github.com/pawelmalak/flame.git
synced 2025-07-23 21:29:37 +02:00
fix integrations
This commit is contained in:
parent
e5154576b4
commit
e7cd4d7705
21 changed files with 125 additions and 63 deletions
|
@ -42,7 +42,7 @@ export const AppCard = (props: Props): JSX.Element => {
|
|||
|
||||
<div className={classes.Apps}>
|
||||
{category.apps.map((app: App) => {
|
||||
const redirectUrl = urlParser(app.url)[1];
|
||||
const [displayUrl, redirectUrl] = urlParser(app.url);
|
||||
|
||||
let iconEl: JSX.Element = <Fragment></Fragment>;
|
||||
|
||||
|
@ -90,7 +90,10 @@ export const AppCard = (props: Props): JSX.Element => {
|
|||
key={`app-${app.id}`}
|
||||
>
|
||||
{app.icon && iconEl}
|
||||
{app.name}
|
||||
<div className={classes.AppCardDetails}>
|
||||
<h5>{app.name}</h5>
|
||||
<span>{displayUrl}</span>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { useSelector } from 'react-redux';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { Category } from '../../../interfaces';
|
||||
import { State } from '../../../store/reducers';
|
||||
import { Message } from '../../UI';
|
||||
import { AppCard } from '../AppCard/AppCard';
|
||||
import classes from './AppGrid.module.css';
|
||||
|
@ -20,6 +22,10 @@ export const AppGrid = (props: Props): JSX.Element => {
|
|||
fromHomepage = false,
|
||||
} = props;
|
||||
|
||||
const {
|
||||
config: { config }
|
||||
} = useSelector((state: State) => state);
|
||||
|
||||
let apps: JSX.Element;
|
||||
|
||||
if (categories.length) {
|
||||
|
@ -28,7 +34,7 @@ export const AppGrid = (props: Props): JSX.Element => {
|
|||
} else {
|
||||
apps = (
|
||||
<div className={classes.AppGrid}>
|
||||
{categories.map(
|
||||
{categories.filter((category : Category) => !config.hideEmptyCategories || category.apps.length > 0).map(
|
||||
(category: Category): JSX.Element => (
|
||||
<AppCard
|
||||
category={category}
|
||||
|
|
|
@ -30,16 +30,9 @@ export const Apps = (props: Props): JSX.Element => {
|
|||
|
||||
// Get Redux action creators
|
||||
const dispatch = useDispatch();
|
||||
const { getCategories, setEditCategory, setEditApp } =
|
||||
const { setEditCategory, setEditApp } =
|
||||
bindActionCreators(actionCreators, dispatch);
|
||||
|
||||
// Load categories if array is empty
|
||||
useEffect(() => {
|
||||
if (!categories.length) {
|
||||
getCategories();
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Form
|
||||
const [modalIsOpen, setModalIsOpen] = useState(false);
|
||||
const [formContentType, setFormContentType] = useState(ContentType.category);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { useSelector } from 'react-redux';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { Category } from '../../../interfaces';
|
||||
import { State } from '../../../store/reducers';
|
||||
import { Message } from '../../UI';
|
||||
import { BookmarkCard } from '../BookmarkCard/BookmarkCard';
|
||||
import classes from './BookmarkGrid.module.css';
|
||||
|
@ -20,6 +22,10 @@ export const BookmarkGrid = (props: Props): JSX.Element => {
|
|||
fromHomepage = false,
|
||||
} = props;
|
||||
|
||||
const {
|
||||
config: { config }
|
||||
} = useSelector((state: State) => state);
|
||||
|
||||
let bookmarks: JSX.Element;
|
||||
|
||||
if (categories.length) {
|
||||
|
@ -28,7 +34,7 @@ export const BookmarkGrid = (props: Props): JSX.Element => {
|
|||
} else {
|
||||
bookmarks = (
|
||||
<div className={classes.BookmarkGrid}>
|
||||
{categories.map(
|
||||
{categories.filter((category : Category) => !config.hideEmptyCategories || category.apps.length > 0).map(
|
||||
(category: Category): JSX.Element => (
|
||||
<BookmarkCard
|
||||
category={category}
|
||||
|
|
|
@ -30,16 +30,9 @@ export const Bookmarks = (props: Props): JSX.Element => {
|
|||
|
||||
// Get Redux action creators
|
||||
const dispatch = useDispatch();
|
||||
const { getCategories, setEditCategory, setEditBookmark } =
|
||||
const { setEditCategory, setEditBookmark } =
|
||||
bindActionCreators(actionCreators, dispatch);
|
||||
|
||||
// Load categories if array is empty
|
||||
useEffect(() => {
|
||||
if (!categories.length) {
|
||||
getCategories();
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Form
|
||||
const [modalIsOpen, setModalIsOpen] = useState(false);
|
||||
const [formContentType, setFormContentType] = useState(ContentType.category);
|
||||
|
|
|
@ -283,7 +283,7 @@ export const UISettings = (): JSX.Element => {
|
|||
</select>
|
||||
</InputGroup>
|
||||
|
||||
{/* HIDE CATEGORIES */}
|
||||
{/* HIDE BOOKMARKS */}
|
||||
<InputGroup>
|
||||
<label htmlFor="hideBookmarks">Hide bookmarks</label>
|
||||
<select
|
||||
|
@ -297,6 +297,20 @@ export const UISettings = (): JSX.Element => {
|
|||
</select>
|
||||
</InputGroup>
|
||||
|
||||
{/* HIDE EMPTY CATEGORIES */}
|
||||
<InputGroup>
|
||||
<label htmlFor="hideEmptyCategories">Hide empty categories</label>
|
||||
<select
|
||||
id="hideEmptyCategories"
|
||||
name="hideEmptyCategories"
|
||||
value={formData.hideEmptyCategories ? 1 : 0}
|
||||
onChange={(e) => inputChangeHandler(e, { isBool: true })}
|
||||
>
|
||||
<option value={1}>True</option>
|
||||
<option value={0}>False</option>
|
||||
</select>
|
||||
</InputGroup>
|
||||
|
||||
<Button>Save changes</Button>
|
||||
</form>
|
||||
);
|
||||
|
|
|
@ -16,6 +16,7 @@ export interface Config {
|
|||
searchSameTab: boolean;
|
||||
hideApps: boolean;
|
||||
hideBookmarks: boolean;
|
||||
hideEmptyCategories: boolean;
|
||||
hideSearch: boolean;
|
||||
defaultSearchProvider: string;
|
||||
dockerApps: boolean;
|
||||
|
|
|
@ -23,6 +23,7 @@ export interface OtherSettingsForm {
|
|||
hideHeader: boolean;
|
||||
hideApps: boolean;
|
||||
hideBookmarks: boolean;
|
||||
hideEmptyCategories: boolean;
|
||||
useOrdering: string;
|
||||
appsSameTab: boolean;
|
||||
bookmarksSameTab: boolean;
|
||||
|
|
|
@ -5,8 +5,6 @@ import { Action } from '../actions';
|
|||
import { categoriesReducer, CategoriesState } from './category';
|
||||
|
||||
interface AppsState extends CategoriesState {
|
||||
loading: boolean;
|
||||
errors: string | undefined;
|
||||
categories: Category[];
|
||||
categoryInEdit: Category | null;
|
||||
appInEdit: App | null;
|
||||
|
|
|
@ -5,8 +5,6 @@ import { Action } from '../actions';
|
|||
import { categoriesReducer, CategoriesState } from './category';
|
||||
|
||||
interface BookmarksState extends CategoriesState {
|
||||
loading: boolean;
|
||||
errors: string | undefined;
|
||||
categories: Category[];
|
||||
categoryInEdit: Category | null;
|
||||
bookmarkInEdit: Bookmark | null;
|
||||
|
|
|
@ -16,6 +16,7 @@ export const configTemplate: Config = {
|
|||
searchSameTab: false,
|
||||
hideApps: false,
|
||||
hideBookmarks: false,
|
||||
hideEmptyCategories: true,
|
||||
hideSearch: false,
|
||||
defaultSearchProvider: 'l',
|
||||
dockerApps: false,
|
||||
|
|
|
@ -8,6 +8,7 @@ export const otherSettingsTemplate: OtherSettingsForm = {
|
|||
hideHeader: false,
|
||||
hideApps: false,
|
||||
hideBookmarks: false,
|
||||
hideEmptyCategories: true,
|
||||
useOrdering: 'createdAt',
|
||||
appsSameTab: false,
|
||||
bookmarksSameTab: false,
|
||||
|
|
|
@ -115,7 +115,7 @@ const useDocker = async (apps) => {
|
|||
const icons = labels['flame.icon'] ? labels['flame.icon'].split(';') : [];
|
||||
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
const category = categoriesLabels[i] ? categories.find(category => category.name.toUpperCase() === categoriesLabels[i].toUpperCase()) : dockerDefaultCategory;
|
||||
let category = categoriesLabels[i] ? categories.find(category => category.name.toUpperCase() === categoriesLabels[i].toUpperCase()) : dockerDefaultCategory;
|
||||
if (!category) {
|
||||
category = await createNewCategory(categoriesLabels[i]);
|
||||
if (category) {
|
||||
|
@ -129,7 +129,7 @@ const useDocker = async (apps) => {
|
|||
name: names[i] || names[0],
|
||||
url: urls[i] || urls[0],
|
||||
icon: icons[i] || 'docker',
|
||||
category: category.id,
|
||||
categoryId: category.id,
|
||||
orderId: orders[i] || 500,
|
||||
});
|
||||
}
|
||||
|
@ -141,7 +141,6 @@ const useDocker = async (apps) => {
|
|||
await app.update({ isPinned: false });
|
||||
}
|
||||
}
|
||||
|
||||
for (const item of dockerApps) {
|
||||
// If app already exists, update it
|
||||
if (apps.some((app) => app.name === item.name)) {
|
||||
|
|
|
@ -67,7 +67,7 @@ const useKubernetes = async (apps) => {
|
|||
const icons = annotations['flame.pawelmalak/icon'] ? annotations['flame.pawelmalak/icon'].split(';') : [];
|
||||
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
const category = categoriesLabels[i] ? categories.find(category => category.name.toUpperCase() === categoriesLabels[i].toUpperCase()) : kubernetesDefaultCategory;
|
||||
let category = categoriesLabels[i] ? categories.find(category => category.name.toUpperCase() === categoriesLabels[i].toUpperCase()) : kubernetesDefaultCategory;
|
||||
if (!category) {
|
||||
category = await createNewCategory(categoriesLabels[i]);
|
||||
if (category) {
|
||||
|
@ -81,7 +81,7 @@ const useKubernetes = async (apps) => {
|
|||
name: names[i] || names[0],
|
||||
url: urls[i] || urls[0],
|
||||
icon: icons[i] || 'kubernetes',
|
||||
category: category.id,
|
||||
categoryId: category.id,
|
||||
orderId: orders[i] || 500,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -10,12 +10,11 @@ const { useKubernetes, useDocker } = require('./docker');
|
|||
// @access Public
|
||||
const getAllApps = asyncWrapper(async (req, res, next) => {
|
||||
const {
|
||||
useOrdering: orderType,
|
||||
dockerApps: useDockerAPI,
|
||||
kubernetesApps: useKubernetesAPI,
|
||||
useOrdering: orderType
|
||||
} = await loadConfig();
|
||||
|
||||
let apps = await loadIntegrationsApps();
|
||||
// Load apps to create/update apps from integrations (Docker, Kubernetes, etc.)
|
||||
await initIntegrationsApps();
|
||||
|
||||
// apps visibility
|
||||
const where = req.isAuthenticated ? {} : { isPublic: true };
|
||||
|
@ -44,26 +43,4 @@ const getAllApps = asyncWrapper(async (req, res, next) => {
|
|||
});
|
||||
});
|
||||
|
||||
const loadIntegrationsApps = asyncWrapper(async () => {
|
||||
const {
|
||||
dockerApps: useDockerAPI,
|
||||
kubernetesApps: useKubernetesAPI,
|
||||
} = await loadConfig();
|
||||
|
||||
let apps;
|
||||
|
||||
if (useDockerAPI) {
|
||||
await useDocker(apps);
|
||||
}
|
||||
|
||||
if (useKubernetesAPI) {
|
||||
await useKubernetes(apps);
|
||||
}
|
||||
|
||||
return apps;
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
getAllApps,
|
||||
loadIntegrationsApps
|
||||
}
|
||||
module.exports = getAllApps;
|
||||
|
|
42
controllers/apps/getIntegrationsApps.js
Normal file
42
controllers/apps/getIntegrationsApps.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
const asyncWrapper = require('../../middleware/asyncWrapper');
|
||||
const App = require('../../models/App');
|
||||
const { Sequelize } = require('sequelize');
|
||||
const loadConfig = require('../../utils/loadConfig');
|
||||
|
||||
const { useKubernetes, useDocker } = require('./docker');
|
||||
|
||||
// @desc Get all apps
|
||||
// @route GET /api/integrationsApps
|
||||
// @access Public
|
||||
const getIntegrationsApps = asyncWrapper(async (req, res, next) => {
|
||||
const {
|
||||
useOrdering: orderType,
|
||||
dockerApps: useDockerAPI,
|
||||
kubernetesApps: useKubernetesAPI,
|
||||
} = await loadConfig();
|
||||
|
||||
let apps;
|
||||
|
||||
if (useDockerAPI) {
|
||||
await useDocker(apps);
|
||||
}
|
||||
|
||||
if (useKubernetesAPI) {
|
||||
await useKubernetes(apps);
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
// Set header to fetch containers info every time
|
||||
return res.status(200).setHeader('Cache-Control', 'no-store').json({
|
||||
success: true,
|
||||
data: apps,
|
||||
});
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
data: apps,
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = getIntegrationsApps;
|
|
@ -4,5 +4,5 @@ module.exports = {
|
|||
deleteApp: require('./deleteApp'),
|
||||
updateApp: require('./updateApp'),
|
||||
reorderApps: require('./reorderApps'),
|
||||
getAllApps: require('./getAllApps').getAllApps,
|
||||
getAllApps: require('./getAllApps'),
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@ const App = require('../../models/App');
|
|||
const Bookmark = require('../../models/Bookmark');
|
||||
const { Sequelize } = require('sequelize');
|
||||
const loadConfig = require('../../utils/loadConfig');
|
||||
const loadIntegrationsApps = require('../apps/getAllApps').loadIntegrationsApps;
|
||||
const initIntegrationsApps = require('../../utils/init/initIntegrationsApps');
|
||||
|
||||
// @desc Get all categories
|
||||
// @route GET /api/categories
|
||||
|
@ -12,8 +12,8 @@ const loadIntegrationsApps = require('../apps/getAllApps').loadIntegrationsApps;
|
|||
const getAllCategories = asyncWrapper(async (req, res, next) => {
|
||||
const { useOrdering: orderType } = await loadConfig();
|
||||
|
||||
// Load apps to create apps from integrations (Docker, Kubernetes, etc.)
|
||||
await loadIntegrationsApps();
|
||||
// Load apps to create/update apps from integrations (Docker, Kubernetes, etc.)
|
||||
await initIntegrationsApps();
|
||||
|
||||
let categories;
|
||||
let output;
|
||||
|
|
|
@ -13,6 +13,7 @@ const Sockets = require('./Sockets');
|
|||
|
||||
// Utils
|
||||
const initApp = require('./utils/init');
|
||||
const initIntegrationsApps = require('./utils/init/initIntegrationsApps');
|
||||
const Logger = require('./utils/Logger');
|
||||
const logger = new Logger();
|
||||
|
||||
|
@ -24,6 +25,9 @@ const logger = new Logger();
|
|||
await connectDB();
|
||||
await associateModels();
|
||||
|
||||
// Load apps to create/update apps from integrations (Docker, Kubernetes, etc.)
|
||||
await initIntegrationsApps();
|
||||
|
||||
// Create server for Express API and WebSockets
|
||||
const server = http.createServer();
|
||||
server.on('request', api);
|
||||
|
|
24
utils/init/initIntegrationsApps.js
Normal file
24
utils/init/initIntegrationsApps.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
const { useKubernetes, useDocker } = require('../../controllers/apps/docker');
|
||||
const asyncWrapper = require('../../middleware/asyncWrapper');
|
||||
const loadConfig = require('../loadConfig');
|
||||
|
||||
const loadIntegrationsApps = asyncWrapper(async () => {
|
||||
const {
|
||||
dockerApps: useDockerAPI,
|
||||
kubernetesApps: useKubernetesAPI,
|
||||
} = await loadConfig();
|
||||
|
||||
let apps;
|
||||
|
||||
if (useDockerAPI) {
|
||||
await useDocker(apps);
|
||||
}
|
||||
|
||||
if (useKubernetesAPI) {
|
||||
await useKubernetes(apps);
|
||||
}
|
||||
|
||||
return apps;
|
||||
});
|
||||
|
||||
module.exports = loadIntegrationsApps;
|
|
@ -14,6 +14,7 @@
|
|||
"searchSameTab": false,
|
||||
"hideApps": false,
|
||||
"hideBookmarks": false,
|
||||
"hideEmptyCategories": true,
|
||||
"hideSearch": false,
|
||||
"defaultSearchProvider": "l",
|
||||
"dockerApps": false,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue