unfinished work that adds loading the list of apps dynamically

This commit is contained in:
Maarten de Waard 2022-09-29 15:37:41 +02:00
parent 14b4a58d46
commit 86192f28fd
No known key found for this signature in database
GPG key ID: 1D3E893A657CC8DA
10 changed files with 101 additions and 65 deletions

View file

@ -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/',
},
];

View file

@ -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>

View file

@ -23,5 +23,5 @@ search:
great: stomach`;
export const initialAppForm = {
subdomain: '',
url: '',
} as App;

View file

@ -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>

View file

@ -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>

View file

@ -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 {

View file

@ -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,
};
};

View file

@ -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 {