@open-mercato/core 0.10.1-develop.7833.1.d6cbf0e3ab → 0.10.1-develop.7841.1.af87ac614d
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/.turbo/turbo-build.log +1 -1
- package/dist/modules/cart/api/current/lines/bulk/route.js +1 -1
- package/dist/modules/cart/api/current/lines/bulk/route.js.map +2 -2
- package/dist/modules/cart/api/current/lines/route.js +1 -1
- package/dist/modules/cart/api/current/lines/route.js.map +2 -2
- package/dist/modules/cart/commands/lines.js +5 -10
- package/dist/modules/cart/commands/lines.js.map +2 -2
- package/dist/modules/cart/lib/currentCartRoute.js +8 -0
- package/dist/modules/cart/lib/currentCartRoute.js.map +3 -3
- package/dist/modules/cart/lib/lineMutationLock.js +52 -0
- package/dist/modules/cart/lib/lineMutationLock.js.map +7 -0
- package/dist/modules/customer_accounts/api/admin/roles.js +25 -2
- package/dist/modules/customer_accounts/api/admin/roles.js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/users.js +24 -7
- package/dist/modules/customer_accounts/api/admin/users.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.js +77 -15
- package/dist/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js +12 -1
- package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js.map +2 -2
- package/dist/modules/customer_accounts/data/validators.js +2 -1
- package/dist/modules/customer_accounts/data/validators.js.map +2 -2
- package/dist/modules/customer_accounts/lib/adminOrganizationScope.js +46 -0
- package/dist/modules/customer_accounts/lib/adminOrganizationScope.js.map +7 -0
- package/dist/modules/customers/api/customer-dictionary-entries/route.js +86 -0
- package/dist/modules/customers/api/customer-dictionary-entries/route.js.map +7 -0
- package/dist/modules/customers/api/dictionaries/[kind]/route.js +29 -7
- package/dist/modules/customers/api/dictionaries/[kind]/route.js.map +2 -2
- package/dist/modules/customers/cli.js +28 -110
- package/dist/modules/customers/cli.js.map +3 -3
- package/dist/modules/customers/components/DictionarySettings.js +1 -1
- package/dist/modules/customers/components/DictionarySettings.js.map +1 -1
- package/dist/modules/customers/components/detail/ManageTagsDialog.js +1 -1
- package/dist/modules/customers/components/detail/ManageTagsDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/TaskDialog.js +14 -1
- package/dist/modules/customers/components/detail/TaskDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/TaskForm.js +1 -16
- package/dist/modules/customers/components/detail/TaskForm.js.map +2 -2
- package/dist/modules/customers/components/detail/TasksSection.js +38 -10
- package/dist/modules/customers/components/detail/TasksSection.js.map +2 -2
- package/dist/modules/customers/components/detail/hooks/useCustomerDictionary.js +12 -5
- package/dist/modules/customers/components/detail/hooks/useCustomerDictionary.js.map +2 -2
- package/dist/modules/customers/components/detail/hooks/useInteractions.js +3 -13
- package/dist/modules/customers/components/detail/hooks/useInteractions.js.map +2 -2
- package/dist/modules/customers/lib/dictionaryDefaults.js +134 -0
- package/dist/modules/customers/lib/dictionaryDefaults.js.map +7 -0
- package/dist/modules/customers/lib/dictionaryLabels.js +59 -0
- package/dist/modules/customers/lib/dictionaryLabels.js.map +7 -0
- package/dist/modules/customers/lib/interactionCompatibility.js +1 -0
- package/dist/modules/customers/lib/interactionCompatibility.js.map +2 -2
- package/dist/modules/customers/translations.js +9 -0
- package/dist/modules/customers/translations.js.map +7 -0
- package/dist/modules/eudr/index.js +13 -0
- package/dist/modules/eudr/index.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +3 -3
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/components/documents/ItemsSection.js +75 -21
- package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/lineItemUtils.js +2 -2
- package/dist/modules/sales/components/documents/lineItemUtils.js.map +2 -2
- package/dist/modules/staff/api/timesheets/access-requests/route.js +11 -5
- package/dist/modules/staff/api/timesheets/access-requests/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-projects/route.js +19 -12
- package/dist/modules/staff/api/timesheets/time-projects/route.js.map +2 -2
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.js +21 -12
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js +14 -9
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/NoProjectAccess.js +31 -10
- package/dist/modules/staff/lib/time-tracking-ui/NoProjectAccess.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/projectAccessScope.js +64 -0
- package/dist/modules/staff/lib/time-tracking-ui/projectAccessScope.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/projectAccessScopeHeaders.js +13 -0
- package/dist/modules/staff/lib/time-tracking-ui/projectAccessScopeHeaders.js.map +7 -0
- package/dist/modules/sync_excel/index.js +11 -1
- package/dist/modules/sync_excel/index.js.map +2 -2
- package/dist/modules/translations/di.js +2 -0
- package/dist/modules/translations/di.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/cart/api/current/lines/bulk/route.ts +1 -1
- package/src/modules/cart/api/current/lines/route.ts +1 -1
- package/src/modules/cart/commands/lines.ts +5 -10
- package/src/modules/cart/i18n/de.json +1 -0
- package/src/modules/cart/i18n/en.json +1 -0
- package/src/modules/cart/i18n/es.json +1 -0
- package/src/modules/cart/i18n/ko.json +1 -0
- package/src/modules/cart/i18n/pl.json +1 -0
- package/src/modules/cart/lib/currentCartRoute.ts +8 -0
- package/src/modules/cart/lib/lineMutationLock.ts +59 -0
- package/src/modules/customer_accounts/api/admin/roles.ts +26 -2
- package/src/modules/customer_accounts/api/admin/users.ts +26 -7
- package/src/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.tsx +96 -13
- package/src/modules/customer_accounts/backend/customer_accounts/users/page.tsx +9 -1
- package/src/modules/customer_accounts/data/validators.ts +1 -0
- package/src/modules/customer_accounts/i18n/de.json +10 -0
- package/src/modules/customer_accounts/i18n/en.json +10 -0
- package/src/modules/customer_accounts/i18n/es.json +10 -0
- package/src/modules/customer_accounts/i18n/ko.json +10 -0
- package/src/modules/customer_accounts/i18n/pl.json +10 -0
- package/src/modules/customer_accounts/lib/adminOrganizationScope.ts +71 -0
- package/src/modules/customers/api/customer-dictionary-entries/route.ts +82 -0
- package/src/modules/customers/api/dictionaries/[kind]/route.ts +29 -6
- package/src/modules/customers/cli.ts +23 -124
- package/src/modules/customers/components/DictionarySettings.tsx +1 -1
- package/src/modules/customers/components/detail/ManageTagsDialog.tsx +1 -1
- package/src/modules/customers/components/detail/TaskDialog.tsx +15 -1
- package/src/modules/customers/components/detail/TaskForm.tsx +1 -17
- package/src/modules/customers/components/detail/TasksSection.tsx +44 -14
- package/src/modules/customers/components/detail/hooks/useCustomerDictionary.ts +14 -8
- package/src/modules/customers/components/detail/hooks/useInteractions.ts +3 -4
- package/src/modules/customers/i18n/de.json +81 -0
- package/src/modules/customers/i18n/en.json +81 -0
- package/src/modules/customers/i18n/es.json +81 -0
- package/src/modules/customers/i18n/ko.json +81 -0
- package/src/modules/customers/i18n/pl.json +81 -0
- package/src/modules/customers/lib/dictionaryDefaults.ts +137 -0
- package/src/modules/customers/lib/dictionaryLabels.ts +73 -0
- package/src/modules/customers/lib/interactionCompatibility.ts +1 -0
- package/src/modules/customers/translations.ts +5 -0
- package/src/modules/eudr/index.ts +13 -0
- package/src/modules/sales/commands/documents.ts +3 -3
- package/src/modules/sales/components/documents/ItemsSection.tsx +82 -23
- package/src/modules/sales/components/documents/lineItemUtils.ts +2 -2
- package/src/modules/sales/i18n/de.json +1 -0
- package/src/modules/sales/i18n/en.json +1 -0
- package/src/modules/sales/i18n/es.json +1 -0
- package/src/modules/sales/i18n/ko.json +1 -0
- package/src/modules/sales/i18n/pl.json +1 -0
- package/src/modules/staff/api/timesheets/access-requests/route.ts +13 -14
- package/src/modules/staff/api/timesheets/time-projects/route.ts +22 -13
- package/src/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.tsx +25 -14
- package/src/modules/staff/backend/staff/time-tracking/projects/[id]/page.tsx +14 -13
- package/src/modules/staff/lib/time-tracking-ui/NoProjectAccess.tsx +30 -8
- package/src/modules/staff/lib/time-tracking-ui/projectAccessScope.ts +102 -0
- package/src/modules/staff/lib/time-tracking-ui/projectAccessScopeHeaders.ts +15 -0
- package/src/modules/sync_excel/index.ts +10 -0
- package/src/modules/translations/di.ts +2 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
|
+
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
2
3
|
import { z } from 'zod'
|
|
3
4
|
import type { OpenApiRouteDoc, OpenApiMethodDoc } from '@open-mercato/shared/lib/openapi'
|
|
4
5
|
import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
|
|
@@ -8,6 +9,7 @@ import { RbacService } from '@open-mercato/core/modules/auth/services/rbacServic
|
|
|
8
9
|
import { CustomerRole, CustomerRoleAcl } from '@open-mercato/core/modules/customer_accounts/data/entities'
|
|
9
10
|
import { createRoleSchema } from '@open-mercato/core/modules/customer_accounts/data/validators'
|
|
10
11
|
import { emitCustomerAccountsEvent } from '@open-mercato/core/modules/customer_accounts/events'
|
|
12
|
+
import { resolveAdminTargetOrganization } from '@open-mercato/core/modules/customer_accounts/lib/adminOrganizationScope'
|
|
11
13
|
|
|
12
14
|
export const metadata = {}
|
|
13
15
|
|
|
@@ -25,6 +27,21 @@ export async function GET(req: Request) {
|
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
const url = new URL(req.url)
|
|
30
|
+
const requestedOrganizationId = url.searchParams.get('organizationId')
|
|
31
|
+
let organizationId = auth.orgId
|
|
32
|
+
if (requestedOrganizationId) {
|
|
33
|
+
const target = await resolveAdminTargetOrganization({ container, auth, request: req, requestedOrganizationId })
|
|
34
|
+
if (!target.ok) return target.response
|
|
35
|
+
organizationId = target.organizationId
|
|
36
|
+
if (organizationId !== auth.orgId) {
|
|
37
|
+
const hasTargetAccess = await rbacService.userHasAllFeatures(auth.sub, ['customer_accounts.view'], { tenantId: auth.tenantId, organizationId })
|
|
38
|
+
if (!hasTargetAccess) {
|
|
39
|
+
const { translate } = await resolveTranslations()
|
|
40
|
+
return NextResponse.json({ ok: false, error: translate('customer_accounts.admin.errors.insufficientPermissions', 'Insufficient permissions') }, { status: 403 })
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
28
45
|
const page = Math.max(1, parseInt(url.searchParams.get('page') || '1', 10) || 1)
|
|
29
46
|
const pageSize = Math.min(100, Math.max(1, parseInt(url.searchParams.get('pageSize') || '50', 10) || 50))
|
|
30
47
|
const search = (url.searchParams.get('search') || '').trim()
|
|
@@ -33,7 +50,7 @@ export async function GET(req: Request) {
|
|
|
33
50
|
|
|
34
51
|
const where: Record<string, unknown> = {
|
|
35
52
|
tenantId: auth.tenantId,
|
|
36
|
-
organizationId
|
|
53
|
+
organizationId,
|
|
37
54
|
deletedAt: null,
|
|
38
55
|
}
|
|
39
56
|
|
|
@@ -179,14 +196,21 @@ const errorSchema = z.object({ ok: z.literal(false), error: z.string() })
|
|
|
179
196
|
|
|
180
197
|
const getMethodDoc: OpenApiMethodDoc = {
|
|
181
198
|
summary: 'List customer roles (admin)',
|
|
182
|
-
description: 'Returns
|
|
199
|
+
description: 'Returns customer roles for the caller\'s active organization, or for the organization passed as organizationId when it is within the caller\'s organization scope.',
|
|
183
200
|
tags: ['Customer Accounts Admin'],
|
|
201
|
+
query: z.object({
|
|
202
|
+
page: z.number().int().positive().optional(),
|
|
203
|
+
pageSize: z.number().int().positive().max(100).optional(),
|
|
204
|
+
search: z.string().optional(),
|
|
205
|
+
organizationId: z.string().uuid().optional(),
|
|
206
|
+
}),
|
|
184
207
|
responses: [{
|
|
185
208
|
status: 200,
|
|
186
209
|
description: 'Role list',
|
|
187
210
|
schema: z.object({ ok: z.literal(true), items: z.array(roleSchema), total: z.number(), totalPages: z.number(), page: z.number() }),
|
|
188
211
|
}],
|
|
189
212
|
errors: [
|
|
213
|
+
{ status: 400, description: 'Organization not found or outside the caller scope', schema: errorSchema },
|
|
190
214
|
{ status: 401, description: 'Not authenticated', schema: errorSchema },
|
|
191
215
|
{ status: 403, description: 'Insufficient permissions', schema: errorSchema },
|
|
192
216
|
],
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
|
+
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
2
3
|
import { z } from 'zod'
|
|
3
4
|
import type { OpenApiRouteDoc, OpenApiMethodDoc } from '@open-mercato/shared/lib/openapi'
|
|
4
5
|
import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
|
|
@@ -13,6 +14,7 @@ import { adminCreateUserSchema } from '@open-mercato/core/modules/customer_accou
|
|
|
13
14
|
import { emitCustomerAccountsEvent } from '@open-mercato/core/modules/customer_accounts/events'
|
|
14
15
|
import { findAndCountWithDecryption, findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
15
16
|
import { isOwnedCompanyEntity } from '@open-mercato/core/modules/customer_accounts/lib/customerEntityOwnership'
|
|
17
|
+
import { resolveAdminTargetOrganization } from '@open-mercato/core/modules/customer_accounts/lib/adminOrganizationScope'
|
|
16
18
|
import { lookupHashCandidates } from '@open-mercato/shared/lib/encryption/aes'
|
|
17
19
|
import { E } from '#generated/entities.ids.generated'
|
|
18
20
|
import { resolveSearchConfig } from '@open-mercato/shared/lib/search/config'
|
|
@@ -259,6 +261,23 @@ export async function POST(req: Request) {
|
|
|
259
261
|
return NextResponse.json({ ok: false, error: 'Validation failed', details: parsed.error.flatten().fieldErrors }, { status: 400 })
|
|
260
262
|
}
|
|
261
263
|
|
|
264
|
+
const target = await resolveAdminTargetOrganization({
|
|
265
|
+
container,
|
|
266
|
+
auth,
|
|
267
|
+
request: req,
|
|
268
|
+
requestedOrganizationId: parsed.data.organizationId,
|
|
269
|
+
})
|
|
270
|
+
if (!target.ok) return target.response
|
|
271
|
+
const organizationId = target.organizationId
|
|
272
|
+
|
|
273
|
+
if (organizationId !== auth.orgId) {
|
|
274
|
+
const hasTargetAccess = await rbacService.userHasAllFeatures(auth.sub, ['customer_accounts.manage'], { tenantId: auth.tenantId, organizationId })
|
|
275
|
+
if (!hasTargetAccess) {
|
|
276
|
+
const { translate } = await resolveTranslations()
|
|
277
|
+
return NextResponse.json({ ok: false, error: translate('customer_accounts.admin.errors.insufficientPermissions', 'Insufficient permissions') }, { status: 403 })
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
262
281
|
const em = container.resolve('em') as EntityManager
|
|
263
282
|
const customerUserService = container.resolve('customerUserService') as CustomerUserService
|
|
264
283
|
|
|
@@ -281,11 +300,11 @@ export async function POST(req: Request) {
|
|
|
281
300
|
{
|
|
282
301
|
id: { $in: requestedRoleIds } as any,
|
|
283
302
|
tenantId: auth.tenantId,
|
|
284
|
-
organizationId
|
|
303
|
+
organizationId,
|
|
285
304
|
deletedAt: null,
|
|
286
305
|
} as any,
|
|
287
306
|
undefined,
|
|
288
|
-
{ tenantId: auth.tenantId, organizationId
|
|
307
|
+
{ tenantId: auth.tenantId, organizationId },
|
|
289
308
|
)
|
|
290
309
|
if (validRoles.length !== requestedRoleIds.length) {
|
|
291
310
|
const foundIds = new Set(validRoles.map((role) => role.id))
|
|
@@ -301,7 +320,7 @@ export async function POST(req: Request) {
|
|
|
301
320
|
if (parsed.data.customerEntityId) {
|
|
302
321
|
const owned = await isOwnedCompanyEntity(em, parsed.data.customerEntityId, {
|
|
303
322
|
tenantId: auth.tenantId,
|
|
304
|
-
organizationId
|
|
323
|
+
organizationId,
|
|
305
324
|
})
|
|
306
325
|
if (!owned) {
|
|
307
326
|
return NextResponse.json({ ok: false, error: 'Company not found' }, { status: 400 })
|
|
@@ -312,7 +331,7 @@ export async function POST(req: Request) {
|
|
|
312
331
|
parsed.data.email,
|
|
313
332
|
parsed.data.password,
|
|
314
333
|
parsed.data.displayName,
|
|
315
|
-
{ tenantId: auth.tenantId!, organizationId
|
|
334
|
+
{ tenantId: auth.tenantId!, organizationId },
|
|
316
335
|
)
|
|
317
336
|
user.emailVerifiedAt = new Date()
|
|
318
337
|
|
|
@@ -341,7 +360,7 @@ export async function POST(req: Request) {
|
|
|
341
360
|
id: user.id,
|
|
342
361
|
email: user.email,
|
|
343
362
|
tenantId: auth.tenantId,
|
|
344
|
-
organizationId
|
|
363
|
+
organizationId,
|
|
345
364
|
createdBy: auth.sub,
|
|
346
365
|
}).catch(() => undefined)
|
|
347
366
|
|
|
@@ -434,12 +453,12 @@ const getMethodDoc: OpenApiMethodDoc = {
|
|
|
434
453
|
|
|
435
454
|
const postMethodDoc: OpenApiMethodDoc = {
|
|
436
455
|
summary: 'Create customer user (admin)',
|
|
437
|
-
description: 'Creates a new customer user directly. Staff-initiated, bypasses signup flow.',
|
|
456
|
+
description: 'Creates a new customer user directly. Staff-initiated, bypasses signup flow. Pass organizationId to create the user in a specific organization within the caller\'s organization scope; it defaults to the caller\'s active organization. Roles and the company link are validated against the target organization.',
|
|
438
457
|
tags: ['Customer Accounts Admin'],
|
|
439
458
|
requestBody: { schema: adminCreateUserSchema },
|
|
440
459
|
responses: [{ status: 201, description: 'User created', schema: successSchema }],
|
|
441
460
|
errors: [
|
|
442
|
-
{ status: 400, description: 'Validation failed', schema: errorSchema },
|
|
461
|
+
{ status: 400, description: 'Validation failed, organization not found or outside the caller scope, or no organization could be resolved', schema: errorSchema },
|
|
443
462
|
{ status: 401, description: 'Not authenticated', schema: errorSchema },
|
|
444
463
|
{ status: 403, description: 'Insufficient permissions', schema: errorSchema },
|
|
445
464
|
{ status: 409, description: 'Email already exists', schema: errorSchema },
|
package/src/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.tsx
CHANGED
|
@@ -6,6 +6,7 @@ import Link from 'next/link'
|
|
|
6
6
|
import { useRouter } from 'next/navigation'
|
|
7
7
|
import { Globe, Settings } from 'lucide-react'
|
|
8
8
|
import { DataTable } from '@open-mercato/ui/backend/DataTable'
|
|
9
|
+
import { ErrorMessage, LoadingMessage } from '@open-mercato/ui/backend/detail'
|
|
9
10
|
import type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'
|
|
10
11
|
import { RowActions } from '@open-mercato/ui/backend/RowActions'
|
|
11
12
|
import { Button } from '@open-mercato/ui/primitives/button'
|
|
@@ -20,6 +21,7 @@ import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
|
20
21
|
import { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'
|
|
21
22
|
import { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'
|
|
22
23
|
import { ListEmptyState } from '@open-mercato/ui/backend/filters/ListEmptyState'
|
|
24
|
+
import { OrganizationSelect } from '@open-mercato/core/modules/directory/components/OrganizationSelect'
|
|
23
25
|
import type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'
|
|
24
26
|
import { buildPortalRootUrl, buildPortalUrlPattern } from '../../../lib/portalUrl'
|
|
25
27
|
import { useDemoPortalAccounts } from '../useDemoPortalAccounts'
|
|
@@ -54,38 +56,49 @@ function formatDate(value: string | null | undefined, fallback: string): string
|
|
|
54
56
|
return date.toLocaleDateString()
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
|
|
59
|
+
type RoleOption = { value: string; label: string; id: string }
|
|
60
|
+
|
|
61
|
+
type OrganizationRolesState =
|
|
62
|
+
| { organizationId: string; status: 'loading' | 'error' }
|
|
63
|
+
| { organizationId: string; status: 'loaded'; options: RoleOption[] }
|
|
64
|
+
|
|
65
|
+
async function fetchRoleFilterOptions(organizationId?: string | null): Promise<RoleOption[] | null> {
|
|
58
66
|
try {
|
|
67
|
+
const params = new URLSearchParams({ pageSize: '100' })
|
|
68
|
+
if (organizationId) params.set('organizationId', organizationId)
|
|
59
69
|
const call = await apiCall<{ items?: Array<{ id: string; name: string }> }>(
|
|
60
|
-
|
|
70
|
+
`/api/customer_accounts/admin/roles?${params.toString()}`,
|
|
61
71
|
)
|
|
62
|
-
if (!call.ok) return
|
|
63
|
-
const items =
|
|
72
|
+
if (!call.ok || !Array.isArray(call.result?.items)) return null
|
|
73
|
+
const items = call.result.items
|
|
64
74
|
return items
|
|
65
75
|
.filter((item) => typeof item?.id === 'string' && typeof item?.name === 'string')
|
|
66
76
|
.map((item) => ({ value: item.id, label: item.name, id: item.id }))
|
|
67
77
|
} catch {
|
|
68
|
-
return
|
|
78
|
+
return null
|
|
69
79
|
}
|
|
70
80
|
}
|
|
71
81
|
|
|
72
82
|
function CreateUserDialog({
|
|
73
83
|
open,
|
|
74
84
|
onOpenChange,
|
|
75
|
-
roleOptions,
|
|
76
85
|
onCreated,
|
|
77
86
|
onRunMutation,
|
|
87
|
+
activeOrganizationId,
|
|
78
88
|
}: {
|
|
79
89
|
open: boolean
|
|
80
90
|
onOpenChange: (next: boolean) => void
|
|
81
|
-
roleOptions: Array<{ id: string; label: string }>
|
|
82
91
|
onCreated: () => void
|
|
83
92
|
onRunMutation: <T>(operation: () => Promise<T>) => Promise<T>
|
|
93
|
+
activeOrganizationId: string | null
|
|
84
94
|
}) {
|
|
85
95
|
const t = useT()
|
|
86
96
|
const [email, setEmail] = React.useState('')
|
|
87
97
|
const [displayName, setDisplayName] = React.useState('')
|
|
88
98
|
const [password, setPassword] = React.useState('')
|
|
99
|
+
const [organizationId, setOrganizationId] = React.useState<string | null>(null)
|
|
100
|
+
const [organizationRoles, setOrganizationRoles] = React.useState<OrganizationRolesState | null>(null)
|
|
101
|
+
const [roleReloadToken, setRoleReloadToken] = React.useState(0)
|
|
89
102
|
const [selectedRoleIds, setSelectedRoleIds] = React.useState<string[]>([])
|
|
90
103
|
const [isSubmitting, setIsSubmitting] = React.useState(false)
|
|
91
104
|
|
|
@@ -93,6 +106,34 @@ function CreateUserDialog({
|
|
|
93
106
|
setEmail('')
|
|
94
107
|
setDisplayName('')
|
|
95
108
|
setPassword('')
|
|
109
|
+
setOrganizationId(null)
|
|
110
|
+
setSelectedRoleIds([])
|
|
111
|
+
}, [])
|
|
112
|
+
|
|
113
|
+
const requireOrganization = !activeOrganizationId
|
|
114
|
+
const roleOrganizationId = organizationId ?? activeOrganizationId
|
|
115
|
+
|
|
116
|
+
React.useEffect(() => {
|
|
117
|
+
if (!open || !roleOrganizationId) {
|
|
118
|
+
setOrganizationRoles(null)
|
|
119
|
+
return
|
|
120
|
+
}
|
|
121
|
+
let cancelled = false
|
|
122
|
+
setOrganizationRoles({ organizationId: roleOrganizationId, status: 'loading' })
|
|
123
|
+
fetchRoleFilterOptions(roleOrganizationId).then((opts) => {
|
|
124
|
+
if (cancelled) return
|
|
125
|
+
setOrganizationRoles(opts === null
|
|
126
|
+
? { organizationId: roleOrganizationId, status: 'error' }
|
|
127
|
+
: { organizationId: roleOrganizationId, status: 'loaded', options: opts })
|
|
128
|
+
})
|
|
129
|
+
return () => { cancelled = true }
|
|
130
|
+
}, [open, roleOrganizationId, roleReloadToken])
|
|
131
|
+
|
|
132
|
+
const currentOrganizationRoles = organizationRoles?.organizationId === roleOrganizationId ? organizationRoles : null
|
|
133
|
+
const availableRoleOptions = currentOrganizationRoles?.status === 'loaded' ? currentOrganizationRoles.options : []
|
|
134
|
+
|
|
135
|
+
const handleOrganizationChange = React.useCallback((next: string | null) => {
|
|
136
|
+
setOrganizationId(next ?? null)
|
|
96
137
|
setSelectedRoleIds([])
|
|
97
138
|
}, [])
|
|
98
139
|
|
|
@@ -102,6 +143,10 @@ function CreateUserDialog({
|
|
|
102
143
|
flash(t('customer_accounts.admin.createUser.error.required', 'Email, name, and password are required'), 'error')
|
|
103
144
|
return
|
|
104
145
|
}
|
|
146
|
+
if (requireOrganization && !organizationId) {
|
|
147
|
+
flash(t('customer_accounts.admin.createUser.error.organizationRequired', 'Select an organization for the new user'), 'error')
|
|
148
|
+
return
|
|
149
|
+
}
|
|
105
150
|
setIsSubmitting(true)
|
|
106
151
|
try {
|
|
107
152
|
await onRunMutation(async () => {
|
|
@@ -115,6 +160,7 @@ function CreateUserDialog({
|
|
|
115
160
|
displayName: displayName.trim(),
|
|
116
161
|
password,
|
|
117
162
|
roleIds: selectedRoleIds.length > 0 ? selectedRoleIds : undefined,
|
|
163
|
+
organizationId: organizationId ?? undefined,
|
|
118
164
|
}),
|
|
119
165
|
},
|
|
120
166
|
)
|
|
@@ -133,7 +179,7 @@ function CreateUserDialog({
|
|
|
133
179
|
} finally {
|
|
134
180
|
setIsSubmitting(false)
|
|
135
181
|
}
|
|
136
|
-
}, [displayName, email, onCreated, onOpenChange, onRunMutation, password, resetForm, selectedRoleIds, t])
|
|
182
|
+
}, [displayName, email, onCreated, onOpenChange, onRunMutation, organizationId, password, requireOrganization, resetForm, selectedRoleIds, t])
|
|
137
183
|
|
|
138
184
|
const handleKeyDown = React.useCallback((event: React.KeyboardEvent) => {
|
|
139
185
|
if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {
|
|
@@ -189,11 +235,43 @@ function CreateUserDialog({
|
|
|
189
235
|
autoComplete="new-password"
|
|
190
236
|
/>
|
|
191
237
|
</div>
|
|
192
|
-
|
|
238
|
+
<div className="space-y-2">
|
|
239
|
+
<label className="text-sm font-medium" htmlFor="create-organization">
|
|
240
|
+
{t('customer_accounts.admin.createUser.fields.organization', 'Organization')}
|
|
241
|
+
</label>
|
|
242
|
+
<OrganizationSelect
|
|
243
|
+
id="create-organization"
|
|
244
|
+
value={organizationId}
|
|
245
|
+
onChange={handleOrganizationChange}
|
|
246
|
+
required={requireOrganization}
|
|
247
|
+
includeEmptyOption
|
|
248
|
+
emptyOptionLabel={requireOrganization
|
|
249
|
+
? t('customer_accounts.admin.createUser.fields.organizationPlaceholder', 'Select an organization')
|
|
250
|
+
: t('customer_accounts.admin.createUser.fields.organizationCurrent', 'Current organization')}
|
|
251
|
+
className="w-full h-9 rounded border px-2 text-sm"
|
|
252
|
+
/>
|
|
253
|
+
</div>
|
|
254
|
+
{roleOrganizationId && (
|
|
193
255
|
<div className="space-y-2">
|
|
194
256
|
<p className="text-sm font-medium">{t('customer_accounts.admin.createUser.fields.roles', 'Roles')}</p>
|
|
257
|
+
{currentOrganizationRoles?.status === 'error' ? (
|
|
258
|
+
<ErrorMessage
|
|
259
|
+
label={t('customer_accounts.admin.createUser.error.loadRoles', 'Could not load roles for this organization')}
|
|
260
|
+
action={
|
|
261
|
+
<Button type="button" variant="outline" size="sm" onClick={() => setRoleReloadToken((token) => token + 1)}>
|
|
262
|
+
{t('customer_accounts.admin.createUser.actions.retryRoles', 'Retry')}
|
|
263
|
+
</Button>
|
|
264
|
+
}
|
|
265
|
+
/>
|
|
266
|
+
) : currentOrganizationRoles?.status !== 'loaded' ? (
|
|
267
|
+
<LoadingMessage label={t('customer_accounts.admin.createUser.loadingRoles', 'Loading roles...')} />
|
|
268
|
+
) : availableRoleOptions.length === 0 ? (
|
|
269
|
+
<p className="text-sm text-muted-foreground">
|
|
270
|
+
{t('customer_accounts.admin.createUser.noRoles', 'No roles are available for this organization')}
|
|
271
|
+
</p>
|
|
272
|
+
) : null}
|
|
195
273
|
<div className="flex flex-wrap gap-2">
|
|
196
|
-
{
|
|
274
|
+
{availableRoleOptions.map((role) => {
|
|
197
275
|
const isSelected = selectedRoleIds.includes(role.id)
|
|
198
276
|
return (
|
|
199
277
|
<Button
|
|
@@ -233,9 +311,14 @@ function CreateUserDialog({
|
|
|
233
311
|
export type PortalUsersPageClientProps = {
|
|
234
312
|
portalOrigin: string
|
|
235
313
|
portalOrgSlug?: string | null
|
|
314
|
+
activeOrganizationId?: string | null
|
|
236
315
|
}
|
|
237
316
|
|
|
238
|
-
export function PortalUsersPageClient({
|
|
317
|
+
export function PortalUsersPageClient({
|
|
318
|
+
portalOrigin,
|
|
319
|
+
portalOrgSlug = null,
|
|
320
|
+
activeOrganizationId = null,
|
|
321
|
+
}: PortalUsersPageClientProps) {
|
|
239
322
|
const { confirm, ConfirmDialogElement } = useConfirmDialog()
|
|
240
323
|
const t = useT()
|
|
241
324
|
const router = useRouter()
|
|
@@ -274,7 +357,7 @@ export function PortalUsersPageClient({ portalOrigin, portalOrgSlug = null }: Po
|
|
|
274
357
|
React.useEffect(() => {
|
|
275
358
|
let cancelled = false
|
|
276
359
|
fetchRoleFilterOptions().then((opts) => {
|
|
277
|
-
if (!cancelled) setRoleOptions(opts)
|
|
360
|
+
if (!cancelled) setRoleOptions(opts ?? [])
|
|
278
361
|
})
|
|
279
362
|
return () => { cancelled = true }
|
|
280
363
|
}, [])
|
|
@@ -613,9 +696,9 @@ export function PortalUsersPageClient({ portalOrigin, portalOrgSlug = null }: Po
|
|
|
613
696
|
<CreateUserDialog
|
|
614
697
|
open={createDialogOpen}
|
|
615
698
|
onOpenChange={setCreateDialogOpen}
|
|
616
|
-
roleOptions={roleOptions}
|
|
617
699
|
onCreated={() => setReloadToken((token) => token + 1)}
|
|
618
700
|
onRunMutation={runMutationWithContext}
|
|
701
|
+
activeOrganizationId={activeOrganizationId}
|
|
619
702
|
/>
|
|
620
703
|
{ConfirmDialogElement}
|
|
621
704
|
</>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { headers } from 'next/headers'
|
|
2
|
+
import { getAuthFromCookies } from '@open-mercato/shared/lib/auth/server'
|
|
3
|
+
import { resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
|
|
2
4
|
import { Page, PageBody } from '@open-mercato/ui/backend/Page'
|
|
3
5
|
import { resolvePortalRequestOrigin } from '../../../lib/portalUrl'
|
|
4
6
|
import { resolveCurrentOrgPortalSlug } from '../../../lib/portalOrgSlug'
|
|
@@ -7,10 +9,16 @@ import { PortalUsersPageClient } from './PortalUsersPageClient'
|
|
|
7
9
|
export default async function CustomerAccountsPage() {
|
|
8
10
|
const portalOrigin = resolvePortalRequestOrigin(await headers())
|
|
9
11
|
const portalOrgSlug = await resolveCurrentOrgPortalSlug()
|
|
12
|
+
const auth = await getAuthFromCookies().catch(() => null)
|
|
13
|
+
const activeOrganizationId = resolveActiveOrganizationId(auth)
|
|
10
14
|
return (
|
|
11
15
|
<Page>
|
|
12
16
|
<PageBody className="space-y-4">
|
|
13
|
-
<PortalUsersPageClient
|
|
17
|
+
<PortalUsersPageClient
|
|
18
|
+
portalOrigin={portalOrigin}
|
|
19
|
+
portalOrgSlug={portalOrgSlug}
|
|
20
|
+
activeOrganizationId={activeOrganizationId}
|
|
21
|
+
/>
|
|
14
22
|
</PageBody>
|
|
15
23
|
</Page>
|
|
16
24
|
)
|
|
@@ -96,6 +96,7 @@ export const adminCreateUserSchema = z.object({
|
|
|
96
96
|
displayName: displayNameField,
|
|
97
97
|
roleIds: z.array(z.string().uuid()).optional(),
|
|
98
98
|
customerEntityId: z.string().uuid().optional(),
|
|
99
|
+
organizationId: z.string().uuid().optional(),
|
|
99
100
|
})
|
|
100
101
|
|
|
101
102
|
export const adminUpdateUserSchema = z.object({
|
|
@@ -18,16 +18,24 @@
|
|
|
18
18
|
"customer_accounts.admin.createUser.actions.cancel": "Abbrechen",
|
|
19
19
|
"customer_accounts.admin.createUser.actions.create": "Benutzer erstellen",
|
|
20
20
|
"customer_accounts.admin.createUser.actions.creating": "Erstellen...",
|
|
21
|
+
"customer_accounts.admin.createUser.actions.retryRoles": "Erneut versuchen",
|
|
22
|
+
"customer_accounts.admin.createUser.error.loadRoles": "Die Rollen dieser Organisation konnten nicht geladen werden",
|
|
23
|
+
"customer_accounts.admin.createUser.error.organizationRequired": "Wählen Sie eine Organisation für den neuen Benutzer aus",
|
|
21
24
|
"customer_accounts.admin.createUser.error.required": "E-Mail, Name und Passwort sind erforderlich",
|
|
22
25
|
"customer_accounts.admin.createUser.error.save": "Benutzer konnte nicht erstellt werden",
|
|
23
26
|
"customer_accounts.admin.createUser.fields.displayName": "Anzeigename",
|
|
24
27
|
"customer_accounts.admin.createUser.fields.displayNamePlaceholder": "Max Mustermann",
|
|
25
28
|
"customer_accounts.admin.createUser.fields.email": "E-Mail",
|
|
26
29
|
"customer_accounts.admin.createUser.fields.emailPlaceholder": "benutzer@beispiel.de",
|
|
30
|
+
"customer_accounts.admin.createUser.fields.organization": "Organisation",
|
|
31
|
+
"customer_accounts.admin.createUser.fields.organizationCurrent": "Aktuelle Organisation",
|
|
32
|
+
"customer_accounts.admin.createUser.fields.organizationPlaceholder": "Organisation auswählen",
|
|
27
33
|
"customer_accounts.admin.createUser.fields.password": "Passwort",
|
|
28
34
|
"customer_accounts.admin.createUser.fields.passwordPlaceholder": "Min. 8 Zeichen",
|
|
29
35
|
"customer_accounts.admin.createUser.fields.roles": "Rollen",
|
|
30
36
|
"customer_accounts.admin.createUser.flash.created": "Benutzer erstellt",
|
|
37
|
+
"customer_accounts.admin.createUser.loadingRoles": "Rollen werden geladen...",
|
|
38
|
+
"customer_accounts.admin.createUser.noRoles": "Für diese Organisation sind keine Rollen verfügbar",
|
|
31
39
|
"customer_accounts.admin.createUser.title": "Kundenbenutzer erstellen",
|
|
32
40
|
"customer_accounts.admin.detail.actions.backToList": "Back to list",
|
|
33
41
|
"customer_accounts.admin.detail.actions.delete": "Delete",
|
|
@@ -96,6 +104,8 @@
|
|
|
96
104
|
"customer_accounts.admin.error.delete": "Failed to delete user",
|
|
97
105
|
"customer_accounts.admin.error.loadUsers": "Failed to load customer users",
|
|
98
106
|
"customer_accounts.admin.error.toggleActive": "Failed to update user status",
|
|
107
|
+
"customer_accounts.admin.errors.insufficientPermissions": "Unzureichende Berechtigungen",
|
|
108
|
+
"customer_accounts.admin.errors.organizationNotFound": "Organisation nicht gefunden",
|
|
99
109
|
"customer_accounts.admin.filters.active": "Active",
|
|
100
110
|
"customer_accounts.admin.filters.inactive": "Inactive",
|
|
101
111
|
"customer_accounts.admin.filters.role": "Role",
|
|
@@ -18,16 +18,24 @@
|
|
|
18
18
|
"customer_accounts.admin.createUser.actions.cancel": "Cancel",
|
|
19
19
|
"customer_accounts.admin.createUser.actions.create": "Create User",
|
|
20
20
|
"customer_accounts.admin.createUser.actions.creating": "Creating...",
|
|
21
|
+
"customer_accounts.admin.createUser.actions.retryRoles": "Retry",
|
|
22
|
+
"customer_accounts.admin.createUser.error.loadRoles": "Could not load roles for this organization",
|
|
23
|
+
"customer_accounts.admin.createUser.error.organizationRequired": "Select an organization for the new user",
|
|
21
24
|
"customer_accounts.admin.createUser.error.required": "Email, name, and password are required",
|
|
22
25
|
"customer_accounts.admin.createUser.error.save": "Failed to create user",
|
|
23
26
|
"customer_accounts.admin.createUser.fields.displayName": "Display Name",
|
|
24
27
|
"customer_accounts.admin.createUser.fields.displayNamePlaceholder": "John Doe",
|
|
25
28
|
"customer_accounts.admin.createUser.fields.email": "Email",
|
|
26
29
|
"customer_accounts.admin.createUser.fields.emailPlaceholder": "user@example.com",
|
|
30
|
+
"customer_accounts.admin.createUser.fields.organization": "Organization",
|
|
31
|
+
"customer_accounts.admin.createUser.fields.organizationCurrent": "Current organization",
|
|
32
|
+
"customer_accounts.admin.createUser.fields.organizationPlaceholder": "Select an organization",
|
|
27
33
|
"customer_accounts.admin.createUser.fields.password": "Password",
|
|
28
34
|
"customer_accounts.admin.createUser.fields.passwordPlaceholder": "Min. 8 characters",
|
|
29
35
|
"customer_accounts.admin.createUser.fields.roles": "Roles",
|
|
30
36
|
"customer_accounts.admin.createUser.flash.created": "User created",
|
|
37
|
+
"customer_accounts.admin.createUser.loadingRoles": "Loading roles...",
|
|
38
|
+
"customer_accounts.admin.createUser.noRoles": "No roles are available for this organization",
|
|
31
39
|
"customer_accounts.admin.createUser.title": "Create Customer User",
|
|
32
40
|
"customer_accounts.admin.detail.actions.backToList": "Back to list",
|
|
33
41
|
"customer_accounts.admin.detail.actions.delete": "Delete",
|
|
@@ -96,6 +104,8 @@
|
|
|
96
104
|
"customer_accounts.admin.error.delete": "Failed to delete user",
|
|
97
105
|
"customer_accounts.admin.error.loadUsers": "Failed to load customer users",
|
|
98
106
|
"customer_accounts.admin.error.toggleActive": "Failed to update user status",
|
|
107
|
+
"customer_accounts.admin.errors.insufficientPermissions": "Insufficient permissions",
|
|
108
|
+
"customer_accounts.admin.errors.organizationNotFound": "Organization not found",
|
|
99
109
|
"customer_accounts.admin.filters.active": "Active",
|
|
100
110
|
"customer_accounts.admin.filters.inactive": "Inactive",
|
|
101
111
|
"customer_accounts.admin.filters.role": "Role",
|
|
@@ -18,16 +18,24 @@
|
|
|
18
18
|
"customer_accounts.admin.createUser.actions.cancel": "Cancelar",
|
|
19
19
|
"customer_accounts.admin.createUser.actions.create": "Crear usuario",
|
|
20
20
|
"customer_accounts.admin.createUser.actions.creating": "Creando...",
|
|
21
|
+
"customer_accounts.admin.createUser.actions.retryRoles": "Reintentar",
|
|
22
|
+
"customer_accounts.admin.createUser.error.loadRoles": "No se pudieron cargar los roles de esta organización",
|
|
23
|
+
"customer_accounts.admin.createUser.error.organizationRequired": "Selecciona una organización para el nuevo usuario",
|
|
21
24
|
"customer_accounts.admin.createUser.error.required": "Correo, nombre y contraseña son obligatorios",
|
|
22
25
|
"customer_accounts.admin.createUser.error.save": "No se pudo crear el usuario",
|
|
23
26
|
"customer_accounts.admin.createUser.fields.displayName": "Nombre para mostrar",
|
|
24
27
|
"customer_accounts.admin.createUser.fields.displayNamePlaceholder": "Juan García",
|
|
25
28
|
"customer_accounts.admin.createUser.fields.email": "Correo electrónico",
|
|
26
29
|
"customer_accounts.admin.createUser.fields.emailPlaceholder": "usuario@ejemplo.com",
|
|
30
|
+
"customer_accounts.admin.createUser.fields.organization": "Organización",
|
|
31
|
+
"customer_accounts.admin.createUser.fields.organizationCurrent": "Organización actual",
|
|
32
|
+
"customer_accounts.admin.createUser.fields.organizationPlaceholder": "Selecciona una organización",
|
|
27
33
|
"customer_accounts.admin.createUser.fields.password": "Contraseña",
|
|
28
34
|
"customer_accounts.admin.createUser.fields.passwordPlaceholder": "Mín. 8 caracteres",
|
|
29
35
|
"customer_accounts.admin.createUser.fields.roles": "Roles",
|
|
30
36
|
"customer_accounts.admin.createUser.flash.created": "Usuario creado",
|
|
37
|
+
"customer_accounts.admin.createUser.loadingRoles": "Cargando roles...",
|
|
38
|
+
"customer_accounts.admin.createUser.noRoles": "No hay roles disponibles para esta organización",
|
|
31
39
|
"customer_accounts.admin.createUser.title": "Crear usuario de cliente",
|
|
32
40
|
"customer_accounts.admin.detail.actions.backToList": "Back to list",
|
|
33
41
|
"customer_accounts.admin.detail.actions.delete": "Delete",
|
|
@@ -96,6 +104,8 @@
|
|
|
96
104
|
"customer_accounts.admin.error.delete": "Failed to delete user",
|
|
97
105
|
"customer_accounts.admin.error.loadUsers": "Failed to load customer users",
|
|
98
106
|
"customer_accounts.admin.error.toggleActive": "Failed to update user status",
|
|
107
|
+
"customer_accounts.admin.errors.insufficientPermissions": "Permisos insuficientes",
|
|
108
|
+
"customer_accounts.admin.errors.organizationNotFound": "Organización no encontrada",
|
|
99
109
|
"customer_accounts.admin.filters.active": "Active",
|
|
100
110
|
"customer_accounts.admin.filters.inactive": "Inactive",
|
|
101
111
|
"customer_accounts.admin.filters.role": "Role",
|
|
@@ -18,16 +18,24 @@
|
|
|
18
18
|
"customer_accounts.admin.createUser.actions.cancel": "취소",
|
|
19
19
|
"customer_accounts.admin.createUser.actions.create": "사용자 생성",
|
|
20
20
|
"customer_accounts.admin.createUser.actions.creating": "생성 중...",
|
|
21
|
+
"customer_accounts.admin.createUser.actions.retryRoles": "다시 시도",
|
|
22
|
+
"customer_accounts.admin.createUser.error.loadRoles": "이 조직의 역할을 불러오지 못했습니다",
|
|
23
|
+
"customer_accounts.admin.createUser.error.organizationRequired": "새 사용자의 조직을 선택하세요",
|
|
21
24
|
"customer_accounts.admin.createUser.error.required": "이메일, 이름, 비밀번호는 필수입니다",
|
|
22
25
|
"customer_accounts.admin.createUser.error.save": "사용자 생성에 실패했습니다",
|
|
23
26
|
"customer_accounts.admin.createUser.fields.displayName": "표시 이름",
|
|
24
27
|
"customer_accounts.admin.createUser.fields.displayNamePlaceholder": "홍길동",
|
|
25
28
|
"customer_accounts.admin.createUser.fields.email": "이메일",
|
|
26
29
|
"customer_accounts.admin.createUser.fields.emailPlaceholder": "user@example.com",
|
|
30
|
+
"customer_accounts.admin.createUser.fields.organization": "조직",
|
|
31
|
+
"customer_accounts.admin.createUser.fields.organizationCurrent": "현재 조직",
|
|
32
|
+
"customer_accounts.admin.createUser.fields.organizationPlaceholder": "조직 선택",
|
|
27
33
|
"customer_accounts.admin.createUser.fields.password": "비밀번호",
|
|
28
34
|
"customer_accounts.admin.createUser.fields.passwordPlaceholder": "최소 8자",
|
|
29
35
|
"customer_accounts.admin.createUser.fields.roles": "역할",
|
|
30
36
|
"customer_accounts.admin.createUser.flash.created": "사용자가 생성되었습니다",
|
|
37
|
+
"customer_accounts.admin.createUser.loadingRoles": "역할을 불러오는 중...",
|
|
38
|
+
"customer_accounts.admin.createUser.noRoles": "이 조직에 사용 가능한 역할이 없습니다",
|
|
31
39
|
"customer_accounts.admin.createUser.title": "고객 사용자 생성",
|
|
32
40
|
"customer_accounts.admin.detail.actions.backToList": "목록으로 돌아가기",
|
|
33
41
|
"customer_accounts.admin.detail.actions.delete": "삭제",
|
|
@@ -96,6 +104,8 @@
|
|
|
96
104
|
"customer_accounts.admin.error.delete": "사용자 삭제에 실패했습니다",
|
|
97
105
|
"customer_accounts.admin.error.loadUsers": "고객 사용자를 불러오지 못했습니다",
|
|
98
106
|
"customer_accounts.admin.error.toggleActive": "사용자 상태 업데이트에 실패했습니다",
|
|
107
|
+
"customer_accounts.admin.errors.insufficientPermissions": "권한이 부족합니다",
|
|
108
|
+
"customer_accounts.admin.errors.organizationNotFound": "조직을 찾을 수 없습니다",
|
|
99
109
|
"customer_accounts.admin.filters.active": "활성",
|
|
100
110
|
"customer_accounts.admin.filters.inactive": "비활성",
|
|
101
111
|
"customer_accounts.admin.filters.role": "역할",
|
|
@@ -18,16 +18,24 @@
|
|
|
18
18
|
"customer_accounts.admin.createUser.actions.cancel": "Anuluj",
|
|
19
19
|
"customer_accounts.admin.createUser.actions.create": "Utwórz użytkownika",
|
|
20
20
|
"customer_accounts.admin.createUser.actions.creating": "Tworzenie...",
|
|
21
|
+
"customer_accounts.admin.createUser.actions.retryRoles": "Spróbuj ponownie",
|
|
22
|
+
"customer_accounts.admin.createUser.error.loadRoles": "Nie udało się wczytać ról tej organizacji",
|
|
23
|
+
"customer_accounts.admin.createUser.error.organizationRequired": "Wybierz organizację dla nowego użytkownika",
|
|
21
24
|
"customer_accounts.admin.createUser.error.required": "E-mail, nazwa i hasło są wymagane",
|
|
22
25
|
"customer_accounts.admin.createUser.error.save": "Nie udało się utworzyć użytkownika",
|
|
23
26
|
"customer_accounts.admin.createUser.fields.displayName": "Nazwa wyświetlana",
|
|
24
27
|
"customer_accounts.admin.createUser.fields.displayNamePlaceholder": "Jan Kowalski",
|
|
25
28
|
"customer_accounts.admin.createUser.fields.email": "E-mail",
|
|
26
29
|
"customer_accounts.admin.createUser.fields.emailPlaceholder": "uzytkownik@przyklad.pl",
|
|
30
|
+
"customer_accounts.admin.createUser.fields.organization": "Organizacja",
|
|
31
|
+
"customer_accounts.admin.createUser.fields.organizationCurrent": "Bieżąca organizacja",
|
|
32
|
+
"customer_accounts.admin.createUser.fields.organizationPlaceholder": "Wybierz organizację",
|
|
27
33
|
"customer_accounts.admin.createUser.fields.password": "Hasło",
|
|
28
34
|
"customer_accounts.admin.createUser.fields.passwordPlaceholder": "Min. 8 znaków",
|
|
29
35
|
"customer_accounts.admin.createUser.fields.roles": "Role",
|
|
30
36
|
"customer_accounts.admin.createUser.flash.created": "Użytkownik utworzony",
|
|
37
|
+
"customer_accounts.admin.createUser.loadingRoles": "Wczytywanie ról...",
|
|
38
|
+
"customer_accounts.admin.createUser.noRoles": "W tej organizacji nie ma dostępnych ról",
|
|
31
39
|
"customer_accounts.admin.createUser.title": "Utwórz użytkownika klienta",
|
|
32
40
|
"customer_accounts.admin.detail.actions.backToList": "Powrót do listy",
|
|
33
41
|
"customer_accounts.admin.detail.actions.delete": "Usuń",
|
|
@@ -96,6 +104,8 @@
|
|
|
96
104
|
"customer_accounts.admin.error.delete": "Nie udało się usunąć użytkownika",
|
|
97
105
|
"customer_accounts.admin.error.loadUsers": "Nie udało się załadować kont klientów",
|
|
98
106
|
"customer_accounts.admin.error.toggleActive": "Nie udało się zmienić statusu użytkownika",
|
|
107
|
+
"customer_accounts.admin.errors.insufficientPermissions": "Niewystarczające uprawnienia",
|
|
108
|
+
"customer_accounts.admin.errors.organizationNotFound": "Nie znaleziono organizacji",
|
|
99
109
|
"customer_accounts.admin.filters.active": "Aktywny",
|
|
100
110
|
"customer_accounts.admin.filters.inactive": "Nieaktywny",
|
|
101
111
|
"customer_accounts.admin.filters.role": "Rola",
|