@bigbinary/neeto-custom-domains-frontend 3.1.13 → 3.1.14

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.
@@ -30,12 +30,17 @@
30
30
  "delete": "Delete custom domain?",
31
31
  "search": "Search custom domains",
32
32
  "notFound": "There are no custom domains to show.",
33
+ "tooltipContent": "Delete the currently added custom domain to add a new one.",
33
34
  "placeholder": "{{subdomainPlaceholder,anyCase}}.yourbusiness.com",
34
- "redirectionTooltipDescription": "Visiting {{fromDomain}} will redirect you to {{toDomain}}.",
35
+ "activeTooltipDescription": "Your custom domain is active.",
36
+ "pendingTooltipDescription": "Your custom domain is pending validation.",
37
+ "failedTooltipDescription": "Your custom domain is failed to validate. Please try again later.",
38
+ "redirectionTooltipDescription": "Your custom domain is active. Visiting <b>{{fromDomain}}</b> will redirect you to <b>{{toDomain}}</b>.",
35
39
  "cname": "CNAME",
36
40
  "label": "Domain name",
37
41
  "domainValidation": "Domain validation",
38
42
  "domainRedirection": "Domain redirection",
43
+ "domainValidationTitle": "Add the DNS record to your DNS provider",
39
44
  "cnameRecordTitle": "Setting up {{domainName}}",
40
45
  "cnameRecordInfo": "Go to your DNS provider and add the following DNS record by copying the exact settings listed below. View <Link>help article</Link> to understand how to add a DNS record.",
41
46
  "dnsProviderCnameRecordInfo": "We have detected that {{dnsProvider,anyCase}} is your DNS provider. Please <Login>log in</Login> to your {{dnsProvider,anyCase}} account and add the following DNS record by copying the exact settings listed below. View <Link>help article</Link> for adding DNS record in {{dnsProvider,anyCase}}.",
@@ -90,8 +95,8 @@
90
95
  "customDomain": "Add domain of your choice in case you do not prefer to use the default Neeto domain."
91
96
  },
92
97
  "noData": {
93
- "title": "There are no custom domains to show.",
94
- "helpText": "Here is how you can <helpLink>add a custom domain</helpLink>."
98
+ "title": "No custom domain has been added.",
99
+ "helpText": "Add your custom domain to have a personalized URL."
95
100
  }
96
101
  }
97
102
  }
@@ -11,16 +11,17 @@ import axios from 'axios';
11
11
  import Alert from '@bigbinary/neetoui/Alert';
12
12
  import { Trans, useTranslation } from 'react-i18next';
13
13
  import { jsx, jsxs } from 'react/jsx-runtime';
14
+ import classNames from 'classnames';
14
15
  import { SINGULAR } from '@bigbinary/neeto-commons-frontend/constants';
15
- import { hyphenize } from '@bigbinary/neeto-commons-frontend/utils/general';
16
- import Redirection from '@bigbinary/neeto-icons/Redirection';
16
+ import CustomDomain$1 from '@bigbinary/neeto-icons/CustomDomain';
17
+ import ExternalLink from '@bigbinary/neeto-icons/ExternalLink';
17
18
  import CardLayout from '@bigbinary/neeto-molecules/CardLayout';
18
19
  import MoreDropdown from '@bigbinary/neeto-molecules/MoreDropdown';
19
20
  import Button from '@bigbinary/neetoui/Button';
20
21
  import Typography from '@bigbinary/neetoui/Typography';
21
- import Tag from '@bigbinary/neetoui/Tag';
22
- import NoData from '@bigbinary/neetoui/NoData';
23
- import Tooltip from '@bigbinary/neetoui/Tooltip';
22
+ import CheckCircle from '@bigbinary/neeto-icons/CheckCircle';
23
+ import Warning2 from '@bigbinary/neeto-icons/Warning2';
24
+ import CloseCircle from '@bigbinary/neeto-icons/CloseCircle';
24
25
  import Pane from '@bigbinary/neetoui/Pane';
25
26
  import Stepper from '@bigbinary/neetoui/Stepper';
26
27
  import Callout from '@bigbinary/neetoui/Callout';
@@ -29,6 +30,8 @@ import Input from '@bigbinary/neetoui/formik/Input';
29
30
  import Form from '@bigbinary/neetoui/formik/Form';
