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/admin/site-settings/row-entry-inner.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 { Input, Select } from "antd";
7
import { CSSProperties } from "react";
8
9
import { LanguageModelVendorAvatar } from "@cocalc/frontend/components/language-model-icon";
10
import Password, {
11
PasswordTextArea,
12
} from "@cocalc/frontend/components/password";
13
import { modelToName } from "@cocalc/frontend/frame-editors/llm/llm-selector";
14
import { LOCALIZATIONS } from "@cocalc/frontend/i18n";
15
import { LOCALE } from "@cocalc/util/consts/locale";
16
import { USER_SELECTABLE_LANGUAGE_MODELS } from "@cocalc/util/db-schema/llm-utils";
17
import {
18
ConfigValid,
19
to_list_of_llms,
20
to_list_of_locale,
21
} from "@cocalc/util/db-schema/site-defaults";
22
import { RowEntryInnerProps } from "./row-entry";
23
24
export function testIsInvalid(value, valid?: ConfigValid): boolean {
25
return (
26
(Array.isArray(valid) && !valid.includes(value)) ||
27
(typeof valid == "function" && !valid(value))
28
);
29
}
30
31
export function rowEntryStyle(value, valid?: ConfigValid): CSSProperties {
32
if (testIsInvalid(value, valid)) {
33
return { border: "2px solid red" };
34
}
35
return {};
36
}
37
38
export function RowEntryInner({
39
name,
40
value,
41
valid,
42
password,
43
multiline,
44
onChangeEntry,
45
isReadonly,
46
clearable,
47
update,
48
}: RowEntryInnerProps) {
49
if (isReadonly == null) return null; // typescript
50
const disabled = isReadonly[name] == true;
51
52
if (name === "selectable_llms") {
53
return (
54
<Select
55
mode="multiple"
56
style={{ width: "100%" }}
57
placeholder="Select user selectable LLMs"
58
optionLabelProp="label"
59
defaultValue={to_list_of_llms(value, false)}
60
onChange={(value: Array<string>) => {
61
onChangeEntry(name, value.join(","));
62
update();
63
}}
64
options={USER_SELECTABLE_LANGUAGE_MODELS.map((model) => {
65
return { label: modelToName(model), value: model };
66
})}
67
optionRender={(option) => (
68
<>
69
<LanguageModelVendorAvatar model={(option.value as string) ?? ""} />{" "}
70
{option.label}
71
</>
72
)}
73
/>
74
);
75
} else if (name === "i18n") {
76
return (
77
<Select
78
mode="multiple"
79
style={{ width: "100%" }}
80
placeholder="Select user selectable language locale"
81
optionLabelProp="label"
82
defaultValue={to_list_of_locale(value, false)}
83
onChange={(value: Array<string>) => {
84
onChangeEntry(name, value.join(","));
85
update();
86
}}
87
options={LOCALE.map((l) => {
88
return { label: LOCALIZATIONS[l].name, value: l };
89
})}
90
optionRender={(option) => (
91
<>
92
{option.value ? LOCALIZATIONS[option.value].flag : ""}{" "}
93
{option.label}
94
</>
95
)}
96
/>
97
);
98
} else if (Array.isArray(valid)) {
99
return (
100
<Select
101
defaultValue={value}
102
disabled={disabled}
103
onChange={(value) => {
104
// should never happen, because this is not a "multiple" Select
105
if (Array.isArray(value)) {
106
console.warn(`Got array value for ${name}: ${value}`);
107
return;
108
}
109
onChangeEntry(name, value);
110
update();
111
}}
112
style={{ width: "100%" }}
113
options={valid.map((value) => {
114
const label = name === "default_llm" ? modelToName(value) : value;
115
return { value, label };
116
})}
117
/>
118
);
119
} else {
120
if (password) {
121
if (multiline != null) {
122
return (
123
<PasswordTextArea
124
rows={multiline}
125
autoComplete="off"
126
style={rowEntryStyle(value, valid)}
127
defaultValue={value}
128
visibilityToggle={true}
129
disabled={disabled}
130
onChange={(e) => onChangeEntry(name, e.target.value)}
131
/>
132
);
133
} else {
134
return (
135
<Password
136
autoComplete="off"
137
style={rowEntryStyle(value, valid)}
138
defaultValue={value}
139
visibilityToggle={true}
140
disabled={disabled}
141
onChange={(e) => onChangeEntry(name, e.target.value)}
142
/>
143
);
144
}
145
} else {
146
if (multiline != null) {
147
const style = {
148
...rowEntryStyle(value, valid),
149
fontFamily: "monospace",
150
fontSize: "80%",
151
} as CSSProperties;
152
return (
153
<Input.TextArea
154
autoComplete="off"
155
rows={multiline}
156
style={style}
157
defaultValue={value}
158
disabled={disabled}
159
onChange={(e) => onChangeEntry(name, e.target.value)}
160
/>
161
);
162
} else {
163
return (
164
<Input
165
autoComplete="off"
166
style={rowEntryStyle(value, valid)}
167
defaultValue={value}
168
disabled={disabled}
169
onChange={(e) => onChangeEntry(name, e.target.value)}
170
allowClear={clearable}
171
/>
172
);
173
}
174
}
175
}
176
}
177
178