CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/app/render.tsx
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import ReactDOM from "react-dom";
7
import { createRoot } from "react-dom/client";
8
9
import {
10
redux,
11
Redux,
12
useAsyncEffect,
13
useTypedRedux,
14
} from "@cocalc/frontend/app-framework";
15
import {
16
getLocale,
17
LOCALIZATIONS,
18
OTHER_SETTINGS_LOCALE_KEY,
19
} from "@cocalc/frontend/i18n";
20
import { QueryParams } from "@cocalc/frontend/misc/query-params";
21
import { AppContext, useAppContextProvider } from "./context";
22
import { Localize, useLocalizationCtx } from "./localize";
23
24
// App uses the context provided by Redux (for the locale, etc.) and Localize.
25
function App({ children }) {
26
const appState = useAppContextProvider();
27
const { setLocale } = useLocalizationCtx();
28
const other_settings = useTypedRedux("account", "other_settings");
29
30
// setting via ?lang=[locale] takes precedece over account settings
31
// additionally ?lang_temp=[locale] temporarily changes it, used by these impersonation admin links
32
useAsyncEffect(async () => {
33
const lang_set = QueryParams.get("lang");
34
// lang_temp sets the language *temporarily*, i.e. without changing the account settings and it is sticky
35
// this is useful for impersonation – https://github.com/sagemathinc/cocalc/issues/7782
36
const lang_temp = QueryParams.get("lang_temp");
37
const temp = lang_temp != null;
38
const lang = temp ? lang_temp : lang_set;
39
if (lang != null) {
40
if (lang in LOCALIZATIONS) {
41
console.warn(
42
`URL query parameter 'lang=${lang}' – overriding user configuration ${
43
temp ? "temporary" : "permanent"
44
}.`,
45
);
46
if (!temp) {
47
const store = redux.getStore("account");
48
// we have to ensure the account store is available, because this code runs very early
49
await store.async_wait({
50
until: () => store.get_account_id() != null,
51
});
52
redux
53
.getActions("account")
54
.set_other_settings(OTHER_SETTINGS_LOCALE_KEY, lang);
55
}
56
setLocale(lang);
57
} else {
58
console.warn(
59
`URL query parameter '${JSON.stringify({
60
lang_set,
61
lang_temp,
62
})}' provided, but not a valid locale.`,
63
`Known values: ${Object.keys(LOCALIZATIONS)}`,
64
);
65
}
66
if (!temp) {
67
// removing the parameter, otherwise this conflicts with further changes of account settings
68
QueryParams.remove("lang");
69
}
70
} else {
71
setLocale(getLocale(other_settings));
72
}
73
}, [getLocale(other_settings)]);
74
75
return <AppContext.Provider value={appState}>{children}</AppContext.Provider>;
76
}
77
78
function Root({ Page }) {
79
return (
80
<Redux>
81
<Localize>
82
<App>
83
<Page />
84
</App>
85
</Localize>
86
</Redux>
87
);
88
}
89
90
export async function render(): Promise<void> {
91
finishedLoading(); // comment this out to leave the loading/startup banner visible so you can use the Chrome dev tools with it.
92
const container = document.getElementById("cocalc-webapp-container");
93
const root = createRoot(container!);
94
const { Page } = await import("./page");
95
root.render(<Root Page={Page} />);
96
}
97
98
export async function xxx_render(): Promise<void> {
99
finishedLoading(); // comment this out to leave the loading/startup banner visible
100
const { Page } = await import("./page");
101
ReactDOM.render(
102
<Root Page={Page} />,
103
document.getElementById("cocalc-webapp-container"),
104
);
105
}
106
107
// When loading is done, remove any visible artifacts.
108
// This doesn't remove anything added to the head.
109
function finishedLoading() {
110
const load = document.getElementById("cocalc-load-container");
111
if (load != null) {
112
load.innerHTML = "";
113
load.remove();
114
}
115
}
116
117