diff --git a/mateclaw-ui/src/views/Security/AutoApproveGrants/index.vue b/mateclaw-ui/src/views/Security/AutoApproveGrants/index.vue index f8fbd584..28cdcd47 100644 --- a/mateclaw-ui/src/views/Security/AutoApproveGrants/index.vue +++ b/mateclaw-ui/src/views/Security/AutoApproveGrants/index.vue @@ -164,96 +164,137 @@ /> - - - - {{ t('approval.grant.createWorkspaceWarning') }} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {{ t('common.cancel') }} - - {{ t('common.confirm') }} - - - + + + + + + + + {{ dialogWorkspaceWide + ? t('approval.grant.createWorkspaceBtn') + : t('approval.grant.createBtn') }} + + × + + + + + {{ t('approval.grant.createWorkspaceWarning') }} + + + + {{ t('approval.grant.form.scopeType') }} * + + CONVERSATION + AGENT + USER + WORKSPACE + + + + {{ t('approval.grant.form.scopeId') }} * + + + + {{ t('approval.grant.form.toolName') }} + + + + {{ t('approval.grant.form.ruleId') }} + + + + {{ t('approval.grant.form.maxSeverity') }} + + LOW + MEDIUM + HIGH + + + + {{ t('approval.grant.form.grantKind') }} + + {{ t('approval.grant.kind.always') }} + {{ t('approval.grant.kind.until') }} + {{ t('approval.grant.kind.conversationEnd') }} + + + + {{ t('approval.grant.form.expireAt') }} * + + + + {{ t('approval.grant.form.note') }} + + + + + {{ t('approval.grant.form.password') }} + * + + + + + + + + + + + + @@ -268,6 +309,7 @@ import { Plus, Refresh, Unlock, + WarningFilled, } from '@element-plus/icons-vue' import { approvalApi } from '@/api' import type { @@ -559,11 +601,145 @@ onMounted(loadGrants) justify-content: flex-end; } -.warning-banner { - margin-bottom: 16px; +/* ─── Modal (mirrors ToolGuard / edit-rule pattern) ──────────────────── */ +.modal-overlay { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.45); + display: flex; + align-items: center; + justify-content: center; + z-index: 2000; + padding: 24px; +} +.modal { + background: var(--mc-surface-primary, #fff); + border-radius: 12px; + width: min(640px, 100%); + max-height: 88vh; + display: flex; + flex-direction: column; + box-shadow: 0 16px 48px rgba(0, 0, 0, 0.18); + overflow: hidden; +} +.modal-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 16px 20px; + border-bottom: 1px solid var(--mc-border-light, #e5e7eb); +} +.modal-header h3 { + margin: 0; + font-size: 16px; + font-weight: 600; + color: var(--mc-text-primary, #0f172a); + display: inline-flex; + align-items: center; + gap: 8px; +} +.modal-header__icon { + color: var(--mc-danger, #b91c1c); +} +.modal-close { + background: none; + border: none; + font-size: 22px; + line-height: 1; + cursor: pointer; + color: var(--mc-text-tertiary, #94a3b8); +} +.modal-close:hover { color: var(--mc-text-primary, #0f172a); } +.modal-body { + padding: 20px; + overflow-y: auto; +} +.modal-footer { + padding: 12px 20px; + border-top: 1px solid var(--mc-border-light, #e5e7eb); + display: flex; + justify-content: flex-end; + gap: 8px; } -.grant-form { - padding-top: 4px; +/* Danger banner inside the workspace-wide create modal — bright red so the + destructive variant looks instantly different from the routine flow. */ +.danger-banner { + display: flex; + align-items: flex-start; + gap: 10px; + padding: 12px 14px; + margin-bottom: 16px; + background: #fef2f2; + border: 1px solid #fecaca; + border-radius: 8px; + color: #991b1b; + font-size: 13px; + line-height: 1.5; +} +.danger-banner .el-icon { flex-shrink: 0; margin-top: 1px; } + +/* Form grid layout — two columns on wide modal, one column when narrow. + form-group--full breaks across both columns (note, password). */ +.form-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 14px 16px; +} +.form-group { + display: flex; + flex-direction: column; + gap: 6px; +} +.form-group--full { grid-column: 1 / -1; } +.form-group label { + font-size: 13px; + font-weight: 500; + color: var(--mc-text-secondary, #475569); +} +.form-group label .required { + color: var(--mc-danger, #b91c1c); + margin-left: 2px; +} +.form-input { + padding: 8px 10px; + border: 1px solid var(--mc-border-light, #e5e7eb); + border-radius: 6px; + background: var(--mc-surface-primary, #fff); + color: var(--mc-text-primary, #0f172a); + font-size: 13px; + width: 100%; + box-sizing: border-box; + transition: border-color 0.15s; +} +.form-input:focus { + outline: none; + border-color: var(--mc-primary, #d97757); +} +.form-input:disabled { + background: var(--mc-surface-tertiary, #f1f5f9); + cursor: not-allowed; +} +.form-input.mono { + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; + font-size: 12px; +} + +/* Password input with the Lock icon as a visual prefix. */ +.password-wrap { + position: relative; + display: flex; + align-items: center; +} +.password-wrap__icon { + position: absolute; + left: 10px; + color: var(--mc-text-tertiary, #94a3b8); + pointer-events: none; +} +.form-input--with-icon { padding-left: 32px; } + +@media (max-width: 560px) { + .form-grid { grid-template-columns: 1fr; } }