unfinished work that adds loading the list of apps dynamically
This commit is contained in:
parent
14b4a58d46
commit
86192f28fd
10 changed files with 101 additions and 65 deletions
|
|
@ -5,28 +5,24 @@ export const appAccessList = [
|
|||
name: 'wekan',
|
||||
image: '/assets/wekan.svg',
|
||||
label: 'Wekan',
|
||||
defaultSubdomain: 'wekan.{domain}',
|
||||
documentationUrl: 'https://github.com/wekan/wekan/wiki',
|
||||
},
|
||||
{
|
||||
name: 'wordpress',
|
||||
image: '/assets/wordpress.svg',
|
||||
label: 'Wordpress',
|
||||
defaultSubdomain: 'www.{domain}',
|
||||
documentationUrl: 'https://wordpress.org/support/',
|
||||
},
|
||||
{
|
||||
name: 'nextcloud',
|
||||
image: '/assets/nextcloud.svg',
|
||||
label: 'Nextcloud',
|
||||
defaultSubdomain: 'files.{domain}',
|
||||
documentationUrl: 'https://docs.nextcloud.com/server/latest/user_manual/en/',
|
||||
},
|
||||
{
|
||||
name: 'zulip',
|
||||
image: '/assets/zulip.svg',
|
||||
label: 'Zulip',
|
||||
defaultSubdomain: 'zulip.{domain}',
|
||||
documentationUrl: 'https://docs.zulip.com/help/',
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import _ from 'lodash';
|
|||
import { App, useApps } from 'src/services/apps';
|
||||
import { Modal } from 'src/components';
|
||||
import { Input } from 'src/components/Form';
|
||||
import { appAccessList } from 'src/components/UserModal/consts';
|
||||
import { AppInstallModalProps } from './types';
|
||||
import { initialAppForm, initialCode } from './consts';
|
||||
|
||||
|
|
@ -16,8 +15,6 @@ export const AppInstallModal = ({ open, onClose, appSlug }: AppInstallModalProps
|
|||
defaultValues: initialAppForm,
|
||||
});
|
||||
|
||||
const getDefaultSubdomain = () => _.get(_.find(appAccessList, ['name', appSlug]), 'defaultSubdomain', '');
|
||||
|
||||
useEffect(() => {
|
||||
if (appSlug) {
|
||||
loadApp(appSlug);
|
||||
|
|
@ -32,11 +29,11 @@ export const AppInstallModal = ({ open, onClose, appSlug }: AppInstallModalProps
|
|||
useEffect(() => {
|
||||
if (!_.isEmpty(app)) {
|
||||
setAppName(app.name);
|
||||
reset({ subdomain: getDefaultSubdomain(), configuration: initialCode, slug: appSlug ?? '' });
|
||||
reset({ url: app.url, configuration: initialCode, slug: appSlug ?? '' });
|
||||
}
|
||||
|
||||
return () => {
|
||||
reset({ subdomain: getDefaultSubdomain(), configuration: initialCode, slug: appSlug ?? '' });
|
||||
reset({ url: initialAppForm.url, configuration: initialCode, slug: appSlug ?? '' });
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [app, reset, open]);
|
||||
|
|
@ -73,13 +70,7 @@ export const AppInstallModal = ({ open, onClose, appSlug }: AppInstallModalProps
|
|||
|
||||
<div className="mt-6 grid grid-cols-1 gap-y-6 gap-x-4 sm:grid-cols-6">
|
||||
<div className="sm:col-span-3">
|
||||
<Input
|
||||
control={control}
|
||||
name="subdomain"
|
||||
label="Subdomain"
|
||||
onKeyPress={handleKeyPress}
|
||||
required={false}
|
||||
/>
|
||||
<Input control={control} name="url" label="URL" onKeyPress={handleKeyPress} required={false} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -23,5 +23,5 @@ search:
|
|||
great: stomach`;
|
||||
|
||||
export const initialAppForm = {
|
||||
subdomain: '',
|
||||
url: '',
|
||||
} as App;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,22 @@
|
|||
import React from 'react';
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import React, { useEffect } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import { DASHBOARD_APPS, DASHBOARD_QUICK_ACCESS } from './consts';
|
||||
import { useApps } from 'src/services/apps';
|
||||
// import { DASHBOARD_QUICK_ACCESS } from './consts';
|
||||
import { DashboardCard } from './components';
|
||||
|
||||
export const Dashboard: React.FC = () => {
|
||||
const host = window.location.hostname;
|
||||
const splitedDomain = host.split('.');
|
||||
splitedDomain.shift();
|
||||
const rootDomain = splitedDomain.join('.');
|
||||
const { apps, appTableLoading, loadApps } = useApps();
|
||||
|
||||
// Tell React to load the apps
|
||||
useEffect(() => {
|
||||
loadApps();
|
||||
|
||||
return () => {};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
|
|
@ -19,37 +28,11 @@ export const Dashboard: React.FC = () => {
|
|||
|
||||
<div className="max-w-7xl mx-auto py-4 px-3 sm:px-6 lg:px-8 h-full flex-grow">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 md:gap-4 lg:grid-cols-4 mb-10">
|
||||
{DASHBOARD_APPS(rootDomain!).map((app) => (
|
||||
<DashboardCard app={app} key={app.name} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="max-w-4xl mx-auto py-4 sm:px-6 lg:px-8 h-full flex-grow">
|
||||
<div className="pb-4 border-b border-gray-200 sm:flex sm:items-center">
|
||||
<h3 className="text-lg leading-6 font-medium text-gray-900">Utilities</h3>
|
||||
</div>
|
||||
|
||||
<dl className="mt-5 grid grid-cols-1 gap-2 sm:grid-cols-2">
|
||||
{DASHBOARD_QUICK_ACCESS(rootDomain!).map((item) => (
|
||||
<a
|
||||
href={item.url}
|
||||
key={item.name}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className={clsx('bg-white rounded-lg overflow-hidden sm:p-2 flex items-center group', {
|
||||
'opacity-40 cursor-default': !item.active,
|
||||
})}
|
||||
>
|
||||
<div className="w-16 h-16 flex items-center justify-center bg-primary-100 group-hover:bg-primary-200 transition-colors rounded-lg mr-4">
|
||||
<item.icon className="h-6 w-6 text-primary-900" aria-hidden="true" />
|
||||
</div>
|
||||
<div>
|
||||
<dt className="truncate text-sm leading-5 font-medium">{item.name}</dt>
|
||||
<dd className="mt-1 text-gray-500 text-sm leading-5 font-normal">{item.description}</dd>
|
||||
</div>
|
||||
</a>
|
||||
{apps
|
||||
.filter((app) => app.slug !== 'dashboard')
|
||||
.map((app) => (
|
||||
<DashboardCard app={app} key={app.name} />
|
||||
))}
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export const DashboardCard: React.FC<any> = ({ app }: { app: any }) => {
|
|||
<img
|
||||
className="h-16 w-16 rounded-md overflow-hidden mr-4 flex-shrink-0"
|
||||
src={app.assetSrc}
|
||||
alt="Nextcloud"
|
||||
alt={app.name}
|
||||
/>
|
||||
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import { AppActionTypes } from './actions';
|
||||
|
||||
const initialUsersState: any = {
|
||||
users: [],
|
||||
user: {},
|
||||
userModalLoading: false,
|
||||
usersLoading: false,
|
||||
const initialAppsState: any = {
|
||||
apps: [],
|
||||
app: {},
|
||||
appModalLoading: false,
|
||||
appsLoading: false,
|
||||
};
|
||||
|
||||
const appsReducer = (state: any = initialUsersState, action: any) => {
|
||||
const appsReducer = (state: any = initialAppsState, action: any) => {
|
||||
switch (action.type) {
|
||||
case AppActionTypes.FETCH_APPS:
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@ import { App, AppStatus } from './types';
|
|||
|
||||
const transformAppStatus = (status: string) => {
|
||||
switch (status) {
|
||||
case 'installed':
|
||||
case 'App installed and running':
|
||||
return AppStatus.Installed;
|
||||
case 'installing':
|
||||
return AppStatus.Installing;
|
||||
case 'not_installed':
|
||||
case 'Not installed':
|
||||
return AppStatus.NotInstalled;
|
||||
// For now default to "Installing" status for any app that isn't installed
|
||||
// or not installed. Could also mean "upgrading", or "broken"...
|
||||
default:
|
||||
return AppStatus.NotInstalled;
|
||||
return AppStatus.Installing;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -19,8 +19,10 @@ export const transformApp = (response: any): App => {
|
|||
name: response.name ?? '',
|
||||
slug: response.slug ?? '',
|
||||
status: transformAppStatus(response.status),
|
||||
subdomain: response.subdomain,
|
||||
url: response.url,
|
||||
automaticUpdates: response.automatic_updates,
|
||||
assetSrc: `/assets/${response.slug}.svg`,
|
||||
markdownSrc: `/markdown/${response.slug}.md`,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -33,7 +35,7 @@ export const transformAppRequest = (data: App) => {
|
|||
|
||||
export const transformInstallAppRequest = (data: App) => {
|
||||
return {
|
||||
subdomain: data.subdomain,
|
||||
url: data.url,
|
||||
configuration: data.configuration,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@ export interface App {
|
|||
name: string;
|
||||
slug: string;
|
||||
status?: AppStatus;
|
||||
subdomain?: string;
|
||||
url: string;
|
||||
automaticUpdates: boolean;
|
||||
configuration?: string;
|
||||
assetSrc?: string;
|
||||
markdownSrc?: string;
|
||||
}
|
||||
|
||||
export interface DisableAppForm {
|
||||
|
|
|
|||
Reference in a new issue