nucleus-core-ts 0.10.147 → 0.10.151
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/LICENSE +48 -48
- package/dist/.build-ok +1 -1
- package/dist/fe/components/AuthorizationPage/labels.js +13 -13
- package/dist/fe/components/Captcha/labels.js +17 -17
- package/dist/fe/components/ChatPanel/helpers.js +17 -17
- package/dist/fe/components/ChatPanel/labels.js +16 -16
- package/dist/fe/components/DataTable/labels.js +16 -16
- package/dist/fe/components/DevicesPage/components/DeviceCard.js +15 -15
- package/dist/fe/components/DevicesPage/components/DevicesPage.js +9 -9
- package/dist/fe/components/DevicesPage/labels.js +12 -12
- package/dist/fe/components/ForgotPasswordPage/labels.js +8 -8
- package/dist/fe/components/FormBuilder/components/FormField.js +5 -5
- package/dist/fe/components/FormBuilder/utils/fieldMapping.js +9 -9
- package/dist/fe/components/IntegrationsPage/components/ConnectionAuthFields.js +8 -8
- package/dist/fe/components/IntegrationsPage/components/ConnectionBasicFields.js +3 -3
- package/dist/fe/components/IntegrationsPage/components/ConnectionExport.js +23 -23
- package/dist/fe/components/IntegrationsPage/components/ConnectionForm.js +22 -22
- package/dist/fe/components/IntegrationsPage/components/ConnectionList.js +7 -7
- package/dist/fe/components/IntegrationsPage/components/ConnectionOauthFields.js +6 -6
- package/dist/fe/components/IntegrationsPage/components/ConnectionSettingsTab.js +24 -24
- package/dist/fe/components/IntegrationsPage/components/ConnectionSwitcher.js +19 -19
- package/dist/fe/components/IntegrationsPage/components/ConnectionTabs.js +15 -15
- package/dist/fe/components/IntegrationsPage/components/ConnectionTest.js +21 -21
- package/dist/fe/components/IntegrationsPage/components/ConnectionTransfer.js +18 -18
- package/dist/fe/components/IntegrationsPage/components/CredentialFields.js +19 -19
- package/dist/fe/components/IntegrationsPage/components/CredentialSlotRow.js +8 -8
- package/dist/fe/components/IntegrationsPage/components/EndpointForm.js +7 -7
- package/dist/fe/components/IntegrationsPage/components/EndpointFormFields.js +12 -12
- package/dist/fe/components/IntegrationsPage/components/EndpointList.js +7 -7
- package/dist/fe/components/IntegrationsPage/components/EndpointSample.js +36 -36
- package/dist/fe/components/IntegrationsPage/components/EndpointsTab.js +29 -29
- package/dist/fe/components/IntegrationsPage/components/FieldMappingRow.js +7 -7
- package/dist/fe/components/IntegrationsPage/components/FieldMappingRows.js +6 -6
- package/dist/fe/components/IntegrationsPage/components/IntegrationsPage.js +60 -60
- package/dist/fe/components/IntegrationsPage/components/MappingAccountFields.js +15 -15
- package/dist/fe/components/IntegrationsPage/components/MappingEditor.js +9 -9
- package/dist/fe/components/IntegrationsPage/components/MappingList.js +23 -23
- package/dist/fe/components/IntegrationsPage/components/MappingPasswordField.js +12 -12
- package/dist/fe/components/IntegrationsPage/components/MappingScheduleFields.js +23 -23
- package/dist/fe/components/IntegrationsPage/components/MappingWriteModeFields.js +31 -31
- package/dist/fe/components/IntegrationsPage/components/MappingsTab.js +56 -56
- package/dist/fe/components/IntegrationsPage/components/PaginationFields.js +11 -11
- package/dist/fe/components/IntegrationsPage/components/ParamBindingRows.js +15 -15
- package/dist/fe/components/IntegrationsPage/components/Primitives.js +28 -28
- package/dist/fe/components/IntegrationsPage/components/ReferenceCheckRows.js +9 -9
- package/dist/fe/components/IntegrationsPage/components/RunConfirmStep.js +6 -6
- package/dist/fe/components/IntegrationsPage/components/RunHistory.js +6 -6
- package/dist/fe/components/IntegrationsPage/components/RunHistoryRow.js +9 -9
- package/dist/fe/components/IntegrationsPage/components/RunPanel.js +40 -40
- package/dist/fe/components/IntegrationsPage/components/RunPasswordField.js +18 -18
- package/dist/fe/components/IntegrationsPage/components/RunPlanIssues.js +6 -6
- package/dist/fe/components/IntegrationsPage/components/RunPlanReferences.js +12 -12
- package/dist/fe/components/IntegrationsPage/components/RunPlanSuggestions.js +11 -11
- package/dist/fe/components/IntegrationsPage/components/RunPlanSummary.js +6 -6
- package/dist/fe/components/IntegrationsPage/components/RunProgressBar.js +6 -6
- package/dist/fe/components/IntegrationsPage/components/RunRevertConflicts.js +6 -6
- package/dist/fe/components/IntegrationsPage/components/Skeletons.js +7 -7
- package/dist/fe/components/IntegrationsPage/components/authOptions.js +4 -4
- package/dist/fe/components/IntegrationsPage/components/connectionDraft.js +27 -27
- package/dist/fe/components/IntegrationsPage/components/credentialSlots.js +25 -25
- package/dist/fe/components/IntegrationsPage/components/deleteIsConfirmed.js +9 -9
- package/dist/fe/components/IntegrationsPage/components/fieldMappingOptions.js +4 -4
- package/dist/fe/components/IntegrationsPage/components/formSupport.js +34 -34
- package/dist/fe/components/IntegrationsPage/components/jsonArray.js +14 -14
- package/dist/fe/components/IntegrationsPage/components/jsonObjectField.js +15 -15
- package/dist/fe/components/IntegrationsPage/components/mappingDraft.js +10 -10
- package/dist/fe/components/IntegrationsPage/components/mappingStaleness.js +22 -22
- package/dist/fe/components/IntegrationsPage/components/nextRuns.js +8 -8
- package/dist/fe/components/IntegrationsPage/components/passwordIsNeeded.js +13 -13
- package/dist/fe/components/IntegrationsPage/components/pathParams.js +6 -6
- package/dist/fe/components/IntegrationsPage/components/runFormat.js +18 -18
- package/dist/fe/components/IntegrationsPage/components/settleOwnership.js +18 -18
- package/dist/fe/components/IntegrationsPage/components/useInfiniteList.js +8 -8
- package/dist/fe/components/IntegrationsPage/store/index.js +20 -20
- package/dist/fe/components/IntegrationsPage/store/upsertInto.js +12 -12
- package/dist/fe/components/IntegrationsPage/text/context.js +6 -6
- package/dist/fe/components/IntegrationsPage/text/index.js +18 -18
- package/dist/fe/components/IntegrationsPage/theme/index.js +29 -29
- package/dist/fe/components/IntegrationsPage/types/records.js +10 -10
- package/dist/fe/components/IntegrationsPage/types/results.js +3 -3
- package/dist/fe/components/NotificationCenter/labels.js +17 -17
- package/dist/fe/components/ProfilePage/labels.js +10 -10
- package/dist/fe/components/ResetPasswordPage/labels.js +4 -4
- package/dist/fe/components/SetPasswordPage/labels.js +11 -11
- package/dist/fe/components/UsersPage/labels.js +14 -14
- package/dist/fe/utils/columnUtils.js +24 -24
- package/dist/fe/utils/searchFold.js +36 -36
- package/dist/index.js +6 -6
- package/dist/server.js +6 -6
- package/dist/src/Client/Proxy/authz.js +4 -4
- package/dist/src/Client/Proxy/httpProxy.js +136 -136
- package/dist/src/Client/Proxy/largeBody.js +29 -29
- package/dist/src/Client/Proxy/utils.js +32 -32
- package/dist/src/Client/Proxy/wsProxy.js +59 -59
- package/dist/src/Managers/Redis/index.d.ts +14 -0
- package/dist/src/Nucleus/routes/auth/admin/impersonationStore.d.ts +3 -4
- package/dist/src/Nucleus/routes/auth/refresh/issuedPair.d.ts +67 -0
- package/dist/src/Nucleus/routes/auth/refresh/recordIssued.d.ts +15 -6
- package/dist/src/Nucleus/routes/auth/refresh/refreshChain.d.ts +56 -0
- package/dist/src/Services/Auth/SessionStore/utils.d.ts +2 -0
- package/dist/src/Shared/cron.js +71 -71
- package/dist/src/Shared/redactSecrets.js +156 -156
- package/dist/src/Shared/redaction/bare.js +61 -61
- package/dist/src/Shared/redaction/floor.js +48 -48
- package/dist/src/Shared/redaction/freeText.js +70 -70
- package/dist/src/Shared/redaction/json.js +30 -30
- package/dist/src/Shared/redaction/lists.js +23 -23
- package/dist/src/Shared/redaction/markers.js +28 -28
- package/dist/src/Shared/redaction/names.js +49 -49
- package/dist/src/Shared/redaction/pairs.js +54 -54
- package/dist/src/Shared/redaction/secretString.js +29 -29
- package/dist/src/Shared/redaction/structured.js +52 -52
- package/dist/src/Shared/redaction/walk.js +25 -25
- package/infra/scripts/generate-project.ts +766 -766
- package/infra/templates/README.md +57 -57
- package/infra/templates/backend/.dockerignore +9 -9
- package/infra/templates/backend/.env.example +15 -15
- package/infra/templates/backend/README.md +28 -28
- package/infra/templates/backend/azure-pipelines.yml +135 -135
- package/infra/templates/backend/k8s/Dockerfile +31 -31
- package/infra/templates/backend/k8s/configmap.yaml +26 -26
- package/infra/templates/backend/k8s/deployment.yaml +85 -85
- package/infra/templates/backend/k8s/pvc.yaml +12 -12
- package/infra/templates/backend/k8s/service.yaml +13 -13
- package/infra/templates/backend/tsconfig.json +22 -22
- package/infra/templates/frontend/.dockerignore +10 -10
- package/infra/templates/frontend/.env.example +8 -8
- package/infra/templates/frontend/.env.local.example +10 -10
- package/infra/templates/frontend/README.md +69 -69
- package/infra/templates/frontend/app/[tablename]/page.tsx +37 -37
- package/infra/templates/frontend/app/_components/AuthWrapper/index.tsx +63 -63
- package/infra/templates/frontend/app/authorization/page.tsx +43 -43
- package/infra/templates/frontend/app/change-password/page.tsx +23 -23
- package/infra/templates/frontend/app/devices/page.tsx +127 -127
- package/infra/templates/frontend/app/forgot-password/page.tsx +20 -20
- package/infra/templates/frontend/app/globals.css +28 -28
- package/infra/templates/frontend/app/layout.tsx +35 -35
- package/infra/templates/frontend/app/login/page.tsx +33 -33
- package/infra/templates/frontend/app/page.tsx +565 -565
- package/infra/templates/frontend/app/profile/page.tsx +92 -92
- package/infra/templates/frontend/app/register/page.tsx +27 -27
- package/infra/templates/frontend/app/reset-password/page.tsx +60 -60
- package/infra/templates/frontend/app/set-password/page.tsx +43 -43
- package/infra/templates/frontend/app/ui-docs/page.tsx +52 -52
- package/infra/templates/frontend/app/users/page.tsx +52 -52
- package/infra/templates/frontend/app/verify-email/page.tsx +41 -41
- package/infra/templates/frontend/app/verify-magic-link/page.tsx +46 -46
- package/infra/templates/frontend/azure-pipelines.yml +137 -137
- package/infra/templates/frontend/code-and-design-principles.md +438 -438
- package/infra/templates/frontend/k8s/Dockerfile +50 -50
- package/infra/templates/frontend/k8s/configmap.yaml +18 -18
- package/infra/templates/frontend/k8s/deployment.yaml +72 -72
- package/infra/templates/frontend/k8s/ingress.yaml +36 -36
- package/infra/templates/frontend/k8s/service.yaml +14 -14
- package/infra/templates/frontend/lib/api/endpoints.ts +37 -37
- package/infra/templates/frontend/lib/api/factory.ts +44 -44
- package/infra/templates/frontend/lib/api/hook.ts +10 -10
- package/infra/templates/frontend/next.config.ts +19 -19
- package/infra/templates/frontend/package.json +34 -34
- package/infra/templates/frontend/postcss.config.mjs +5 -5
- package/infra/templates/frontend/server.ts +114 -114
- package/infra/templates/frontend/tsconfig.json +23 -23
- package/package.json +1 -1
- package/public/components/CTA.tsx +25 -25
- package/public/components/Capabilities.tsx +67 -67
- package/public/components/Features.tsx +107 -107
- package/public/components/Footer.tsx +58 -58
- package/public/components/Hero.tsx +51 -51
- package/public/components/Managers.tsx +55 -55
- package/public/components/Nav.tsx +91 -91
- package/public/components/Stack.tsx +36 -36
- package/public/components/docs/Docs.tsx +60 -60
- package/public/components/docs/DocsContent.tsx +176 -176
- package/public/components/docs/DocsRightSidebar.tsx +53 -53
- package/public/components/docs/DocsSidebar.tsx +54 -54
- package/public/components/docs/content/authentication.ts +836 -836
- package/public/components/docs/content/authorization.ts +268 -268
- package/public/components/docs/content/backupRestore.ts +173 -173
- package/public/components/docs/content/clientModule.ts +287 -287
- package/public/components/docs/content/entityCrud.ts +682 -682
- package/public/components/docs/content/monitoring.ts +313 -313
- package/public/components/docs/content/multiTenant.ts +269 -269
- package/public/components/docs/content/oauthApiKeys.ts +325 -325
- package/public/components/docs/content/pubsub.ts +131 -131
- package/public/components/docs/content/storageCdn.ts +171 -171
- package/public/components/docs/content/verification.ts +289 -289
- package/public/components/docs/docsData.ts +113 -113
- package/public/components/docs/index.ts +6 -6
- package/public/components/index.ts +9 -9
- package/public/docs.css +629 -629
- package/public/index.html +81 -81
- package/public/index.tsx +42 -42
- package/public/store.ts +76 -76
- package/public/styles.css +858 -858
- package/schemas/config.nucleus.json +2651 -2651
- package/scripts/audit-purge-noise.ts +120 -120
- package/scripts/build.ts +582 -582
- package/scripts/generate-system-tables-types.ts +18 -18
- package/scripts/generate-types-schema.test.ts +73 -73
- package/scripts/generate-types-schema.ts +1284 -1284
- package/scripts/packagedScripts.test.ts +87 -87
- package/scripts/publish.ts +276 -276
- package/scripts/skillCitations.test.ts +107 -107
- package/scripts/verify-publishable.ts +40 -40
package/LICENSE
CHANGED
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
Nucleus Core - Proprietary Software License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2024-2026 Hidayet Can Özcan <hidayetcan@gmail.com>
|
|
4
|
-
All Rights Reserved.
|
|
5
|
-
|
|
6
|
-
TERMS AND CONDITIONS
|
|
7
|
-
|
|
8
|
-
1. GRANT OF LICENSE
|
|
9
|
-
This software and associated documentation files (the "Software") are
|
|
10
|
-
licensed, not sold. Subject to the terms of this license, you are granted
|
|
11
|
-
a non-exclusive, non-transferable, limited license to use the Software
|
|
12
|
-
solely for your internal business purposes.
|
|
13
|
-
|
|
14
|
-
2. RESTRICTIONS
|
|
15
|
-
You may NOT:
|
|
16
|
-
- Copy, modify, or distribute the Software
|
|
17
|
-
- Reverse engineer, decompile, or disassemble the Software
|
|
18
|
-
- Sublicense, rent, lease, or lend the Software
|
|
19
|
-
- Use the Software to create derivative works
|
|
20
|
-
- Remove or alter any proprietary notices or labels on the Software
|
|
21
|
-
- Share, publish, or make the Software available to third parties
|
|
22
|
-
|
|
23
|
-
3. INTELLECTUAL PROPERTY
|
|
24
|
-
The Software is protected by copyright and other intellectual property
|
|
25
|
-
laws. The author retains all right, title, and interest in and to the
|
|
26
|
-
Software, including all intellectual property rights.
|
|
27
|
-
|
|
28
|
-
4. NO WARRANTY
|
|
29
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
30
|
-
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
31
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
32
|
-
|
|
33
|
-
5. LIMITATION OF LIABILITY
|
|
34
|
-
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
35
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
36
|
-
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
37
|
-
DEALINGS IN THE SOFTWARE.
|
|
38
|
-
|
|
39
|
-
6. TERMINATION
|
|
40
|
-
This license is effective until terminated. It will terminate automatically
|
|
41
|
-
if you fail to comply with any term of this license. Upon termination,
|
|
42
|
-
you must destroy all copies of the Software.
|
|
43
|
-
|
|
44
|
-
7. GOVERNING LAW
|
|
45
|
-
This license shall be governed by and construed in accordance with the
|
|
46
|
-
laws of Turkey.
|
|
47
|
-
|
|
48
|
-
For licensing inquiries, please contact: hidayetcan@gmail.com
|
|
1
|
+
Nucleus Core - Proprietary Software License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2026 Hidayet Can Özcan <hidayetcan@gmail.com>
|
|
4
|
+
All Rights Reserved.
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS
|
|
7
|
+
|
|
8
|
+
1. GRANT OF LICENSE
|
|
9
|
+
This software and associated documentation files (the "Software") are
|
|
10
|
+
licensed, not sold. Subject to the terms of this license, you are granted
|
|
11
|
+
a non-exclusive, non-transferable, limited license to use the Software
|
|
12
|
+
solely for your internal business purposes.
|
|
13
|
+
|
|
14
|
+
2. RESTRICTIONS
|
|
15
|
+
You may NOT:
|
|
16
|
+
- Copy, modify, or distribute the Software
|
|
17
|
+
- Reverse engineer, decompile, or disassemble the Software
|
|
18
|
+
- Sublicense, rent, lease, or lend the Software
|
|
19
|
+
- Use the Software to create derivative works
|
|
20
|
+
- Remove or alter any proprietary notices or labels on the Software
|
|
21
|
+
- Share, publish, or make the Software available to third parties
|
|
22
|
+
|
|
23
|
+
3. INTELLECTUAL PROPERTY
|
|
24
|
+
The Software is protected by copyright and other intellectual property
|
|
25
|
+
laws. The author retains all right, title, and interest in and to the
|
|
26
|
+
Software, including all intellectual property rights.
|
|
27
|
+
|
|
28
|
+
4. NO WARRANTY
|
|
29
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
30
|
+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
31
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
32
|
+
|
|
33
|
+
5. LIMITATION OF LIABILITY
|
|
34
|
+
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
35
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
36
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
37
|
+
DEALINGS IN THE SOFTWARE.
|
|
38
|
+
|
|
39
|
+
6. TERMINATION
|
|
40
|
+
This license is effective until terminated. It will terminate automatically
|
|
41
|
+
if you fail to comply with any term of this license. Upon termination,
|
|
42
|
+
you must destroy all copies of the Software.
|
|
43
|
+
|
|
44
|
+
7. GOVERNING LAW
|
|
45
|
+
This license shall be governed by and construed in accordance with the
|
|
46
|
+
laws of Turkey.
|
|
47
|
+
|
|
48
|
+
For licensing inquiries, please contact: hidayetcan@gmail.com
|
package/dist/.build-ok
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.10.
|
|
1
|
+
0.10.151
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Every word the authorization screens say, so a portal can say them in its
|
|
3
|
-
* own language.
|
|
4
|
-
*
|
|
5
|
-
* This is the screen an administrator opens to decide who may do what, and
|
|
6
|
-
* until now it said "Roles", "Show assigned only", "No claims match your
|
|
7
|
-
* filters" and "Are you sure you want to delete this role?" in English no
|
|
8
|
-
* matter what language the rest of the portal spoke. `title` was already a
|
|
9
|
-
* prop — which is the tell: an installation could translate the heading and
|
|
10
|
-
* nothing underneath it.
|
|
11
|
-
*
|
|
12
|
-
* Defaults stay English, so an installation that passes no labels is
|
|
13
|
-
* completely unaffected.
|
|
1
|
+
/**
|
|
2
|
+
* Every word the authorization screens say, so a portal can say them in its
|
|
3
|
+
* own language.
|
|
4
|
+
*
|
|
5
|
+
* This is the screen an administrator opens to decide who may do what, and
|
|
6
|
+
* until now it said "Roles", "Show assigned only", "No claims match your
|
|
7
|
+
* filters" and "Are you sure you want to delete this role?" in English no
|
|
8
|
+
* matter what language the rest of the portal spoke. `title` was already a
|
|
9
|
+
* prop — which is the tell: an installation could translate the heading and
|
|
10
|
+
* nothing underneath it.
|
|
11
|
+
*
|
|
12
|
+
* Defaults stay English, so an installation that passes no labels is
|
|
13
|
+
* completely unaffected.
|
|
14
14
|
*/ export const DEFAULT_AUTHORIZATION_LABELS = {
|
|
15
15
|
locale: 'en-US',
|
|
16
16
|
title: 'Authorization Management',
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Every word the security check says.
|
|
3
|
-
*
|
|
4
|
-
* This is the most-read component in the kit and the one nobody thought to
|
|
5
|
-
* translate: it sits on the sign-in form, so on an installation of 879 people
|
|
6
|
-
* it is shown several hundred times a morning. A portal could pass `label` and
|
|
7
|
-
* change the heading — and the box under the heading still said "Enter the
|
|
8
|
-
* result", "New challenge", "Expires in 1:30" and, when somebody was slow,
|
|
9
|
-
* "Captcha expired. Please refresh." Four sentences of English on the first
|
|
10
|
-
* screen of a portal that is otherwise entirely in its own language.
|
|
11
|
-
*
|
|
12
|
-
* The placeholders are per challenge type because the instruction is different
|
|
13
|
-
* for each: a sum wants its result, an image wants the letters in it, and the
|
|
14
|
-
* puzzle wants an order. `expiresIn` takes the formatted clock as `{time}` so a
|
|
15
|
-
* translation can put it where its own grammar wants it.
|
|
16
|
-
*
|
|
17
|
-
* Defaults stay English, so an installation that passes nothing is unchanged.
|
|
1
|
+
/**
|
|
2
|
+
* Every word the security check says.
|
|
3
|
+
*
|
|
4
|
+
* This is the most-read component in the kit and the one nobody thought to
|
|
5
|
+
* translate: it sits on the sign-in form, so on an installation of 879 people
|
|
6
|
+
* it is shown several hundred times a morning. A portal could pass `label` and
|
|
7
|
+
* change the heading — and the box under the heading still said "Enter the
|
|
8
|
+
* result", "New challenge", "Expires in 1:30" and, when somebody was slow,
|
|
9
|
+
* "Captcha expired. Please refresh." Four sentences of English on the first
|
|
10
|
+
* screen of a portal that is otherwise entirely in its own language.
|
|
11
|
+
*
|
|
12
|
+
* The placeholders are per challenge type because the instruction is different
|
|
13
|
+
* for each: a sum wants its result, an image wants the letters in it, and the
|
|
14
|
+
* puzzle wants an order. `expiresIn` takes the formatted clock as `{time}` so a
|
|
15
|
+
* translation can put it where its own grammar wants it.
|
|
16
|
+
*
|
|
17
|
+
* Defaults stay English, so an installation that passes nothing is unchanged.
|
|
18
18
|
*/ export const DEFAULT_CAPTCHA_LABELS = {
|
|
19
19
|
heading: 'Security Check',
|
|
20
20
|
clickRefresh: 'Click refresh to load captcha',
|
|
@@ -14,16 +14,16 @@ export function initialsOf(name) {
|
|
|
14
14
|
const initials = parts.map((p)=>p[0]?.toUpperCase() ?? '').join('');
|
|
15
15
|
return initials || '?';
|
|
16
16
|
}
|
|
17
|
-
/**
|
|
18
|
-
* The age of a message, in the panel's own words.
|
|
19
|
-
*
|
|
20
|
-
* The units used to be English letters written into the source (`5m`, `3h`,
|
|
21
|
-
* `2d`), which no installation could change, and the fallback past a week was a
|
|
22
|
-
* bare `toLocaleDateString()` — no locale, so the string came out in the
|
|
23
|
-
* SERVER's locale during the server render and the BROWSER's after hydration.
|
|
24
|
-
* The same row rendered twice, differently, and React tore. Both halves now
|
|
25
|
-
* come from the labels: the units as functions of the number, the date under
|
|
26
|
-
* the named `locale`.
|
|
17
|
+
/**
|
|
18
|
+
* The age of a message, in the panel's own words.
|
|
19
|
+
*
|
|
20
|
+
* The units used to be English letters written into the source (`5m`, `3h`,
|
|
21
|
+
* `2d`), which no installation could change, and the fallback past a week was a
|
|
22
|
+
* bare `toLocaleDateString()` — no locale, so the string came out in the
|
|
23
|
+
* SERVER's locale during the server render and the BROWSER's after hydration.
|
|
24
|
+
* The same row rendered twice, differently, and React tore. Both halves now
|
|
25
|
+
* come from the labels: the units as functions of the number, the date under
|
|
26
|
+
* the named `locale`.
|
|
27
27
|
*/ export function formatRelativeTime(iso, labels) {
|
|
28
28
|
if (!iso) return '';
|
|
29
29
|
const date = new Date(iso);
|
|
@@ -37,13 +37,13 @@ export function initialsOf(name) {
|
|
|
37
37
|
if (days < 7) return labels.daysAgo(days);
|
|
38
38
|
return date.toLocaleDateString(labels.locale);
|
|
39
39
|
}
|
|
40
|
-
/**
|
|
41
|
-
* The clock beneath a message.
|
|
42
|
-
*
|
|
43
|
-
* `hour12` is pinned as well as the locale: left to the environment, a locale
|
|
44
|
-
* that prints "2:32 PM" on one machine prints "14:32" on the other, which is
|
|
45
|
-
* the same hydration tear by a different route. A 24-hour clock is the one both
|
|
46
|
-
* ends can agree on without asking anybody.
|
|
40
|
+
/**
|
|
41
|
+
* The clock beneath a message.
|
|
42
|
+
*
|
|
43
|
+
* `hour12` is pinned as well as the locale: left to the environment, a locale
|
|
44
|
+
* that prints "2:32 PM" on one machine prints "14:32" on the other, which is
|
|
45
|
+
* the same hydration tear by a different route. A 24-hour clock is the one both
|
|
46
|
+
* ends can agree on without asking anybody.
|
|
47
47
|
*/ export function formatClockTime(iso, labels) {
|
|
48
48
|
return new Date(iso).toLocaleTimeString(labels.locale, {
|
|
49
49
|
hour: '2-digit',
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Every word the chat says, so a portal can say them in its own language.
|
|
3
|
-
*
|
|
4
|
-
* The panel wrote them in English inside the components, and the one label the
|
|
5
|
-
* consumer COULD pass — `title` — was the tell: an intranet in Turkish set the
|
|
6
|
-
* heading to "Sohbetler" and the panel underneath it still said "No
|
|
7
|
-
* conversations yet" and "Select a conversation to start chatting". Two
|
|
8
|
-
* sentences of English on the one screen in the product where people talk to
|
|
9
|
-
* each other.
|
|
10
|
-
*
|
|
11
|
-
* Defaults stay English, so nothing that does not pass labels changes.
|
|
12
|
-
*
|
|
13
|
-
* Anything that interpolates a value is a FUNCTION of that value, never a
|
|
14
|
-
* translated fragment glued to an untranslated one: "3 participants" is
|
|
15
|
-
* "3 katılımcı" in Turkish but "typing" moves to the end of its sentence, and
|
|
16
|
-
* a concatenation would produce a sentence in neither language.
|
|
1
|
+
/**
|
|
2
|
+
* Every word the chat says, so a portal can say them in its own language.
|
|
3
|
+
*
|
|
4
|
+
* The panel wrote them in English inside the components, and the one label the
|
|
5
|
+
* consumer COULD pass — `title` — was the tell: an intranet in Turkish set the
|
|
6
|
+
* heading to "Sohbetler" and the panel underneath it still said "No
|
|
7
|
+
* conversations yet" and "Select a conversation to start chatting". Two
|
|
8
|
+
* sentences of English on the one screen in the product where people talk to
|
|
9
|
+
* each other.
|
|
10
|
+
*
|
|
11
|
+
* Defaults stay English, so nothing that does not pass labels changes.
|
|
12
|
+
*
|
|
13
|
+
* Anything that interpolates a value is a FUNCTION of that value, never a
|
|
14
|
+
* translated fragment glued to an untranslated one: "3 participants" is
|
|
15
|
+
* "3 katılımcı" in Turkish but "typing" moves to the end of its sentence, and
|
|
16
|
+
* a concatenation would produce a sentence in neither language.
|
|
17
17
|
*/ export const DEFAULT_CHAT_LABELS = {
|
|
18
18
|
loadingConversations: 'Loading conversations...',
|
|
19
19
|
noConversations: 'No conversations yet',
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Every word this table says on its own, so a portal can say them in its own
|
|
3
|
-
* language.
|
|
4
|
-
*
|
|
5
|
-
* The DataTable is the one component in the kit that almost every screen of an
|
|
6
|
-
* installation is built out of — every list of employees, documents, requests
|
|
7
|
-
* and announcements is this table. Column headers and cell contents already
|
|
8
|
-
* come from the caller, which hid the problem: the words the table supplies
|
|
9
|
-
* *itself* were welded into the components. A Turkish intranet could name its
|
|
10
|
-
* columns "Ad", "Birim", "Tarih" and still show "No data available" when the
|
|
11
|
-
* list was empty, "Loading..." while it filled, "Save"/"Cancel" on every
|
|
12
|
-
* inline edit, and "3 item selected" over a selection toolbar whose own buttons
|
|
13
|
-
* were Turkish. Half a screen in one language and half in another.
|
|
14
|
-
*
|
|
15
|
-
* Defaults stay English, so an installation that passes no labels keeps the
|
|
16
|
-
* words it has today.
|
|
1
|
+
/**
|
|
2
|
+
* Every word this table says on its own, so a portal can say them in its own
|
|
3
|
+
* language.
|
|
4
|
+
*
|
|
5
|
+
* The DataTable is the one component in the kit that almost every screen of an
|
|
6
|
+
* installation is built out of — every list of employees, documents, requests
|
|
7
|
+
* and announcements is this table. Column headers and cell contents already
|
|
8
|
+
* come from the caller, which hid the problem: the words the table supplies
|
|
9
|
+
* *itself* were welded into the components. A Turkish intranet could name its
|
|
10
|
+
* columns "Ad", "Birim", "Tarih" and still show "No data available" when the
|
|
11
|
+
* list was empty, "Loading..." while it filled, "Save"/"Cancel" on every
|
|
12
|
+
* inline edit, and "3 item selected" over a selection toolbar whose own buttons
|
|
13
|
+
* were Turkish. Half a screen in one language and half in another.
|
|
14
|
+
*
|
|
15
|
+
* Defaults stay English, so an installation that passes no labels keeps the
|
|
16
|
+
* words it has today.
|
|
17
17
|
*/ export const DEFAULT_DATA_TABLE_LABELS = {
|
|
18
18
|
tableLabel: 'Data table',
|
|
19
19
|
empty: 'No data available',
|
|
@@ -76,16 +76,16 @@ function getTrustScoreColor(score) {
|
|
|
76
76
|
if (score >= 40) return 'bg-orange-500';
|
|
77
77
|
return 'bg-red-500';
|
|
78
78
|
}
|
|
79
|
-
/**
|
|
80
|
-
* When a device was last here, in a form that cannot tear on hydration.
|
|
81
|
-
*
|
|
82
|
-
* It used to be `toLocaleDateString(undefined, …)`, which reads the SERVER's
|
|
83
|
-
* locale while the page renders on the server and the BROWSER's once React
|
|
84
|
-
* takes over — two different strings for the same row, and React replacing one
|
|
85
|
-
* with the other after mount. It also printed 8/5/2026, which in Turkey reads
|
|
86
|
-
* as the 8th of May. The locale is now named by the labels, and the clock is
|
|
87
|
-
* pinned to 24 hours so "14:32" does not become "2:32 PM" between the two
|
|
88
|
-
* passes.
|
|
79
|
+
/**
|
|
80
|
+
* When a device was last here, in a form that cannot tear on hydration.
|
|
81
|
+
*
|
|
82
|
+
* It used to be `toLocaleDateString(undefined, …)`, which reads the SERVER's
|
|
83
|
+
* locale while the page renders on the server and the BROWSER's once React
|
|
84
|
+
* takes over — two different strings for the same row, and React replacing one
|
|
85
|
+
* with the other after mount. It also printed 8/5/2026, which in Turkey reads
|
|
86
|
+
* as the 8th of May. The locale is now named by the labels, and the clock is
|
|
87
|
+
* pinned to 24 hours so "14:32" does not become "2:32 PM" between the two
|
|
88
|
+
* passes.
|
|
89
89
|
*/ function formatDate(dateString, say) {
|
|
90
90
|
if (!dateString) return say.unknown;
|
|
91
91
|
const date = new Date(dateString);
|
|
@@ -100,11 +100,11 @@ function getTrustScoreColor(score) {
|
|
|
100
100
|
timeZone: say.timeZone || undefined
|
|
101
101
|
});
|
|
102
102
|
}
|
|
103
|
-
/**
|
|
104
|
-
* The device kind, in words. The server sends `mobile` / `tablet` / `desktop`
|
|
105
|
-
* and the card used to print that raw value, so a Turkish portal read
|
|
106
|
-
* "mobile • Chrome". Anything else the server sends is named as unknown rather
|
|
107
|
-
* than shown in the server's vocabulary.
|
|
103
|
+
/**
|
|
104
|
+
* The device kind, in words. The server sends `mobile` / `tablet` / `desktop`
|
|
105
|
+
* and the card used to print that raw value, so a Turkish portal read
|
|
106
|
+
* "mobile • Chrome". Anything else the server sends is named as unknown rather
|
|
107
|
+
* than shown in the server's vocabulary.
|
|
108
108
|
*/ function deviceTypeWord(deviceType, say) {
|
|
109
109
|
switch(deviceType?.toLowerCase()){
|
|
110
110
|
case 'mobile':
|
|
@@ -12,15 +12,15 @@ import { devicesPageTheme } from '../theme';
|
|
|
12
12
|
import { DeviceCard } from './DeviceCard';
|
|
13
13
|
import { DevicesHeader } from './DevicesHeader';
|
|
14
14
|
gsap.registerPlugin(useGSAP);
|
|
15
|
-
/**
|
|
16
|
-
* When a waiting device asked, in a form that cannot tear on hydration.
|
|
17
|
-
*
|
|
18
|
-
* It used to be a bare `toLocaleString()`, which reads the SERVER's locale
|
|
19
|
-
* while the page renders on the server and the BROWSER's once React takes over
|
|
20
|
-
* — two different strings for the same tile, and React replacing one with the
|
|
21
|
-
* other after mount. It also printed 8/5/2026, which in Turkey reads as the 8th
|
|
22
|
-
* of May. The locale comes from the labels now, and the clock is pinned to 24
|
|
23
|
-
* hours so the two passes cannot disagree over "14:32" and "2:32 PM".
|
|
15
|
+
/**
|
|
16
|
+
* When a waiting device asked, in a form that cannot tear on hydration.
|
|
17
|
+
*
|
|
18
|
+
* It used to be a bare `toLocaleString()`, which reads the SERVER's locale
|
|
19
|
+
* while the page renders on the server and the BROWSER's once React takes over
|
|
20
|
+
* — two different strings for the same tile, and React replacing one with the
|
|
21
|
+
* other after mount. It also printed 8/5/2026, which in Turkey reads as the 8th
|
|
22
|
+
* of May. The locale comes from the labels now, and the clock is pinned to 24
|
|
23
|
+
* hours so the two passes cannot disagree over "14:32" and "2:32 PM".
|
|
24
24
|
*/ function formatRequestedAt(value, say) {
|
|
25
25
|
if (!value) return say.unknown;
|
|
26
26
|
const when = new Date(value);
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Every word this page says, so a portal can say them in its own language.
|
|
3
|
-
*
|
|
4
|
-
* `title` and `subtitle` were already props — which is the tell: an
|
|
5
|
-
* installation could rename the heading and nothing underneath it, so the page
|
|
6
|
-
* that lists where an account is signed in read "Etkin Cihazlar" over "Manage
|
|
7
|
-
* devices that have access to your account", "Last Active", "Trust Score: 80%"
|
|
8
|
-
* and "Are you sure you want to revoke access for this device?". This is the
|
|
9
|
-
* screen an employee opens when they think somebody else is on their account,
|
|
10
|
-
* and every word on it has to be one they can act on.
|
|
11
|
-
*
|
|
12
|
-
* Defaults stay English, so an installation that passes no labels is unchanged.
|
|
1
|
+
/**
|
|
2
|
+
* Every word this page says, so a portal can say them in its own language.
|
|
3
|
+
*
|
|
4
|
+
* `title` and `subtitle` were already props — which is the tell: an
|
|
5
|
+
* installation could rename the heading and nothing underneath it, so the page
|
|
6
|
+
* that lists where an account is signed in read "Etkin Cihazlar" over "Manage
|
|
7
|
+
* devices that have access to your account", "Last Active", "Trust Score: 80%"
|
|
8
|
+
* and "Are you sure you want to revoke access for this device?". This is the
|
|
9
|
+
* screen an employee opens when they think somebody else is on their account,
|
|
10
|
+
* and every word on it has to be one they can act on.
|
|
11
|
+
*
|
|
12
|
+
* Defaults stay English, so an installation that passes no labels is unchanged.
|
|
13
13
|
*/ export const DEFAULT_DEVICES_PAGE_LABELS = {
|
|
14
14
|
title: 'Active Devices',
|
|
15
15
|
subtitle: 'Manage devices that have access to your account',
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Every word this page says, so a portal can say them in its own language.
|
|
3
|
-
*
|
|
4
|
-
* `title` and `subtitle` were already props; everything under them was English
|
|
5
|
-
* — including the whole success state, which is the only screen somebody who
|
|
6
|
-
* has lost their password actually reads.
|
|
7
|
-
*
|
|
8
|
-
* Defaults stay English, so nothing that does not pass labels changes.
|
|
1
|
+
/**
|
|
2
|
+
* Every word this page says, so a portal can say them in its own language.
|
|
3
|
+
*
|
|
4
|
+
* `title` and `subtitle` were already props; everything under them was English
|
|
5
|
+
* — including the whole success state, which is the only screen somebody who
|
|
6
|
+
* has lost their password actually reads.
|
|
7
|
+
*
|
|
8
|
+
* Defaults stay English, so nothing that does not pass labels changes.
|
|
9
9
|
*/ export const DEFAULT_FORGOT_PASSWORD_LABELS = {
|
|
10
10
|
emailLabel: 'Email',
|
|
11
11
|
emailPlaceholder: 'you@example.com',
|
|
@@ -195,11 +195,11 @@ export function FormField({ column, config, value, onChange, error, size = 'md',
|
|
|
195
195
|
children: renderInput()
|
|
196
196
|
});
|
|
197
197
|
}
|
|
198
|
-
/**
|
|
199
|
-
* The values a dropdown offers. Without a contract these were the raw database
|
|
200
|
-
* enum members with their underscores taken out — `in_progress` shown to a
|
|
201
|
-
* Turkish employee as "In Progress" — so they go through `optionLabel`, which
|
|
202
|
-
* an installation can point at its own words.
|
|
198
|
+
/**
|
|
199
|
+
* The values a dropdown offers. Without a contract these were the raw database
|
|
200
|
+
* enum members with their underscores taken out — `in_progress` shown to a
|
|
201
|
+
* Turkish employee as "In Progress" — so they go through `optionLabel`, which
|
|
202
|
+
* an installation can point at its own words.
|
|
203
203
|
*/ function getSelectOptions(column, say, locale, customOptions) {
|
|
204
204
|
if (customOptions) {
|
|
205
205
|
return customOptions;
|
|
@@ -211,15 +211,15 @@ export function getDefaultValue(column) {
|
|
|
211
211
|
return '';
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
|
-
/**
|
|
215
|
-
* Turns a database name into something readable — `first_name` into
|
|
216
|
-
* "First Name".
|
|
217
|
-
*
|
|
218
|
-
* The locale is not decoration: `toUpperCase()` applies English casing rules
|
|
219
|
-
* wherever it runs, so a column named `iban` came out "Iban" on a Turkish
|
|
220
|
-
* portal where the language wants "İban". Passing the locale makes the first
|
|
221
|
-
* letter the one the reader's language uses, and makes the server render and
|
|
222
|
-
* the browser render agree on it.
|
|
214
|
+
/**
|
|
215
|
+
* Turns a database name into something readable — `first_name` into
|
|
216
|
+
* "First Name".
|
|
217
|
+
*
|
|
218
|
+
* The locale is not decoration: `toUpperCase()` applies English casing rules
|
|
219
|
+
* wherever it runs, so a column named `iban` came out "Iban" on a Turkish
|
|
220
|
+
* portal where the language wants "İban". Passing the locale makes the first
|
|
221
|
+
* letter the one the reader's language uses, and makes the server render and
|
|
222
|
+
* the browser render agree on it.
|
|
223
223
|
*/ export function formatLabel(name, locale) {
|
|
224
224
|
return name.replace(/_/g, ' ').replace(/([a-z])([A-Z])/g, '$1 $2').replace(/\b\w/g, (char)=>locale ? char.toLocaleUpperCase(locale) : char.toUpperCase());
|
|
225
225
|
}
|
|
@@ -7,14 +7,14 @@ import { ConnectionOauthFields } from './ConnectionOauthFields';
|
|
|
7
7
|
import { usesHeaderName, usesQueryParam } from './connectionDraft';
|
|
8
8
|
import { describedBy } from './formSupport';
|
|
9
9
|
import { Field } from './Primitives';
|
|
10
|
-
/**
|
|
11
|
-
* How the connection proves who it is.
|
|
12
|
-
*
|
|
13
|
-
* Only the boxes the chosen auth type reads are on screen. A form that showed
|
|
14
|
-
* all of them would invite an operator to fill in a token URL that a bearer
|
|
15
|
-
* connection never looks at, and then to spend an afternoon on why it changed
|
|
16
|
-
* nothing. The secrets themselves are not here — they live in CredentialFields,
|
|
17
|
-
* because they are written and never read back.
|
|
10
|
+
/**
|
|
11
|
+
* How the connection proves who it is.
|
|
12
|
+
*
|
|
13
|
+
* Only the boxes the chosen auth type reads are on screen. A form that showed
|
|
14
|
+
* all of them would invite an operator to fill in a token URL that a bearer
|
|
15
|
+
* connection never looks at, and then to spend an afternoon on why it changed
|
|
16
|
+
* nothing. The secrets themselves are not here — they live in CredentialFields,
|
|
17
|
+
* because they are written and never read back.
|
|
18
18
|
*/ const theme = integrationsPageTheme;
|
|
19
19
|
export function ConnectionAuthFields(props) {
|
|
20
20
|
const labels = useLabels();
|
|
@@ -5,9 +5,9 @@ import { useLabels } from '../text/context';
|
|
|
5
5
|
import { integrationsPageTheme } from '../theme';
|
|
6
6
|
import { describedBy } from './formSupport';
|
|
7
7
|
import { Field } from './Primitives';
|
|
8
|
-
/**
|
|
9
|
-
* What the connection IS: its name, where it lives, and the two switches that
|
|
10
|
-
* decide whether it is used and how carefully.
|
|
8
|
+
/**
|
|
9
|
+
* What the connection IS: its name, where it lives, and the two switches that
|
|
10
|
+
* decide whether it is used and how carefully.
|
|
11
11
|
*/ const theme = integrationsPageTheme;
|
|
12
12
|
const CHECKBOX = 'h-4 w-4 shrink-0 accent-sky-600 dark:accent-sky-500';
|
|
13
13
|
export function ConnectionBasicFields({ draft, errors, disabled, onChange }) {
|
|
@@ -5,29 +5,29 @@ import { useIntegrationsStore } from '../store';
|
|
|
5
5
|
import { useLabels } from '../text/context';
|
|
6
6
|
import { integrationsPageTheme as theme } from '../theme';
|
|
7
7
|
import { Notice } from './Primitives';
|
|
8
|
-
/**
|
|
9
|
-
* Taking one whole integration somewhere else.
|
|
10
|
-
*
|
|
11
|
-
* A connection is the address, the calls it makes, the parameters those calls
|
|
12
|
-
* take from each other, and the mappings that turn the answers into rows.
|
|
13
|
-
* Rebuilding that by hand in a second environment is hours of work and a fresh
|
|
14
|
-
* chance to get one field wrong in a way nobody notices until an import writes
|
|
15
|
-
* it. So it travels as one file.
|
|
16
|
-
*
|
|
17
|
-
* ## Why this is not next to Import
|
|
18
|
-
*
|
|
19
|
-
* It was, and it could not be pressed. Both buttons lived in the connection
|
|
20
|
-
* rail, and Export is only meaningful once a connection is CHOSEN — but
|
|
21
|
-
* choosing one replaces the rail with the connection's own screens, taking the
|
|
22
|
-
* button with it. So the button existed, was correct, and was reachable only in
|
|
23
|
-
* the state where it was disabled.
|
|
24
|
-
*
|
|
25
|
-
* Import belongs where there is nothing chosen yet, because that is when you
|
|
26
|
-
* bring one in. Export belongs here, on the connection being exported.
|
|
27
|
-
*
|
|
28
|
-
* The file carries NO credentials — deliberately, and it says so on both sides,
|
|
29
|
-
* because a connection that arrives looking configured and cannot authenticate
|
|
30
|
-
* is a confusing half hour otherwise.
|
|
8
|
+
/**
|
|
9
|
+
* Taking one whole integration somewhere else.
|
|
10
|
+
*
|
|
11
|
+
* A connection is the address, the calls it makes, the parameters those calls
|
|
12
|
+
* take from each other, and the mappings that turn the answers into rows.
|
|
13
|
+
* Rebuilding that by hand in a second environment is hours of work and a fresh
|
|
14
|
+
* chance to get one field wrong in a way nobody notices until an import writes
|
|
15
|
+
* it. So it travels as one file.
|
|
16
|
+
*
|
|
17
|
+
* ## Why this is not next to Import
|
|
18
|
+
*
|
|
19
|
+
* It was, and it could not be pressed. Both buttons lived in the connection
|
|
20
|
+
* rail, and Export is only meaningful once a connection is CHOSEN — but
|
|
21
|
+
* choosing one replaces the rail with the connection's own screens, taking the
|
|
22
|
+
* button with it. So the button existed, was correct, and was reachable only in
|
|
23
|
+
* the state where it was disabled.
|
|
24
|
+
*
|
|
25
|
+
* Import belongs where there is nothing chosen yet, because that is when you
|
|
26
|
+
* bring one in. Export belongs here, on the connection being exported.
|
|
27
|
+
*
|
|
28
|
+
* The file carries NO credentials — deliberately, and it says so on both sides,
|
|
29
|
+
* because a connection that arrives looking configured and cannot authenticate
|
|
30
|
+
* is a confusing half hour otherwise.
|
|
31
31
|
*/ /** A filename somebody can still recognise a week later. */ const fileNameFor = (slug)=>`integration-${slug || 'connection'}.json`;
|
|
32
32
|
export function ConnectionExport({ actions, source }) {
|
|
33
33
|
const labels = useLabels();
|
|
@@ -10,12 +10,12 @@ import { draftFromSource, draftPatchFromSource, draftToSource, emptyConnectionDr
|
|
|
10
10
|
import { errorText } from './formSupport';
|
|
11
11
|
import { Badge } from './Primitives';
|
|
12
12
|
import { CardSkeleton } from './Skeletons';
|
|
13
|
-
/**
|
|
14
|
-
* Add or edit one connection.
|
|
15
|
-
*
|
|
16
|
-
* The form holds a draft rather than editing the record in place, so abandoning
|
|
17
|
-
* a half-finished change costs nothing and the saved record is never a mixture
|
|
18
|
-
* of what was stored and what is being typed.
|
|
13
|
+
/**
|
|
14
|
+
* Add or edit one connection.
|
|
15
|
+
*
|
|
16
|
+
* The form holds a draft rather than editing the record in place, so abandoning
|
|
17
|
+
* a half-finished change costs nothing and the saved record is never a mixture
|
|
18
|
+
* of what was stored and what is being typed.
|
|
19
19
|
*/ const theme = integrationsPageTheme;
|
|
20
20
|
export function ConnectionForm({ actions, source, loading = false, onSaved }) {
|
|
21
21
|
const t = useLabels().errors;
|
|
@@ -59,22 +59,22 @@ export function ConnectionForm({ actions, source, loading = false, onSaved }) {
|
|
|
59
59
|
// it into the list, and selecting an id the list does not hold is the
|
|
60
60
|
// state every card below renders a skeleton for.
|
|
61
61
|
onSaved?.(saved);
|
|
62
|
-
/**
|
|
63
|
-
* The boxes are re-derived from what was actually STORED.
|
|
64
|
-
*
|
|
65
|
-
* The effect above resets them only when the id changes, so a create
|
|
66
|
-
* showed the truth and an edit never did. Two ways that was visible:
|
|
67
|
-
* emptying "Timeout" and saving left the box empty while the connection
|
|
68
|
-
* went on timing out at the stored value — the draft omits a blank
|
|
69
|
-
* timeout, so the patch never mentions it and the server rightly keeps
|
|
70
|
-
* what it had; and a trailing space in the name was trimmed on the way
|
|
71
|
-
* out, so the switcher above showed "Acme" while the box below still
|
|
72
|
-
* read "Acme ". One screen, disagreeing with itself, until F5.
|
|
73
|
-
*
|
|
74
|
-
* MERGED rather than replaced: a field-scoped patch claim can strip
|
|
75
|
-
* columns out of the reply, and re-deriving wholesale from a partial
|
|
76
|
-
* record would blank the boxes those columns fill. Nothing can have been
|
|
77
|
-
* typed in the meantime — every field is disabled while `saving`.
|
|
62
|
+
/**
|
|
63
|
+
* The boxes are re-derived from what was actually STORED.
|
|
64
|
+
*
|
|
65
|
+
* The effect above resets them only when the id changes, so a create
|
|
66
|
+
* showed the truth and an edit never did. Two ways that was visible:
|
|
67
|
+
* emptying "Timeout" and saving left the box empty while the connection
|
|
68
|
+
* went on timing out at the stored value — the draft omits a blank
|
|
69
|
+
* timeout, so the patch never mentions it and the server rightly keeps
|
|
70
|
+
* what it had; and a trailing space in the name was trimmed on the way
|
|
71
|
+
* out, so the switcher above showed "Acme" while the box below still
|
|
72
|
+
* read "Acme ". One screen, disagreeing with itself, until F5.
|
|
73
|
+
*
|
|
74
|
+
* MERGED rather than replaced: a field-scoped patch claim can strip
|
|
75
|
+
* columns out of the reply, and re-deriving wholesale from a partial
|
|
76
|
+
* record would blank the boxes those columns fill. Nothing can have been
|
|
77
|
+
* typed in the meantime — every field is disabled while `saving`.
|
|
78
78
|
*/ if (source) setDraft((current)=>({
|
|
79
79
|
...current,
|
|
80
80
|
...draftPatchFromSource(saved)
|
|
@@ -9,13 +9,13 @@ import { ConnectionTransfer } from './ConnectionTransfer';
|
|
|
9
9
|
import { Badge, Field, Notice } from './Primitives';
|
|
10
10
|
import { ListSkeleton } from './Skeletons';
|
|
11
11
|
import { useInfiniteList } from './useInfiniteList';
|
|
12
|
-
/**
|
|
13
|
-
* The rail of connections.
|
|
14
|
-
*
|
|
15
|
-
* The server owns the list: what the operator types goes back out as a `search`
|
|
16
|
-
* on the next request, and the next page arrives when the sentinel comes into
|
|
17
|
-
* view. Nothing here narrows what has already been fetched, so the rail behaves
|
|
18
|
-
* the same at four connections and at four hundred.
|
|
12
|
+
/**
|
|
13
|
+
* The rail of connections.
|
|
14
|
+
*
|
|
15
|
+
* The server owns the list: what the operator types goes back out as a `search`
|
|
16
|
+
* on the next request, and the next page arrives when the sentinel comes into
|
|
17
|
+
* view. Nothing here narrows what has already been fetched, so the rail behaves
|
|
18
|
+
* the same at four connections and at four hundred.
|
|
19
19
|
*/ const theme = integrationsPageTheme;
|
|
20
20
|
const PAGE_SIZE = 20;
|
|
21
21
|
const SEARCH_DEBOUNCE_MS = 300;
|