refactor: full-stack restructure with multi-tenancy, workspace management, and K8s diagnostics

- Add Workspace domain (entity, repository, service, handler, DTO)
- Add multi-tenant K8s client with tenant binding and quota management
- Add K8s diagnostics client (instance diagnostics)
- Add authorization middleware (authz package)
- Restructure frontend to feature-based architecture (features/)
- Add User Management page in configuration
- Add AccessDenied page and route guards
- Refactor shared components (form inputs, layout, UI)
- Update Tailwind config for new design system
- Add comprehensive documentation (docs/, tasks/, plans)
- Improve cluster service with better kubeconfig handling
- Add tests for crypto, config, helm client, tenant binding
This commit is contained in:
Ivan087
2026-05-12 16:15:14 +08:00
parent c5e51ed069
commit 7f238a3168
172 changed files with 15703 additions and 3162 deletions

View File

@ -171,7 +171,7 @@ export const DropdownSelect: React.FC<DropdownSelectProps> = ({
return createPortal(
<div
ref={dropdownRef}
className="fixed bg-gray-800 border border-gray-700 rounded-lg shadow-2xl flex flex-col"
className="fixed bg-white border border-slate-200 rounded-md shadow-2xl flex flex-col"
style={{
top: `${dropdownPosition.top}px`,
left: `${dropdownPosition.left}px`,
@ -192,7 +192,7 @@ export const DropdownSelect: React.FC<DropdownSelectProps> = ({
role="listbox"
>
{options.length === 0 ? (
<li className="px-3 py-2 text-gray-500 text-sm text-center">
<li className="px-3 py-2 text-slate-500 text-sm text-center">
No options available
</li>
) : (
@ -204,14 +204,14 @@ export const DropdownSelect: React.FC<DropdownSelectProps> = ({
<li
key={option.value}
onClick={() => !option.disabled && handleSelect(option.value)}
className={`px-4 py-3 text-sm transition border-b border-gray-700/30 last:border-0 ${
className={`px-4 py-3 text-sm transition border-b border-slate-100 last:border-0 ${
option.disabled
? 'text-gray-600 cursor-not-allowed bg-gray-900/50'
? 'text-slate-400 cursor-not-allowed bg-slate-50'
: isHighlighted
? 'bg-blue-600 text-white cursor-pointer'
: value === option.value
? 'bg-gray-700 text-white cursor-pointer'
: 'text-gray-300 hover:bg-gray-700 cursor-pointer'
? 'bg-blue-50 text-blue-700 cursor-pointer'
: 'text-slate-700 hover:bg-slate-50 cursor-pointer'
}`}
role="option"
aria-selected={value === option.value}
@ -237,31 +237,31 @@ export const DropdownSelect: React.FC<DropdownSelectProps> = ({
onClick={handleToggle}
onKeyDown={handleKeyDown}
tabIndex={disabled ? -1 : 0}
className={`w-full px-3 py-2 bg-gray-800 border border-gray-700 text-white rounded-lg transition flex items-center justify-between ${
className={`w-full px-3 py-2 bg-white border border-slate-300 text-slate-900 rounded-md transition flex items-center justify-between ${
disabled
? 'opacity-50 cursor-not-allowed'
: 'cursor-pointer hover:border-gray-600 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500'
: 'cursor-pointer hover:border-slate-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500'
}`}
role="combobox"
aria-expanded={isOpen}
aria-haspopup="listbox"
>
<span className={value ? 'text-white' : 'text-gray-500'}>
<span className={value ? 'text-slate-900' : 'text-slate-400'}>
{displayText || placeholder}
</span>
<div className="flex items-center gap-1">
{value && !required && !disabled && (
<button
onClick={handleClear}
className="p-0.5 hover:bg-gray-700 rounded transition"
className="p-0.5 hover:bg-slate-100 rounded transition"
type="button"
tabIndex={-1}
>
<X className="w-4 h-4 text-gray-400" />
<X className="w-4 h-4 text-slate-400" />
</button>
)}
<ChevronDown
className={`w-4 h-4 text-gray-400 transition-transform ${
className={`w-4 h-4 text-slate-400 transition-transform ${
isOpen ? 'transform rotate-180' : ''
}`}
/>
@ -285,4 +285,3 @@ export const DropdownSelect: React.FC<DropdownSelectProps> = ({
</div>
);
};