@easyling/sanity-connector 0.0.1 → 0.0.2-rc.1
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/.tsbuildinfo +1 -1
- package/package.json +18 -12
- package/dist/actions/bulkTranslate.d.ts +0 -7
- package/dist/actions/bulkTranslate.d.ts.map +0 -1
- package/dist/actions/bulkTranslate.js +0 -543
- package/dist/actions/bulkTranslate.js.map +0 -1
- package/dist/actions/manageDNTFields.d.ts +0 -12
- package/dist/actions/manageDNTFields.d.ts.map +0 -1
- package/dist/actions/manageDNTFields.js +0 -100
- package/dist/actions/manageDNTFields.js.map +0 -1
- package/dist/actions/translateDocument.d.ts +0 -7
- package/dist/actions/translateDocument.d.ts.map +0 -1
- package/dist/actions/translateDocument.js +0 -256
- package/dist/actions/translateDocument.js.map +0 -1
- package/dist/components/RadioWithDefault.d.ts +0 -17
- package/dist/components/RadioWithDefault.d.ts.map +0 -1
- package/dist/components/RadioWithDefault.js +0 -29
- package/dist/components/RadioWithDefault.js.map +0 -1
- package/dist/components/auth/AuthNavbar.d.ts +0 -18
- package/dist/components/auth/AuthNavbar.d.ts.map +0 -1
- package/dist/components/auth/AuthNavbar.js +0 -15
- package/dist/components/auth/AuthNavbar.js.map +0 -1
- package/dist/components/auth/AuthStatus.d.ts +0 -27
- package/dist/components/auth/AuthStatus.d.ts.map +0 -1
- package/dist/components/auth/AuthStatus.js +0 -82
- package/dist/components/auth/AuthStatus.js.map +0 -1
- package/dist/components/auth/AuthStatusWrapper.d.ts +0 -15
- package/dist/components/auth/AuthStatusWrapper.d.ts.map +0 -1
- package/dist/components/auth/AuthStatusWrapper.js +0 -39
- package/dist/components/auth/AuthStatusWrapper.js.map +0 -1
- package/dist/components/auth/MigrationPrompt.d.ts +0 -20
- package/dist/components/auth/MigrationPrompt.d.ts.map +0 -1
- package/dist/components/auth/MigrationPrompt.js +0 -16
- package/dist/components/auth/MigrationPrompt.js.map +0 -1
- package/dist/components/auth/MigrationPromptWrapper.d.ts +0 -14
- package/dist/components/auth/MigrationPromptWrapper.d.ts.map +0 -1
- package/dist/components/auth/MigrationPromptWrapper.js +0 -16
- package/dist/components/auth/MigrationPromptWrapper.js.map +0 -1
- package/dist/components/auth/OAuthCallback.d.ts +0 -20
- package/dist/components/auth/OAuthCallback.d.ts.map +0 -1
- package/dist/components/auth/OAuthCallback.js +0 -12
- package/dist/components/auth/OAuthCallback.js.map +0 -1
- package/dist/components/auth/index.d.ts +0 -15
- package/dist/components/auth/index.d.ts.map +0 -1
- package/dist/components/auth/index.js +0 -12
- package/dist/components/auth/index.js.map +0 -1
- package/dist/components/config/LocaleConfigTool.d.ts +0 -17
- package/dist/components/config/LocaleConfigTool.d.ts.map +0 -1
- package/dist/components/config/LocaleConfigTool.js +0 -186
- package/dist/components/config/LocaleConfigTool.js.map +0 -1
- package/dist/components/config/LocaleConfigToolWrapper.d.ts +0 -13
- package/dist/components/config/LocaleConfigToolWrapper.d.ts.map +0 -1
- package/dist/components/config/LocaleConfigToolWrapper.js +0 -26
- package/dist/components/config/LocaleConfigToolWrapper.js.map +0 -1
- package/dist/components/config/OAuthConfig.d.ts +0 -26
- package/dist/components/config/OAuthConfig.d.ts.map +0 -1
- package/dist/components/config/OAuthConfig.js +0 -152
- package/dist/components/config/OAuthConfig.js.map +0 -1
- package/dist/components/config/OAuthConfigWrapper.d.ts +0 -13
- package/dist/components/config/OAuthConfigWrapper.d.ts.map +0 -1
- package/dist/components/config/OAuthConfigWrapper.js +0 -41
- package/dist/components/config/OAuthConfigWrapper.js.map +0 -1
- package/dist/components/config/PasswordInput.d.ts +0 -14
- package/dist/components/config/PasswordInput.d.ts.map +0 -1
- package/dist/components/config/PasswordInput.js +0 -23
- package/dist/components/config/PasswordInput.js.map +0 -1
- package/dist/components/config/index.d.ts +0 -9
- package/dist/components/config/index.d.ts.map +0 -1
- package/dist/components/config/index.js +0 -8
- package/dist/components/config/index.js.map +0 -1
- package/dist/components/config/localeConfigToolDefinition.d.ts +0 -13
- package/dist/components/config/localeConfigToolDefinition.d.ts.map +0 -1
- package/dist/components/config/localeConfigToolDefinition.js +0 -19
- package/dist/components/config/localeConfigToolDefinition.js.map +0 -1
- package/dist/components/config/oauthConfigToolDefinition.d.ts +0 -13
- package/dist/components/config/oauthConfigToolDefinition.d.ts.map +0 -1
- package/dist/components/config/oauthConfigToolDefinition.js +0 -19
- package/dist/components/config/oauthConfigToolDefinition.js.map +0 -1
- package/dist/components/dialogs/ConfirmationDialog.d.ts +0 -21
- package/dist/components/dialogs/ConfirmationDialog.d.ts.map +0 -1
- package/dist/components/dialogs/ConfirmationDialog.js +0 -28
- package/dist/components/dialogs/ConfirmationDialog.js.map +0 -1
- package/dist/components/dialogs/ErrorDialog.d.ts +0 -21
- package/dist/components/dialogs/ErrorDialog.d.ts.map +0 -1
- package/dist/components/dialogs/ErrorDialog.js +0 -28
- package/dist/components/dialogs/ErrorDialog.js.map +0 -1
- package/dist/components/dialogs/LocaleSelectionDialog.d.ts +0 -41
- package/dist/components/dialogs/LocaleSelectionDialog.d.ts.map +0 -1
- package/dist/components/dialogs/LocaleSelectionDialog.js +0 -117
- package/dist/components/dialogs/LocaleSelectionDialog.js.map +0 -1
- package/dist/components/dialogs/SuccessDialog.d.ts +0 -19
- package/dist/components/dialogs/SuccessDialog.d.ts.map +0 -1
- package/dist/components/dialogs/SuccessDialog.js +0 -37
- package/dist/components/dialogs/SuccessDialog.js.map +0 -1
- package/dist/components/dialogs/index.d.ts +0 -12
- package/dist/components/dialogs/index.d.ts.map +0 -1
- package/dist/components/dialogs/index.js +0 -8
- package/dist/components/dialogs/index.js.map +0 -1
- package/dist/components/dnt/DNTFieldBadge.d.ts +0 -16
- package/dist/components/dnt/DNTFieldBadge.d.ts.map +0 -1
- package/dist/components/dnt/DNTFieldBadge.js +0 -56
- package/dist/components/dnt/DNTFieldBadge.js.map +0 -1
- package/dist/components/dnt/DNTFieldComponent.d.ts +0 -17
- package/dist/components/dnt/DNTFieldComponent.d.ts.map +0 -1
- package/dist/components/dnt/DNTFieldComponent.js +0 -21
- package/dist/components/dnt/DNTFieldComponent.js.map +0 -1
- package/dist/components/dnt/DNTFieldInput.d.ts +0 -14
- package/dist/components/dnt/DNTFieldInput.d.ts.map +0 -1
- package/dist/components/dnt/DNTFieldInput.js +0 -76
- package/dist/components/dnt/DNTFieldInput.js.map +0 -1
- package/dist/components/dnt/index.d.ts +0 -7
- package/dist/components/dnt/index.d.ts.map +0 -1
- package/dist/components/dnt/index.js +0 -7
- package/dist/components/dnt/index.js.map +0 -1
- package/dist/config/index.d.ts +0 -6
- package/dist/config/index.d.ts.map +0 -1
- package/dist/config/index.js +0 -6
- package/dist/config/index.js.map +0 -1
- package/dist/config/pluginConfig.d.ts +0 -163
- package/dist/config/pluginConfig.d.ts.map +0 -1
- package/dist/config/pluginConfig.js +0 -548
- package/dist/config/pluginConfig.js.map +0 -1
- package/dist/index.d.ts +0 -12
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -12
- package/dist/index.js.map +0 -1
- package/dist/plugin.d.ts +0 -3
- package/dist/plugin.d.ts.map +0 -1
- package/dist/plugin.js +0 -137
- package/dist/plugin.js.map +0 -1
- package/dist/services/authStateManager.d.ts +0 -94
- package/dist/services/authStateManager.d.ts.map +0 -1
- package/dist/services/authStateManager.js +0 -208
- package/dist/services/authStateManager.js.map +0 -1
- package/dist/services/contentExtractor.d.ts +0 -95
- package/dist/services/contentExtractor.d.ts.map +0 -1
- package/dist/services/contentExtractor.js +0 -516
- package/dist/services/contentExtractor.js.map +0 -1
- package/dist/services/dialogService.d.ts +0 -96
- package/dist/services/dialogService.d.ts.map +0 -1
- package/dist/services/dialogService.js +0 -244
- package/dist/services/dialogService.js.map +0 -1
- package/dist/services/dntServiceManager.d.ts +0 -44
- package/dist/services/dntServiceManager.d.ts.map +0 -1
- package/dist/services/dntServiceManager.js +0 -74
- package/dist/services/dntServiceManager.js.map +0 -1
- package/dist/services/dntStorageAdapter.d.ts +0 -73
- package/dist/services/dntStorageAdapter.d.ts.map +0 -1
- package/dist/services/dntStorageAdapter.js +0 -192
- package/dist/services/dntStorageAdapter.js.map +0 -1
- package/dist/services/documentCreationService.d.ts +0 -139
- package/dist/services/documentCreationService.d.ts.map +0 -1
- package/dist/services/documentCreationService.js +0 -938
- package/dist/services/documentCreationService.js.map +0 -1
- package/dist/services/localeService.d.ts +0 -160
- package/dist/services/localeService.d.ts.map +0 -1
- package/dist/services/localeService.js +0 -300
- package/dist/services/localeService.js.map +0 -1
- package/dist/services/localeStorageAdapter.d.ts +0 -42
- package/dist/services/localeStorageAdapter.d.ts.map +0 -1
- package/dist/services/localeStorageAdapter.js +0 -107
- package/dist/services/localeStorageAdapter.js.map +0 -1
- package/dist/services/oauthConfigStorage.d.ts +0 -46
- package/dist/services/oauthConfigStorage.d.ts.map +0 -1
- package/dist/services/oauthConfigStorage.js +0 -122
- package/dist/services/oauthConfigStorage.js.map +0 -1
- package/dist/services/oauthService.d.ts +0 -48
- package/dist/services/oauthService.d.ts.map +0 -1
- package/dist/services/oauthService.js +0 -71
- package/dist/services/oauthService.js.map +0 -1
- package/dist/services/oauthServiceManager.d.ts +0 -189
- package/dist/services/oauthServiceManager.d.ts.map +0 -1
- package/dist/services/oauthServiceManager.js +0 -380
- package/dist/services/oauthServiceManager.js.map +0 -1
- package/dist/services/tokenStorage.d.ts +0 -54
- package/dist/services/tokenStorage.d.ts.map +0 -1
- package/dist/services/tokenStorage.js +0 -140
- package/dist/services/tokenStorage.js.map +0 -1
- package/dist/services/translationService.d.ts +0 -374
- package/dist/services/translationService.d.ts.map +0 -1
- package/dist/services/translationService.js +0 -687
- package/dist/services/translationService.js.map +0 -1
- package/dist/services/unifiedConfigStorage.d.ts +0 -124
- package/dist/services/unifiedConfigStorage.d.ts.map +0 -1
- package/dist/services/unifiedConfigStorage.js +0 -304
- package/dist/services/unifiedConfigStorage.js.map +0 -1
- package/dist/test-utils.d.ts +0 -9
- package/dist/test-utils.d.ts.map +0 -1
- package/dist/test-utils.js +0 -13
- package/dist/test-utils.js.map +0 -1
- package/dist/types/dialog.d.ts +0 -107
- package/dist/types/dialog.d.ts.map +0 -1
- package/dist/types/dialog.js +0 -6
- package/dist/types/dialog.js.map +0 -1
- package/dist/types/dnt.d.ts +0 -84
- package/dist/types/dnt.d.ts.map +0 -1
- package/dist/types/dnt.js +0 -5
- package/dist/types/dnt.js.map +0 -1
- package/dist/types/index.d.ts +0 -12
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -6
- package/dist/types/index.js.map +0 -1
- package/dist/types/locale.d.ts +0 -116
- package/dist/types/locale.d.ts.map +0 -1
- package/dist/types/locale.js +0 -189
- package/dist/types/locale.js.map +0 -1
- package/dist/types/oauth.d.ts +0 -90
- package/dist/types/oauth.d.ts.map +0 -1
- package/dist/types/oauth.js +0 -62
- package/dist/types/oauth.js.map +0 -1
- package/dist/types/pluginConfig.d.ts +0 -45
- package/dist/types/pluginConfig.d.ts.map +0 -1
- package/dist/types/pluginConfig.js +0 -6
- package/dist/types/pluginConfig.js.map +0 -1
- package/dist/types/translation.d.ts +0 -122
- package/dist/types/translation.d.ts.map +0 -1
- package/dist/types/translation.js +0 -6
- package/dist/types/translation.js.map +0 -1
- package/dist/utils/htmlFormatter.d.ts +0 -66
- package/dist/utils/htmlFormatter.d.ts.map +0 -1
- package/dist/utils/htmlFormatter.js +0 -191
- package/dist/utils/htmlFormatter.js.map +0 -1
- package/dist/utils/index.d.ts +0 -15
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -16
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -105
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -229
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/oauthErrorFeedback.d.ts +0 -76
- package/dist/utils/oauthErrorFeedback.d.ts.map +0 -1
- package/dist/utils/oauthErrorFeedback.js +0 -134
- package/dist/utils/oauthErrorFeedback.js.map +0 -1
- package/dist/utils/oauthLogger.d.ts +0 -176
- package/dist/utils/oauthLogger.d.ts.map +0 -1
- package/dist/utils/oauthLogger.js +0 -282
- package/dist/utils/oauthLogger.js.map +0 -1
- package/dist/utils/validator.d.ts +0 -67
- package/dist/utils/validator.d.ts.map +0 -1
- package/dist/utils/validator.js +0 -390
- package/dist/utils/validator.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,27 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@easyling/sanity-connector",
|
|
3
|
-
"version": "0.0.1",
|
|
3
|
+
"version": "0.0.2-rc.1",
|
|
4
4
|
"description": "A Sanity Studio plugin that enables document translation with support for single and bulk operations. Extracts document content as HTML and prepares translation requests for external services.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
7
|
-
"types": "dist/index.d.ts",
|
|
7
|
+
"types": "dist-types/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
|
-
"types": "./dist/index.d.ts",
|
|
10
|
+
"types": "./dist-types/index.d.ts",
|
|
11
11
|
"import": "./dist/index.js",
|
|
12
12
|
"require": "./dist/index.js"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
16
|
"dist",
|
|
17
|
+
"dist-types",
|
|
17
18
|
"README.md",
|
|
18
19
|
"LICENSE"
|
|
19
20
|
],
|
|
20
21
|
"scripts": {
|
|
21
22
|
"build": "npm run clean && tsc",
|
|
22
|
-
"build:bundle": "npm run clean && webpack build && tsc --project tsconfig.
|
|
23
|
+
"build:bundle": "npm run clean && webpack build && tsc --project tsconfig.types.json",
|
|
23
24
|
"build:watch": "tsc --watch",
|
|
24
|
-
"clean": "rimraf dist",
|
|
25
|
+
"clean": "rimraf dist dist-types",
|
|
25
26
|
"dev": "npm run build:watch",
|
|
26
27
|
"test": "jest",
|
|
27
28
|
"test:watch": "jest --watch",
|
|
@@ -53,16 +54,16 @@
|
|
|
53
54
|
},
|
|
54
55
|
"homepage": "",
|
|
55
56
|
"peerDependencies": {
|
|
56
|
-
"react": "^
|
|
57
|
-
"react-dom": "^
|
|
58
|
-
"sanity": "^
|
|
57
|
+
"react": "^19.0.0",
|
|
58
|
+
"react-dom": "^19.0.0",
|
|
59
|
+
"sanity": "^4.0.0"
|
|
59
60
|
},
|
|
60
61
|
"devDependencies": {
|
|
61
62
|
"@testing-library/jest-dom": "^6.9.1",
|
|
62
63
|
"@testing-library/react": "^16.3.0",
|
|
63
64
|
"@types/jest": "^29.0.0",
|
|
64
|
-
"@types/react": "^
|
|
65
|
-
"@types/react-dom": "^
|
|
65
|
+
"@types/react": "^19.0.0",
|
|
66
|
+
"@types/react-dom": "^19.0.0",
|
|
66
67
|
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
|
67
68
|
"@typescript-eslint/parser": "^6.21.0",
|
|
68
69
|
"eslint": "^8.0.0",
|
|
@@ -74,7 +75,12 @@
|
|
|
74
75
|
"ts-loader": "^9.5.4",
|
|
75
76
|
"typescript": "^5.0.0",
|
|
76
77
|
"webpack": "^5.103.0",
|
|
77
|
-
"
|
|
78
|
-
"
|
|
78
|
+
"@easyling/sanity": "^1.0.6",
|
|
79
|
+
"webpack-cli": "^6.0.1"
|
|
80
|
+
},
|
|
81
|
+
"dependencies": {
|
|
82
|
+
"@sanity/icons": "^2.0.0",
|
|
83
|
+
"@sanity/ui": "^1.0.0",
|
|
84
|
+
"protobufjs": "^7.5.4"
|
|
79
85
|
}
|
|
80
86
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bulkTranslate.d.ts","sourceRoot":"","sources":["../../src/actions/bulkTranslate.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAA6B,MAAM,QAAQ,CAAC;AA8lCzD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,IAK/B,CAAC"}
|
|
@@ -1,543 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState, useCallback, useEffect } from 'react';
|
|
3
|
-
import { useClient } from 'sanity';
|
|
4
|
-
import { TranslateIcon, CheckmarkIcon, CloseIcon, WarningOutlineIcon, RefreshIcon, ChevronDownIcon, ChevronRightIcon } from '@sanity/icons';
|
|
5
|
-
import { Card, Stack, Text, Button, Flex, Box, Spinner, Badge, Checkbox } from '@sanity/ui';
|
|
6
|
-
import { ContentExtractor } from '../services/contentExtractor';
|
|
7
|
-
import { DocumentCreationService } from '../services/documentCreationService';
|
|
8
|
-
import { LocaleService } from '../services/localeService';
|
|
9
|
-
import { SanityLocaleStorageAdapter } from '../services/localeStorageAdapter';
|
|
10
|
-
import { useDialogService } from '../services/dialogService';
|
|
11
|
-
import { OAuthServiceManager } from '../services/oauthServiceManager';
|
|
12
|
-
/**
|
|
13
|
-
* Bulk Translation Tool Component
|
|
14
|
-
* Requirements: 2.2, 2.4, 3.1, 3.4, 4.1, 4.3
|
|
15
|
-
*/
|
|
16
|
-
const BulkTranslateTool = () => {
|
|
17
|
-
const client = useClient();
|
|
18
|
-
const dialogService = useDialogService();
|
|
19
|
-
const [state, setState] = useState({
|
|
20
|
-
isProcessing: false,
|
|
21
|
-
isLoadingDocuments: false,
|
|
22
|
-
selectedDocuments: [],
|
|
23
|
-
availableDocuments: {},
|
|
24
|
-
selectedTypes: new Set(),
|
|
25
|
-
selectedDocumentIds: new Set(),
|
|
26
|
-
expandedTypes: new Set(),
|
|
27
|
-
summary: null,
|
|
28
|
-
error: null,
|
|
29
|
-
processingStatus: [],
|
|
30
|
-
currentProcessingIndex: -1,
|
|
31
|
-
createDocuments: false,
|
|
32
|
-
documentCreationResult: null,
|
|
33
|
-
selectedLocales: null
|
|
34
|
-
});
|
|
35
|
-
/**
|
|
36
|
-
* Fetch all documents from Sanity, grouped by type and ordered by creation date
|
|
37
|
-
*/
|
|
38
|
-
const fetchDocuments = useCallback(async () => {
|
|
39
|
-
setState(prev => ({ ...prev, isLoadingDocuments: true, error: null }));
|
|
40
|
-
try {
|
|
41
|
-
// Query all documents, excluding system documents, Sanity internal documents, and plugin internal types (EL_*)
|
|
42
|
-
const query = `*[!(_id in path("_.**")) && !(_type match "sanity.**") && !(_type match "EL_*")] | order(_createdAt desc) {
|
|
43
|
-
_id,
|
|
44
|
-
_type,
|
|
45
|
-
_createdAt,
|
|
46
|
-
_updatedAt,
|
|
47
|
-
_rev,
|
|
48
|
-
title,
|
|
49
|
-
name,
|
|
50
|
-
heading,
|
|
51
|
-
label,
|
|
52
|
-
...
|
|
53
|
-
}`;
|
|
54
|
-
console.log('Fetching documents from Sanity...');
|
|
55
|
-
const documents = await client.fetch(query);
|
|
56
|
-
console.log(`Fetched ${documents.length} documents`);
|
|
57
|
-
// Group documents by type
|
|
58
|
-
const documentsByType = {};
|
|
59
|
-
documents.forEach(doc => {
|
|
60
|
-
if (!documentsByType[doc._type]) {
|
|
61
|
-
documentsByType[doc._type] = [];
|
|
62
|
-
}
|
|
63
|
-
documentsByType[doc._type].push(doc);
|
|
64
|
-
});
|
|
65
|
-
// Log the grouping for debugging
|
|
66
|
-
Object.keys(documentsByType).forEach(type => {
|
|
67
|
-
console.log(`Type "${type}": ${documentsByType[type].length} documents`);
|
|
68
|
-
});
|
|
69
|
-
setState(prev => ({
|
|
70
|
-
...prev,
|
|
71
|
-
availableDocuments: documentsByType,
|
|
72
|
-
isLoadingDocuments: false
|
|
73
|
-
}));
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
console.error('Failed to fetch documents:', error);
|
|
77
|
-
setState(prev => ({
|
|
78
|
-
...prev,
|
|
79
|
-
error: error instanceof Error ? error.message : 'Failed to fetch documents',
|
|
80
|
-
isLoadingDocuments: false
|
|
81
|
-
}));
|
|
82
|
-
}
|
|
83
|
-
}, [client]);
|
|
84
|
-
// Load documents on component mount
|
|
85
|
-
useEffect(() => {
|
|
86
|
-
fetchDocuments();
|
|
87
|
-
}, [fetchDocuments]);
|
|
88
|
-
/**
|
|
89
|
-
* Handle document type selection (select/deselect all documents of a type)
|
|
90
|
-
*/
|
|
91
|
-
const handleTypeSelection = useCallback((type, selected) => {
|
|
92
|
-
setState(prev => {
|
|
93
|
-
const newSelectedTypes = new Set(prev.selectedTypes);
|
|
94
|
-
const newSelectedDocumentIds = new Set(prev.selectedDocumentIds);
|
|
95
|
-
if (selected) {
|
|
96
|
-
newSelectedTypes.add(type);
|
|
97
|
-
// Add all documents of this type to selected documents
|
|
98
|
-
if (prev.availableDocuments[type]) {
|
|
99
|
-
prev.availableDocuments[type].forEach(doc => {
|
|
100
|
-
newSelectedDocumentIds.add(doc._id);
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
newSelectedTypes.delete(type);
|
|
106
|
-
// Remove all documents of this type from selected documents
|
|
107
|
-
if (prev.availableDocuments[type]) {
|
|
108
|
-
prev.availableDocuments[type].forEach(doc => {
|
|
109
|
-
newSelectedDocumentIds.delete(doc._id);
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
// Update selected documents array based on selected IDs
|
|
114
|
-
const newSelectedDocuments = Object.values(prev.availableDocuments)
|
|
115
|
-
.flat()
|
|
116
|
-
.filter(doc => newSelectedDocumentIds.has(doc._id));
|
|
117
|
-
// Create processing status for selected documents
|
|
118
|
-
const processingStatus = newSelectedDocuments.map(doc => ({
|
|
119
|
-
documentId: doc._id,
|
|
120
|
-
title: getDocumentTitle(doc),
|
|
121
|
-
status: 'pending'
|
|
122
|
-
}));
|
|
123
|
-
return {
|
|
124
|
-
...prev,
|
|
125
|
-
selectedTypes: newSelectedTypes,
|
|
126
|
-
selectedDocumentIds: newSelectedDocumentIds,
|
|
127
|
-
selectedDocuments: newSelectedDocuments,
|
|
128
|
-
processingStatus,
|
|
129
|
-
summary: null,
|
|
130
|
-
error: null,
|
|
131
|
-
currentProcessingIndex: -1
|
|
132
|
-
};
|
|
133
|
-
});
|
|
134
|
-
}, []);
|
|
135
|
-
/**
|
|
136
|
-
* Handle individual document selection
|
|
137
|
-
*/
|
|
138
|
-
const handleDocumentSelection = useCallback((document, selected) => {
|
|
139
|
-
setState(prev => {
|
|
140
|
-
const newSelectedDocumentIds = new Set(prev.selectedDocumentIds);
|
|
141
|
-
const newSelectedTypes = new Set(prev.selectedTypes);
|
|
142
|
-
if (selected) {
|
|
143
|
-
newSelectedDocumentIds.add(document._id);
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
newSelectedDocumentIds.delete(document._id);
|
|
147
|
-
// If no documents of this type are selected, remove the type from selectedTypes
|
|
148
|
-
const typeDocuments = prev.availableDocuments[document._type] || [];
|
|
149
|
-
const hasOtherSelectedInType = typeDocuments.some(doc => doc._id !== document._id && newSelectedDocumentIds.has(doc._id));
|
|
150
|
-
if (!hasOtherSelectedInType) {
|
|
151
|
-
newSelectedTypes.delete(document._type);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
// Check if all documents of this type are now selected
|
|
155
|
-
const typeDocuments = prev.availableDocuments[document._type] || [];
|
|
156
|
-
const allTypeDocumentsSelected = typeDocuments.every(doc => newSelectedDocumentIds.has(doc._id));
|
|
157
|
-
if (allTypeDocumentsSelected && typeDocuments.length > 0) {
|
|
158
|
-
newSelectedTypes.add(document._type);
|
|
159
|
-
}
|
|
160
|
-
// Update selected documents array
|
|
161
|
-
const newSelectedDocuments = Object.values(prev.availableDocuments)
|
|
162
|
-
.flat()
|
|
163
|
-
.filter(doc => newSelectedDocumentIds.has(doc._id));
|
|
164
|
-
// Create processing status for selected documents
|
|
165
|
-
const processingStatus = newSelectedDocuments.map(doc => ({
|
|
166
|
-
documentId: doc._id,
|
|
167
|
-
title: getDocumentTitle(doc),
|
|
168
|
-
status: 'pending'
|
|
169
|
-
}));
|
|
170
|
-
return {
|
|
171
|
-
...prev,
|
|
172
|
-
selectedTypes: newSelectedTypes,
|
|
173
|
-
selectedDocumentIds: newSelectedDocumentIds,
|
|
174
|
-
selectedDocuments: newSelectedDocuments,
|
|
175
|
-
processingStatus,
|
|
176
|
-
summary: null,
|
|
177
|
-
error: null,
|
|
178
|
-
currentProcessingIndex: -1
|
|
179
|
-
};
|
|
180
|
-
});
|
|
181
|
-
}, []);
|
|
182
|
-
/**
|
|
183
|
-
* Toggle expansion of document type to show individual documents
|
|
184
|
-
*/
|
|
185
|
-
const handleTypeExpansion = useCallback((type) => {
|
|
186
|
-
setState(prev => {
|
|
187
|
-
const newExpandedTypes = new Set(prev.expandedTypes);
|
|
188
|
-
if (newExpandedTypes.has(type)) {
|
|
189
|
-
newExpandedTypes.delete(type);
|
|
190
|
-
}
|
|
191
|
-
else {
|
|
192
|
-
newExpandedTypes.add(type);
|
|
193
|
-
}
|
|
194
|
-
return {
|
|
195
|
-
...prev,
|
|
196
|
-
expandedTypes: newExpandedTypes
|
|
197
|
-
};
|
|
198
|
-
});
|
|
199
|
-
}, []);
|
|
200
|
-
/**
|
|
201
|
-
* Select all documents of all types
|
|
202
|
-
*/
|
|
203
|
-
const handleSelectAll = useCallback(() => {
|
|
204
|
-
const allTypes = Object.keys(state.availableDocuments);
|
|
205
|
-
const allDocuments = Object.values(state.availableDocuments).flat();
|
|
206
|
-
const allDocumentIds = new Set(allDocuments.map(doc => doc._id));
|
|
207
|
-
const processingStatus = allDocuments.map(doc => ({
|
|
208
|
-
documentId: doc._id,
|
|
209
|
-
title: getDocumentTitle(doc),
|
|
210
|
-
status: 'pending'
|
|
211
|
-
}));
|
|
212
|
-
setState(prev => ({
|
|
213
|
-
...prev,
|
|
214
|
-
selectedTypes: new Set(allTypes),
|
|
215
|
-
selectedDocumentIds: allDocumentIds,
|
|
216
|
-
selectedDocuments: allDocuments,
|
|
217
|
-
processingStatus,
|
|
218
|
-
summary: null,
|
|
219
|
-
error: null,
|
|
220
|
-
currentProcessingIndex: -1,
|
|
221
|
-
documentCreationResult: null
|
|
222
|
-
}));
|
|
223
|
-
}, [state.availableDocuments]);
|
|
224
|
-
/**
|
|
225
|
-
* Clear all selections
|
|
226
|
-
*/
|
|
227
|
-
const handleClearSelection = useCallback(() => {
|
|
228
|
-
setState(prev => ({
|
|
229
|
-
...prev,
|
|
230
|
-
selectedTypes: new Set(),
|
|
231
|
-
selectedDocumentIds: new Set(),
|
|
232
|
-
selectedDocuments: [],
|
|
233
|
-
processingStatus: [],
|
|
234
|
-
summary: null,
|
|
235
|
-
error: null,
|
|
236
|
-
currentProcessingIndex: -1,
|
|
237
|
-
documentCreationResult: null
|
|
238
|
-
}));
|
|
239
|
-
}, []);
|
|
240
|
-
/**
|
|
241
|
-
* Get document title from various possible fields
|
|
242
|
-
*/
|
|
243
|
-
const getDocumentTitle = (doc) => {
|
|
244
|
-
const titleFields = ['title', 'name', 'heading', 'label'];
|
|
245
|
-
for (const field of titleFields) {
|
|
246
|
-
if (doc[field] && typeof doc[field] === 'string') {
|
|
247
|
-
return doc[field];
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
return `${doc._type} (${doc._id})`;
|
|
251
|
-
};
|
|
252
|
-
const handleBulkTranslate = useCallback(async () => {
|
|
253
|
-
if (state.selectedDocuments.length === 0) {
|
|
254
|
-
await dialogService.showError({
|
|
255
|
-
title: 'No Documents Selected',
|
|
256
|
-
message: 'Please select at least one document to translate.',
|
|
257
|
-
error: new Error('No documents selected for translation')
|
|
258
|
-
});
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
try {
|
|
262
|
-
// Get OAuth service manager and check authentication
|
|
263
|
-
// Requirements: 4.1, 4.2, 4.3, 10.5
|
|
264
|
-
const serviceManager = OAuthServiceManager.getInstance(client);
|
|
265
|
-
const authStateManager = serviceManager.getAuthStateManager();
|
|
266
|
-
const authState = authStateManager.getState();
|
|
267
|
-
// If OAuth is configured but not authenticated, prompt user to authenticate
|
|
268
|
-
if (serviceManager.isOAuthConfigured() && authState.state !== 'authenticated') {
|
|
269
|
-
await dialogService.showError({
|
|
270
|
-
title: 'Authentication Required',
|
|
271
|
-
message: 'You need to configure your Easyling credentials to use translation services.',
|
|
272
|
-
error: new Error('Please go to the Easyling Configuration tool to enter your access token and project ID.')
|
|
273
|
-
});
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
// Initialize locale service
|
|
277
|
-
const storageAdapter = new SanityLocaleStorageAdapter(client);
|
|
278
|
-
const localeService = new LocaleService(storageAdapter);
|
|
279
|
-
// Load locale configuration
|
|
280
|
-
await localeService.loadConfig();
|
|
281
|
-
const enabledLocales = localeService.getEnabledLocales();
|
|
282
|
-
// Check if locales are configured
|
|
283
|
-
if (enabledLocales.length === 0) {
|
|
284
|
-
await dialogService.showError({
|
|
285
|
-
title: 'No Locales Configured',
|
|
286
|
-
message: 'Please configure target locales before translating documents.',
|
|
287
|
-
error: new Error('No translation locales have been configured. Please use the Locale Configuration tool to add target languages.')
|
|
288
|
-
});
|
|
289
|
-
return;
|
|
290
|
-
}
|
|
291
|
-
// Show locale selection dialog
|
|
292
|
-
const selectedLocalesResult = await dialogService.showLocaleSelection({
|
|
293
|
-
title: 'Select Target Locales',
|
|
294
|
-
message: `Choose the languages to translate ${state.selectedDocuments.length} document${state.selectedDocuments.length !== 1 ? 's' : ''} into:`,
|
|
295
|
-
availableLocales: enabledLocales,
|
|
296
|
-
selectedLocales: [],
|
|
297
|
-
selectedDocuments: state.selectedDocuments,
|
|
298
|
-
mode: 'bulk',
|
|
299
|
-
allowMultiple: true,
|
|
300
|
-
required: true,
|
|
301
|
-
showCreationModeOption: true,
|
|
302
|
-
defaultCreationMode: 'draft'
|
|
303
|
-
});
|
|
304
|
-
// User cancelled locale selection
|
|
305
|
-
if (!selectedLocalesResult || !selectedLocalesResult.locales || selectedLocalesResult.locales.length === 0) {
|
|
306
|
-
return;
|
|
307
|
-
}
|
|
308
|
-
const selectedLocales = selectedLocalesResult.locales;
|
|
309
|
-
const creationMode = selectedLocalesResult.creationMode || 'draft';
|
|
310
|
-
// Ask user if they want to create new documents
|
|
311
|
-
const shouldCreateDocuments = await dialogService.showConfirmation({
|
|
312
|
-
title: 'Confirm Bulk Translation',
|
|
313
|
-
message: `Translate ${state.selectedDocuments.length} document${state.selectedDocuments.length !== 1 ? 's' : ''} to ${selectedLocales.length} locale${selectedLocales.length !== 1 ? 's' : ''}?`,
|
|
314
|
-
details: `This will:\n• Send translation requests for all selected documents\n• Create new documents with translated content for successful translations\n• Preserve the original document structures\n\nTarget locales: ${selectedLocales.join(', ')}`,
|
|
315
|
-
confirmText: 'Translate & Create Documents',
|
|
316
|
-
cancelText: 'Cancel',
|
|
317
|
-
tone: 'primary'
|
|
318
|
-
});
|
|
319
|
-
// User cancelled confirmation
|
|
320
|
-
if (!shouldCreateDocuments) {
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
setState(prev => ({
|
|
324
|
-
...prev,
|
|
325
|
-
isProcessing: true,
|
|
326
|
-
error: null,
|
|
327
|
-
summary: null,
|
|
328
|
-
currentProcessingIndex: 0,
|
|
329
|
-
createDocuments: shouldCreateDocuments,
|
|
330
|
-
documentCreationResult: null,
|
|
331
|
-
selectedLocales
|
|
332
|
-
}));
|
|
333
|
-
// Initialize services
|
|
334
|
-
const contentExtractor = new ContentExtractor();
|
|
335
|
-
const translationService = serviceManager.getTranslationService();
|
|
336
|
-
const documentCreationService = new DocumentCreationService(client);
|
|
337
|
-
console.log(`Starting bulk translation for ${state.selectedDocuments.length} documents`);
|
|
338
|
-
// Extract content from all selected documents
|
|
339
|
-
const extractedContents = await contentExtractor.extractBulkStructuredContent(state.selectedDocuments);
|
|
340
|
-
// Filter out documents with no content and update status
|
|
341
|
-
const validContents = extractedContents.filter(content => {
|
|
342
|
-
const hasContent = content.htmlContent && content.htmlContent.trim().length > 0;
|
|
343
|
-
if (!hasContent) {
|
|
344
|
-
// Update status for documents with no content
|
|
345
|
-
setState(prev => ({
|
|
346
|
-
...prev,
|
|
347
|
-
processingStatus: prev.processingStatus.map(status => status.documentId === content.documentId
|
|
348
|
-
? { ...status, status: 'failed', error: 'No translatable content found' }
|
|
349
|
-
: status)
|
|
350
|
-
}));
|
|
351
|
-
}
|
|
352
|
-
return hasContent;
|
|
353
|
-
});
|
|
354
|
-
if (validContents.length === 0) {
|
|
355
|
-
throw new Error('No translatable content found in selected documents');
|
|
356
|
-
}
|
|
357
|
-
console.log(`Processing ${validContents.length} documents with valid content`);
|
|
358
|
-
// Process documents one by one with progress updates
|
|
359
|
-
const summary = {
|
|
360
|
-
totalDocuments: state.selectedDocuments.length,
|
|
361
|
-
processedDocuments: 0,
|
|
362
|
-
failedDocuments: 0,
|
|
363
|
-
requests: [],
|
|
364
|
-
responses: []
|
|
365
|
-
};
|
|
366
|
-
for (let i = 0; i < validContents.length; i++) {
|
|
367
|
-
const content = validContents[i];
|
|
368
|
-
// Update current processing index and document status
|
|
369
|
-
setState(prev => ({
|
|
370
|
-
...prev,
|
|
371
|
-
currentProcessingIndex: i,
|
|
372
|
-
processingStatus: prev.processingStatus.map(status => status.documentId === content.documentId
|
|
373
|
-
? { ...status, status: 'processing' }
|
|
374
|
-
: status)
|
|
375
|
-
}));
|
|
376
|
-
try {
|
|
377
|
-
// Prepare and send translation request with selected locales
|
|
378
|
-
const request = translationService.prepareTranslationRequest(content, undefined, // documentType - use default
|
|
379
|
-
undefined, // sourceLanguage - use default
|
|
380
|
-
undefined, // targetLanguage - not used for multi-locale
|
|
381
|
-
selectedLocales // targetLocales array
|
|
382
|
-
);
|
|
383
|
-
const response = await translationService.sendTranslationRequest(request);
|
|
384
|
-
// Update summary
|
|
385
|
-
summary.requests.push(request);
|
|
386
|
-
summary.responses.push(response);
|
|
387
|
-
if (response.success) {
|
|
388
|
-
summary.processedDocuments++;
|
|
389
|
-
// Update document status to completed
|
|
390
|
-
setState(prev => ({
|
|
391
|
-
...prev,
|
|
392
|
-
processingStatus: prev.processingStatus.map(status => status.documentId === content.documentId
|
|
393
|
-
? { ...status, status: 'completed', response }
|
|
394
|
-
: status)
|
|
395
|
-
}));
|
|
396
|
-
}
|
|
397
|
-
else {
|
|
398
|
-
summary.failedDocuments++;
|
|
399
|
-
// Update document status to failed
|
|
400
|
-
setState(prev => ({
|
|
401
|
-
...prev,
|
|
402
|
-
processingStatus: prev.processingStatus.map(status => status.documentId === content.documentId
|
|
403
|
-
? { ...status, status: 'failed', error: response.error, response }
|
|
404
|
-
: status)
|
|
405
|
-
}));
|
|
406
|
-
}
|
|
407
|
-
// Add a small delay to make progress visible
|
|
408
|
-
await new Promise(resolve => setTimeout(resolve, 500));
|
|
409
|
-
}
|
|
410
|
-
catch (error) {
|
|
411
|
-
console.error(`Failed to process document ${content.documentId}:`, error);
|
|
412
|
-
summary.failedDocuments++;
|
|
413
|
-
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
414
|
-
summary.responses.push({
|
|
415
|
-
success: false,
|
|
416
|
-
error: errorMessage
|
|
417
|
-
});
|
|
418
|
-
// Update document status to failed
|
|
419
|
-
setState(prev => ({
|
|
420
|
-
...prev,
|
|
421
|
-
processingStatus: prev.processingStatus.map(status => status.documentId === content.documentId
|
|
422
|
-
? { ...status, status: 'failed', error: errorMessage }
|
|
423
|
-
: status)
|
|
424
|
-
}));
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
// Create documents if user requested and we have successful translations
|
|
428
|
-
let documentCreationResult = null;
|
|
429
|
-
if (shouldCreateDocuments && summary.processedDocuments > 0) {
|
|
430
|
-
console.log('Creating new documents from successful translations...');
|
|
431
|
-
// Get successful translations and their corresponding original documents
|
|
432
|
-
const successfulResponses = summary.responses.filter(response => response.success);
|
|
433
|
-
const successfulDocuments = state.selectedDocuments.filter(doc => {
|
|
434
|
-
const responseIndex = summary.responses.findIndex((_, index) => {
|
|
435
|
-
const request = summary.requests[index];
|
|
436
|
-
return request && request.documentId === doc._id;
|
|
437
|
-
});
|
|
438
|
-
return responseIndex >= 0 && summary.responses[responseIndex].success;
|
|
439
|
-
});
|
|
440
|
-
if (successfulDocuments.length > 0 && successfulResponses.length > 0) {
|
|
441
|
-
documentCreationResult = await documentCreationService.createBulkDocumentsFromTranslations(successfulDocuments, successfulResponses, {
|
|
442
|
-
targetLanguage: 'translated',
|
|
443
|
-
createAsVariant: true,
|
|
444
|
-
creationMode: creationMode
|
|
445
|
-
});
|
|
446
|
-
console.log('Document Creation Summary:', {
|
|
447
|
-
totalDocuments: documentCreationResult.totalDocuments,
|
|
448
|
-
successfulCreations: documentCreationResult.successfulCreations,
|
|
449
|
-
failedCreations: documentCreationResult.failedCreations,
|
|
450
|
-
errors: documentCreationResult.errors
|
|
451
|
-
});
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
// Log bulk operation summary
|
|
455
|
-
console.log('Bulk Translation Summary:', {
|
|
456
|
-
timestamp: new Date().toISOString(),
|
|
457
|
-
totalDocuments: summary.totalDocuments,
|
|
458
|
-
processedDocuments: summary.processedDocuments,
|
|
459
|
-
failedDocuments: summary.failedDocuments,
|
|
460
|
-
successRate: summary.totalDocuments > 0
|
|
461
|
-
? ((summary.processedDocuments / summary.totalDocuments) * 100).toFixed(2) + '%'
|
|
462
|
-
: '0%'
|
|
463
|
-
});
|
|
464
|
-
setState(prev => ({
|
|
465
|
-
...prev,
|
|
466
|
-
summary,
|
|
467
|
-
documentCreationResult,
|
|
468
|
-
isProcessing: false,
|
|
469
|
-
currentProcessingIndex: -1
|
|
470
|
-
}));
|
|
471
|
-
console.log('Bulk translation completed:', summary);
|
|
472
|
-
// Show completion message to user
|
|
473
|
-
if (shouldCreateDocuments && documentCreationResult) {
|
|
474
|
-
dialogService.showSuccess({
|
|
475
|
-
title: 'Bulk Translation Completed',
|
|
476
|
-
message: `Successfully translated ${summary.processedDocuments} of ${summary.totalDocuments} documents to ${selectedLocales.length} locale${selectedLocales.length !== 1 ? 's' : ''}`,
|
|
477
|
-
details: `Translations: ${summary.processedDocuments}/${summary.totalDocuments} successful\nDocuments created: ${documentCreationResult.successfulCreations}/${documentCreationResult.totalDocuments} successful\nTarget locales: ${selectedLocales.join(', ')}\n\nCheck the console for detailed results and new document structures.`
|
|
478
|
-
});
|
|
479
|
-
}
|
|
480
|
-
else {
|
|
481
|
-
dialogService.showSuccess({
|
|
482
|
-
title: 'Bulk Translation Completed',
|
|
483
|
-
message: `Successfully translated ${summary.processedDocuments} of ${summary.totalDocuments} documents`,
|
|
484
|
-
details: `Translations: ${summary.processedDocuments}/${summary.totalDocuments} successful\nTarget locales: ${selectedLocales.join(', ')}\n\nTranslation responses have been logged to the console for verification.`
|
|
485
|
-
});
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
catch (error) {
|
|
489
|
-
console.error('Bulk translation failed:', error);
|
|
490
|
-
// Show error dialog
|
|
491
|
-
await dialogService.showError({
|
|
492
|
-
title: 'Bulk Translation Failed',
|
|
493
|
-
message: 'An error occurred during bulk translation.',
|
|
494
|
-
error: error instanceof Error ? error : new Error('An unexpected error occurred')
|
|
495
|
-
});
|
|
496
|
-
setState(prev => ({
|
|
497
|
-
...prev,
|
|
498
|
-
error: error instanceof Error ? error.message : 'An unexpected error occurred',
|
|
499
|
-
isProcessing: false,
|
|
500
|
-
currentProcessingIndex: -1
|
|
501
|
-
}));
|
|
502
|
-
}
|
|
503
|
-
}, [state.selectedDocuments, client, dialogService]);
|
|
504
|
-
return (_jsx(Card, { padding: 4, children: _jsxs(Stack, { space: 4, children: [_jsx(Text, { size: 2, weight: "semibold", children: "Bulk Document Translation" }), _jsx(Text, { size: 1, muted: true, children: "Select multiple documents to translate them in batch. Translation requests will be logged to the console for verification." }), _jsx(Card, { padding: 3, border: true, children: _jsxs(Stack, { space: 3, children: [_jsxs(Flex, { align: "center", justify: "space-between", children: [_jsx(Text, { size: 1, weight: "medium", children: "Document Selection" }), _jsxs(Flex, { gap: 2, children: [_jsx(Button, { text: "Refresh", icon: RefreshIcon, onClick: fetchDocuments, disabled: state.isLoadingDocuments, mode: "ghost", fontSize: 1 }), state.selectedDocuments.length > 0 && (_jsx(Button, { text: "Clear All", tone: "critical", mode: "ghost", onClick: handleClearSelection, fontSize: 1 }))] })] }), state.isLoadingDocuments ? (_jsxs(Flex, { align: "center", gap: 2, children: [_jsx(Spinner, { size: 1 }), _jsx(Text, { size: 1, muted: true, children: "Loading documents..." })] })) : Object.keys(state.availableDocuments).length === 0 ? (_jsx(Text, { size: 1, muted: true, children: "No documents found" })) : (_jsxs(Stack, { space: 3, children: [_jsxs(Flex, { align: "center", justify: "space-between", children: [_jsxs(Text, { size: 1, children: ["Selected: ", state.selectedDocuments.length, " documents from ", state.selectedTypes.size, " types"] }), _jsx(Button, { text: "Select All Types", onClick: handleSelectAll, mode: "ghost", fontSize: 1 })] }), _jsxs(Stack, { space: 2, children: [_jsx(Text, { size: 1, weight: "medium", children: "Document Types" }), Object.entries(state.availableDocuments)
|
|
505
|
-
.sort(([a], [b]) => a.localeCompare(b))
|
|
506
|
-
.map(([type, documents]) => {
|
|
507
|
-
const isExpanded = state.expandedTypes.has(type);
|
|
508
|
-
const selectedInType = documents.filter(doc => state.selectedDocumentIds.has(doc._id)).length;
|
|
509
|
-
const isPartiallySelected = selectedInType > 0 && selectedInType < documents.length;
|
|
510
|
-
const isFullySelected = selectedInType === documents.length;
|
|
511
|
-
return (_jsx(Card, { padding: 2, border: true, children: _jsxs(Stack, { space: 2, children: [_jsxs(Flex, { align: "center", justify: "space-between", children: [_jsxs(Flex, { align: "center", gap: 2, children: [_jsx(Checkbox, { checked: isFullySelected, indeterminate: isPartiallySelected, onChange: (event) => handleTypeSelection(type, event.currentTarget.checked) }), _jsx(Button, { icon: isExpanded ? ChevronDownIcon : ChevronRightIcon, mode: "ghost", onClick: () => handleTypeExpansion(type), style: { minWidth: 'auto', padding: '4px' } }), _jsxs(Box, { children: [_jsx(Text, { size: 1, weight: "medium", children: type }), _jsxs(Text, { size: 0, muted: true, children: [selectedInType, "/", documents.length, " selected \u2022 Latest: ", new Date(documents[0]._createdAt).toLocaleDateString()] })] })] }), _jsx(Badge, { tone: selectedInType > 0 ? "positive" : "primary", fontSize: 0, children: selectedInType > 0 ? `${selectedInType}/${documents.length}` : documents.length })] }), isExpanded && (_jsx(Box, { style: { marginLeft: '32px' }, children: _jsx(Stack, { space: 1, children: documents.map((doc) => (_jsx(Card, { padding: 2, tone: "transparent", border: true, children: _jsxs(Flex, { align: "center", justify: "space-between", children: [_jsxs(Flex, { align: "center", gap: 2, children: [_jsx(Checkbox, { checked: state.selectedDocumentIds.has(doc._id), onChange: (event) => handleDocumentSelection(doc, event.currentTarget.checked) }), _jsxs(Box, { children: [_jsx(Text, { size: 1, children: getDocumentTitle(doc) }), _jsxs(Text, { size: 0, muted: true, children: [doc._id, " \u2022 ", new Date(doc._createdAt).toLocaleDateString()] })] })] }), state.selectedDocumentIds.has(doc._id) && (_jsx(Badge, { tone: "positive", fontSize: 0, children: "Selected" }))] }) }, doc._id))) }) }))] }) }, type));
|
|
512
|
-
})] }), state.selectedDocuments.length > 0 && (_jsxs(Stack, { space: 2, children: [_jsxs(Text, { size: 1, weight: "medium", children: ["Selected Documents (", state.selectedDocuments.length, ")"] }), _jsx(Box, { style: { maxHeight: '200px', overflowY: 'auto' }, children: _jsxs(Stack, { space: 1, children: [state.selectedDocuments.slice(0, 10).map((doc) => (_jsx(Card, { padding: 2, tone: "primary", children: _jsxs(Flex, { align: "center", justify: "space-between", children: [_jsxs(Box, { children: [_jsx(Text, { size: 1, weight: "medium", children: getDocumentTitle(doc) }), _jsxs(Text, { size: 0, muted: true, children: [doc._type, " \u2022 ", new Date(doc._createdAt).toLocaleDateString()] })] }), _jsx(Badge, { tone: "primary", fontSize: 0, children: doc._type })] }) }, doc._id))), state.selectedDocuments.length > 10 && (_jsxs(Text, { size: 0, muted: true, style: { textAlign: 'center', padding: '8px' }, children: ["... and ", state.selectedDocuments.length - 10, " more documents"] }))] }) })] }))] }))] }) }), state.selectedDocuments.length > 0 && (_jsx(Card, { padding: 3, border: true, children: _jsxs(Stack, { space: 3, children: [_jsx(Text, { size: 1, weight: "medium", children: "Translation Action" }), state.selectedLocales && state.selectedLocales.length > 0 && (_jsx(Card, { padding: 2, tone: "primary", children: _jsxs(Text, { size: 1, children: ["Target Locales: ", state.selectedLocales.join(', ')] }) })), _jsx(Button, { text: state.isProcessing ? 'Processing...' : `Translate ${state.selectedDocuments.length} Documents`, icon: state.isProcessing ? Spinner : TranslateIcon, onClick: handleBulkTranslate, tone: "primary", disabled: state.isProcessing })] }) })), state.isProcessing && state.processingStatus.length > 0 && (_jsx(Card, { padding: 3, border: true, children: _jsxs(Stack, { space: 3, children: [_jsx(Text, { size: 1, weight: "medium", children: "Translation Progress" }), _jsxs(Stack, { space: 2, children: [_jsxs(Flex, { align: "center", justify: "space-between", children: [_jsxs(Text, { size: 1, children: ["Overall Progress: ", state.currentProcessingIndex + 1, " of ", state.selectedDocuments.length] }), _jsx(Text, { size: 1, muted: true, children: state.currentProcessingIndex >= 0
|
|
513
|
-
? `${Math.round(((state.currentProcessingIndex + 1) / state.selectedDocuments.length) * 100)}%`
|
|
514
|
-
: '0%' })] }), _jsx(Box, { style: {
|
|
515
|
-
width: '100%',
|
|
516
|
-
height: '8px',
|
|
517
|
-
backgroundColor: '#e0e0e0',
|
|
518
|
-
borderRadius: '4px',
|
|
519
|
-
overflow: 'hidden'
|
|
520
|
-
}, children: _jsx(Box, { style: {
|
|
521
|
-
width: `${state.currentProcessingIndex >= 0
|
|
522
|
-
? ((state.currentProcessingIndex + 1) / state.selectedDocuments.length) * 100
|
|
523
|
-
: 0}%`,
|
|
524
|
-
height: '100%',
|
|
525
|
-
backgroundColor: '#0066cc',
|
|
526
|
-
transition: 'width 0.3s ease'
|
|
527
|
-
} }) })] }), _jsxs(Stack, { space: 2, children: [_jsx(Text, { size: 1, weight: "medium", children: "Document Status" }), state.processingStatus.map((status) => (_jsx(Card, { padding: 2, border: true, children: _jsxs(Flex, { align: "center", justify: "space-between", children: [_jsxs(Box, { flex: 1, children: [_jsx(Text, { size: 1, weight: "medium", children: status.title }), _jsxs(Text, { size: 0, muted: true, children: ["ID: ", status.documentId] }), status.error && (_jsxs(Text, { size: 0, style: { color: 'red' }, children: ["Error: ", status.error] }))] }), _jsxs(Box, { children: [status.status === 'pending' && (_jsx(Badge, { tone: "default", fontSize: 0, children: "Pending" })), status.status === 'processing' && (_jsx(Badge, { tone: "primary", fontSize: 0, children: _jsxs(Flex, { align: "center", gap: 1, children: [_jsx(Spinner, { size: 0 }), "Processing"] }) })), status.status === 'completed' && (_jsx(Badge, { tone: "positive", fontSize: 0, children: _jsxs(Flex, { align: "center", gap: 1, children: [_jsx(CheckmarkIcon, {}), "Completed"] }) })), status.status === 'failed' && (_jsx(Badge, { tone: "critical", fontSize: 0, children: _jsxs(Flex, { align: "center", gap: 1, children: [_jsx(CloseIcon, {}), "Failed"] }) }))] })] }) }, status.documentId)))] })] }) })), state.error && (_jsx(Card, { padding: 3, tone: "critical", border: true, children: _jsxs(Text, { size: 1, weight: "medium", children: ["Error: ", state.error] }) })), state.summary && (_jsx(Card, { padding: 3, tone: state.summary.failedDocuments === 0 ? "positive" : "caution", border: true, children: _jsxs(Stack, { space: 3, children: [_jsxs(Flex, { align: "center", gap: 2, children: [state.summary.failedDocuments === 0 ? (_jsx(CheckmarkIcon, { style: { color: 'green' } })) : (_jsx(WarningOutlineIcon, { style: { color: 'orange' } })), _jsx(Text, { size: 1, weight: "medium", children: "Translation Summary" })] }), _jsxs(Stack, { space: 2, children: [_jsxs(Flex, { align: "center", justify: "space-between", children: [_jsx(Text, { size: 1, children: "Total Documents:" }), _jsx(Badge, { tone: "primary", children: state.summary.totalDocuments })] }), _jsxs(Flex, { align: "center", justify: "space-between", children: [_jsx(Text, { size: 1, children: "Successfully Processed:" }), _jsx(Badge, { tone: "positive", children: state.summary.processedDocuments })] }), _jsxs(Flex, { align: "center", justify: "space-between", children: [_jsx(Text, { size: 1, children: "Failed:" }), _jsx(Badge, { tone: "critical", children: state.summary.failedDocuments })] }), _jsxs(Flex, { align: "center", justify: "space-between", children: [_jsx(Text, { size: 1, children: "Success Rate:" }), _jsx(Badge, { tone: state.summary.failedDocuments === 0 ? "positive" : "caution", children: state.summary.totalDocuments > 0
|
|
528
|
-
? `${((state.summary.processedDocuments / state.summary.totalDocuments) * 100).toFixed(1)}%`
|
|
529
|
-
: '0%' })] })] }), state.processingStatus.length > 0 && (_jsxs(Stack, { space: 2, children: [_jsx(Text, { size: 1, weight: "medium", children: "Detailed Results" }), state.processingStatus.map((status) => (_jsx(Card, { padding: 2, border: true, children: _jsxs(Flex, { align: "center", justify: "space-between", children: [_jsxs(Box, { flex: 1, children: [_jsx(Text, { size: 1, weight: "medium", children: status.title }), _jsxs(Text, { size: 0, muted: true, children: ["ID: ", status.documentId] }), status.error && (_jsxs(Text, { size: 0, style: { color: 'red' }, children: ["Error: ", status.error] }))] }), _jsxs(Box, { children: [status.status === 'pending' && (_jsx(Badge, { tone: "default", fontSize: 0, children: "Pending" })), status.status === 'processing' && (_jsx(Badge, { tone: "primary", fontSize: 0, children: _jsxs(Flex, { align: "center", gap: 1, children: [_jsx(Spinner, { size: 0 }), "Processing"] }) })), status.status === 'completed' && (_jsx(Badge, { tone: "positive", fontSize: 0, children: _jsxs(Flex, { align: "center", gap: 1, children: [_jsx(CheckmarkIcon, {}), "Completed"] }) })), status.status === 'failed' && (_jsx(Badge, { tone: "critical", fontSize: 0, children: _jsxs(Flex, { align: "center", gap: 1, children: [_jsx(CloseIcon, {}), "Failed"] }) }))] })] }) }, status.documentId)))] }))] }) })), state.documentCreationResult && (_jsx(Card, { padding: 3, tone: state.documentCreationResult.failedCreations === 0 ? "positive" : "caution", border: true, children: _jsxs(Stack, { space: 3, children: [_jsxs(Flex, { align: "center", gap: 2, children: [state.documentCreationResult.failedCreations === 0 ? (_jsx(CheckmarkIcon, { style: { color: 'green' } })) : (_jsx(WarningOutlineIcon, { style: { color: 'orange' } })), _jsx(Text, { size: 1, weight: "medium", children: "Document Creation Summary" })] }), _jsxs(Stack, { space: 2, children: [_jsxs(Flex, { align: "center", justify: "space-between", children: [_jsx(Text, { size: 1, children: "Documents to Create:" }), _jsx(Badge, { tone: "primary", children: state.documentCreationResult.totalDocuments })] }), _jsxs(Flex, { align: "center", justify: "space-between", children: [_jsx(Text, { size: 1, children: "Successfully Created:" }), _jsx(Badge, { tone: "positive", children: state.documentCreationResult.successfulCreations })] }), _jsxs(Flex, { align: "center", justify: "space-between", children: [_jsx(Text, { size: 1, children: "Failed to Create:" }), _jsx(Badge, { tone: "critical", children: state.documentCreationResult.failedCreations })] }), _jsxs(Flex, { align: "center", justify: "space-between", children: [_jsx(Text, { size: 1, children: "Creation Success Rate:" }), _jsx(Badge, { tone: state.documentCreationResult.failedCreations === 0 ? "positive" : "caution", children: state.documentCreationResult.totalDocuments > 0
|
|
530
|
-
? `${((state.documentCreationResult.successfulCreations / state.documentCreationResult.totalDocuments) * 100).toFixed(1)}%`
|
|
531
|
-
: '0%' })] })] }), state.documentCreationResult.errors.length > 0 && (_jsxs(Stack, { space: 2, children: [_jsx(Text, { size: 1, weight: "medium", children: "Creation Errors" }), _jsx(Box, { style: { maxHeight: '150px', overflowY: 'auto' }, children: _jsx(Stack, { space: 1, children: state.documentCreationResult.errors.map((error, index) => (_jsx(Card, { padding: 2, tone: "critical", children: _jsx(Text, { size: 0, style: { color: 'red' }, children: error }) }, index))) }) })] }))] }) }))] }) }));
|
|
532
|
-
};
|
|
533
|
-
/**
|
|
534
|
-
* Bulk Translation Tool Definition
|
|
535
|
-
* Requirements: 2.1, 2.5, 4.1, 4.2
|
|
536
|
-
*/
|
|
537
|
-
export const bulkTranslateTool = {
|
|
538
|
-
name: 'bulk-translate',
|
|
539
|
-
title: 'Bulk Translate',
|
|
540
|
-
icon: TranslateIcon,
|
|
541
|
-
component: BulkTranslateTool
|
|
542
|
-
};
|
|
543
|
-
//# sourceMappingURL=bulkTranslate.js.map
|