30
31
  import Radio from '@bigbinary/neetoui/formik/Radio';
31
32
  import { t as t$1 } from 'i18next';
33
+ import Tag from '@bigbinary/neetoui/Tag';
34
+ import Tooltip from '@bigbinary/neetoui/Tooltip';
32
35
  import psl from 'psl';
33
36
  import { isNil } from 'ramda';
34
37
  import * as Yup from 'yup';
@@ -142,13 +145,17 @@ var STATUS_TAG_STYLES = {
142
145
  pending: "warning",
143
146
  failed: "danger"
144
147
  };
148
+ var STATUS_ICON = {
149
+ active: CheckCircle,
150
+ pending: Warning2,
151
+ failed: CloseCircle
152
+ };
145
153
 
146
154
  var Domain = function Domain(_ref) {
147
155
  var isCustomDomainAdded = _ref.isCustomDomainAdded,
148
156
  openPane = _ref.openPane,
149
157
  customDomains = _ref.customDomains,
150
158
  openDeleteAlert = _ref.openDeleteAlert,
151
- helpDocUrl = _ref.helpDocUrl,
152
159
  setSelectedCustomDomain = _ref.setSelectedCustomDomain;
153
160
  var _useTranslation = useTranslation(),
154
161
  t = _useTranslation.t;
@@ -161,101 +168,131 @@ var Domain = function Domain(_ref) {
161
168
  openDeleteAlert();
162
169
  };
163
170
  return isCustomDomainAdded ? /*#__PURE__*/jsx(CardLayout, {
164
- title: t("neetoCustomDomains.connectionTitle"),
165
- children: /*#__PURE__*/jsxs("div", {
166
- className: "space-y-1",
167
- children: [customDomains === null || customDomains === void 0 ? void 0 : customDomains.map(function (customDomain, index) {
168
- var _customDomain$redirec, _customDomain$redirec2;
171
+ actionBlock: /*#__PURE__*/jsx(Button, {
172
+ disabled: isCustomDomainAdded,
173
+ label: t("neetoCustomDomains.actions.add", {
174
+ what: t("neetoCustomDomains.customDomain", SINGULAR)
175
+ }),
176
+ tooltipProps: {
177
+ content: t("neetoCustomDomains.tooltipContent")
178
+ },
179
+ onClick: openPane
180
+ }),
181
+ children: /*#__PURE__*/jsx("div", {
182
+ className: "flex flex-col gap-y-6 divide-y divide-gray-200",
183
+ children: customDomains === null || customDomains === void 0 ? void 0 : customDomains.map(function (customDomain, index) {
184
+ var _customDomain$redirec;
169
185
  return /*#__PURE__*/jsxs("div", {
170
- className: "neeto-ui-border-gray-200 neeto-ui-rounded neeto-ui-bg-gray-50 flex items-center justify-between border p-2",
186
+ className: "flex items-center gap-x-3 pb-6 last:pb-0",
171
187
  "data-cy": "custom-domain-item",
172
- children: [/*#__PURE__*/jsxs("div", {
173
- className: "flex items-center space-x-2",
174
- children: [/*#__PURE__*/jsx(Typography, {
175
- "data-cy": "custom-domain-host-name",
176
- style: "body2",
177
- children: customDomain === null || customDomain === void 0 ? void 0 : customDomain.hostname
178
- }), /*#__PURE__*/jsx(Tag, {
179
- "data-cy": "".concat(hyphenize(customDomain === null || customDomain === void 0 ? void 0 : customDomain.status), "-tag-container"),
180
- style: STATUS_TAG_STYLES[customDomain === null || customDomain === void 0 ? void 0 : customDomain.status],
181
- label: t("neetoCustomDomains.status.domain.".concat(customDomain === null || customDomain === void 0 ? void 0 : customDomain.status))
182
- })]
188
+ children: [/*#__PURE__*/jsx("div", {
189
+ className: classNames("neeto-ui-rounded-lg flex items-center justify-center p-2", {
190
+ "neeto-ui-bg-success-100": (customDomain === null || customDomain === void 0 ? void 0 : customDomain.status) === "active",
191
+ "neeto-ui-bg-warning-100": (customDomain === null || customDomain === void 0 ? void 0 : customDomain.status) === "pending",
192
+ "neeto-ui-bg-error-100": (customDomain === null || customDomain === void 0 ? void 0 : customDomain.status) === "failed"
193
+ }),
194
+ children: function () {
195
+ var IconComponent = STATUS_ICON[customDomain === null || customDomain === void 0 ? void 0 : customDomain.status] || CustomDomain$1;
196
+ return /*#__PURE__*/jsx(IconComponent, {
197
+ size: 32,
198
+ className: classNames({
199
+ "neeto-ui-text-success-800": (customDomain === null || customDomain === void 0 ? void 0 : customDomain.status) === "active",
200
+ "neeto-ui-text-warning-800": (customDomain === null || customDomain === void 0 ? void 0 : customDomain.status) === "pending",
201
+ "neeto-ui-text-error-800": (customDomain === null || customDomain === void 0 ? void 0 : customDomain.status) === "failed"
202
+ })
203
+ });
204
+ }()
183
205
  }), /*#__PURE__*/jsxs("div", {
184
- className: "flex items-center gap-2",
185
- children: [(customDomain === null || customDomain === void 0 ? void 0 : customDomain.redirection) && /*#__PURE__*/jsx(Tooltip, {
186
- content: t("neetoCustomDomains.redirectionTooltipDescription", {
187
- fromDomain: customDomain === null || customDomain === void 0 ? void 0 : customDomain.hostname,
188
- toDomain: customDomain === null || customDomain === void 0 || (_customDomain$redirec = customDomain.redirection) === null || _customDomain$redirec === void 0 ? void 0 : _customDomain$redirec.toHostname
189
- }),
190
- children: /*#__PURE__*/jsx(Tag, {
191
- icon: Redirection,
192
- label: customDomain === null || customDomain === void 0 || (_customDomain$redirec2 = customDomain.redirection) === null || _customDomain$redirec2 === void 0 ? void 0 : _customDomain$redirec2.toHostname,
193
- style: "secondary"
194
- })
195
- }), /*#__PURE__*/jsx(MoreDropdown, {
196
- dropdownButtonProps: {
197
- "data-testid": "nui-dropdown-icon-".concat(customDomain === null || customDomain === void 0 ? void 0 : customDomain.id),
198
- "data-cy": "custom-domains-more-dropdown-button"
199
- },
200
- dropdownProps: {
201
- position: "bottom-end",
202
- strategy: "fixed",
203
- autoWidth: true
204
- },
205
- menuItems: [{
206
- label: t("neetoCustomDomains.actions.edit"),
206
+ className: "flex flex-col gap-y-1",
207
+ children: [/*#__PURE__*/jsxs("div", {
208
+ className: "flex items-center gap-x-3",
209
+ children: [/*#__PURE__*/jsxs("div", {
210
+ className: "hover:neeto-ui-text-accent-800 flex cursor-pointer items-center gap-x-2",
207
211
  onClick: function onClick() {
208
- return handleEditClick(customDomain);
212
+ return window.open("https://".concat(customDomain === null || customDomain === void 0 ? void 0 : customDomain.hostname), "_blank", "noopener,noreferrer");
209
213
  },
210
- key: "edit-custom-domain-button",
211
- "data-cy": "edit-custom-domain-button"
212
- }, {
213
- label: t("neetoCustomDomains.actions.delete"),
214
- onClick: function onClick() {
215
- return handleDeleteClick(customDomain);
214
+ children: [/*#__PURE__*/jsx(Typography, {
215
+ className: "hover:neeto-ui-text-accent-800",
216
+ style: "h4",
217
+ weight: "medium",
218
+ children: customDomain === null || customDomain === void 0 ? void 0 : customDomain.hostname
219
+ }), (customDomain === null || customDomain === void 0 ? void 0 : customDomain.status) === "active" && /*#__PURE__*/jsx(ExternalLink, {
220
+ size: 16
221
+ })]
222
+ }), /*#__PURE__*/jsx(MoreDropdown, {
223
+ dropdownButtonProps: {
224
+ "data-testid": "nui-dropdown-icon-".concat(customDomain === null || customDomain === void 0 ? void 0 : customDomain.id),
225
+ "data-cy": "custom-domains-more-dropdown-button",
226
+ isRounded: true,
227
+ style: "tertiary",
228
+ size: "small"
229
+ },
230
+ dropdownProps: {
231
+ position: "bottom-end",
232
+ strategy: "fixed",
233
+ autoWidth: true
234
+ },
235
+ menuItems: [{
236
+ label: t("neetoCustomDomains.actions.edit"),
237
+ onClick: function onClick() {
238
+ return handleEditClick(customDomain);
239
+ },
240
+ key: "edit-custom-domain-button",
241
+ "data-cy": "edit-custom-domain-button"
242
+ }, {
243
+ label: t("neetoCustomDomains.actions.delete"),
244
+ onClick: function onClick() {
245
+ return handleDeleteClick(customDomain);
246
+ },
247
+ key: "delete-custom-domain",
248
+ "data-cy": "delete-custom-domain-button"
249
+ }]
250
+ })]
251
+ }), /*#__PURE__*/jsxs(Typography, {
252
+ className: "neeto-ui-text-gray-600",
253
+ style: "body2",
254
+ children: [(customDomain === null || customDomain === void 0 ? void 0 : customDomain.status) === "active" && (customDomain === null || customDomain === void 0 ? void 0 : customDomain.redirection) && /*#__PURE__*/jsx(Trans, {
255
+ components: {
256
+ b: /*#__PURE__*/jsx("b", {})
216
257
  },
217
- key: "delete-custom-domain",
218
- "data-cy": "delete-custom-domain-button"
219
- }]
258
+ i18nKey: "neetoCustomDomains.redirectionTooltipDescription",
259
+ values: {
260
+ fromDomain: customDomain === null || customDomain === void 0 ? void 0 : customDomain.hostname,
261
+ toDomain: customDomain === null || customDomain === void 0 || (_customDomain$redirec = customDomain.redirection) === null || _customDomain$redirec === void 0 ? void 0 : _customDomain$redirec.toHostname
262
+ }
263
+ }), (customDomain === null || customDomain === void 0 ? void 0 : customDomain.status) === "active" && !(customDomain !== null && customDomain !== void 0 && customDomain.redirection) && t("neetoCustomDomains.activeTooltipDescription"), (customDomain === null || customDomain === void 0 ? void 0 : customDomain.status) === "pending" && t("neetoCustomDomains.pendingTooltipDescription"), (customDomain === null || customDomain === void 0 ? void 0 : customDomain.status) === "failed" && t("neetoCustomDomains.failedTooltipDescription")]
220
264
  })]
221
265
  })]
222
266
  }, index);
223
- }), /*#__PURE__*/jsx(Typography, {
224
- style: "body2",
225
- children: /*#__PURE__*/jsx(Trans, {
226
- i18nKey: "neetoCustomDomains.readHelpArticle",
227
- components: {
228
- Link: /*#__PURE__*/jsx(Button, {
229
- href: helpDocUrl,
230
- rel: "noreferrer",
231
- style: "link",
232
- target: "_blank"
233
- })
234
- }
235
- })
236
- })]
267
+ })
237
268
  })
238
- }) : /*#__PURE__*/jsx("div", {
239
- className: "flex h-full w-full items-center justify-center",
240
- children: /*#__PURE__*/jsx(NoData, {
241
- className: "w-full",
242
- title: t("neetoCustomDomains.noData.title"),
243
- helpText: /*#__PURE__*/jsx(Trans, {
244
- i18nKey: "neetoCustomDomains.noData.helpText",
245
- components: {
246
- helpLink: /*#__PURE__*/jsx(Button, {
247
- href: helpDocUrl,
248
- style: "link",
249
- target: "_blank"
250
- })
251
- }
269
+ }) : /*#__PURE__*/jsx(CardLayout, {
270
+ actionBlock: /*#__PURE__*/jsx(Button, {
271
+ label: t("neetoCustomDomains.actions.add", {
272
+ what: t("neetoCustomDomains.customDomain", SINGULAR)
252
273
  }),
253
- primaryButtonProps: {
254
- label: t("neetoCustomDomains.actions.add", {
255
- what: t("neetoCustomDomains.customDomain", SINGULAR)
256
- }),
257
- onClick: openPane
258
- }
274
+ onClick: openPane
275
+ }),
276
+ children: /*#__PURE__*/jsxs("div", {
277
+ className: "flex h-full w-full items-center gap-x-3",
278
+ children: [/*#__PURE__*/jsx("div", {
279
+ className: "neeto-ui-bg-gray-100 neeto-ui-rounded-lg flex items-center justify-center p-2",
280
+ children: /*#__PURE__*/jsx(CustomDomain$1, {
281
+ className: "neeto-ui-text-gray-600",
282
+ size: 32
283
+ })
284
+ }), /*#__PURE__*/jsxs("div", {
285
+ className: "flex flex-col gap-y-1",
286
+ children: [/*#__PURE__*/jsx(Typography, {
287
+ style: "h4",
288
+ weight: "medium",
289
+ children: t("neetoCustomDomains.noData.title")
290
+ }), /*#__PURE__*/jsx(Typography, {
291
+ className: "neeto-ui-text-gray-600",
292
+ style: "body2",
293
+ children: t("neetoCustomDomains.noData.helpText")
294
+ })]
295
+ })]
259
296
  })
260
297
  });
261
298
  };
@@ -1055,21 +1092,21 @@ var Validation = function Validation(_ref) {
1055
1092
  var _dnsHelpDocs$dnsProvi, _dnsHelpDocs$dnsProvi2, _dnsHelpDocs$unknown;
1056
1093
  var children = _ref3.children;
1057
1094
  return /*#__PURE__*/jsx(Button, {
1095
+ label: children,
1058
1096
  rel: "noreferrer",
1059
1097
  style: "link",
1060
1098
  target: "_blank",
1061
- href: (_dnsHelpDocs$dnsProvi = (_dnsHelpDocs$dnsProvi2 = dnsHelpDocs[dnsProvider]) === null || _dnsHelpDocs$dnsProvi2 === void 0 ? void 0 : _dnsHelpDocs$dnsProvi2[domainType]) !== null && _dnsHelpDocs$dnsProvi !== void 0 ? _dnsHelpDocs$dnsProvi : (_dnsHelpDocs$unknown = dnsHelpDocs.unknown) === null || _dnsHelpDocs$unknown === void 0 ? void 0 : _dnsHelpDocs$unknown[domainType],
1062
- label: children
1099
+ href: (_dnsHelpDocs$dnsProvi = (_dnsHelpDocs$dnsProvi2 = dnsHelpDocs[dnsProvider]) === null || _dnsHelpDocs$dnsProvi2 === void 0 ? void 0 : _dnsHelpDocs$dnsProvi2[domainType]) !== null && _dnsHelpDocs$dnsProvi !== void 0 ? _dnsHelpDocs$dnsProvi : (_dnsHelpDocs$unknown = dnsHelpDocs.unknown) === null || _dnsHelpDocs$unknown === void 0 ? void 0 : _dnsHelpDocs$unknown[domainType]
1063
1100
  });
1064
1101
  };
1065
1102
  var LoginLink = function LoginLink(_ref4) {
1066
1103
  var children = _ref4.children;
1067
1104
  return /*#__PURE__*/jsx(Button, {
1068
1105
  href: dnsProviderInfo === null || dnsProviderInfo === void 0 ? void 0 : dnsProviderInfo.loginUrl,
1106
+ label: children,
1069
1107
  rel: "noreferrer",
1070
1108
  style: "link",
1071
- target: "_blank",
1072
- label: children
1109
+ target: "_blank"
1073
1110
  });
1074
1111
  };
1075
1112
  var components = {
@@ -1080,21 +1117,25 @@ var Validation = function Validation(_ref) {
1080
1117
  return /*#__PURE__*/jsxs("div", {
1081
1118
  children: [/*#__PURE__*/jsxs(Pane.Body, {
1082
1119
  className: "space-y-4",
1083
- children: [/*#__PURE__*/jsx("div", {
1120
+ children: [/*#__PURE__*/jsxs("div", {
1084
1121
  className: "space-y-2",
1085
- children: /*#__PURE__*/jsx(Typography, {
1122
+ children: [/*#__PURE__*/jsx(Typography, {
1123
+ style: "h4",
1124
+ weight: "medium",
1125
+ children: t("neetoCustomDomains.domainValidationTitle")
1126
+ }), /*#__PURE__*/jsx(Typography, {
1086
1127
  style: "body2",
1087
1128
  children: dnsProvider !== "unknown" ? /*#__PURE__*/jsx(Trans, {
1129
+ components: components,
1088
1130
  i18nKey: "neetoCustomDomains.dnsProviderCnameRecordInfo",
1089
1131
  values: {
1090
1132
  dnsProvider: dnsProviderInfo === null || dnsProviderInfo === void 0 ? void 0 : dnsProviderInfo.name
1091
- },
1092
- components: components
1133
+ }
1093
1134
  }) : /*#__PURE__*/jsx(Trans, {
1094
- i18nKey: "neetoCustomDomains.cnameRecordInfo",
1095
- components: components
1135
+ components: components,
1136
+ i18nKey: "neetoCustomDomains.cnameRecordInfo"
1096
1137
  })
1097
- })
1138
+ })]
1098
1139
  }), /*#__PURE__*/jsx("div", {
1099
1140
  className: "space-y-1",
1100
1141
  children: /*#__PURE__*/jsx(Table, {
@@ -1117,17 +1158,17 @@ var Validation = function Validation(_ref) {
1117
1158
  children: /*#__PURE__*/jsx(Typography, {
1118
1159
  style: "body2",
1119
1160
  children: dnsProvider !== "unknown" ? /*#__PURE__*/jsx(Trans, {
1161
+ components: components,
1120
1162
  i18nKey: "neetoCustomDomains.domainValidationFailedForKnownProvider",
1121
1163
  values: {
1122
1164
  dnsProvider: dnsProviderInfo.name
1123
- },
1124
- components: components
1165
+ }
1125
1166
  }) : /*#__PURE__*/jsx(Trans, {
1167
+ components: components,
1126
1168
  i18nKey: "neetoCustomDomains.domainValidationFailedForUnknownProvider",
1127
1169
  values: {
1128
1170
  dnsProvider: dnsProviderInfo.name
1129
- },
1130
- components: components
1171
+ }
1131
1172
  })
1132
1173
  })
1133
1174
  }), isNotEmpty(errorKey) && status === "pending" && /*#__PURE__*/jsx(Callout, {
@@ -1150,8 +1191,8 @@ var Validation = function Validation(_ref) {
1150
1191
  label: t("neetoCustomDomains.validation.buttonLabel.iHaveAddedTheRecords"),
1151
1192
  onClick: validateDomain
1152
1193
  }), /*#__PURE__*/jsx(Button, {
1153
- label: t("neetoCustomDomains.actions.cancel"),
1154
1194
  "data-cy": "cancel-button",
1195
+ label: t("neetoCustomDomains.actions.cancel"),
1155
1196
  style: "text",
1156
1197
  onClick: onClose
1157
1198
  })]
@@ -1209,18 +1250,12 @@ var DomainPane = function DomainPane(_ref) {
1209
1250
  style: "h2",
1210
1251
  children: t("neetoCustomDomains.addNew")
1211
1252
  }), /*#__PURE__*/jsx("div", {
1212
- className: "-ml-2 neeto_custom_domain_stepper",
1253
+ className: "neeto_custom_domain_stepper -ml-2",
1213
1254
  children: /*#__PURE__*/jsx(Stepper, {
1214
1255
  activeIndex: CURRENT_STEP[getCurrentStep(primaryDomain)],
1215
1256
  setActiveIndex: noop,
1216
1257
  steps: STEPS
1217
1258
  })
1218
- }), primaryDomain && /*#__PURE__*/jsx(Typography, {
1219
- style: "h4",
1220
- weight: "medium",
1221
- children: t("neetoCustomDomains.cnameRecordTitle", {
1222
- domainName: primaryDomain.hostname
1223
- })
1224
1259
  })]
1225
1260
  }), function (_primaryDomain$hostna) {
1226
1261
  var currentStep = getCurrentStep(primaryDomain);
@@ -1229,7 +1264,7 @@ var DomainPane = function DomainPane(_ref) {
1229
1264
  var shouldShowLoader = isLoading || isStrategyStep && isSubdomain;
1230
1265
  if (shouldShowLoader) {
1231
1266
  return /*#__PURE__*/jsx("div", {
1232
- className: "flex justify-center items-center grow w-full",
1267
+ className: "flex w-full grow items-center justify-center",
1233
1268
  children: /*#__PURE__*/jsx(Spinner, {})
1234
1269
  });
1235
1270
  }