@jtl-software/cloud-app-template-frontend-react 0.0.11 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/package.json +1 -1
- package/src/App.tsx +9 -1
- package/src/common/ConfigWarningBanner.tsx +73 -0
- package/manifest.json +0 -104
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @jtl/cloud-app-template-frontend-react
|
|
2
2
|
|
|
3
|
+
## 0.0.13
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#43](https://github.com/jtl-software/cloud-apps-cli/pull/43) [`90cd2f7`](https://github.com/jtl-software/cloud-apps-cli/commit/90cd2f7eb422dcb9e6870cc7ec51015941eeed7b) Thanks [@tobilen](https://github.com/tobilen)! - Warn loudly when CLIENT_ID / CLIENT_SECRET are missing. Backends print a red startup banner pointing at the env/config file, and expose `GET /health` returning `{ status, missing }`. The React frontend polls `/health` and renders a yellow banner across all routes when the backend reports a misconfiguration, so the dev sees the issue in the browser even if they missed the terminal output.
|
|
8
|
+
|
|
9
|
+
- [#43](https://github.com/jtl-software/cloud-apps-cli/pull/43) [`27055e6`](https://github.com/jtl-software/cloud-apps-cli/commit/27055e6d01e3a30e3a5de97f2e56772dbf4f0dfd) Thanks [@tobilen](https://github.com/tobilen)! - Moved the manifest.json out of the frontend package
|
|
10
|
+
|
|
11
|
+
- [#43](https://github.com/jtl-software/cloud-apps-cli/pull/43) [`36d1518`](https://github.com/jtl-software/cloud-apps-cli/commit/36d1518f8214fdee56cff202456f6b35f8912346) Thanks [@tobilen](https://github.com/tobilen)! - Add register command to generated project
|
|
12
|
+
|
|
13
|
+
## 0.0.12
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- [#36](https://github.com/jtl-software/cloud-apps-cli/pull/36) [`adca670`](https://github.com/jtl-software/cloud-apps-cli/commit/adca670a52296d01b2c153b722cc3b51993125d5) Thanks [@tobilen](https://github.com/tobilen)! - Fix .env file detection & deprecated manifest fields
|
|
18
|
+
|
|
3
19
|
## 0.0.11
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/package.json
CHANGED
package/src/App.tsx
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { AppBridge } from '@jtl-software/cloud-apps-core';
|
|
2
2
|
import './App.css';
|
|
3
|
+
import ConfigWarningBanner from './common/ConfigWarningBanner';
|
|
3
4
|
import { ErpPage, GraphqlDemoPage, HubPage, PanePage, SetupPage, WelcomePage } from './pages';
|
|
4
5
|
import { useEffect } from 'react';
|
|
5
6
|
|
|
6
7
|
type AppMode = 'setup' | 'erp' | 'pane' | 'hub' | 'graphql-demo';
|
|
7
8
|
|
|
8
|
-
const
|
|
9
|
+
const AppRouter: React.FC<{ appBridge: AppBridge | null }> = ({ appBridge }) => {
|
|
9
10
|
const mode: AppMode = location.pathname.substring(1) as AppMode;
|
|
10
11
|
|
|
11
12
|
useEffect((): void => {
|
|
@@ -37,4 +38,11 @@ const App: React.FC<{ appBridge: AppBridge | null }> = ({ appBridge }) => {
|
|
|
37
38
|
}
|
|
38
39
|
};
|
|
39
40
|
|
|
41
|
+
const App: React.FC<{ appBridge: AppBridge | null }> = ({ appBridge }) => (
|
|
42
|
+
<>
|
|
43
|
+
<ConfigWarningBanner />
|
|
44
|
+
<AppRouter appBridge={appBridge} />
|
|
45
|
+
</>
|
|
46
|
+
);
|
|
47
|
+
|
|
40
48
|
export default App;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { Box, Stack, Text } from '@jtl-software/platform-ui-react';
|
|
3
|
+
import { TriangleAlert } from 'lucide-react';
|
|
4
|
+
import { apiUrl } from './constants';
|
|
5
|
+
|
|
6
|
+
type HealthResponse = {
|
|
7
|
+
status: 'ok' | 'misconfigured';
|
|
8
|
+
missing: string[];
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const POLL_INTERVAL_MS = 5000;
|
|
12
|
+
|
|
13
|
+
const ConfigWarningBanner: React.FC = () => {
|
|
14
|
+
const [missing, setMissing] = useState<string[] | null>(null);
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
let cancelled = false;
|
|
18
|
+
|
|
19
|
+
const check = async (): Promise<void> => {
|
|
20
|
+
try {
|
|
21
|
+
const res = await fetch(`${apiUrl}/health`);
|
|
22
|
+
if (!res.ok) return;
|
|
23
|
+
const data = (await res.json()) as HealthResponse;
|
|
24
|
+
if (cancelled) return;
|
|
25
|
+
setMissing(data.status === 'misconfigured' ? data.missing : null);
|
|
26
|
+
} catch {
|
|
27
|
+
// Backend not reachable yet (still starting). Try again on the next tick.
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
void check();
|
|
32
|
+
const id = window.setInterval(check, POLL_INTERVAL_MS);
|
|
33
|
+
return () => {
|
|
34
|
+
cancelled = true;
|
|
35
|
+
window.clearInterval(id);
|
|
36
|
+
};
|
|
37
|
+
}, []);
|
|
38
|
+
|
|
39
|
+
if (!missing || missing.length === 0) return null;
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<Box
|
|
43
|
+
className="border-b border-amber-300 bg-amber-50 px-4 py-3 text-amber-900"
|
|
44
|
+
role="alert"
|
|
45
|
+
>
|
|
46
|
+
<Stack spacing="3" direction="row" itemAlign="start">
|
|
47
|
+
<TriangleAlert size={20} color="#b45309" strokeWidth={2} />
|
|
48
|
+
<Stack spacing="1" direction="column">
|
|
49
|
+
<Text type="small" weight="semibold">
|
|
50
|
+
Backend is missing credentials: {missing.join(', ')}
|
|
51
|
+
</Text>
|
|
52
|
+
<Text type="xs">
|
|
53
|
+
Every JTL API call will fail until you add these to{' '}
|
|
54
|
+
<code className="rounded bg-amber-100 px-1 py-0.5">packages/backend/.env</code> (Node) or{' '}
|
|
55
|
+
<code className="rounded bg-amber-100 px-1 py-0.5">appsettings.Local.json</code> (.NET).
|
|
56
|
+
Get the values from the{' '}
|
|
57
|
+
<a
|
|
58
|
+
href="https://partner.jtl-cloud.com/"
|
|
59
|
+
target="_blank"
|
|
60
|
+
rel="noopener noreferrer"
|
|
61
|
+
className="underline"
|
|
62
|
+
>
|
|
63
|
+
Partner Portal
|
|
64
|
+
</a>{' '}
|
|
65
|
+
under your app's <strong>Client credentials</strong>, then restart the backend.
|
|
66
|
+
</Text>
|
|
67
|
+
</Stack>
|
|
68
|
+
</Stack>
|
|
69
|
+
</Box>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default ConfigWarningBanner;
|
package/manifest.json
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"manifest": {
|
|
3
|
-
"manifestVersion": "1.0.0",
|
|
4
|
-
"technicalName": "{{APP_TECHNICAL_NAME}}",
|
|
5
|
-
"version": "1.0.0",
|
|
6
|
-
"requirements": {
|
|
7
|
-
"minCloudApiVersion": "1.0.0"
|
|
8
|
-
},
|
|
9
|
-
"lifecycle": {
|
|
10
|
-
"configurationUrl": "http://localhost:3004/setup"
|
|
11
|
-
},
|
|
12
|
-
"capabilities": {
|
|
13
|
-
"hub": {
|
|
14
|
-
"appLauncher": {
|
|
15
|
-
"redirectUrl": "http://localhost:3004/hub",
|
|
16
|
-
"closedPreviewUrl": "http://localhost:3004/hub"
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
"erp": {
|
|
20
|
-
"menuItems": [
|
|
21
|
-
{
|
|
22
|
-
"id": "{{APP_NAME}}-menu",
|
|
23
|
-
"name": "{{APP_NAME}}",
|
|
24
|
-
"url": "http://localhost:3004/erp"
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
"id": "{{APP_NAME}}-graphql-demo",
|
|
28
|
-
"name": "GraphQL Demo",
|
|
29
|
-
"url": "http://localhost:3004/graphql-demo"
|
|
30
|
-
}
|
|
31
|
-
],
|
|
32
|
-
"api": {
|
|
33
|
-
"scopes": []
|
|
34
|
-
},
|
|
35
|
-
"pane": [
|
|
36
|
-
{
|
|
37
|
-
"id": "{{APP_NAME}}-customer-pane",
|
|
38
|
-
"context": "customers",
|
|
39
|
-
"matchChildContext": true,
|
|
40
|
-
"title": "{{APP_NAME}}",
|
|
41
|
-
"url": "http://localhost:3004/pane",
|
|
42
|
-
"requiredScopes": []
|
|
43
|
-
}
|
|
44
|
-
]
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
"listing": {
|
|
49
|
-
"version": "1.0.0",
|
|
50
|
-
"listingVersion": "1.0.0",
|
|
51
|
-
"defaultLocale": "de-DE",
|
|
52
|
-
"name": {
|
|
53
|
-
"de-DE": {
|
|
54
|
-
"short": "{{APP_NAME}}",
|
|
55
|
-
"full": "{{APP_NAME}}"
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
"description": {
|
|
59
|
-
"de-DE": {
|
|
60
|
-
"short": "{{APP_DESCRIPTION_SHORT}}",
|
|
61
|
-
"full": "{{APP_DESCRIPTION}}"
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
"benefits": {
|
|
65
|
-
"de-DE": []
|
|
66
|
-
},
|
|
67
|
-
"category": {
|
|
68
|
-
"main": "",
|
|
69
|
-
"sub": []
|
|
70
|
-
},
|
|
71
|
-
"media": {
|
|
72
|
-
"icons": {
|
|
73
|
-
"light": "https://hub.jtl-cloud.com/assets/image-placeholder.png",
|
|
74
|
-
"dark": "https://hub.jtl-cloud.com/assets/image-placeholder.png"
|
|
75
|
-
},
|
|
76
|
-
"screenshots": ["https://hub.jtl-cloud.com/assets/image-placeholder.png"],
|
|
77
|
-
"video": ""
|
|
78
|
-
},
|
|
79
|
-
"pricing": {
|
|
80
|
-
"freePlan": true
|
|
81
|
-
},
|
|
82
|
-
"support": {
|
|
83
|
-
"url": {
|
|
84
|
-
"de-DE": "https://example.com/support-for-app-xy"
|
|
85
|
-
},
|
|
86
|
-
"documentation": {
|
|
87
|
-
"de-DE": "https://example.com/guide-for-app-xy"
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
"legal": {
|
|
91
|
-
"privacyPolicy": "https://example.com/privacy",
|
|
92
|
-
"termsOfUse": "https://example.com/terms-of-use",
|
|
93
|
-
"gdpr": {
|
|
94
|
-
"request": "https://example.com/gdpr/request",
|
|
95
|
-
"delete": "https://example.com/gdpr/delete"
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
|
-
"editorial": {
|
|
99
|
-
"status": true
|
|
100
|
-
},
|
|
101
|
-
"distributionType": "PRIVATE",
|
|
102
|
-
"listingVersionStatus": "DRAFT"
|
|
103
|
-
}
|
|
104
|
-
}
|