improve admin release and deployment safeguards
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
@@ -60,7 +60,9 @@ export function LauncherAppsPage() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [workingId, setWorkingId] = useState('');
|
||||
const [syncing, setSyncing] = useState(false);
|
||||
const [unlinking, setUnlinking] = useState(false);
|
||||
const [editingLink, setEditingLink] = useState<LauncherAppLink | null>(null);
|
||||
const [unlinkTarget, setUnlinkTarget] = useState<LauncherAppLink | null>(null);
|
||||
const [displayForm, setDisplayForm] = useState<DisplayForm | null>(null);
|
||||
const loadingVisible = useMinimumLoading(loading);
|
||||
|
||||
@@ -107,17 +109,23 @@ export function LauncherAppsPage() {
|
||||
.finally(() => setWorkingId(''));
|
||||
};
|
||||
|
||||
const unlink = (link: LauncherAppLink) => {
|
||||
setWorkingId(link.id);
|
||||
deleteLauncherAppLink(link.id)
|
||||
const unlink = () => {
|
||||
if (!unlinkTarget || unlinking) return;
|
||||
setUnlinking(true);
|
||||
setWorkingId(unlinkTarget.id);
|
||||
deleteLauncherAppLink(unlinkTarget.id)
|
||||
.then(() => {
|
||||
toast({ type: 'success', message: '런처 앱 연결을 해제했습니다.' });
|
||||
setUnlinkTarget(null);
|
||||
refresh();
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
toast({ type: 'error', title: '연결 해제 실패', message: error.message });
|
||||
})
|
||||
.finally(() => setWorkingId(''));
|
||||
.finally(() => {
|
||||
setWorkingId('');
|
||||
setUnlinking(false);
|
||||
});
|
||||
};
|
||||
|
||||
const syncAdminApps = () => {
|
||||
@@ -240,7 +248,7 @@ export function LauncherAppsPage() {
|
||||
<Button variant="outline" className="size-8 px-0" aria-label={`${link.app.name} 표시 설정`} onClick={() => openSettings(link)} disabled={workingId === `${link.id}-settings`}>
|
||||
<MoreHorizontal className="size-4" />
|
||||
</Button>
|
||||
<Button variant="outline" className="size-8 border-rose-500/40 px-0 text-rose-300 hover:bg-rose-500/10" aria-label={`${link.app.name} 연결 해제`} onClick={() => unlink(link)} disabled={workingId === link.id}>
|
||||
<Button variant="outline" className="size-8 border-rose-500/40 px-0 text-rose-300 hover:bg-rose-500/10" aria-label={`${link.app.name} 연결 해제`} onClick={() => setUnlinkTarget(link)} disabled={workingId === link.id}>
|
||||
<Unlink className="size-4" />
|
||||
</Button>
|
||||
</div>
|
||||
@@ -349,6 +357,30 @@ export function LauncherAppsPage() {
|
||||
) : null}
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
open={Boolean(unlinkTarget)}
|
||||
title="앱 연결 해제"
|
||||
onClose={() => {
|
||||
if (!unlinking) setUnlinkTarget(null);
|
||||
}}
|
||||
footer={
|
||||
<>
|
||||
<Button variant="outline" disabled={unlinking} onClick={() => setUnlinkTarget(null)}>취소</Button>
|
||||
<Button className="bg-rose-600 text-white hover:bg-rose-500" disabled={unlinking} onClick={unlink}>
|
||||
{unlinking ? '해제 중' : '해제'}
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<div className="space-y-3 text-sm">
|
||||
<p>
|
||||
<span className="font-semibold text-foreground">{unlinkTarget?.displayName || unlinkTarget?.app.name || '-'}</span>
|
||||
{' '}앱의 런처 연결을 해제합니다.
|
||||
</p>
|
||||
<p className="text-muted-foreground">연결을 해제하면 런처 홈에 표시되지 않습니다.</p>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<LoadingModal open={loadingVisible} />
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user