ode-explorer 1.0.0-explorer
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/.eslintrc.cjs +61 -0
- package/.husky/pre-commit +4 -0
- package/.prettierignore +6 -0
- package/README.md +136 -0
- package/TOOLS.md +31 -0
- package/index.html +19 -0
- package/lighthouserc.json +37 -0
- package/package.json +84 -0
- package/prettier.config.js +9 -0
- package/public/apps.svg +492 -0
- package/public/locales/en/translations.json +3 -0
- package/public/locales/fr/translations.json +3 -0
- package/src/app/App.tsx +175 -0
- package/src/assets/images/library.jpg +0 -0
- package/src/assets/images/react.svg +1 -0
- package/src/assets/images/vite.svg +1 -0
- package/src/components/AppHeader.tsx +12 -0
- package/src/components/FakeCard.tsx +47 -0
- package/src/contexts/ExplorerContext.tsx +100 -0
- package/src/contexts/OdeContext.tsx +115 -0
- package/src/hooks/adapters/explorer/ResourceCardWrapper.tsx +27 -0
- package/src/hooks/adapters/explorer/TreeNodeFolderWrapper.tsx +24 -0
- package/src/hooks/adapters/explorer/types.tsx +13 -0
- package/src/hooks/adapters/explorer/useExplorerAdapter.tsx +63 -0
- package/src/hooks/useI18n.tsx +9 -0
- package/src/hooks/useOdeBackend.tsx +64 -0
- package/src/i18n.ts +31 -0
- package/src/index.css +129 -0
- package/src/main.tsx +34 -0
- package/src/pages/Blog.tsx +3 -0
- package/src/pages/Home.tsx +20 -0
- package/src/vite-env.d.ts +1 -0
- package/tsconfig.json +28 -0
- package/tsconfig.node.json +9 -0
- package/vite.config.ts +73 -0
package/src/i18n.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import i18n from "i18next";
|
|
2
|
+
import LanguageDetector from "i18next-browser-languagedetector";
|
|
3
|
+
import Backend from "i18next-http-backend";
|
|
4
|
+
import { initReactI18next } from "react-i18next";
|
|
5
|
+
|
|
6
|
+
/* function getLoadPath(): string {
|
|
7
|
+
if (import.meta.env.DEV) {
|
|
8
|
+
return "/locales/{{lng}}/{{ns}}.json";
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return "assets/js/explorer/locales/{{lng}}/{{ns}}.json";
|
|
12
|
+
} */
|
|
13
|
+
|
|
14
|
+
i18n
|
|
15
|
+
.use(Backend)
|
|
16
|
+
.use(LanguageDetector) // detect user language
|
|
17
|
+
.use(initReactI18next) // passes i18n down to react-i18next
|
|
18
|
+
.init({
|
|
19
|
+
fallbackLng: "fr",
|
|
20
|
+
lng: "fr", // language to use, more information here: https://www.i18next.com/overview/configuration-options#languages-namespaces-resources
|
|
21
|
+
// you can use the i18n.changeLanguage function to change the language manually: https://www.i18next.com/overview/api#changelanguage
|
|
22
|
+
// if you're using a language detector, do not define the lng option
|
|
23
|
+
interpolation: {
|
|
24
|
+
escapeValue: false, // react already safes from xss
|
|
25
|
+
},
|
|
26
|
+
/* backend: {
|
|
27
|
+
loadPath: getLoadPath(),
|
|
28
|
+
}, */
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export default i18n;
|
package/src/index.css
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
.card .app-card p {
|
|
2
|
+
display: none;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
/* :root {
|
|
6
|
+
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
|
|
7
|
+
font-size: 16px;
|
|
8
|
+
line-height: 24px;
|
|
9
|
+
font-weight: 400;
|
|
10
|
+
|
|
11
|
+
color-scheme: light dark;
|
|
12
|
+
color: rgba(255, 255, 255, 0.87);
|
|
13
|
+
background-color: #242424;
|
|
14
|
+
|
|
15
|
+
font-synthesis: none;
|
|
16
|
+
text-rendering: optimizeLegibility;
|
|
17
|
+
-webkit-font-smoothing: antialiased;
|
|
18
|
+
-moz-osx-font-smoothing: grayscale;
|
|
19
|
+
-webkit-text-size-adjust: 100%;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
a {
|
|
23
|
+
font-weight: 500;
|
|
24
|
+
color: #646cff;
|
|
25
|
+
text-decoration: inherit;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
a:hover {
|
|
29
|
+
color: #535bf2;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
body {
|
|
33
|
+
margin: 0;
|
|
34
|
+
display: flex;
|
|
35
|
+
place-items: center;
|
|
36
|
+
min-width: 320px;
|
|
37
|
+
min-height: 100vh;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
h1 {
|
|
41
|
+
font-size: 3.2em;
|
|
42
|
+
line-height: 1.1;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
button {
|
|
46
|
+
border-radius: 8px;
|
|
47
|
+
border: 1px solid transparent;
|
|
48
|
+
padding: 0.6em 1.2em;
|
|
49
|
+
font-size: 1em;
|
|
50
|
+
font-weight: 500;
|
|
51
|
+
font-family: inherit;
|
|
52
|
+
background-color: #1a1a1a;
|
|
53
|
+
cursor: pointer;
|
|
54
|
+
transition: border-color 0.25s;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
button:hover {
|
|
58
|
+
border-color: #646cff;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
button:focus,
|
|
62
|
+
button:focus-visible {
|
|
63
|
+
outline: 4px auto -webkit-focus-ring-color;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@media (prefers-color-scheme: light) {
|
|
67
|
+
:root {
|
|
68
|
+
color: #213547;
|
|
69
|
+
background-color: #ffffff;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
a:hover {
|
|
73
|
+
color: #747bff;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
button {
|
|
77
|
+
background-color: #f9f9f9;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
#root {
|
|
82
|
+
max-width: 1280px;
|
|
83
|
+
margin: 0 auto;
|
|
84
|
+
padding: 2rem;
|
|
85
|
+
text-align: center;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.logo {
|
|
89
|
+
height: 6em;
|
|
90
|
+
padding: 1.5em;
|
|
91
|
+
will-change: filter;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.logo:hover {
|
|
95
|
+
filter: drop-shadow(0 0 2em #646cffaa);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.logo.react:hover {
|
|
99
|
+
filter: drop-shadow(0 0 2em #61dafbaa);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
@keyframes logo-spin {
|
|
103
|
+
from {
|
|
104
|
+
transform: rotate(0deg);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
to {
|
|
108
|
+
transform: rotate(360deg);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
113
|
+
a:nth-of-type(2) .logo {
|
|
114
|
+
animation: logo-spin infinite 20s linear;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.card {
|
|
119
|
+
padding: 2em;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.read-the-docs {
|
|
123
|
+
color: #888;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
button {
|
|
127
|
+
margin-inline: 0.5rem;
|
|
128
|
+
}
|
|
129
|
+
*/
|
package/src/main.tsx
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// import { StrictMode } from "react";
|
|
2
|
+
import ExplorerContextProvider from "@contexts/ExplorerContext";
|
|
3
|
+
import OdeProvider, { OdeProviderParams } from "@contexts/OdeContext";
|
|
4
|
+
import { APP, App as AppName, RESOURCE } from "ode-ts-client";
|
|
5
|
+
import { createRoot } from "react-dom/client";
|
|
6
|
+
import { BrowserRouter } from "react-router-dom";
|
|
7
|
+
|
|
8
|
+
import App from "./app/App";
|
|
9
|
+
// import "./i18n";
|
|
10
|
+
|
|
11
|
+
const rootElement = document.querySelector<HTMLElement>("[data-ode-app]");
|
|
12
|
+
if (rootElement && rootElement.dataset && rootElement.dataset.odeApp) {
|
|
13
|
+
const { odeApp } = rootElement.dataset;
|
|
14
|
+
const params: OdeProviderParams = { app: APP.PORTAL };
|
|
15
|
+
// Inject params (JSON object or string) read from index.html in OdeProvider
|
|
16
|
+
try {
|
|
17
|
+
const p = JSON.parse(odeApp);
|
|
18
|
+
Object.assign(params, p);
|
|
19
|
+
} catch {
|
|
20
|
+
params.app = odeApp as AppName;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
createRoot(rootElement!).render(
|
|
24
|
+
<BrowserRouter>
|
|
25
|
+
<OdeProvider params={params}>
|
|
26
|
+
<ExplorerContextProvider types={[RESOURCE.BLOG]}>
|
|
27
|
+
<App />
|
|
28
|
+
</ExplorerContextProvider>
|
|
29
|
+
</OdeProvider>
|
|
30
|
+
</BrowserRouter>,
|
|
31
|
+
);
|
|
32
|
+
} else {
|
|
33
|
+
// HTTP 500 screen ?
|
|
34
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export default function Home() {
|
|
2
|
+
return (
|
|
3
|
+
<div>
|
|
4
|
+
<h1>Explore</h1>
|
|
5
|
+
<div>
|
|
6
|
+
<p>
|
|
7
|
+
Edit<code>src/App.tsx</code> and save to test HMR
|
|
8
|
+
</p>
|
|
9
|
+
<p className="read-the-docs">
|
|
10
|
+
Click on the Vite and React logos to learn more
|
|
11
|
+
</p>
|
|
12
|
+
</div>
|
|
13
|
+
<div>
|
|
14
|
+
<p>Change language:</p>
|
|
15
|
+
<button type="button">fr</button>
|
|
16
|
+
<button type="button">en</button>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
|
6
|
+
"allowJs": false,
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"esModuleInterop": false,
|
|
9
|
+
"allowSyntheticDefaultImports": true,
|
|
10
|
+
"strict": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"module": "ESNext",
|
|
13
|
+
"moduleResolution": "Node",
|
|
14
|
+
"resolveJsonModule": true,
|
|
15
|
+
"isolatedModules": true,
|
|
16
|
+
"noEmit": true,
|
|
17
|
+
"jsx": "react-jsx",
|
|
18
|
+
"baseUrl": "./src",
|
|
19
|
+
"paths": {
|
|
20
|
+
"@components/*": ["./components/*"],
|
|
21
|
+
"@pages/*": ["./pages/*"],
|
|
22
|
+
"@hooks/*": ["./hooks/*"],
|
|
23
|
+
"@contexts/*": ["./contexts/*"]
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"include": ["src"],
|
|
27
|
+
"references": [{ "path": "./tsconfig.node.json" }]
|
|
28
|
+
}
|
package/vite.config.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { defineConfig } from "vite";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import react from "@vitejs/plugin-react";
|
|
4
|
+
|
|
5
|
+
// https://vitejs.dev/config/
|
|
6
|
+
export default defineConfig({
|
|
7
|
+
resolve: {
|
|
8
|
+
alias: [
|
|
9
|
+
{ find: "~", replacement: path.resolve(__dirname, "src") },
|
|
10
|
+
{
|
|
11
|
+
find: "@components",
|
|
12
|
+
replacement: path.resolve(__dirname, "./src/components"),
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
find: "@pages",
|
|
16
|
+
replacement: path.resolve(__dirname, "./src/pages"),
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
find: "@hooks",
|
|
20
|
+
replacement: path.resolve(__dirname, "./src/hooks"),
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
find: "@contexts",
|
|
24
|
+
replacement: path.resolve(__dirname, "./src/contexts"),
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
build: {
|
|
29
|
+
assetsDir: "assets/js/explorer/",
|
|
30
|
+
},
|
|
31
|
+
plugins: [react()],
|
|
32
|
+
/* server: {
|
|
33
|
+
host: "0.0.0.0",
|
|
34
|
+
port: 3000,
|
|
35
|
+
open: true,
|
|
36
|
+
}, */
|
|
37
|
+
server: {
|
|
38
|
+
proxy: {
|
|
39
|
+
// List of all applications
|
|
40
|
+
"/applications-list": {
|
|
41
|
+
target: "http://localhost:8090",
|
|
42
|
+
changeOrigin: false,
|
|
43
|
+
},
|
|
44
|
+
// Public Conf
|
|
45
|
+
"/conf/public": {
|
|
46
|
+
target: "http://localhost:8090",
|
|
47
|
+
changeOrigin: false,
|
|
48
|
+
},
|
|
49
|
+
"^/(?=assets|theme|locale|i18n|skin)": {
|
|
50
|
+
target: "http://localhost:8090",
|
|
51
|
+
changeOrigin: false,
|
|
52
|
+
},
|
|
53
|
+
// Entcore urls
|
|
54
|
+
"^/(?=auth|cas|userbook|directory|communication|conversation|portal|session|timeline|workspace)":
|
|
55
|
+
{
|
|
56
|
+
target: "http://localhost:8090",
|
|
57
|
+
changeOrigin: false,
|
|
58
|
+
},
|
|
59
|
+
// App urls
|
|
60
|
+
"/blog": {
|
|
61
|
+
target: "http://localhost:8090",
|
|
62
|
+
changeOrigin: false,
|
|
63
|
+
},
|
|
64
|
+
"/explorer": {
|
|
65
|
+
target: "http://localhost:8090",
|
|
66
|
+
changeOrigin: false,
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
host: "0.0.0.0",
|
|
70
|
+
port: 3000,
|
|
71
|
+
//open: true,
|
|
72
|
+
},
|
|
73
|
+
});
|