forked from baron/baron-sso
누락 locale 키 추가 및 린트 정리
This commit is contained in:
@@ -17,6 +17,7 @@ import { useCallback, useEffect, useState } from "react";
|
|||||||
import { useAuth } from "react-oidc-context";
|
import { useAuth } from "react-oidc-context";
|
||||||
import { Link, useNavigate, useParams } from "react-router-dom";
|
import { Link, useNavigate, useParams } from "react-router-dom";
|
||||||
import { PageHeader } from "../../../../common/core/components/page";
|
import { PageHeader } from "../../../../common/core/components/page";
|
||||||
|
import { DeveloperAccessRequestCard } from "../../components/common/DeveloperAccessRequestCard";
|
||||||
import { Badge } from "../../components/ui/badge";
|
import { Badge } from "../../components/ui/badge";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
import {
|
import {
|
||||||
@@ -30,7 +31,6 @@ import { Input } from "../../components/ui/input";
|
|||||||
import { Label } from "../../components/ui/label";
|
import { Label } from "../../components/ui/label";
|
||||||
import { Switch } from "../../components/ui/switch";
|
import { Switch } from "../../components/ui/switch";
|
||||||
import { Textarea } from "../../components/ui/textarea";
|
import { Textarea } from "../../components/ui/textarea";
|
||||||
import { DeveloperAccessRequestCard } from "../../components/common/DeveloperAccessRequestCard";
|
|
||||||
import { toast } from "../../components/ui/use-toast";
|
import { toast } from "../../components/ui/use-toast";
|
||||||
import type {
|
import type {
|
||||||
ClientStatus,
|
ClientStatus,
|
||||||
@@ -1208,7 +1208,10 @@ function ClientGeneralPage() {
|
|||||||
"msg.dev.clients.general.create_forbidden_detail",
|
"msg.dev.clients.general.create_forbidden_detail",
|
||||||
"개발자 권한 신청에서 연동 앱 추가 권한을 선택한 뒤 승인받아주세요.",
|
"개발자 권한 신청에서 연동 앱 추가 권한을 선택한 뒤 승인받아주세요.",
|
||||||
)}
|
)}
|
||||||
actionLabel={t("ui.dev.welcome.btn_request", "개발자 등록 신청하기")}
|
actionLabel={t(
|
||||||
|
"ui.dev.welcome.btn_request",
|
||||||
|
"개발자 등록 신청하기",
|
||||||
|
)}
|
||||||
onAction={() => navigate("/developer-requests")}
|
onAction={() => navigate("/developer-requests")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ import {
|
|||||||
toggleSort,
|
toggleSort,
|
||||||
} from "../../../../common/core/utils";
|
} from "../../../../common/core/utils";
|
||||||
import { SearchFilterBar } from "../../../../common/ui/search-filter-bar";
|
import { SearchFilterBar } from "../../../../common/ui/search-filter-bar";
|
||||||
import { DeveloperAccessRequestCard } from "../../components/common/DeveloperAccessRequestCard";
|
|
||||||
import {
|
import {
|
||||||
commonTableShellClass,
|
commonTableShellClass,
|
||||||
commonTableViewportClass,
|
commonTableViewportClass,
|
||||||
} from "../../../../common/ui/table";
|
} from "../../../../common/ui/table";
|
||||||
|
import { DeveloperAccessRequestCard } from "../../components/common/DeveloperAccessRequestCard";
|
||||||
import { ForbiddenMessage } from "../../components/common/ForbiddenMessage";
|
import { ForbiddenMessage } from "../../components/common/ForbiddenMessage";
|
||||||
import { Badge } from "../../components/ui/badge";
|
import { Badge } from "../../components/ui/badge";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
@@ -243,7 +243,10 @@ function ClientsPage() {
|
|||||||
"msg.dev.clients.access_denied_detail",
|
"msg.dev.clients.access_denied_detail",
|
||||||
"개발자 권한 신청에서 개요 또는 연동 앱 추가 권한을 선택한 뒤 승인받아주세요.",
|
"개발자 권한 신청에서 개요 또는 연동 앱 추가 권한을 선택한 뒤 승인받아주세요.",
|
||||||
)}
|
)}
|
||||||
actionLabel={t("ui.dev.welcome.btn_request", "개발자 등록 신청하기")}
|
actionLabel={t(
|
||||||
|
"ui.dev.welcome.btn_request",
|
||||||
|
"개발자 등록 신청하기",
|
||||||
|
)}
|
||||||
onAction={() => navigate("/developer-requests")}
|
onAction={() => navigate("/developer-requests")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -25,18 +25,16 @@ export function normalizeDeveloperAccessPages(
|
|||||||
): DeveloperAccessPage[] {
|
): DeveloperAccessPage[] {
|
||||||
const normalized = new Set<DeveloperAccessPage>();
|
const normalized = new Set<DeveloperAccessPage>();
|
||||||
for (const raw of pages) {
|
for (const raw of pages) {
|
||||||
const page = String(raw ?? "").trim().toLowerCase();
|
const page = String(raw ?? "")
|
||||||
|
.trim()
|
||||||
|
.toLowerCase();
|
||||||
if (!page) {
|
if (!page) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (page === "all") {
|
if (page === "all") {
|
||||||
return ["all"];
|
return ["all"];
|
||||||
}
|
}
|
||||||
if (
|
if (page === "overview" || page === "client_create" || page === "audit") {
|
||||||
page === "overview" ||
|
|
||||||
page === "client_create" ||
|
|
||||||
page === "audit"
|
|
||||||
) {
|
|
||||||
normalized.add(page);
|
normalized.add(page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,20 +27,20 @@ import { Textarea } from "../../components/ui/textarea";
|
|||||||
import { toast } from "../../components/ui/use-toast";
|
import { toast } from "../../components/ui/use-toast";
|
||||||
import {
|
import {
|
||||||
createDeveloperGrant,
|
createDeveloperGrant,
|
||||||
fetchDeveloperGrants,
|
|
||||||
fetchDevUsers,
|
|
||||||
fetchDevUser,
|
|
||||||
revokeDeveloperGrant,
|
|
||||||
type DevAssignableUser,
|
type DevAssignableUser,
|
||||||
|
fetchDeveloperGrants,
|
||||||
|
fetchDevUser,
|
||||||
|
fetchDevUsers,
|
||||||
|
revokeDeveloperGrant,
|
||||||
} from "../../lib/devApi";
|
} from "../../lib/devApi";
|
||||||
import { t } from "../../lib/i18n";
|
import { t } from "../../lib/i18n";
|
||||||
import { resolveProfileRole } from "../../lib/role";
|
import { resolveProfileRole } from "../../lib/role";
|
||||||
import { fetchMe } from "../auth/authApi";
|
import { fetchMe } from "../auth/authApi";
|
||||||
import {
|
import {
|
||||||
developerAccessPageOptions,
|
|
||||||
normalizeDeveloperAccessPages,
|
|
||||||
normalizeDeveloperAccessPageSelection,
|
|
||||||
type DeveloperAccessPage,
|
type DeveloperAccessPage,
|
||||||
|
developerAccessPageOptions,
|
||||||
|
normalizeDeveloperAccessPageSelection,
|
||||||
|
normalizeDeveloperAccessPages,
|
||||||
} from "../developer-access/developerAccessPages";
|
} from "../developer-access/developerAccessPages";
|
||||||
|
|
||||||
function formatUserLabel(user: DevAssignableUser) {
|
function formatUserLabel(user: DevAssignableUser) {
|
||||||
@@ -74,10 +74,7 @@ export default function DeveloperGrantsPage() {
|
|||||||
const [grantNotes, setGrantNotes] = useState("");
|
const [grantNotes, setGrantNotes] = useState("");
|
||||||
const [adminNotes, setAdminNotes] = useState<Record<number, string>>({});
|
const [adminNotes, setAdminNotes] = useState<Record<number, string>>({});
|
||||||
|
|
||||||
const {
|
const { data: userSearchData, isFetching: isUserSearchLoading } = useQuery({
|
||||||
data: userSearchData,
|
|
||||||
isFetching: isUserSearchLoading,
|
|
||||||
} = useQuery({
|
|
||||||
queryKey: ["developer-grant-users", deferredUserSearch],
|
queryKey: ["developer-grant-users", deferredUserSearch],
|
||||||
queryFn: () => fetchDevUsers(deferredUserSearch, 10),
|
queryFn: () => fetchDevUsers(deferredUserSearch, 10),
|
||||||
enabled:
|
enabled:
|
||||||
@@ -87,10 +84,8 @@ export default function DeveloperGrantsPage() {
|
|||||||
selectedUser == null,
|
selectedUser == null,
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const { data: selectedUserDetail, isFetching: isSelectedUserDetailLoading } =
|
||||||
data: selectedUserDetail,
|
useQuery({
|
||||||
isFetching: isSelectedUserDetailLoading,
|
|
||||||
} = useQuery({
|
|
||||||
queryKey: ["developer-grant-user", selectedUser?.id],
|
queryKey: ["developer-grant-user", selectedUser?.id],
|
||||||
queryFn: () => fetchDevUser(selectedUser?.id || ""),
|
queryFn: () => fetchDevUser(selectedUser?.id || ""),
|
||||||
enabled: hasAccessToken && isSuperAdmin && selectedUser != null,
|
enabled: hasAccessToken && isSuperAdmin && selectedUser != null,
|
||||||
@@ -145,13 +140,8 @@ export default function DeveloperGrantsPage() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const revokeGrantMutation = useMutation({
|
const revokeGrantMutation = useMutation({
|
||||||
mutationFn: ({
|
mutationFn: ({ id, adminNotes }: { id: number; adminNotes: string }) =>
|
||||||
id,
|
revokeDeveloperGrant(id, adminNotes),
|
||||||
adminNotes,
|
|
||||||
}: {
|
|
||||||
id: number;
|
|
||||||
adminNotes: string;
|
|
||||||
}) => revokeDeveloperGrant(id, adminNotes),
|
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ["developer-grants"] });
|
queryClient.invalidateQueries({ queryKey: ["developer-grants"] });
|
||||||
toast(
|
toast(
|
||||||
@@ -203,10 +193,7 @@ export default function DeveloperGrantsPage() {
|
|||||||
const handleGrant = () => {
|
const handleGrant = () => {
|
||||||
if (!selectedUser) {
|
if (!selectedUser) {
|
||||||
toast(
|
toast(
|
||||||
t(
|
t("msg.dev.grants.user_required", "부여할 사용자를 선택해주세요."),
|
||||||
"msg.dev.grants.user_required",
|
|
||||||
"부여할 사용자를 선택해주세요.",
|
|
||||||
),
|
|
||||||
"error",
|
"error",
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@@ -374,10 +361,7 @@ export default function DeveloperGrantsPage() {
|
|||||||
<CardHeader className="space-y-1 pb-3">
|
<CardHeader className="space-y-1 pb-3">
|
||||||
<div className="flex items-center justify-between gap-2">
|
<div className="flex items-center justify-between gap-2">
|
||||||
<CardTitle className="text-base">
|
<CardTitle className="text-base">
|
||||||
{t(
|
{t("ui.dev.grants.selected_info", "선택된 사용자 정보")}
|
||||||
"ui.dev.grants.selected_info",
|
|
||||||
"선택된 사용자 정보",
|
|
||||||
)}
|
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<Badge variant="secondary">
|
<Badge variant="secondary">
|
||||||
{t("ui.dev.grants.read_only", "읽기 전용")}
|
{t("ui.dev.grants.read_only", "읽기 전용")}
|
||||||
@@ -476,7 +460,9 @@ export default function DeveloperGrantsPage() {
|
|||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={checked}
|
checked={checked}
|
||||||
onChange={() => handleAccessPageToggle(option.value)}
|
onChange={() =>
|
||||||
|
handleAccessPageToggle(option.value)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<span className="font-medium">{option.label}</span>
|
<span className="font-medium">{option.label}</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -577,8 +563,12 @@ export default function DeveloperGrantsPage() {
|
|||||||
<TableRow>
|
<TableRow>
|
||||||
<TableHead>{t("ui.dev.grants.user", "사용자")}</TableHead>
|
<TableHead>{t("ui.dev.grants.user", "사용자")}</TableHead>
|
||||||
<TableHead>{t("ui.dev.grants.tenant", "테넌트")}</TableHead>
|
<TableHead>{t("ui.dev.grants.tenant", "테넌트")}</TableHead>
|
||||||
<TableHead>{t("ui.dev.grants.reason", "부여 사유")}</TableHead>
|
<TableHead>
|
||||||
<TableHead>{t("ui.dev.grants.pages", "권한 페이지")}</TableHead>
|
{t("ui.dev.grants.reason", "부여 사유")}
|
||||||
|
</TableHead>
|
||||||
|
<TableHead>
|
||||||
|
{t("ui.dev.grants.pages", "권한 페이지")}
|
||||||
|
</TableHead>
|
||||||
<TableHead>{t("ui.dev.grants.status", "상태")}</TableHead>
|
<TableHead>{t("ui.dev.grants.status", "상태")}</TableHead>
|
||||||
<TableHead>{t("ui.dev.grants.date", "부여일")}</TableHead>
|
<TableHead>{t("ui.dev.grants.date", "부여일")}</TableHead>
|
||||||
<TableHead className="text-right">
|
<TableHead className="text-right">
|
||||||
@@ -605,7 +595,9 @@ export default function DeveloperGrantsPage() {
|
|||||||
<TableCell>
|
<TableCell>
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<div className="font-medium">
|
<div className="font-medium">
|
||||||
{grant.organization || grant.tenantId || t("ui.common.na", "없음")}
|
{grant.organization ||
|
||||||
|
grant.tenantId ||
|
||||||
|
t("ui.common.na", "없음")}
|
||||||
</div>
|
</div>
|
||||||
<div className="font-mono text-xs text-muted-foreground">
|
<div className="font-mono text-xs text-muted-foreground">
|
||||||
{grant.tenantId || t("ui.common.na", "없음")}
|
{grant.tenantId || t("ui.common.na", "없음")}
|
||||||
|
|||||||
@@ -48,10 +48,10 @@ import { t } from "../../lib/i18n";
|
|||||||
import { resolveProfileRole } from "../../lib/role";
|
import { resolveProfileRole } from "../../lib/role";
|
||||||
import { fetchMe } from "../auth/authApi";
|
import { fetchMe } from "../auth/authApi";
|
||||||
import {
|
import {
|
||||||
developerAccessPageOptions,
|
|
||||||
normalizeDeveloperAccessPages,
|
|
||||||
normalizeDeveloperAccessPageSelection,
|
|
||||||
type DeveloperAccessPage,
|
type DeveloperAccessPage,
|
||||||
|
developerAccessPageOptions,
|
||||||
|
normalizeDeveloperAccessPageSelection,
|
||||||
|
normalizeDeveloperAccessPages,
|
||||||
} from "../developer-access/developerAccessPages";
|
} from "../developer-access/developerAccessPages";
|
||||||
|
|
||||||
export default function DeveloperRequestPage() {
|
export default function DeveloperRequestPage() {
|
||||||
@@ -158,9 +158,7 @@ export default function DeveloperRequestPage() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasActiveRequest = requests?.some(
|
const hasActiveRequest = requests?.some((r) => r.status === "pending");
|
||||||
(r) => r.status === "pending",
|
|
||||||
);
|
|
||||||
const approvedRequestCount =
|
const approvedRequestCount =
|
||||||
requests?.filter((request) => request.status === "approved").length ?? 0;
|
requests?.filter((request) => request.status === "approved").length ?? 0;
|
||||||
const isActionPending =
|
const isActionPending =
|
||||||
@@ -269,7 +267,8 @@ export default function DeveloperRequestPage() {
|
|||||||
</TableCell>
|
</TableCell>
|
||||||
)}
|
)}
|
||||||
<TableCell>
|
<TableCell>
|
||||||
{req.organization?.trim() || t("ui.common.na", "없음")}
|
{req.organization?.trim() ||
|
||||||
|
t("ui.common.na", "없음")}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="max-w-md">
|
<TableCell className="max-w-md">
|
||||||
<div className="truncate" title={req.reason}>
|
<div className="truncate" title={req.reason}>
|
||||||
@@ -284,15 +283,15 @@ export default function DeveloperRequestPage() {
|
|||||||
<TableCell>
|
<TableCell>
|
||||||
<div className="flex flex-wrap gap-1">
|
<div className="flex flex-wrap gap-1">
|
||||||
{req.accessPages?.length ? (
|
{req.accessPages?.length ? (
|
||||||
normalizeDeveloperAccessPages(req.accessPages).map(
|
normalizeDeveloperAccessPages(
|
||||||
(page) => (
|
req.accessPages,
|
||||||
|
).map((page) => (
|
||||||
<Badge key={page} variant="outline">
|
<Badge key={page} variant="outline">
|
||||||
{developerAccessPageOptions.find(
|
{developerAccessPageOptions.find(
|
||||||
(option) => option.value === page,
|
(option) => option.value === page,
|
||||||
)?.label ?? page}
|
)?.label ?? page}
|
||||||
</Badge>
|
</Badge>
|
||||||
),
|
))
|
||||||
)
|
|
||||||
) : (
|
) : (
|
||||||
<Badge variant="secondary">
|
<Badge variant="secondary">
|
||||||
{t("ui.common.na", "없음")}
|
{t("ui.common.na", "없음")}
|
||||||
|
|||||||
@@ -607,9 +607,12 @@ export async function cancelDeveloperRequestApproval(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchDeveloperGrants(tenantId?: string) {
|
export async function fetchDeveloperGrants(tenantId?: string) {
|
||||||
const { data } = await apiClient.get<DeveloperGrant[]>("/dev/developer-grants", {
|
const { data } = await apiClient.get<DeveloperGrant[]>(
|
||||||
|
"/dev/developer-grants",
|
||||||
|
{
|
||||||
params: { tenantId },
|
params: { tenantId },
|
||||||
});
|
},
|
||||||
|
);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -331,6 +331,7 @@ user_desc = "Review your request history and submit a new access request."
|
|||||||
desc = "Please enter the reason for your request. It will be approved after administrator review."
|
desc = "Please enter the reason for your request. It will be approved after administrator review."
|
||||||
tenant_required = "Please submit a developer access request."
|
tenant_required = "Please submit a developer access request."
|
||||||
tenant_required_detail = "Enter a request reason and submit it for administrator review."
|
tenant_required_detail = "Enter a request reason and submit it for administrator review."
|
||||||
|
pages_hint = "If you select All, Overview, Add linked app, and Audit Logs are all included."
|
||||||
|
|
||||||
[msg.dev.clients]
|
[msg.dev.clients]
|
||||||
load_error = "Error loading clients: {{error}}"
|
load_error = "Error loading clients: {{error}}"
|
||||||
@@ -1348,6 +1349,7 @@ form.title = "Direct Grant"
|
|||||||
grant = "Grant Directly"
|
grant = "Grant Directly"
|
||||||
input_section = "Input"
|
input_section = "Input"
|
||||||
list.title = "Granted Access"
|
list.title = "Granted Access"
|
||||||
|
pages = "Access Pages"
|
||||||
read_only = "Read Only"
|
read_only = "Read Only"
|
||||||
reason = "Grant Reason"
|
reason = "Grant Reason"
|
||||||
reason_placeholder = "e.g. Developer console access is required for operational support."
|
reason_placeholder = "e.g. Developer console access is required for operational support."
|
||||||
@@ -1365,6 +1367,7 @@ user_search_placeholder = "Search by name or email..."
|
|||||||
email = "Email"
|
email = "Email"
|
||||||
name = "Name"
|
name = "Name"
|
||||||
org = "Organization"
|
org = "Organization"
|
||||||
|
pages = "Access Pages"
|
||||||
phone = "Phone Number"
|
phone = "Phone Number"
|
||||||
reason = "Reason"
|
reason = "Reason"
|
||||||
reason_placeholder = "e.g. I need to create an OIDC client for internal service integration and testing."
|
reason_placeholder = "e.g. I need to create an OIDC client for internal service integration and testing."
|
||||||
@@ -1382,6 +1385,7 @@ actions = "Actions"
|
|||||||
date = "Requested At"
|
date = "Requested At"
|
||||||
org = "Organization"
|
org = "Organization"
|
||||||
reason = "Reason"
|
reason = "Reason"
|
||||||
|
pages = "Access Pages"
|
||||||
status = "Status"
|
status = "Status"
|
||||||
user = "User"
|
user = "User"
|
||||||
|
|
||||||
|
|||||||
@@ -331,6 +331,7 @@ user_desc = "내 신청 내역을 확인하고 새로운 권한을 신청할 수
|
|||||||
desc = "신청 사유를 입력해 주세요. 관리자 확인 후 승인됩니다."
|
desc = "신청 사유를 입력해 주세요. 관리자 확인 후 승인됩니다."
|
||||||
tenant_required = "개발자 권한 신청을 진행해 주세요."
|
tenant_required = "개발자 권한 신청을 진행해 주세요."
|
||||||
tenant_required_detail = "신청 사유를 입력해 제출하면 관리자 검토 후 승인됩니다."
|
tenant_required_detail = "신청 사유를 입력해 제출하면 관리자 검토 후 승인됩니다."
|
||||||
|
pages_hint = "전체를 선택하면 개요, 연동 앱 추가, 감사로그가 모두 포함됩니다."
|
||||||
|
|
||||||
[msg.dev.clients]
|
[msg.dev.clients]
|
||||||
deleted = "앱이 삭제되었습니다."
|
deleted = "앱이 삭제되었습니다."
|
||||||
@@ -1348,6 +1349,7 @@ form.title = "직접 부여"
|
|||||||
grant = "직접 부여"
|
grant = "직접 부여"
|
||||||
input_section = "입력"
|
input_section = "입력"
|
||||||
list.title = "부여된 권한"
|
list.title = "부여된 권한"
|
||||||
|
pages = "권한 페이지"
|
||||||
read_only = "읽기 전용"
|
read_only = "읽기 전용"
|
||||||
reason = "부여 사유"
|
reason = "부여 사유"
|
||||||
reason_placeholder = "예: 운영 지원을 위해 개발 콘솔 접근이 필요합니다."
|
reason_placeholder = "예: 운영 지원을 위해 개발 콘솔 접근이 필요합니다."
|
||||||
@@ -1365,6 +1367,7 @@ user_search_placeholder = "이름 또는 이메일 검색..."
|
|||||||
email = "이메일"
|
email = "이메일"
|
||||||
name = "성함"
|
name = "성함"
|
||||||
org = "소속"
|
org = "소속"
|
||||||
|
pages = "권한 페이지"
|
||||||
phone = "전화번호"
|
phone = "전화번호"
|
||||||
reason = "신청 사유"
|
reason = "신청 사유"
|
||||||
reason_placeholder = "예: 자체 서비스 연동 및 테스트용 OIDC 클라이언트 생성이 필요합니다."
|
reason_placeholder = "예: 자체 서비스 연동 및 테스트용 OIDC 클라이언트 생성이 필요합니다."
|
||||||
@@ -1382,6 +1385,7 @@ actions = "관리"
|
|||||||
date = "신청일"
|
date = "신청일"
|
||||||
org = "소속"
|
org = "소속"
|
||||||
reason = "신청 사유"
|
reason = "신청 사유"
|
||||||
|
pages = "권한 페이지"
|
||||||
status = "상태"
|
status = "상태"
|
||||||
user = "사용자"
|
user = "사용자"
|
||||||
|
|
||||||
|
|||||||
@@ -420,8 +420,37 @@ phone = "Phone"
|
|||||||
reason = "Request Reason"
|
reason = "Request Reason"
|
||||||
reason_placeholder = "Explain why you need developer access."
|
reason_placeholder = "Explain why you need developer access."
|
||||||
role = "Role"
|
role = "Role"
|
||||||
|
pages_hint = "If you select All, Overview, Add linked app, and Audit Logs are all included."
|
||||||
title = "Developer Registration Request"
|
title = "Developer Registration Request"
|
||||||
|
|
||||||
|
[msg.dev.grants]
|
||||||
|
admin_notes_description = "Leaving a short note for the direct grant helps later reviews and revocations."
|
||||||
|
admin_notes_hint = "Revocations are handled from the list below."
|
||||||
|
admin_notes_placeholder = "e.g. Grant access after verifying the test environment"
|
||||||
|
approved = "Approved"
|
||||||
|
count = "Total {{count}}"
|
||||||
|
create_success = "Developer access has been granted directly."
|
||||||
|
description = "Directly grant developer access to users and revoke granted access."
|
||||||
|
empty = "There are no granted permissions."
|
||||||
|
forbidden = "Only super admin can directly grant developer access."
|
||||||
|
forbidden_desc = "This screen is available only to super admin."
|
||||||
|
form.description = "Select a user to view their current tenant, email, and phone, then grant developer access immediately."
|
||||||
|
list.description = "Current developer access grants."
|
||||||
|
load_error = "Failed to load developer access grants."
|
||||||
|
pages_hint = "If you select All, Overview, Add linked app, and Audit Logs are all included."
|
||||||
|
phone_missing = "No phone number is registered."
|
||||||
|
reason = "Grant reason"
|
||||||
|
revoke = "Revoke"
|
||||||
|
revoke_success = "Developer access has been revoked."
|
||||||
|
search_empty = "No users found."
|
||||||
|
search_loading = "Searching users..."
|
||||||
|
selected_info_description = "Review the selected user's tenant, email, and phone."
|
||||||
|
selected_user = "Selected user: {{user}}"
|
||||||
|
tenant_missing = "No tenant information is available for the selected user."
|
||||||
|
tenant_required = "The selected user's tenant information is unavailable."
|
||||||
|
user_required = "Select a user before granting access."
|
||||||
|
user_section_description = "Enter a search term to select a user. The next-step information stays empty until a user is chosen."
|
||||||
|
|
||||||
[msg.dev.request.status]
|
[msg.dev.request.status]
|
||||||
approved = "Approved"
|
approved = "Approved"
|
||||||
cancelled = "Approval Cancelled"
|
cancelled = "Approval Cancelled"
|
||||||
@@ -2377,6 +2406,7 @@ overview = "Overview"
|
|||||||
clients = "Connected Application"
|
clients = "Connected Application"
|
||||||
logout = "Logout"
|
logout = "Logout"
|
||||||
developer_request = "Developer Access Request"
|
developer_request = "Developer Access Request"
|
||||||
|
developer_grants = "Developer Access Grants"
|
||||||
|
|
||||||
[ui.dev.welcome]
|
[ui.dev.welcome]
|
||||||
btn_request = "New Request"
|
btn_request = "New Request"
|
||||||
@@ -2394,6 +2424,7 @@ desc = "Review the information below and enter a request reason to apply for dev
|
|||||||
email = "Email"
|
email = "Email"
|
||||||
name = "Name"
|
name = "Name"
|
||||||
org = "Organization"
|
org = "Organization"
|
||||||
|
pages = "Access Pages"
|
||||||
phone = "Phone"
|
phone = "Phone"
|
||||||
reason = "Request Reason"
|
reason = "Request Reason"
|
||||||
reason_placeholder = "Explain why you need developer access."
|
reason_placeholder = "Explain why you need developer access."
|
||||||
@@ -2411,9 +2442,33 @@ actions = "Actions"
|
|||||||
date = "Requested At"
|
date = "Requested At"
|
||||||
org = "Organization"
|
org = "Organization"
|
||||||
reason = "Request Reason"
|
reason = "Request Reason"
|
||||||
|
pages = "Access Pages"
|
||||||
status = "Status"
|
status = "Status"
|
||||||
user = "User"
|
user = "User"
|
||||||
|
|
||||||
|
[ui.dev.grants]
|
||||||
|
actions = "Actions"
|
||||||
|
admin_notes = "Grant Reason"
|
||||||
|
approved = "Approved"
|
||||||
|
date = "Granted At"
|
||||||
|
email = "Email"
|
||||||
|
form.title = "Direct Grant"
|
||||||
|
grant = "Grant Directly"
|
||||||
|
input_section = "Input"
|
||||||
|
list.title = "Granted Access"
|
||||||
|
pages = "Access Pages"
|
||||||
|
read_only = "Read Only"
|
||||||
|
reason = "Grant Reason"
|
||||||
|
revoke = "Revoke"
|
||||||
|
revoke_notes_placeholder = "Revoke note (optional)..."
|
||||||
|
selected_info = "Selected User Info"
|
||||||
|
status = "Status"
|
||||||
|
phone = "Phone Number"
|
||||||
|
tenant = "Affiliation"
|
||||||
|
user = "User"
|
||||||
|
user_search_placeholder = "Search by name or email..."
|
||||||
|
user_section = "User Selection"
|
||||||
|
|
||||||
[ui.dev.profile]
|
[ui.dev.profile]
|
||||||
error = "Failed to load profile."
|
error = "Failed to load profile."
|
||||||
loading = "Loading profile..."
|
loading = "Loading profile..."
|
||||||
|
|||||||
@@ -421,6 +421,7 @@ overview = "개요"
|
|||||||
clients = "연동 앱"
|
clients = "연동 앱"
|
||||||
logout = "로그아웃"
|
logout = "로그아웃"
|
||||||
developer_request = "개발자 권한 신청"
|
developer_request = "개발자 권한 신청"
|
||||||
|
developer_grants = "개발자 권한 부여"
|
||||||
|
|
||||||
[ui.dev.welcome]
|
[ui.dev.welcome]
|
||||||
btn_request = "신규 신청하기"
|
btn_request = "신규 신청하기"
|
||||||
@@ -438,6 +439,7 @@ desc = "개발자 권한을 신청하려면 아래 정보를 확인한 뒤 신
|
|||||||
email = "이메일"
|
email = "이메일"
|
||||||
name = "성함"
|
name = "성함"
|
||||||
org = "소속"
|
org = "소속"
|
||||||
|
pages = "권한 페이지"
|
||||||
phone = "전화번호"
|
phone = "전화번호"
|
||||||
reason = "신청 사유"
|
reason = "신청 사유"
|
||||||
reason_placeholder = "개발자 권한이 필요한 이유를 작성해주세요."
|
reason_placeholder = "개발자 권한이 필요한 이유를 작성해주세요."
|
||||||
@@ -455,9 +457,54 @@ actions = "관리"
|
|||||||
date = "신청일"
|
date = "신청일"
|
||||||
org = "소속"
|
org = "소속"
|
||||||
reason = "신청 사유"
|
reason = "신청 사유"
|
||||||
|
pages = "권한 페이지"
|
||||||
status = "상태"
|
status = "상태"
|
||||||
user = "사용자"
|
user = "사용자"
|
||||||
|
|
||||||
|
[ui.dev.grants]
|
||||||
|
actions = "관리"
|
||||||
|
admin_notes = "부여 사유"
|
||||||
|
approved = "승인됨"
|
||||||
|
date = "부여일"
|
||||||
|
email = "이메일"
|
||||||
|
form.title = "직접 부여"
|
||||||
|
grant = "직접 부여"
|
||||||
|
input_section = "입력"
|
||||||
|
list.title = "부여된 권한"
|
||||||
|
pages = "권한 페이지"
|
||||||
|
read_only = "읽기 전용"
|
||||||
|
reason = "부여 사유"
|
||||||
|
revoke = "회수"
|
||||||
|
revoke_notes_placeholder = "회수 메모 (선택)..."
|
||||||
|
selected_info = "선택된 사용자 정보"
|
||||||
|
status = "상태"
|
||||||
|
phone = "전화번호"
|
||||||
|
tenant = "소속"
|
||||||
|
user = "사용자"
|
||||||
|
user_search_placeholder = "이름 또는 이메일 검색..."
|
||||||
|
user_section = "사용자 선택"
|
||||||
|
|
||||||
|
[ui.dev.grants]
|
||||||
|
actions = "관리"
|
||||||
|
admin_notes = "부여 사유"
|
||||||
|
approved = "승인됨"
|
||||||
|
date = "부여일"
|
||||||
|
form.title = "직접 부여"
|
||||||
|
grant = "직접 부여"
|
||||||
|
input_section = "입력"
|
||||||
|
list.title = "부여된 권한"
|
||||||
|
pages = "권한 페이지"
|
||||||
|
read_only = "읽기 전용"
|
||||||
|
reason = "부여 사유"
|
||||||
|
revoke = "회수"
|
||||||
|
revoke_notes_placeholder = "회수 메모 (선택)..."
|
||||||
|
selected_info = "선택된 사용자 정보"
|
||||||
|
status = "상태"
|
||||||
|
tenant = "소속"
|
||||||
|
user = "사용자"
|
||||||
|
user_search_placeholder = "이름 또는 이메일 검색..."
|
||||||
|
user_section = "사용자 선택"
|
||||||
|
|
||||||
[ui.dev.tenant]
|
[ui.dev.tenant]
|
||||||
single_notice = "단일 테넌트에 소속되어 전환할 필요가 없습니다."
|
single_notice = "단일 테넌트에 소속되어 전환할 필요가 없습니다."
|
||||||
switch_success = "테넌트 전환 완료"
|
switch_success = "테넌트 전환 완료"
|
||||||
@@ -918,8 +965,37 @@ phone = "전화번호"
|
|||||||
reason = "신청 사유"
|
reason = "신청 사유"
|
||||||
reason_placeholder = "개발자 권한이 필요한 이유를 작성해주세요."
|
reason_placeholder = "개발자 권한이 필요한 이유를 작성해주세요."
|
||||||
role = "역할"
|
role = "역할"
|
||||||
|
pages_hint = "전체를 선택하면 개요, 연동 앱 추가, 감사로그가 모두 포함됩니다."
|
||||||
title = "개발자 등록 신청"
|
title = "개발자 등록 신청"
|
||||||
|
|
||||||
|
[msg.dev.grants]
|
||||||
|
admin_notes_description = "직접 부여의 근거를 간단히 남겨 두면 추후 회수와 검토에 도움이 됩니다."
|
||||||
|
admin_notes_hint = "회수는 목록의 회수 버튼으로 처리합니다."
|
||||||
|
admin_notes_placeholder = "예: 테스트 환경 확인 후 권한 부여"
|
||||||
|
approved = "승인됨"
|
||||||
|
count = "총 {{count}}건"
|
||||||
|
create_success = "개발자 권한을 직접 부여했습니다."
|
||||||
|
description = "사용자에게 개발자 권한을 직접 부여하고, 부여된 권한을 회수합니다."
|
||||||
|
empty = "부여된 권한이 없습니다."
|
||||||
|
forbidden = "개발자 권한 직접 부여는 super admin만 사용할 수 있습니다."
|
||||||
|
forbidden_desc = "이 화면은 super admin만 사용할 수 있습니다."
|
||||||
|
form.description = "사용자를 선택하면 현재 소속 테넌트, 이메일, 전화번호를 확인한 뒤 개발자 권한을 즉시 부여합니다."
|
||||||
|
list.description = "현재 부여된 개발자 권한 목록입니다."
|
||||||
|
load_error = "개발자 권한 목록을 불러오지 못했습니다."
|
||||||
|
pages_hint = "전체를 선택하면 개요, 연동 앱 추가, 감사로그가 모두 포함됩니다."
|
||||||
|
phone_missing = "등록된 전화번호가 없습니다."
|
||||||
|
reason = "부여 사유"
|
||||||
|
revoke = "회수"
|
||||||
|
revoke_success = "개발자 권한을 회수했습니다."
|
||||||
|
search_empty = "검색 결과가 없습니다."
|
||||||
|
search_loading = "사용자를 찾는 중입니다..."
|
||||||
|
selected_info_description = "선택된 사용자의 소속, 이메일, 전화번호를 확인합니다."
|
||||||
|
selected_user = "선택된 사용자: {{user}}"
|
||||||
|
tenant_missing = "선택한 사용자의 테넌트 정보를 확인할 수 없습니다."
|
||||||
|
tenant_required = "선택한 사용자의 테넌트 정보를 확인할 수 없습니다."
|
||||||
|
user_required = "부여할 사용자를 선택해주세요."
|
||||||
|
user_section_description = "검색어를 입력해 사용자를 선택합니다. 선택 전에는 다음 단계 정보가 비어 있습니다."
|
||||||
|
|
||||||
[msg.dev.request.status]
|
[msg.dev.request.status]
|
||||||
approved = "승인됨"
|
approved = "승인됨"
|
||||||
cancelled = "승인 취소됨"
|
cancelled = "승인 취소됨"
|
||||||
|
|||||||
@@ -278,6 +278,7 @@ success = ""
|
|||||||
clients = ""
|
clients = ""
|
||||||
logout = ""
|
logout = ""
|
||||||
developer_request = ""
|
developer_request = ""
|
||||||
|
developer_grants = ""
|
||||||
|
|
||||||
[ui.dev.welcome]
|
[ui.dev.welcome]
|
||||||
btn_request = ""
|
btn_request = ""
|
||||||
@@ -299,6 +300,7 @@ phone = ""
|
|||||||
reason = ""
|
reason = ""
|
||||||
reason_placeholder = ""
|
reason_placeholder = ""
|
||||||
role = ""
|
role = ""
|
||||||
|
pages = ""
|
||||||
title = ""
|
title = ""
|
||||||
|
|
||||||
[ui.dev.request.status]
|
[ui.dev.request.status]
|
||||||
@@ -312,9 +314,33 @@ actions = ""
|
|||||||
date = ""
|
date = ""
|
||||||
org = ""
|
org = ""
|
||||||
reason = ""
|
reason = ""
|
||||||
|
pages = ""
|
||||||
status = ""
|
status = ""
|
||||||
user = ""
|
user = ""
|
||||||
|
|
||||||
|
[ui.dev.grants]
|
||||||
|
actions = ""
|
||||||
|
admin_notes = ""
|
||||||
|
approved = ""
|
||||||
|
date = ""
|
||||||
|
email = ""
|
||||||
|
form.title = ""
|
||||||
|
grant = ""
|
||||||
|
input_section = ""
|
||||||
|
list.title = ""
|
||||||
|
pages = ""
|
||||||
|
read_only = ""
|
||||||
|
reason = ""
|
||||||
|
revoke = ""
|
||||||
|
revoke_notes_placeholder = ""
|
||||||
|
selected_info = ""
|
||||||
|
status = ""
|
||||||
|
phone = ""
|
||||||
|
tenant = ""
|
||||||
|
user = ""
|
||||||
|
user_search_placeholder = ""
|
||||||
|
user_section = ""
|
||||||
|
|
||||||
[ui.dev.tenant]
|
[ui.dev.tenant]
|
||||||
single_notice = ""
|
single_notice = ""
|
||||||
switch_success = ""
|
switch_success = ""
|
||||||
@@ -748,6 +774,34 @@ unknown_error = ""
|
|||||||
[msg.dev]
|
[msg.dev]
|
||||||
logout_confirm = ""
|
logout_confirm = ""
|
||||||
|
|
||||||
|
[msg.dev.grants]
|
||||||
|
admin_notes_description = ""
|
||||||
|
admin_notes_hint = ""
|
||||||
|
admin_notes_placeholder = ""
|
||||||
|
approved = ""
|
||||||
|
count = ""
|
||||||
|
create_success = ""
|
||||||
|
description = ""
|
||||||
|
empty = ""
|
||||||
|
forbidden = ""
|
||||||
|
forbidden_desc = ""
|
||||||
|
form.description = ""
|
||||||
|
list.description = ""
|
||||||
|
load_error = ""
|
||||||
|
pages_hint = ""
|
||||||
|
phone_missing = ""
|
||||||
|
reason = ""
|
||||||
|
revoke = ""
|
||||||
|
revoke_success = ""
|
||||||
|
search_empty = ""
|
||||||
|
search_loading = ""
|
||||||
|
selected_info_description = ""
|
||||||
|
selected_user = ""
|
||||||
|
tenant_missing = ""
|
||||||
|
tenant_required = ""
|
||||||
|
user_required = ""
|
||||||
|
user_section_description = ""
|
||||||
|
|
||||||
[msg.dev.audit]
|
[msg.dev.audit]
|
||||||
access_denied = ""
|
access_denied = ""
|
||||||
access_denied_detail = ""
|
access_denied_detail = ""
|
||||||
@@ -778,6 +832,7 @@ phone = ""
|
|||||||
reason = ""
|
reason = ""
|
||||||
reason_placeholder = ""
|
reason_placeholder = ""
|
||||||
role = ""
|
role = ""
|
||||||
|
pages_hint = ""
|
||||||
title = ""
|
title = ""
|
||||||
|
|
||||||
[msg.dev.request.status]
|
[msg.dev.request.status]
|
||||||
|
|||||||
Reference in New Issue
Block a user