@balena/ui-shared-components 12.3.2-build-fix-non-unified-os-release-variant-selection-c6aa80ca41df6028f60420084ff0be1ab0a19b9b-1 → 12.3.2
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/dist/components/DownloadImageDialog/ImageForm.d.ts +1 -1
- package/dist/components/DownloadImageDialog/ImageForm.js +82 -86
- package/dist/components/DownloadImageDialog/OsTypeSelector.js +3 -3
- package/dist/components/DownloadImageDialog/VariantSelector.js +10 -9
- package/dist/components/DownloadImageDialog/index.js +7 -13
- package/dist/theme.js +10 -0
- package/package.json +2 -2
|
@@ -14,7 +14,7 @@ interface ImageFormProps {
|
|
|
14
14
|
model: DownloadImageFormModel;
|
|
15
15
|
hasEsrVersions?: boolean;
|
|
16
16
|
onSelectedOsTypeChange: (osType: string) => void;
|
|
17
|
-
onChange: (
|
|
17
|
+
onChange: (key: keyof DownloadImageFormModel, value: DownloadImageFormModel[keyof DownloadImageFormModel]) => void;
|
|
18
18
|
}
|
|
19
19
|
export declare const ImageForm: import("react").NamedExoticComponent<ImageFormProps>;
|
|
20
20
|
export {};
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import { __rest } from "tslib";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { Avatar, Box,
|
|
3
|
+
import { Avatar, Box, Checkbox, Chip, Divider, FormControl, FormControlLabel, FormLabel, InputAdornment, Radio, RadioGroup, TextField, Tooltip, Typography, IconButton, Autocomplete, Stack, Accordion, AccordionSummary, AccordionDetails, accordionSummaryClasses, } from '@mui/material';
|
|
4
4
|
import HelpIcon from '@mui/icons-material/Help';
|
|
5
5
|
import { memo, useCallback, useEffect, useMemo, useState } from 'react';
|
|
6
6
|
import { getPreferredVersionOpts, transformVersions } from './version';
|
|
7
7
|
import { OsTypeSelector } from './OsTypeSelector';
|
|
8
8
|
import { VariantSelector } from './VariantSelector';
|
|
9
|
-
import AddIcon from '@mui/icons-material/Add';
|
|
10
|
-
import RemoveIcon from '@mui/icons-material/Remove';
|
|
11
9
|
import ArticleIcon from '@mui/icons-material/Article';
|
|
12
10
|
import { MUILinkWithTracking } from '../MUILinkWithTracking';
|
|
13
11
|
import { Visibility, VisibilityOff } from '@mui/icons-material';
|
|
14
12
|
import { FALLBACK_LOGO_UNKNOWN_DEVICE } from './utils';
|
|
15
13
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
16
|
-
import { faTriangleExclamation } from '@fortawesome/free-solid-svg-icons';
|
|
14
|
+
import { faChevronRight, faTriangleExclamation, } from '@fortawesome/free-solid-svg-icons';
|
|
17
15
|
import { Callout } from '../Callout';
|
|
18
16
|
import { token } from '../../utils/token';
|
|
19
17
|
const POLL_INTERVAL_DOCS = 'https://www.balena.io/docs/reference/supervisor/bandwidth-reduction/#side-effects--warnings';
|
|
@@ -46,37 +44,25 @@ export const ImageForm = memo(function ImageForm({ compatibleDeviceTypes, osVers
|
|
|
46
44
|
const { selectionOpts, preferredSelectionOpts } = useMemo(() => getCategorizedVersions(osVersions, model.deviceType, osType), [osVersions, model.deviceType, osType]);
|
|
47
45
|
const versionSelectionOpts = useMemo(() => (showAllVersions ? selectionOpts : preferredSelectionOpts), [preferredSelectionOpts, selectionOpts, showAllVersions]);
|
|
48
46
|
const showAllVersionsToggle = useMemo(() => preferredSelectionOpts.length < selectionOpts.length, [preferredSelectionOpts.length, selectionOpts.length]);
|
|
49
|
-
const handleVariantChange = useCallback((
|
|
50
|
-
setVariant(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
};
|
|
54
|
-
if (version === null || version === void 0 ? void 0 : version.hasPrebuiltVariants) {
|
|
55
|
-
const rawVersionForVariant = version.rawVersions[newVariant];
|
|
56
|
-
if (rawVersionForVariant != null) {
|
|
57
|
-
newState.version = rawVersionForVariant;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
onChange(newState);
|
|
61
|
-
}, [onChange, version]);
|
|
47
|
+
const handleVariantChange = useCallback((v) => {
|
|
48
|
+
setVariant(v);
|
|
49
|
+
onChange('developmentMode', v === 'dev');
|
|
50
|
+
}, [onChange]);
|
|
62
51
|
const handleVersionChange = useCallback((ver) => {
|
|
63
52
|
var _a;
|
|
64
53
|
ver !== null && ver !== void 0 ? ver : (ver = (_a = versionSelectionOpts.find((v) => v.isRecommended)) !== null && _a !== void 0 ? _a : versionSelectionOpts[0]);
|
|
65
|
-
const newState = {
|
|
66
|
-
developmentMode: variant === 'dev',
|
|
67
|
-
};
|
|
68
54
|
if (ver === null || ver === void 0 ? void 0 : ver.hasPrebuiltVariants) {
|
|
69
55
|
const rawVersionForVariant = ver.rawVersions[variant];
|
|
70
|
-
if (
|
|
56
|
+
if (rawVersionForVariant) {
|
|
57
|
+
onChange('version', rawVersionForVariant);
|
|
58
|
+
setVersion(ver);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
71
61
|
handleVariantChange(variant === 'dev' ? 'prod' : 'dev');
|
|
72
|
-
return;
|
|
73
62
|
}
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
newState.version = ver === null || ver === void 0 ? void 0 : ver.rawVersion;
|
|
63
|
+
return;
|
|
78
64
|
}
|
|
79
|
-
onChange(
|
|
65
|
+
onChange('version', ver === null || ver === void 0 ? void 0 : ver.rawVersion);
|
|
80
66
|
setVersion(ver);
|
|
81
67
|
}, [versionSelectionOpts, variant, onChange, handleVariantChange]);
|
|
82
68
|
// TODO: Revisit this as it is clearly not using hooks as intended
|
|
@@ -108,46 +94,50 @@ export const ImageForm = memo(function ImageForm({ compatibleDeviceTypes, osVers
|
|
|
108
94
|
if (!newDeviceType) {
|
|
109
95
|
return;
|
|
110
96
|
}
|
|
111
|
-
onChange(
|
|
97
|
+
onChange('deviceType', newDeviceType);
|
|
112
98
|
}, [compatibleDeviceTypes, model.deviceType.slug, onChange]);
|
|
113
99
|
const recommendedVersion = useMemo(() => { var _a; return (_a = versionSelectionOpts.find((v) => { var _a; return !((_a = v.knownIssueList) === null || _a === void 0 ? void 0 : _a.length); })) === null || _a === void 0 ? void 0 : _a.value; }, [versionSelectionOpts]);
|
|
114
|
-
return (_jsxs(
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
100
|
+
return (_jsxs(Stack, { action: downloadUrl, method: "post", component: "form", noValidate: true, autoComplete: "off", ref: formElement, gap: 3, children: [_jsx("input", { type: "hidden", name: "deviceType", value: model.deviceType.slug }), _jsx("input", { type: "hidden", name: "_token", value: authToken }), _jsx("input", { type: "hidden", name: "appId", value: applicationId }), _jsx("input", { type: "hidden", name: "fileType", value: ".zip" }), _jsx("input", { type: "hidden", name: "version", value: model.version }), _jsxs(Stack, { direction: "row", flexWrap: "wrap", gap: 2, children: [compatibleDeviceTypes && compatibleDeviceTypes.length > 1 && (_jsx(Autocomplete, { fullWidth: true, value: model.deviceType, options: compatibleDeviceTypes, getOptionLabel: (option) => option.name, renderOption: (props, option) => {
|
|
101
|
+
var _a;
|
|
102
|
+
return (_jsxs(Box, Object.assign({ component: "li" }, props, { children: [_jsx(Avatar, { variant: "square", src: (_a = option.logo) !== null && _a !== void 0 ? _a : FALLBACK_LOGO_UNKNOWN_DEVICE, sx: { mr: 3, width: '20px', height: '20px' } }), _jsx(Typography, { noWrap: true, children: option.name })] })));
|
|
103
|
+
}, renderInput: (_a) => {
|
|
104
|
+
var _b;
|
|
105
|
+
var { InputProps } = _a, params = __rest(_a, ["InputProps"]);
|
|
106
|
+
return (_jsx(TextField, Object.assign({}, params, { label: _jsxs(Stack, { direction: "row", alignItems: "center", gap: 1, children: ["Device type", _jsx(Tooltip, { title: "Applications can support any devices that share the same architecture as their default device type.", children: _jsx(HelpIcon, { color: "info", sx: { fontSize: '1rem' } }) })] }), slotProps: {
|
|
107
|
+
input: Object.assign(Object.assign({}, InputProps), { startAdornment: (_jsx(Avatar, { variant: "square", src: (_b = model.deviceType.logo) !== null && _b !== void 0 ? _b : FALLBACK_LOGO_UNKNOWN_DEVICE, sx: { mr: 3, width: '20px', height: '20px' } })) }),
|
|
108
|
+
} })));
|
|
109
|
+
}, onChange: (_event, value) => {
|
|
110
|
+
if (!value) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
handleSelectedDeviceTypeChange(value);
|
|
114
|
+
}, disableClearable: true,
|
|
115
|
+
// TODO: consider whether there is a better solution than letting the width vary as you search
|
|
116
|
+
slotProps: {
|
|
117
|
+
popper: { sx: { width: 'fit-content' } },
|
|
118
|
+
}, sx: { flex: 1 } })), (!isInitialDefault || osType) &&
|
|
131
119
|
hasEsrVersions &&
|
|
132
|
-
model.deviceType && (_jsx(OsTypeSelector, { supportedOsTypes: osTypes, hasEsrVersions: hasEsrVersions !== null && hasEsrVersions !== void 0 ? hasEsrVersions : false, selectedOsTypeSlug: osType, onSelectedOsTypeChange: onSelectedOsTypeChange }))] }), !isInitialDefault && version && (_jsxs(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
120
|
+
model.deviceType && (_jsx(OsTypeSelector, { supportedOsTypes: osTypes, hasEsrVersions: hasEsrVersions !== null && hasEsrVersions !== void 0 ? hasEsrVersions : false, selectedOsTypeSlug: osType, onSelectedOsTypeChange: onSelectedOsTypeChange }))] }), !isInitialDefault && version && (_jsxs(Stack, { direction: "row", flexWrap: "wrap", maxWidth: "100%", gap: 2, alignItems: "center", children: [_jsx(Autocomplete, { fullWidth: true, id: "e2e-download-image-versions-list", value: version, getOptionLabel: (option) => option.value, isOptionEqualToValue: (option, value) => option.value === value.value, options: versionSelectionOpts, onChange: (_event, ver) => {
|
|
121
|
+
handleVersionChange(ver);
|
|
122
|
+
}, placeholder: "Choose a version...", renderOption: (props, option) => (_jsx(Box, Object.assign({ component: "li" }, props, { children: _jsx(VersionSelectItem, { option: option, isRecommended: option.value === recommendedVersion }) }))), renderInput: (_a) => {
|
|
123
|
+
var { InputProps } = _a, params = __rest(_a, ["InputProps"]);
|
|
124
|
+
return (_jsx(TextField, Object.assign({}, params, { slotProps: {
|
|
125
|
+
input: Object.assign(Object.assign({}, InputProps), { endAdornment: (_jsxs(_Fragment, { children: [version.value === recommendedVersion && (_jsx(Chip, { sx: { ml: 1 }, color: "green", label: "recommended" })), !!(version === null || version === void 0 ? void 0 : version.knownIssueList) && (_jsx(Tooltip, { title: version.knownIssueList, children: _jsx(FontAwesomeIcon, { icon: faTriangleExclamation, color: token('color.icon.warning') }) })), InputProps.endAdornment] })) }),
|
|
126
|
+
}, label: "OS version" })));
|
|
127
|
+
}, disableClearable: true, sx: { flex: 1 } }), showAllVersionsToggle && (_jsx(FormControlLabel, { control: _jsx(Checkbox, { id: "e2e-show-all-versions-check", checked: showAllVersions, onChange: handleShowAllVersions }), label: "Show outdated versions",
|
|
128
|
+
// TODO: Find a better way to center the checkbox with the input only (without the label)
|
|
129
|
+
sx: { mt: 3 } }))] })), _jsx(Divider, { variant: "fullWidth", flexItem: true, sx: { borderStyle: 'dashed' } }), (!isInitialDefault || !variant) && (_jsx(VariantSelector, { version: version, variant: variant, onVariantChange: (v) => {
|
|
130
|
+
handleVariantChange(v ? 'dev' : 'prod');
|
|
131
|
+
} })), _jsx(Divider, { variant: "fullWidth", flexItem: true, sx: { borderStyle: 'dashed' } }), _jsxs(Stack, { children: [_jsxs(FormControl, { children: [_jsx(FormLabel, { id: "network-radio-buttons-group-label", children: _jsx(Typography, { variant: "titleSm", children: "Network" }) }), _jsxs(RadioGroup, { "aria-labelledby": "network-radio-buttons-group-label", value: model.network, name: "network", onChange: (event) => {
|
|
132
|
+
onChange('network', event.target.value);
|
|
133
|
+
}, children: [_jsx(FormControlLabel, { value: "ethernet", control: _jsx(Radio, {}), label: "Ethernet only" }), _jsx(FormControlLabel, { value: "wifi", control: _jsx(Radio, {}), label: "Wifi + Ethernet" })] })] }), model.network === 'wifi' && (_jsxs(Stack, { gap: 3, children: [_jsx(TextField, { value: model.wifiSsid, id: "device-wifi-ssid", slotProps: {
|
|
144
134
|
htmlInput: {
|
|
145
135
|
name: 'wifiSsid',
|
|
146
136
|
autoComplete: 'wifiSsid-auto-complete',
|
|
147
137
|
},
|
|
148
138
|
}, onChange: (event) => {
|
|
149
|
-
onChange(
|
|
150
|
-
}
|
|
139
|
+
onChange('wifiSsid', event.target.value);
|
|
140
|
+
}, label: "WiFi SSID" }), _jsx(TextField, { type: showPassword ? 'text' : 'password', id: "device-wifi-password", value: model.wifiKey, slotProps: {
|
|
151
141
|
htmlInput: {
|
|
152
142
|
name: 'wifiKey',
|
|
153
143
|
},
|
|
@@ -160,37 +150,43 @@ export const ImageForm = memo(function ImageForm({ compatibleDeviceTypes, osVers
|
|
|
160
150
|
}, edge: "end", children: showPassword ? _jsx(VisibilityOff, {}) : _jsx(Visibility, {}) }) })),
|
|
161
151
|
},
|
|
162
152
|
}, onChange: (event) => {
|
|
163
|
-
onChange(
|
|
164
|
-
} })] }))] }), _jsx(Divider, { variant: "fullWidth", sx: {
|
|
153
|
+
onChange('wifiKey', event.target.value);
|
|
154
|
+
}, label: "Wifi Passphrase" })] }))] }), _jsx(Divider, { variant: "fullWidth", sx: { borderStyle: 'dashed' } }), _jsxs(Accordion, { disableGutters: true, elevation: 0, expanded: showAdvancedSettings, onChange: () => {
|
|
165
155
|
setShowAdvancedSettings(!showAdvancedSettings);
|
|
166
|
-
},
|
|
156
|
+
}, sx: {
|
|
157
|
+
border: 'none',
|
|
158
|
+
'&::before': {
|
|
159
|
+
display: 'none',
|
|
160
|
+
},
|
|
161
|
+
[`& .${accordionSummaryClasses.expandIconWrapper}.${accordionSummaryClasses.expanded}`]: {
|
|
162
|
+
transform: 'rotate(90deg)',
|
|
163
|
+
},
|
|
164
|
+
}, children: [_jsx(AccordionSummary, { expandIcon: _jsx(FontAwesomeIcon, { icon: faChevronRight }), sx: { flexDirection: 'row-reverse', gap: 2 }, children: _jsx(Typography, { variant: "titleSm", children: "Advanced settings" }) }), _jsxs(AccordionDetails, { sx: { display: 'flex', flexDirection: 'column', gap: 3 }, children: [_jsx(TextField, { value: model.appUpdatePollInterval, slotProps: {
|
|
165
|
+
htmlInput: {
|
|
166
|
+
name: 'appUpdatePollInterval',
|
|
167
|
+
autoComplete: 'appUpdatePollInterval-auto-complete',
|
|
168
|
+
},
|
|
169
|
+
}, onChange: (event) => {
|
|
170
|
+
onChange('appUpdatePollInterval', event.target.value);
|
|
171
|
+
}, label: _jsxs(Stack, { direction: "row", alignItems: "center", gap: 1, children: ["Check for updates every X minutes", ' ', _jsx(MUILinkWithTracking, { href: POLL_INTERVAL_DOCS, sx: {
|
|
167
172
|
display: 'flex',
|
|
168
173
|
alignItems: 'center',
|
|
169
174
|
height: '1.5rem',
|
|
170
|
-
}, children: _jsx(ArticleIcon, { sx: { ml: 1, fontSize: '1.15rem' } }) })] }), _jsx(TextField, {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
onChange({ provisioningKeyName: event.target.value });
|
|
186
|
-
} }), _jsx(InputLabel, { htmlFor: "provision-key-expiring", sx: { my: 2 }, children: "Provisioning Key expiring on" }), _jsx(TextField, { type: "date", id: "provision-key-expiring", value: (_b = model.provisioningKeyExpiryDate) !== null && _b !== void 0 ? _b : '', slotProps: {
|
|
187
|
-
htmlInput: {
|
|
188
|
-
name: 'provisioningKeyExpiryDate',
|
|
189
|
-
autoComplete: 'provisioningKeyExpiryDate-auto-complete',
|
|
190
|
-
},
|
|
191
|
-
}, onChange: (event) => {
|
|
192
|
-
onChange({ provisioningKeyExpiryDate: event.target.value });
|
|
193
|
-
} })] }) })] }));
|
|
175
|
+
}, children: _jsx(ArticleIcon, { sx: { ml: 1, fontSize: '1.15rem' } }) })] }) }), _jsx(TextField, { name: "provisioningKeyName", value: (_a = model.provisioningKeyName) !== null && _a !== void 0 ? _a : '', slotProps: {
|
|
176
|
+
htmlInput: {
|
|
177
|
+
name: 'provisioningKeyName',
|
|
178
|
+
autoComplete: 'provisioningKeyName-auto-complete',
|
|
179
|
+
},
|
|
180
|
+
}, onChange: (event) => {
|
|
181
|
+
onChange('provisioningKeyName', event.target.value);
|
|
182
|
+
}, label: "Provisioning Key name" }), _jsx(TextField, { type: "date", value: (_b = model.provisioningKeyExpiryDate) !== null && _b !== void 0 ? _b : '', slotProps: {
|
|
183
|
+
htmlInput: {
|
|
184
|
+
name: 'provisioningKeyExpiryDate',
|
|
185
|
+
autoComplete: 'provisioningKeyExpiryDate-auto-complete',
|
|
186
|
+
},
|
|
187
|
+
}, onChange: (event) => {
|
|
188
|
+
onChange('provisioningKeyExpiryDate', event.target.value);
|
|
189
|
+
}, label: "Provisioning Key expiring on" })] })] })] }));
|
|
194
190
|
});
|
|
195
191
|
// TODO: We need a better way than just copying the styling. Consider creating a component to export
|
|
196
192
|
const VersionSelectItem = ({ option, isRecommended, }) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Box, InputLabel, MenuItem, Select, Tooltip, Typography, } from '@mui/material';
|
|
2
|
+
import { Box, InputLabel, MenuItem, Select, Tooltip, Typography, Stack, } from '@mui/material';
|
|
3
3
|
import { getOsTypeName } from './utils';
|
|
4
4
|
import ArticleIcon from '@mui/icons-material/Article';
|
|
5
5
|
import { MUILinkWithTracking } from '../MUILinkWithTracking';
|
|
@@ -30,12 +30,12 @@ export const OsTypeSelector = ({ supportedOsTypes, hasEsrVersions, selectedOsTyp
|
|
|
30
30
|
};
|
|
31
31
|
});
|
|
32
32
|
const selectedOsType = selectOsTypes.find((osType) => osType.slug === selectedOsTypeSlug && osType.supportedForDeviceType);
|
|
33
|
-
return (_jsxs(
|
|
33
|
+
return (_jsxs(Stack, { flex: 1, children: [_jsx(Stack, { direction: "row", alignItems: "center", gap: 1, children: _jsxs(InputLabel, { id: "newAppApplicationType-label", sx: { display: 'flex', alignItems: 'center', gap: 1 }, children: ["OS type", _jsx(MUILinkWithTracking, { sx: { height: 12 }, href: "https://www.balena.io/docs/reference/OS/extended-support-release", children: _jsx(ArticleIcon, { sx: { fontSize: '1rem' } }) })] }) }), _jsx(Select, { id: "newAppApplicationType", fullWidth: true, disabled: supportedOsTypes.length === 0, value: (_a = selectedOsType === null || selectedOsType === void 0 ? void 0 : selectedOsType.slug) !== null && _a !== void 0 ? _a : OsTypesEnum.DEFAULT, renderValue: (selected) => (_jsx(Box, { display: "flex", width: "100%", children: _jsx(OsTypeOption, { osType: selectOsTypes.find((osType) => selected === osType.slug) }) })), onChange: (event) => {
|
|
34
34
|
const osType = selectOsTypes.find((os) => os.slug === event.target.value);
|
|
35
35
|
if (!osType.disabled) {
|
|
36
36
|
onSelectedOsTypeChange(osType.slug);
|
|
37
37
|
}
|
|
38
|
-
}, children: selectOsTypes.map((option) => (
|
|
38
|
+
}, sx: { flex: 1 }, children: selectOsTypes.map((option) => (
|
|
39
39
|
// TODO: Consider adding a tooltip for the disabled options
|
|
40
40
|
_jsx(MenuItem, { value: option.slug, disabled: option.disabled, children: _jsx(OsTypeOption, { osType: option }) }, option.slug))) })] }));
|
|
41
41
|
};
|
|
@@ -1,29 +1,30 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { FormControl, FormControlLabel, FormLabel, Radio, RadioGroup, Stack, Tooltip, Typography, } from '@mui/material';
|
|
3
3
|
import { MUILinkWithTracking } from '../MUILinkWithTracking';
|
|
4
4
|
import { getOsVariantDisplayText } from './utils';
|
|
5
5
|
import { Lightbulb } from '@mui/icons-material';
|
|
6
6
|
import { token } from '../../utils/token';
|
|
7
|
-
|
|
7
|
+
import { Callout } from '../Callout';
|
|
8
|
+
const variantInfo = (selected) => ({
|
|
8
9
|
dev: {
|
|
9
|
-
title: (_jsxs(
|
|
10
|
-
description: (_jsxs(
|
|
10
|
+
title: (_jsxs(Stack, { gap: 1, direction: "row", alignItems: "center", children: [_jsx(Typography, { children: getOsVariantDisplayText('dev') }), _jsxs(Typography, { variant: "bodySm", color: token('color.text.accent'), alignItems: "center", display: "flex", children: [_jsx(Lightbulb, { sx: { width: 14, height: 14 } }), "Recommended for first time users"] })] })),
|
|
11
|
+
description: (_jsxs(Stack, { gap: 1, children: [_jsxs(Typography, { children: ["Development images should be used when you are developing an application and want to use the fast", ' ', _jsx(MUILinkWithTracking, { href: "https://balena.io/docs/development/local-mode/", children: "local mode" }), ' ', "workflow."] }), selected === 'dev' && (_jsxs(Callout, { severity: "warning", size: "sm", children: ["This variant should never be used in production for security reasons.", ' ', _jsx(MUILinkWithTracking, { href: "https://docs.balena.io/reference/OS/overview/#development-vs-production-mode", children: "Learn more" }), "."] }))] })),
|
|
11
12
|
},
|
|
12
13
|
prod: {
|
|
13
14
|
title: _jsx(Typography, { children: getOsVariantDisplayText('prod') }),
|
|
14
15
|
description: (_jsx(_Fragment, { children: "Production images are ready for production deployments, but don't offer easy access for local development." })),
|
|
15
16
|
},
|
|
16
|
-
};
|
|
17
|
+
});
|
|
17
18
|
const BuildVariants = ['dev', 'prod'];
|
|
18
19
|
export const VariantSelector = ({ version, variant, onVariantChange, }) => {
|
|
19
|
-
return (_jsxs(FormControl, { children: [_jsx(FormLabel, { children: "
|
|
20
|
+
return (_jsxs(FormControl, { children: [_jsx(FormLabel, { children: _jsx(Typography, { variant: "titleSm", children: "Edition" }) }), _jsx(RadioGroup, { "aria-labelledby": "variant-radio-buttons-group", name: "developmentMode", value: variant === 'dev', onChange: (event) => {
|
|
20
21
|
onVariantChange(event.target.value === 'true');
|
|
21
|
-
}, children: BuildVariants.map((buildVariant, index) => {
|
|
22
|
+
}, sx: { gap: 2 }, children: BuildVariants.map((buildVariant, index) => {
|
|
22
23
|
const isDev = buildVariant === 'dev';
|
|
23
24
|
const isDisabled = version == null ||
|
|
24
25
|
(version.hasPrebuiltVariants && !version.rawVersions[buildVariant]);
|
|
25
26
|
return (_jsx(Tooltip, { title: isDisabled
|
|
26
27
|
? 'This edition is not available for the selected version'
|
|
27
|
-
: undefined, children: _jsxs(
|
|
28
|
-
}) }, "
|
|
28
|
+
: undefined, children: _jsxs(Stack, { children: [_jsx(FormControlLabel, { sx: { opacity: isDisabled ? 0.4 : 1 }, disabled: isDisabled, value: isDev, control: _jsx(Radio, {}), label: variantInfo(variant)[buildVariant].title }), _jsx(Typography, { sx: { opacity: isDisabled ? 0.4 : 1 }, variant: "bodySm", children: variantInfo(variant)[buildVariant].description })] }) }, index));
|
|
29
|
+
}) }, "variant")] }));
|
|
29
30
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Avatar,
|
|
2
|
+
import { Avatar, DialogActions, DialogContent, Divider, Grid2 as Grid, Stack, Typography, } from '@mui/material';
|
|
3
3
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
4
|
import { FALLBACK_LOGO_UNKNOWN_DEVICE, isUrlAccessible, stripVersionBuild, } from './utils';
|
|
5
5
|
import { ImageForm } from './ImageForm';
|
|
@@ -242,18 +242,18 @@ export const DownloadImageDialog = ({ open, applicationId, releaseId, compatible
|
|
|
242
242
|
const setOsTypeCallback = useCallback((osT) => {
|
|
243
243
|
setOsType(osT);
|
|
244
244
|
}, []);
|
|
245
|
-
const handleChange = useCallback((
|
|
245
|
+
const handleChange = useCallback((key, value) => {
|
|
246
246
|
let newFormModelState;
|
|
247
|
-
if (
|
|
248
|
-
newFormModelState = getInitialState(
|
|
247
|
+
if (key === 'deviceType') {
|
|
248
|
+
newFormModelState = getInitialState(value, applicationId, releaseId);
|
|
249
249
|
}
|
|
250
250
|
else {
|
|
251
|
-
newFormModelState = Object.assign(Object.assign({}, formModel),
|
|
251
|
+
newFormModelState = Object.assign(Object.assign({}, formModel), { [key]: value });
|
|
252
252
|
onFieldChange === null || onFieldChange === void 0 ? void 0 : onFieldChange(newFormModelState);
|
|
253
253
|
}
|
|
254
254
|
setFormModel(newFormModelState);
|
|
255
255
|
}, [formModel, applicationId, releaseId, onFieldChange]);
|
|
256
|
-
return (_jsxs(DialogWithCloseButton, { title: _jsxs(
|
|
256
|
+
return (_jsxs(DialogWithCloseButton, { title: _jsxs(Stack, { direction: "row", alignItems: "center", gap: 2, children: [_jsx(Avatar, { variant: "square", alt: defaultDisplayName, src: (_c = (_b = formModel.deviceType) === null || _b === void 0 ? void 0 : _b.logo) !== null && _c !== void 0 ? _c : FALLBACK_LOGO_UNKNOWN_DEVICE }), _jsx(Typography, { variant: "h5", children: "Add new device" })] }), open: open, onClose: onClose, maxWidth: "lg", fullWidth: true, children: [_jsx(DialogContent, { children: _jsx(Spinner, { show: isValidatingUrl, children: _jsxs(Grid, { container: true, spacing: [0, 0, 4], children: [_jsx(Grid, { size: {
|
|
257
257
|
xs: 12,
|
|
258
258
|
sm: 12,
|
|
259
259
|
md: 6,
|
|
@@ -277,11 +277,5 @@ export const DownloadImageDialog = ({ open, applicationId, releaseId, compatible
|
|
|
277
277
|
: '',
|
|
278
278
|
} })] }), ((_d = formModel.deviceType.imageDownloadAlerts) !== null && _d !== void 0 ? _d : []).map((alert) => {
|
|
279
279
|
return (_jsx(Grid, { pt: 0, size: 12, children: _jsx(Callout, { severity: alert.type, children: alert.message }, alert.message) }, alert.message));
|
|
280
|
-
})] }) }) }), _jsx(DialogActions, {
|
|
281
|
-
display: 'flex',
|
|
282
|
-
position: 'absolute',
|
|
283
|
-
bottom: 0,
|
|
284
|
-
right: 0,
|
|
285
|
-
justifyContent: 'end',
|
|
286
|
-
}, children: _jsx(DropDownButton, { className: "e2e-download-image-submit", items: actions, disabled: isValidatingUrl }) })] }));
|
|
280
|
+
})] }) }) }), _jsx(DialogActions, { children: _jsx(DropDownButton, { className: "e2e-download-image-submit", items: actions, disabled: isValidatingUrl }) })] }));
|
|
287
281
|
};
|
package/dist/theme.js
CHANGED
|
@@ -227,6 +227,16 @@ export const theme = createTheme({
|
|
|
227
227
|
full: shape.borderRadius.full.value,
|
|
228
228
|
},
|
|
229
229
|
components: {
|
|
230
|
+
MuiAccordionSummary: {
|
|
231
|
+
styleOverrides: {
|
|
232
|
+
root: { paddingLeft: 0, paddingRight: 0 },
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
MuiAccordionDetails: {
|
|
236
|
+
styleOverrides: {
|
|
237
|
+
root: { paddingLeft: 0, paddingRight: 0 },
|
|
238
|
+
},
|
|
239
|
+
},
|
|
230
240
|
MuiAlert: {
|
|
231
241
|
defaultProps: {
|
|
232
242
|
iconMapping: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@balena/ui-shared-components",
|
|
3
|
-
"version": "12.3.2
|
|
3
|
+
"version": "12.3.2",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"files": [
|
|
@@ -138,6 +138,6 @@
|
|
|
138
138
|
},
|
|
139
139
|
"homepage": "https://github.com/balena-io/ui-shared-components#readme",
|
|
140
140
|
"versionist": {
|
|
141
|
-
"publishedAt": "2025-04-
|
|
141
|
+
"publishedAt": "2025-04-18T15:47:01.137Z"
|
|
142
142
|
}
|
|
143
143
|
}
|