@lobehub/lobehub 2.0.0-next.267 → 2.0.0-next.269
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/.cursor/rules/microcopy-cn.mdc +75 -63
- package/.cursor/rules/microcopy-en.mdc +4 -8
- package/CHANGELOG.md +50 -0
- package/README.md +8 -8
- package/README.zh-CN.md +8 -8
- package/apps/desktop/src/main/core/browser/Browser.ts +6 -0
- package/apps/desktop/src/main/locales/default/common.ts +2 -2
- package/changelog/v1.json +10 -0
- package/docs/development/database-schema.dbml +4 -0
- package/e2e/CLAUDE.md +9 -8
- package/e2e/cucumber.config.js +1 -0
- package/e2e/src/features/page/README.md +118 -0
- package/e2e/src/features/page/crud.feature +62 -0
- package/e2e/src/features/page/editor-content.feature +93 -0
- package/e2e/src/features/page/editor-meta.feature +60 -0
- package/e2e/src/steps/agent/conversation.steps.ts +4 -4
- package/e2e/src/steps/home/sidebarAgent.steps.ts +91 -94
- package/e2e/src/steps/home/sidebarGroup.steps.ts +4 -4
- package/e2e/src/steps/hooks.ts +2 -0
- package/e2e/src/steps/page/editor-content.steps.ts +344 -0
- package/e2e/src/steps/page/editor-meta.steps.ts +410 -0
- package/e2e/src/steps/page/page-crud.steps.ts +363 -0
- package/e2e/src/support/world.ts +12 -0
- package/locales/ar/file.json +2 -0
- package/locales/bg-BG/file.json +2 -0
- package/locales/de-DE/file.json +2 -0
- package/locales/en-US/auth.json +1 -1
- package/locales/en-US/file.json +2 -0
- package/locales/en-US/metadata.json +2 -2
- package/locales/es-ES/file.json +2 -0
- package/locales/fa-IR/file.json +2 -0
- package/locales/fr-FR/file.json +2 -0
- package/locales/it-IT/file.json +2 -0
- package/locales/ja-JP/file.json +2 -0
- package/locales/ko-KR/file.json +2 -0
- package/locales/nl-NL/file.json +2 -0
- package/locales/pl-PL/file.json +2 -0
- package/locales/pt-BR/file.json +2 -0
- package/locales/ru-RU/file.json +2 -0
- package/locales/tr-TR/file.json +2 -0
- package/locales/vi-VN/file.json +2 -0
- package/locales/zh-CN/file.json +2 -0
- package/locales/zh-TW/file.json +2 -0
- package/package.json +1 -1
- package/packages/builtin-agents/src/agents/agent-builder/index.ts +1 -1
- package/packages/builtin-agents/src/agents/group-agent-builder/index.ts +1 -1
- package/packages/builtin-agents/src/agents/page-agent/index.ts +1 -1
- package/packages/const/src/settings/group.ts +0 -10
- package/packages/database/migrations/0068_update_group_data.sql +4 -0
- package/packages/database/migrations/meta/0068_snapshot.json +9588 -0
- package/packages/database/migrations/meta/_journal.json +7 -0
- package/packages/database/src/models/__tests__/chatGroup.test.ts +5 -7
- package/packages/database/src/models/__tests__/knowledgeBase.test.ts +185 -0
- package/packages/database/src/models/knowledgeBase.ts +67 -3
- package/packages/database/src/repositories/agentGroup/index.test.ts +23 -29
- package/packages/database/src/repositories/agentGroup/index.ts +4 -9
- package/packages/database/src/repositories/knowledge/index.ts +3 -3
- package/packages/database/src/schemas/chatGroup.ts +4 -3
- package/packages/database/src/types/chatGroup.ts +0 -7
- package/packages/types/src/agentGroup/index.ts +30 -9
- package/packages/utils/src/index.ts +1 -0
- package/packages/utils/src/platform.ts +35 -3
- package/src/app/[variants]/(desktop)/desktop-onboarding/_layout/index.tsx +30 -22
- package/src/app/[variants]/(desktop)/desktop-onboarding/_layout/style.ts +8 -5
- package/src/app/[variants]/(main)/_layout/DesktopLayoutContainer.tsx +2 -3
- package/src/app/[variants]/(main)/home/_layout/Body/Agent/ModalProvider.tsx +9 -32
- package/src/app/[variants]/(main)/home/_layout/hooks/useCreateMenuItems.tsx +3 -37
- package/src/app/[variants]/(main)/home/_layout/hooks/useSessionGroupMenuItems.tsx +7 -53
- package/src/app/[variants]/(main)/home/features/RecentPage/List.tsx +2 -1
- package/src/app/[variants]/(main)/resource/features/DndContextWrapper.tsx +1 -1
- package/src/app/[variants]/(main)/resource/library/_layout/Sidebar.tsx +2 -2
- package/src/app/[variants]/(main)/resource/library/features/LibraryMenu.tsx +2 -2
- package/src/app/[variants]/(mobile)/chat/settings/features/SettingButton.tsx +2 -12
- package/src/components/ChatGroupWizard/ChatGroupWizard.tsx +5 -27
- package/src/components/DragUpload/index.tsx +24 -27
- package/src/components/MemberSelectionModal/MemberSelectionModal.tsx +2 -11
- package/src/features/CommandMenu/useCommandMenu.ts +4 -14
- package/src/features/ElectronTitlebar/SimpleTitleBar.tsx +31 -0
- package/src/features/ElectronTitlebar/index.tsx +1 -0
- package/src/features/ResourceManager/components/Editor/index.tsx +2 -3
- package/src/features/ResourceManager/components/Explorer/Header/index.tsx +13 -17
- package/src/features/ResourceManager/components/Explorer/ItemDropdown/useFileItemDropdown.tsx +1 -1
- package/src/features/ResourceManager/components/Explorer/ListView/ListItem/TruncatedFileName.tsx +130 -0
- package/src/features/ResourceManager/components/Explorer/ListView/ListItem/index.tsx +36 -4
- package/src/features/ResourceManager/components/Explorer/ListView/Skeleton.tsx +4 -3
- package/src/features/ResourceManager/components/Explorer/ListView/index.tsx +58 -2
- package/src/features/ResourceManager/components/Explorer/MasonryView/index.tsx +58 -6
- package/src/features/ResourceManager/components/Explorer/MoveToFolderModal.tsx +2 -5
- package/src/features/ResourceManager/components/Explorer/ToolBar/BatchActionsDropdown.tsx +9 -5
- package/src/features/ResourceManager/components/Explorer/index.tsx +11 -56
- package/src/features/ResourceManager/components/Header/AddButton.tsx +5 -6
- package/src/features/ResourceManager/components/LibraryHierarchy/HierarchyNode.tsx +382 -0
- package/src/features/ResourceManager/components/LibraryHierarchy/index.tsx +396 -0
- package/src/features/ResourceManager/components/LibraryHierarchy/styles.ts +19 -0
- package/src/features/ResourceManager/components/LibraryHierarchy/treeState.ts +178 -0
- package/src/features/ResourceManager/components/LibraryHierarchy/types.ts +10 -0
- package/src/features/ResourceManager/index.tsx +3 -0
- package/src/layout/GlobalProvider/GroupWizardProvider.tsx +6 -29
- package/src/locales/default/auth.ts +1 -1
- package/src/locales/default/file.ts +2 -0
- package/src/locales/default/metadata.ts +2 -2
- package/src/server/modules/AgentRuntime/AgentRuntimeCoordinator.ts +30 -30
- package/src/server/modules/AgentRuntime/AgentStateManager.ts +23 -23
- package/src/server/modules/AgentRuntime/InMemoryAgentStateManager.ts +16 -16
- package/src/server/modules/AgentRuntime/InMemoryStreamEventManager.ts +13 -13
- package/src/server/modules/AgentRuntime/RuntimeExecutors.ts +2 -2
- package/src/server/modules/AgentRuntime/StreamEventManager.ts +18 -18
- package/src/server/modules/AgentRuntime/types.ts +21 -21
- package/src/server/routers/lambda/__tests__/agentGroup.test.ts +8 -8
- package/src/server/routers/lambda/agentGroup.ts +10 -12
- package/src/server/services/document/index.ts +1 -0
- package/src/store/agentGroup/slices/curd.test.ts +4 -4
- package/src/store/file/slices/fileManager/action.ts +12 -4
- package/src/store/home/slices/homeInput/action.ts +0 -3
- package/src/store/session/slices/session/action.ts +5 -9
- package/src/utils/platform.ts +2 -0
- package/src/app/[variants]/(mobile)/chat/settings/features/AgentTeamSettings/index.tsx +0 -95
- package/src/features/GroupChatSettings/AgentCard.tsx +0 -154
- package/src/features/GroupChatSettings/AgentTeamChatSettings.tsx +0 -179
- package/src/features/GroupChatSettings/AgentTeamMembersSettings.tsx +0 -244
- package/src/features/GroupChatSettings/AgentTeamMetaSettings.tsx +0 -94
- package/src/features/GroupChatSettings/AgentTeamSettings.tsx +0 -54
- package/src/features/GroupChatSettings/GroupCategory/index.tsx +0 -30
- package/src/features/GroupChatSettings/GroupCategory/useGroupCategory.tsx +0 -42
- package/src/features/GroupChatSettings/GroupChatSettingsProvider.tsx +0 -19
- package/src/features/GroupChatSettings/HostMemberCard.tsx +0 -113
- package/src/features/GroupChatSettings/StoreUpdater.tsx +0 -34
- package/src/features/GroupChatSettings/hooks/useGroupChatSettings.ts +0 -25
- package/src/features/GroupChatSettings/index.ts +0 -16
- package/src/features/GroupChatSettings/store/action.ts +0 -105
- package/src/features/GroupChatSettings/store/index.ts +0 -18
- package/src/features/GroupChatSettings/store/initialState.ts +0 -23
- package/src/features/GroupChatSettings/store/selectors.ts +0 -13
- package/src/features/ResourceManager/components/Tree/index.tsx +0 -883
- /package/src/features/ResourceManager/components/{Tree → LibraryHierarchy}/TreeSkeleton.tsx +0 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Page CRUD Steps
|
|
3
|
+
*
|
|
4
|
+
* Step definitions for Page (文稿) CRUD E2E tests
|
|
5
|
+
* - Create
|
|
6
|
+
* - Rename
|
|
7
|
+
* - Duplicate
|
|
8
|
+
* - Delete
|
|
9
|
+
*/
|
|
10
|
+
import { Given, Then, When } from '@cucumber/cucumber';
|
|
11
|
+
import { expect } from '@playwright/test';
|
|
12
|
+
|
|
13
|
+
import { CustomWorld, WAIT_TIMEOUT } from '../../support/world';
|
|
14
|
+
|
|
15
|
+
// ============================================
|
|
16
|
+
// Helper Functions
|
|
17
|
+
// ============================================
|
|
18
|
+
|
|
19
|
+
async function inputPageName(
|
|
20
|
+
this: CustomWorld,
|
|
21
|
+
newName: string,
|
|
22
|
+
pressEnter: boolean,
|
|
23
|
+
): Promise<void> {
|
|
24
|
+
await this.page.waitForTimeout(300);
|
|
25
|
+
|
|
26
|
+
// Try to find the popover input or inline editing input
|
|
27
|
+
const inputSelectors = [
|
|
28
|
+
'.ant-popover-inner input',
|
|
29
|
+
'.ant-popover-content input',
|
|
30
|
+
'.ant-popover input',
|
|
31
|
+
'input[type="text"]:visible',
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
let renameInput = null;
|
|
35
|
+
|
|
36
|
+
for (const selector of inputSelectors) {
|
|
37
|
+
try {
|
|
38
|
+
const locator = this.page.locator(selector).first();
|
|
39
|
+
await locator.waitFor({ state: 'visible', timeout: 2000 });
|
|
40
|
+
renameInput = locator;
|
|
41
|
+
break;
|
|
42
|
+
} catch {
|
|
43
|
+
// Try next selector
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!renameInput) {
|
|
48
|
+
// Fallback: find any visible input
|
|
49
|
+
const allInputs = this.page.locator('input:visible');
|
|
50
|
+
const count = await allInputs.count();
|
|
51
|
+
|
|
52
|
+
for (let i = 0; i < count; i++) {
|
|
53
|
+
const input = allInputs.nth(i);
|
|
54
|
+
const placeholder = (await input.getAttribute('placeholder').catch(() => '')) || '';
|
|
55
|
+
if (placeholder.includes('Search') || placeholder.includes('搜索')) continue;
|
|
56
|
+
|
|
57
|
+
const isInPopover = await input.evaluate((el) => {
|
|
58
|
+
return el.closest('.ant-popover') !== null || el.closest('[class*="popover"]') !== null;
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
if (isInPopover || count <= 2) {
|
|
62
|
+
renameInput = input;
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (renameInput) {
|
|
69
|
+
await renameInput.click();
|
|
70
|
+
await renameInput.clear();
|
|
71
|
+
await renameInput.fill(newName);
|
|
72
|
+
|
|
73
|
+
if (pressEnter) {
|
|
74
|
+
await renameInput.press('Enter');
|
|
75
|
+
} else {
|
|
76
|
+
await this.page.click('body', { position: { x: 10, y: 10 } });
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
// Keyboard fallback (use modKey for cross-platform support)
|
|
80
|
+
await this.page.keyboard.press(`${this.modKey}+A`);
|
|
81
|
+
await this.page.waitForTimeout(50);
|
|
82
|
+
await this.page.keyboard.type(newName, { delay: 20 });
|
|
83
|
+
|
|
84
|
+
if (pressEnter) {
|
|
85
|
+
await this.page.keyboard.press('Enter');
|
|
86
|
+
} else {
|
|
87
|
+
await this.page.click('body', { position: { x: 10, y: 10 } });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
await this.page.waitForTimeout(1000);
|
|
92
|
+
console.log(` ✅ 已输入新名称 "${newName}"`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ============================================
|
|
96
|
+
// Given Steps
|
|
97
|
+
// ============================================
|
|
98
|
+
|
|
99
|
+
Given('用户在 Page 页面', async function (this: CustomWorld) {
|
|
100
|
+
console.log(' 📍 Step: 导航到 Page 页面...');
|
|
101
|
+
await this.page.goto('/page');
|
|
102
|
+
await this.page.waitForLoadState('networkidle', { timeout: 15_000 });
|
|
103
|
+
await this.page.waitForTimeout(1000);
|
|
104
|
+
|
|
105
|
+
console.log(' ✅ 已进入 Page 页面');
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
Given('用户在 Page 页面有一个文稿', async function (this: CustomWorld) {
|
|
109
|
+
console.log(' 📍 Step: 导航到 Page 页面...');
|
|
110
|
+
await this.page.goto('/page');
|
|
111
|
+
await this.page.waitForLoadState('networkidle', { timeout: 15_000 });
|
|
112
|
+
await this.page.waitForTimeout(1000);
|
|
113
|
+
|
|
114
|
+
console.log(' 📍 Step: 通过 UI 创建新文稿...');
|
|
115
|
+
// Click the new page button to create via UI (ensures proper server-side creation)
|
|
116
|
+
const newPageButton = this.page.locator('svg.lucide-square-pen').first();
|
|
117
|
+
await newPageButton.click();
|
|
118
|
+
await this.page.waitForTimeout(1500);
|
|
119
|
+
|
|
120
|
+
// Wait for the new page to be created and URL to change
|
|
121
|
+
await this.page.waitForURL(/\/page\/.+/, { timeout: WAIT_TIMEOUT });
|
|
122
|
+
|
|
123
|
+
// Create a unique title for this test page
|
|
124
|
+
const uniqueTitle = `E2E Page ${Date.now()}`;
|
|
125
|
+
const defaultTitleRegex = /^(无标题|Untitled)$/;
|
|
126
|
+
|
|
127
|
+
console.log(` 📍 Step: 重命名为唯一标题 "${uniqueTitle}"...`);
|
|
128
|
+
// Find the new page and rename it to ensure uniqueness
|
|
129
|
+
const pageItem = this.page.getByText(defaultTitleRegex).first();
|
|
130
|
+
await expect(pageItem).toBeVisible({ timeout: 5000 });
|
|
131
|
+
|
|
132
|
+
// Right-click to open context menu and rename
|
|
133
|
+
await pageItem.click({ button: 'right' });
|
|
134
|
+
await this.page.waitForTimeout(500);
|
|
135
|
+
|
|
136
|
+
const renameOption = this.page.getByRole('menuitem', { name: /^(rename|重命名)$/i });
|
|
137
|
+
await expect(renameOption).toBeVisible({ timeout: 5000 });
|
|
138
|
+
await renameOption.click();
|
|
139
|
+
await this.page.waitForTimeout(500);
|
|
140
|
+
|
|
141
|
+
// Input the unique name (use modKey for cross-platform support)
|
|
142
|
+
await this.page.keyboard.press(`${this.modKey}+A`);
|
|
143
|
+
await this.page.keyboard.type(uniqueTitle, { delay: 20 });
|
|
144
|
+
await this.page.click('body', { position: { x: 10, y: 10 } });
|
|
145
|
+
await this.page.waitForTimeout(1000);
|
|
146
|
+
|
|
147
|
+
// Wait for the renamed page to be visible
|
|
148
|
+
const renamedItem = this.page.getByText(uniqueTitle, { exact: true }).first();
|
|
149
|
+
await expect(renamedItem).toBeVisible({ timeout: WAIT_TIMEOUT });
|
|
150
|
+
|
|
151
|
+
// Store page reference for later use
|
|
152
|
+
this.testContext.targetItemTitle = uniqueTitle;
|
|
153
|
+
this.testContext.targetType = 'page';
|
|
154
|
+
|
|
155
|
+
console.log(` ✅ 找到文稿: ${uniqueTitle}`);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
Given('用户在 Page 页面有一个文稿 {string}', async function (this: CustomWorld, title: string) {
|
|
159
|
+
console.log(' 📍 Step: 导航到 Page 页面...');
|
|
160
|
+
await this.page.goto('/page');
|
|
161
|
+
await this.page.waitForLoadState('networkidle', { timeout: 15_000 });
|
|
162
|
+
await this.page.waitForTimeout(1000);
|
|
163
|
+
|
|
164
|
+
console.log(' 📍 Step: 通过 UI 创建新文稿...');
|
|
165
|
+
// Click the new page button to create via UI
|
|
166
|
+
const newPageButton = this.page.locator('svg.lucide-square-pen').first();
|
|
167
|
+
await newPageButton.click();
|
|
168
|
+
await this.page.waitForTimeout(1500);
|
|
169
|
+
|
|
170
|
+
// Wait for the new page to be created
|
|
171
|
+
await this.page.waitForURL(/\/page\/.+/, { timeout: WAIT_TIMEOUT });
|
|
172
|
+
|
|
173
|
+
// Default title is "无标题" (Untitled) - support both languages
|
|
174
|
+
const defaultTitleRegex = /^(无标题|Untitled)$/;
|
|
175
|
+
|
|
176
|
+
console.log(` 📍 Step: 通过右键菜单重命名文稿为 "${title}"...`);
|
|
177
|
+
// Find the new page in the sidebar and rename via context menu
|
|
178
|
+
const pageItem = this.page.getByText(defaultTitleRegex).first();
|
|
179
|
+
await expect(pageItem).toBeVisible({ timeout: 5000 });
|
|
180
|
+
|
|
181
|
+
// Right-click to open context menu
|
|
182
|
+
await pageItem.click({ button: 'right' });
|
|
183
|
+
await this.page.waitForTimeout(500);
|
|
184
|
+
|
|
185
|
+
// Select rename option
|
|
186
|
+
const renameOption = this.page.getByRole('menuitem', { name: /^(rename|重命名)$/i });
|
|
187
|
+
await expect(renameOption).toBeVisible({ timeout: 5000 });
|
|
188
|
+
await renameOption.click();
|
|
189
|
+
await this.page.waitForTimeout(500);
|
|
190
|
+
|
|
191
|
+
// Input the new name (use modKey for cross-platform support)
|
|
192
|
+
await this.page.keyboard.press(`${this.modKey}+A`);
|
|
193
|
+
await this.page.keyboard.type(title, { delay: 20 });
|
|
194
|
+
await this.page.click('body', { position: { x: 10, y: 10 } });
|
|
195
|
+
await this.page.waitForTimeout(1000);
|
|
196
|
+
|
|
197
|
+
console.log(' 📍 Step: 查找文稿...');
|
|
198
|
+
const renamedItem = this.page.getByText(title, { exact: true }).first();
|
|
199
|
+
await expect(renamedItem).toBeVisible({ timeout: WAIT_TIMEOUT });
|
|
200
|
+
|
|
201
|
+
this.testContext.targetItemTitle = title;
|
|
202
|
+
this.testContext.targetType = 'page';
|
|
203
|
+
|
|
204
|
+
console.log(` ✅ 找到文稿: ${title}`);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// ============================================
|
|
208
|
+
// When Steps
|
|
209
|
+
// ============================================
|
|
210
|
+
|
|
211
|
+
When('用户点击新建文稿按钮', async function (this: CustomWorld) {
|
|
212
|
+
console.log(' 📍 Step: 点击新建文稿按钮...');
|
|
213
|
+
|
|
214
|
+
// Look for the SquarePen icon button (new page button)
|
|
215
|
+
const newPageButton = this.page.locator('svg.lucide-square-pen').first();
|
|
216
|
+
|
|
217
|
+
if ((await newPageButton.count()) > 0) {
|
|
218
|
+
await newPageButton.click();
|
|
219
|
+
} else {
|
|
220
|
+
// Fallback: look for button with title containing "new" or "新建"
|
|
221
|
+
const buttonByTitle = this.page
|
|
222
|
+
.locator('button[title*="new"], button[title*="新建"], [role="button"][title*="new"]')
|
|
223
|
+
.first();
|
|
224
|
+
if ((await buttonByTitle.count()) > 0) {
|
|
225
|
+
await buttonByTitle.click();
|
|
226
|
+
} else {
|
|
227
|
+
throw new Error('Could not find new page button');
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
await this.page.waitForTimeout(1000);
|
|
232
|
+
console.log(' ✅ 已点击新建文稿按钮');
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
When('用户右键点击该文稿', async function (this: CustomWorld) {
|
|
236
|
+
console.log(' 📍 Step: 右键点击文稿...');
|
|
237
|
+
|
|
238
|
+
const title = this.testContext.targetItemTitle || this.testContext.createdPageTitle;
|
|
239
|
+
// Find the page item by its title text, then find the parent clickable block
|
|
240
|
+
const titleElement = this.page.getByText(title, { exact: true }).first();
|
|
241
|
+
await expect(titleElement).toBeVisible({ timeout: 5000 });
|
|
242
|
+
|
|
243
|
+
// Right-click on the title element (the NavItem Block wraps the text)
|
|
244
|
+
await titleElement.click({ button: 'right' });
|
|
245
|
+
|
|
246
|
+
await this.page.waitForTimeout(800);
|
|
247
|
+
|
|
248
|
+
// Debug: check what menus are visible
|
|
249
|
+
const menuItems = await this.page.locator('[role="menuitem"]').count();
|
|
250
|
+
console.log(` 📍 Debug: Found ${menuItems} menu items after right-click`);
|
|
251
|
+
|
|
252
|
+
console.log(' ✅ 已右键点击文稿');
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
When('用户在菜单中选择复制', async function (this: CustomWorld) {
|
|
256
|
+
console.log(' 📍 Step: 选择复制选项...');
|
|
257
|
+
|
|
258
|
+
// Look for duplicate option (复制 or Duplicate)
|
|
259
|
+
const duplicateOption = this.page.getByRole('menuitem', { name: /复制|duplicate/i });
|
|
260
|
+
await expect(duplicateOption).toBeVisible({ timeout: 5000 });
|
|
261
|
+
await duplicateOption.click();
|
|
262
|
+
await this.page.waitForTimeout(1000);
|
|
263
|
+
|
|
264
|
+
console.log(' ✅ 已选择复制选项');
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
When('用户输入新的文稿名称 {string}', async function (this: CustomWorld, newName: string) {
|
|
268
|
+
console.log(` 📍 Step: 输入新名称 "${newName}"...`);
|
|
269
|
+
await inputPageName.call(this, newName, false);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
When(
|
|
273
|
+
'用户输入新的文稿名称 {string} 并按 Enter',
|
|
274
|
+
async function (this: CustomWorld, newName: string) {
|
|
275
|
+
console.log(` 📍 Step: 输入新名称 "${newName}" 并按 Enter...`);
|
|
276
|
+
await inputPageName.call(this, newName, true);
|
|
277
|
+
},
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
// ============================================
|
|
281
|
+
// Then Steps
|
|
282
|
+
// ============================================
|
|
283
|
+
|
|
284
|
+
Then('应该创建一个新的文稿', async function (this: CustomWorld) {
|
|
285
|
+
console.log(' 📍 Step: 验证新文稿已创建...');
|
|
286
|
+
|
|
287
|
+
await this.page.waitForTimeout(1000);
|
|
288
|
+
|
|
289
|
+
// Check if URL changed to a new page
|
|
290
|
+
const currentUrl = this.page.url();
|
|
291
|
+
expect(currentUrl).toMatch(/\/page\/.+/);
|
|
292
|
+
|
|
293
|
+
console.log(' ✅ 新文稿已创建');
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
Then('文稿列表中应该显示新文稿', async function (this: CustomWorld) {
|
|
297
|
+
console.log(' 📍 Step: 验证文稿列表中显示新文稿...');
|
|
298
|
+
|
|
299
|
+
await this.page.waitForTimeout(500);
|
|
300
|
+
|
|
301
|
+
// Page list items are rendered with NavItem component (not <a> tags)
|
|
302
|
+
// Look for the untitled page in the sidebar list
|
|
303
|
+
const untitledText = this.page.getByText(/无标题|untitled/i).first();
|
|
304
|
+
await expect(untitledText).toBeVisible({ timeout: 5000 });
|
|
305
|
+
|
|
306
|
+
console.log(' ✅ 文稿列表中显示新文稿');
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
Then('该文稿名称应该更新为 {string}', async function (this: CustomWorld, expectedName: string) {
|
|
310
|
+
console.log(` 📍 Step: 验证名称为 "${expectedName}"...`);
|
|
311
|
+
|
|
312
|
+
await this.page.waitForTimeout(1000);
|
|
313
|
+
|
|
314
|
+
// Look for the renamed item in the list
|
|
315
|
+
const renamedItem = this.page.getByText(expectedName, { exact: true }).first();
|
|
316
|
+
await expect(renamedItem).toBeVisible({ timeout: 5000 });
|
|
317
|
+
|
|
318
|
+
console.log(` ✅ 名称已更新为 "${expectedName}"`);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
Then('文稿列表中应该出现 {string}', async function (this: CustomWorld, expectedName: string) {
|
|
322
|
+
console.log(` 📍 Step: 验证文稿列表中出现 "${expectedName}"...`);
|
|
323
|
+
|
|
324
|
+
await this.page.waitForTimeout(2000);
|
|
325
|
+
|
|
326
|
+
// The duplicated page might have "(Copy)" or " (Copy)" or "副本" suffix
|
|
327
|
+
// First try exact match, then try partial match
|
|
328
|
+
let duplicatedItem = this.page.getByText(expectedName, { exact: true }).first();
|
|
329
|
+
|
|
330
|
+
if ((await duplicatedItem.count()) === 0) {
|
|
331
|
+
// Try finding page with "Copy" in the name (could be "Original Page (Copy)" or similar)
|
|
332
|
+
const baseName = expectedName.replace(/\s*\(Copy\)$/, '');
|
|
333
|
+
duplicatedItem = this.page.getByText(new RegExp(`${baseName}.*Copy|${baseName}.*副本`)).first();
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if ((await duplicatedItem.count()) === 0) {
|
|
337
|
+
// Fallback: check if there are at least 2 pages with similar name
|
|
338
|
+
const similarPages = this.page.getByText(expectedName.replace(/\s*\(Copy\)$/, '')).all();
|
|
339
|
+
// eslint-disable-next-line unicorn/no-await-expression-member
|
|
340
|
+
const count = (await similarPages).length;
|
|
341
|
+
console.log(` 📍 Debug: Found ${count} pages with similar name`);
|
|
342
|
+
expect(count).toBeGreaterThanOrEqual(2);
|
|
343
|
+
console.log(` ✅ 文稿列表中出现多个相似名称的文稿`);
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
await expect(duplicatedItem).toBeVisible({ timeout: WAIT_TIMEOUT });
|
|
348
|
+
console.log(` ✅ 文稿列表中出现 "${expectedName}"`);
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
Then('该文稿应该从列表中移除', async function (this: CustomWorld) {
|
|
352
|
+
console.log(' 📍 Step: 验证文稿已移除...');
|
|
353
|
+
|
|
354
|
+
await this.page.waitForTimeout(1000);
|
|
355
|
+
|
|
356
|
+
const title = this.testContext.targetItemTitle || this.testContext.createdPageTitle;
|
|
357
|
+
if (title) {
|
|
358
|
+
const deletedItem = this.page.getByText(title, { exact: true });
|
|
359
|
+
await expect(deletedItem).not.toBeVisible({ timeout: 5000 });
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
console.log(' ✅ 文稿已从列表中移除');
|
|
363
|
+
});
|
package/e2e/src/support/world.ts
CHANGED
|
@@ -3,6 +3,11 @@ import { Browser, BrowserContext, Page, Response, chromium } from '@playwright/t
|
|
|
3
3
|
import * as fs from 'node:fs';
|
|
4
4
|
import * as path from 'node:path';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Default timeout for waiting operations (e.g., waitForURL, toBeVisible)
|
|
8
|
+
*/
|
|
9
|
+
export const WAIT_TIMEOUT = 13_000;
|
|
10
|
+
|
|
6
11
|
export interface TestContext {
|
|
7
12
|
[key: string]: any;
|
|
8
13
|
consoleErrors: string[];
|
|
@@ -17,6 +22,13 @@ export class CustomWorld extends World {
|
|
|
17
22
|
page!: Page;
|
|
18
23
|
testContext: TestContext;
|
|
19
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Get the platform-specific modifier key (Meta for macOS, Control for Linux/Windows)
|
|
27
|
+
*/
|
|
28
|
+
get modKey(): 'Meta' | 'Control' {
|
|
29
|
+
return process.platform === 'darwin' ? 'Meta' : 'Control';
|
|
30
|
+
}
|
|
31
|
+
|
|
20
32
|
constructor(options: IWorldOptions) {
|
|
21
33
|
super(options);
|
|
22
34
|
this.testContext = {
|
package/locales/ar/file.json
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"header.actions.connect": "اتصال...",
|
|
21
21
|
"header.actions.createFolderError": "فشل في إنشاء المجلد",
|
|
22
22
|
"header.actions.creatingFolder": "جارٍ إنشاء المجلد...",
|
|
23
|
+
"header.actions.deleteLibrary": "حذف المكتبة",
|
|
23
24
|
"header.actions.gitignore.apply": "تطبيق القواعد",
|
|
24
25
|
"header.actions.gitignore.cancel": "تجاهل القواعد",
|
|
25
26
|
"header.actions.gitignore.content": "تم اكتشاف ملف .gitignore ({{count}} ملفًا إجمالاً). هل ترغب في تطبيق قواعد التجاهل؟",
|
|
@@ -108,6 +109,7 @@
|
|
|
108
109
|
"portal.openInPageEditor": "تحرير في الصفحة",
|
|
109
110
|
"preview.downloadFile": "تنزيل الملف",
|
|
110
111
|
"preview.unsupportedFileAndContact": "تنسيق هذا الملف غير مدعوم حاليًا للمعاينة عبر الإنترنت. إذا كان لديك طلب للمعاينة، لا تتردد في <1>الاتصال بنا</1>.",
|
|
112
|
+
"resource": "المورد",
|
|
111
113
|
"searchFilePlaceholder": "البحث في الملفات",
|
|
112
114
|
"searchPagePlaceholder": "البحث في الصفحات",
|
|
113
115
|
"tab.all": "الكل",
|
package/locales/bg-BG/file.json
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"header.actions.connect": "Свържи се...",
|
|
21
21
|
"header.actions.createFolderError": "Неуспешно създаване на папка",
|
|
22
22
|
"header.actions.creatingFolder": "Създаване на папка...",
|
|
23
|
+
"header.actions.deleteLibrary": "Изтриване на библиотека",
|
|
23
24
|
"header.actions.gitignore.apply": "Приложи правилата",
|
|
24
25
|
"header.actions.gitignore.cancel": "Игнорирай правилата",
|
|
25
26
|
"header.actions.gitignore.content": "Открит е файл .gitignore (общо {{count}} файла). Искате ли да приложите правилата за игнориране?",
|
|
@@ -108,6 +109,7 @@
|
|
|
108
109
|
"portal.openInPageEditor": "Редактирай в страница",
|
|
109
110
|
"preview.downloadFile": "Изтегли файл",
|
|
110
111
|
"preview.unsupportedFileAndContact": "Този файлов формат не се поддържа за онлайн преглед. Ако имате нужда от поддръжка, <1>свържете се с нас</1>.",
|
|
112
|
+
"resource": "Ресурс",
|
|
111
113
|
"searchFilePlaceholder": "Търсене на файлове",
|
|
112
114
|
"searchPagePlaceholder": "Търсене на страници",
|
|
113
115
|
"tab.all": "Всички",
|
package/locales/de-DE/file.json
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"header.actions.connect": "Verbinden...",
|
|
21
21
|
"header.actions.createFolderError": "Ordner konnte nicht erstellt werden",
|
|
22
22
|
"header.actions.creatingFolder": "Ordner wird erstellt...",
|
|
23
|
+
"header.actions.deleteLibrary": "Bibliothek löschen",
|
|
23
24
|
"header.actions.gitignore.apply": "Regeln anwenden",
|
|
24
25
|
"header.actions.gitignore.cancel": "Regeln ignorieren",
|
|
25
26
|
"header.actions.gitignore.content": ".gitignore-Datei erkannt (insgesamt {{count}} Dateien). Möchten Sie die Ignorierregeln anwenden?",
|
|
@@ -108,6 +109,7 @@
|
|
|
108
109
|
"portal.openInPageEditor": "In Seite bearbeiten",
|
|
109
110
|
"preview.downloadFile": "Datei herunterladen",
|
|
110
111
|
"preview.unsupportedFileAndContact": "Dieses Dateiformat wird derzeit nicht für die Online-Vorschau unterstützt. Wenn Sie eine Vorschau wünschen, <1>kontaktieren Sie uns</1> gerne.",
|
|
112
|
+
"resource": "Ressource",
|
|
111
113
|
"searchFilePlaceholder": "Dateien durchsuchen",
|
|
112
114
|
"searchPagePlaceholder": "Seiten durchsuchen",
|
|
113
115
|
"tab.all": "Alle",
|
package/locales/en-US/auth.json
CHANGED
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
"profile.usernameRule": "Username can only contain letters, numbers, or underscores",
|
|
187
187
|
"profile.usernameUpdateFailed": "Failed to update username, please try again later",
|
|
188
188
|
"signin.subtitle": "Sign up or log in to your {{appName}} account",
|
|
189
|
-
"signin.title": "
|
|
189
|
+
"signin.title": "Where Agents Collaborate",
|
|
190
190
|
"signout": "Log Out",
|
|
191
191
|
"signup": "Sign Up",
|
|
192
192
|
"stats.aiheatmaps": "Activity Index",
|
package/locales/en-US/file.json
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"header.actions.connect": "Connect...",
|
|
21
21
|
"header.actions.createFolderError": "Failed to create folder",
|
|
22
22
|
"header.actions.creatingFolder": "Creating folder...",
|
|
23
|
+
"header.actions.deleteLibrary": "Delete Library",
|
|
23
24
|
"header.actions.gitignore.apply": "Apply Rules",
|
|
24
25
|
"header.actions.gitignore.cancel": "Ignore Rules",
|
|
25
26
|
"header.actions.gitignore.content": ".gitignore file detected ({{count}} files in total). Would you like to apply the ignore rules?",
|
|
@@ -108,6 +109,7 @@
|
|
|
108
109
|
"portal.openInPageEditor": "Edit in Page",
|
|
109
110
|
"preview.downloadFile": "Download File",
|
|
110
111
|
"preview.unsupportedFileAndContact": "This file format is not currently supported for online preview. If you have a request for previewing, feel free to <1>contact us</1>.",
|
|
112
|
+
"resource": "Resource",
|
|
111
113
|
"searchFilePlaceholder": "Search Files",
|
|
112
114
|
"searchPagePlaceholder": "Search Pages",
|
|
113
115
|
"tab.all": "All",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"changelog.description": "Stay updated on the new features and improvements of {{appName}}",
|
|
3
3
|
"changelog.title": "Changelog",
|
|
4
4
|
"chat.description": "{{appName}} brings you the best UI experience for ChatGPT, Claude, Gemini, and OLLaMA.",
|
|
5
|
-
"chat.title": "{{appName}} ·
|
|
5
|
+
"chat.title": "{{appName}} · Where Agents Collaborate",
|
|
6
6
|
"discover.assistants.description": "Content, Q&A, images, video, voice, workflows—browse and add Agents from the Community.",
|
|
7
7
|
"discover.assistants.title": "Agent Community",
|
|
8
8
|
"discover.description": "Explore Agents, Skills, Providers, models, and MCP Servers.",
|
|
@@ -21,5 +21,5 @@
|
|
|
21
21
|
"plugins.description": "Search, charts, academic tools, image/video/voice generation, workflows—add Skills to your Agents.",
|
|
22
22
|
"plugins.title": "Skill Community",
|
|
23
23
|
"welcome.description": "{{appName}} brings you the best UI experience for ChatGPT, Claude, Gemini, and OLLaMA.",
|
|
24
|
-
"welcome.title": "Welcome to {{appName}} ·
|
|
24
|
+
"welcome.title": "Welcome to {{appName}} · Where Agents Collaborate"
|
|
25
25
|
}
|
package/locales/es-ES/file.json
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"header.actions.connect": "Conectar...",
|
|
21
21
|
"header.actions.createFolderError": "No se pudo crear la carpeta",
|
|
22
22
|
"header.actions.creatingFolder": "Creando carpeta...",
|
|
23
|
+
"header.actions.deleteLibrary": "Eliminar biblioteca",
|
|
23
24
|
"header.actions.gitignore.apply": "Aplicar reglas",
|
|
24
25
|
"header.actions.gitignore.cancel": "Ignorar reglas",
|
|
25
26
|
"header.actions.gitignore.content": "Se detectó un archivo .gitignore ({{count}} archivos en total). ¿Deseas aplicar las reglas de exclusión?",
|
|
@@ -108,6 +109,7 @@
|
|
|
108
109
|
"portal.openInPageEditor": "Editar en página",
|
|
109
110
|
"preview.downloadFile": "Descargar archivo",
|
|
110
111
|
"preview.unsupportedFileAndContact": "Este formato de archivo no es compatible con la vista previa en línea. Si deseas solicitar compatibilidad, no dudes en <1>contactarnos</1>.",
|
|
112
|
+
"resource": "Recurso",
|
|
111
113
|
"searchFilePlaceholder": "Buscar archivos",
|
|
112
114
|
"searchPagePlaceholder": "Buscar páginas",
|
|
113
115
|
"tab.all": "Todos",
|
package/locales/fa-IR/file.json
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"header.actions.connect": "اتصال...",
|
|
21
21
|
"header.actions.createFolderError": "ایجاد پوشه با خطا مواجه شد",
|
|
22
22
|
"header.actions.creatingFolder": "در حال ایجاد پوشه...",
|
|
23
|
+
"header.actions.deleteLibrary": "حذف کتابخانه",
|
|
23
24
|
"header.actions.gitignore.apply": "اعمال قوانین",
|
|
24
25
|
"header.actions.gitignore.cancel": "نادیده گرفتن قوانین",
|
|
25
26
|
"header.actions.gitignore.content": "فایل .gitignore شناسایی شد (مجموعاً {{count}} فایل). آیا میخواهید قوانین نادیدهگیری را اعمال کنید؟",
|
|
@@ -108,6 +109,7 @@
|
|
|
108
109
|
"portal.openInPageEditor": "ویرایش در صفحه",
|
|
109
110
|
"preview.downloadFile": "دانلود فایل",
|
|
110
111
|
"preview.unsupportedFileAndContact": "این فرمت فایل در حال حاضر برای پیشنمایش آنلاین پشتیبانی نمیشود. در صورت نیاز به پیشنمایش، لطفاً <1>با ما تماس بگیرید</1>.",
|
|
112
|
+
"resource": "منبع",
|
|
111
113
|
"searchFilePlaceholder": "جستجوی فایلها",
|
|
112
114
|
"searchPagePlaceholder": "جستجوی صفحات",
|
|
113
115
|
"tab.all": "همه",
|
package/locales/fr-FR/file.json
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"header.actions.connect": "Se connecter...",
|
|
21
21
|
"header.actions.createFolderError": "Échec de la création du dossier",
|
|
22
22
|
"header.actions.creatingFolder": "Création du dossier...",
|
|
23
|
+
"header.actions.deleteLibrary": "Supprimer la bibliothèque",
|
|
23
24
|
"header.actions.gitignore.apply": "Appliquer les règles",
|
|
24
25
|
"header.actions.gitignore.cancel": "Ignorer les règles",
|
|
25
26
|
"header.actions.gitignore.content": "Fichier .gitignore détecté ({{count}} fichiers au total). Souhaitez-vous appliquer les règles d’exclusion ?",
|
|
@@ -108,6 +109,7 @@
|
|
|
108
109
|
"portal.openInPageEditor": "Modifier dans la page",
|
|
109
110
|
"preview.downloadFile": "Télécharger le fichier",
|
|
110
111
|
"preview.unsupportedFileAndContact": "Ce format de fichier n’est pas encore pris en charge pour l’aperçu en ligne. Si vous souhaitez en faire la demande, n’hésitez pas à <1>nous contacter</1>.",
|
|
112
|
+
"resource": "Ressource",
|
|
111
113
|
"searchFilePlaceholder": "Rechercher des fichiers",
|
|
112
114
|
"searchPagePlaceholder": "Rechercher des pages",
|
|
113
115
|
"tab.all": "Tous",
|
package/locales/it-IT/file.json
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"header.actions.connect": "Connetti...",
|
|
21
21
|
"header.actions.createFolderError": "Impossibile creare la cartella",
|
|
22
22
|
"header.actions.creatingFolder": "Creazione della cartella in corso...",
|
|
23
|
+
"header.actions.deleteLibrary": "Elimina libreria",
|
|
23
24
|
"header.actions.gitignore.apply": "Applica regole",
|
|
24
25
|
"header.actions.gitignore.cancel": "Ignora regole",
|
|
25
26
|
"header.actions.gitignore.content": "File .gitignore rilevato ({{count}} file in totale). Vuoi applicare le regole di esclusione?",
|
|
@@ -108,6 +109,7 @@
|
|
|
108
109
|
"portal.openInPageEditor": "Modifica nella pagina",
|
|
109
110
|
"preview.downloadFile": "Scarica file",
|
|
110
111
|
"preview.unsupportedFileAndContact": "Questo formato di file non è attualmente supportato per l'anteprima online. Se desideri richiedere il supporto, <1>contattaci</1>.",
|
|
112
|
+
"resource": "Risorsa",
|
|
111
113
|
"searchFilePlaceholder": "Cerca file",
|
|
112
114
|
"searchPagePlaceholder": "Cerca pagine",
|
|
113
115
|
"tab.all": "Tutti",
|
package/locales/ja-JP/file.json
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"header.actions.connect": "接続中...",
|
|
21
21
|
"header.actions.createFolderError": "フォルダーの作成に失敗しました",
|
|
22
22
|
"header.actions.creatingFolder": "フォルダーを作成しています...",
|
|
23
|
+
"header.actions.deleteLibrary": "ライブラリを削除",
|
|
23
24
|
"header.actions.gitignore.apply": "ルールを適用",
|
|
24
25
|
"header.actions.gitignore.cancel": "ルールを無視",
|
|
25
26
|
"header.actions.gitignore.content": ".gitignore ファイルが検出されました(合計 {{count}} 件のファイル)。無視ルールを適用しますか?",
|
|
@@ -108,6 +109,7 @@
|
|
|
108
109
|
"portal.openInPageEditor": "ドキュメントで編集",
|
|
109
110
|
"preview.downloadFile": "ファイルをダウンロード",
|
|
110
111
|
"preview.unsupportedFileAndContact": "このファイル形式はオンラインプレビューをサポートしていません。プレビューのリクエストがある場合は、ぜひ<1>ご連絡ください</1>。",
|
|
112
|
+
"resource": "リソース",
|
|
111
113
|
"searchFilePlaceholder": "ファイルを検索",
|
|
112
114
|
"searchPagePlaceholder": "文書を検索",
|
|
113
115
|
"tab.all": "すべて",
|
package/locales/ko-KR/file.json
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"header.actions.connect": "연결 중...",
|
|
21
21
|
"header.actions.createFolderError": "폴더를 생성하지 못했습니다",
|
|
22
22
|
"header.actions.creatingFolder": "폴더를 생성하는 중...",
|
|
23
|
+
"header.actions.deleteLibrary": "라이브러리 삭제",
|
|
23
24
|
"header.actions.gitignore.apply": "규칙 적용",
|
|
24
25
|
"header.actions.gitignore.cancel": "규칙 무시",
|
|
25
26
|
"header.actions.gitignore.content": ".gitignore 파일이 감지되었습니다 (총 {{count}}개 파일). 무시 규칙을 적용하시겠습니까?",
|
|
@@ -108,6 +109,7 @@
|
|
|
108
109
|
"portal.openInPageEditor": "문서에서 편집",
|
|
109
110
|
"preview.downloadFile": "파일 다운로드",
|
|
110
111
|
"preview.unsupportedFileAndContact": "이 파일 형식은 온라인 미리보기를 지원하지 않습니다. 미리보기 기능이 필요하시면 <1>의견을 보내주세요</1>",
|
|
112
|
+
"resource": "리소스",
|
|
111
113
|
"searchFilePlaceholder": "파일 검색",
|
|
112
114
|
"searchPagePlaceholder": "문서 검색",
|
|
113
115
|
"tab.all": "전체",
|
package/locales/nl-NL/file.json
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"header.actions.connect": "Verbinden...",
|
|
21
21
|
"header.actions.createFolderError": "Map aanmaken mislukt",
|
|
22
22
|
"header.actions.creatingFolder": "Map wordt aangemaakt...",
|
|
23
|
+
"header.actions.deleteLibrary": "Bibliotheek verwijderen",
|
|
23
24
|
"header.actions.gitignore.apply": "Regels toepassen",
|
|
24
25
|
"header.actions.gitignore.cancel": "Regels negeren",
|
|
25
26
|
"header.actions.gitignore.content": ".gitignore-bestand gedetecteerd ({{count}} bestanden in totaal). Wil je de negeerregels toepassen?",
|
|
@@ -108,6 +109,7 @@
|
|
|
108
109
|
"portal.openInPageEditor": "Bewerken in pagina",
|
|
109
110
|
"preview.downloadFile": "Bestand downloaden",
|
|
110
111
|
"preview.unsupportedFileAndContact": "Dit bestandsformaat wordt momenteel niet ondersteund voor online voorbeeldweergave. Heb je een verzoek? <1>Neem contact met ons op</1>.",
|
|
112
|
+
"resource": "Bron",
|
|
111
113
|
"searchFilePlaceholder": "Bestanden zoeken",
|
|
112
114
|
"searchPagePlaceholder": "Pagina’s zoeken",
|
|
113
115
|
"tab.all": "Alles",
|
package/locales/pl-PL/file.json
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"header.actions.connect": "Połącz...",
|
|
21
21
|
"header.actions.createFolderError": "Nie udało się utworzyć folderu",
|
|
22
22
|
"header.actions.creatingFolder": "Tworzenie folderu...",
|
|
23
|
+
"header.actions.deleteLibrary": "Usuń bibliotekę",
|
|
23
24
|
"header.actions.gitignore.apply": "Zastosuj reguły",
|
|
24
25
|
"header.actions.gitignore.cancel": "Ignoruj reguły",
|
|
25
26
|
"header.actions.gitignore.content": "Wykryto plik .gitignore (łącznie {{count}} plików). Czy chcesz zastosować reguły ignorowania?",
|
|
@@ -108,6 +109,7 @@
|
|
|
108
109
|
"portal.openInPageEditor": "Edytuj w stronie",
|
|
109
110
|
"preview.downloadFile": "Pobierz plik",
|
|
110
111
|
"preview.unsupportedFileAndContact": "Ten format pliku nie jest obecnie obsługiwany do podglądu online. Jeśli chcesz zgłosić zapotrzebowanie, <1>skontaktuj się z nami</1>.",
|
|
112
|
+
"resource": "Zasób",
|
|
111
113
|
"searchFilePlaceholder": "Szukaj plików",
|
|
112
114
|
"searchPagePlaceholder": "Szukaj stron",
|
|
113
115
|
"tab.all": "Wszystkie",
|
package/locales/pt-BR/file.json
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"header.actions.connect": "Conectar...",
|
|
21
21
|
"header.actions.createFolderError": "Falha ao criar a pasta",
|
|
22
22
|
"header.actions.creatingFolder": "Criando pasta...",
|
|
23
|
+
"header.actions.deleteLibrary": "Excluir Biblioteca",
|
|
23
24
|
"header.actions.gitignore.apply": "Aplicar Regras",
|
|
24
25
|
"header.actions.gitignore.cancel": "Ignorar Regras",
|
|
25
26
|
"header.actions.gitignore.content": "Arquivo .gitignore detectado ({{count}} arquivos no total). Deseja aplicar as regras de exclusão?",
|
|
@@ -108,6 +109,7 @@
|
|
|
108
109
|
"portal.openInPageEditor": "Editar na Página",
|
|
109
110
|
"preview.downloadFile": "Baixar Arquivo",
|
|
110
111
|
"preview.unsupportedFileAndContact": "Este formato de arquivo não é suportado para visualização online no momento. Se desejar solicitar suporte, <1>entre em contato conosco</1>.",
|
|
112
|
+
"resource": "Recurso",
|
|
111
113
|
"searchFilePlaceholder": "Buscar Arquivos",
|
|
112
114
|
"searchPagePlaceholder": "Buscar Páginas",
|
|
113
115
|
"tab.all": "Todos",
|
package/locales/ru-RU/file.json
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"header.actions.connect": "Подключиться...",
|
|
21
21
|
"header.actions.createFolderError": "Не удалось создать папку",
|
|
22
22
|
"header.actions.creatingFolder": "Создание папки...",
|
|
23
|
+
"header.actions.deleteLibrary": "Удалить библиотеку",
|
|
23
24
|
"header.actions.gitignore.apply": "Применить правила",
|
|
24
25
|
"header.actions.gitignore.cancel": "Игнорировать правила",
|
|
25
26
|
"header.actions.gitignore.content": "Обнаружен файл .gitignore (всего {{count}} файлов). Применить правила игнорирования?",
|
|
@@ -108,6 +109,7 @@
|
|
|
108
109
|
"portal.openInPageEditor": "Редактировать в странице",
|
|
109
110
|
"preview.downloadFile": "Скачать файл",
|
|
110
111
|
"preview.unsupportedFileAndContact": "Этот формат файла пока не поддерживается для онлайн-просмотра. Если у вас есть пожелания, <1>свяжитесь с нами</1>.",
|
|
112
|
+
"resource": "Ресурс",
|
|
111
113
|
"searchFilePlaceholder": "Поиск файлов",
|
|
112
114
|
"searchPagePlaceholder": "Поиск страниц",
|
|
113
115
|
"tab.all": "Все",
|