From bec104a44cedf1bfefac8e9fda0923430ba24b37 Mon Sep 17 00:00:00 2001 From: Levi Yan Date: Sun, 11 May 2025 20:26:16 +0800 Subject: [PATCH] feat: create container button's disable to represent waiting when waiting project completion --- templates/devstar-home-vscode-js.tmpl | 112 +++++++++++++++++++++++--- 1 file changed, 99 insertions(+), 13 deletions(-) diff --git a/templates/devstar-home-vscode-js.tmpl b/templates/devstar-home-vscode-js.tmpl index b0f2a5b2ed..8d55d3fecf 100644 --- a/templates/devstar-home-vscode-js.tmpl +++ b/templates/devstar-home-vscode-js.tmpl @@ -22,7 +22,7 @@ createNewRepositoryButton: "Create New Repository" }, 'zh-cn': { - login_reminder:"请登录!", + login_reminder: "请登录!", login_modal: "登录", username: "用户名", password: "密码", @@ -603,7 +603,7 @@ } // 按钮名称根据语言配置 - switch(LANGUAGE){ + switch (LANGUAGE) { case 'zh-cn': createContainerBtn.textContent = '创建容器'; openProjectBtn.textContent = '打开项目'; @@ -639,21 +639,31 @@ repoList.appendChild(flexItem); // 调整按钮显示 - adjustBtnForRepoItem(repoID, hasDevContainer) + if (hasDevContainer) { + adjustBtnForRepoItem(repoID, 'created') + } else { + adjustBtnForRepoItem(repoID, 'not create') + } } - function adjustBtnForRepoItem(repoId, hasDevContainer) { + function adjustBtnForRepoItem(repoId, status) { + // status: not create, createing, created const createContainerBtn = document.getElementById(`${repoId}_createContainerBtn`); const openProjectBtn = document.getElementById(`${repoId}_openProjectBtn`); const deleteContainerBtn = document.getElementById(`${repoId}_deleteContainerBtn`); - if (hasDevContainer) { - createContainerBtn.style.display = 'none'; - openProjectBtn.style.display = 'block'; - deleteContainerBtn.style.display = 'block'; - } else { + if (status === 'not create') { createContainerBtn.style.display = 'block'; openProjectBtn.style.display = 'none'; deleteContainerBtn.style.display = 'none'; + + } else if (status === 'creating') { + createContainerBtn.classList.toggle('disabled') + openProjectBtn.style.display = 'none'; + deleteContainerBtn.style.display = 'none'; + } else { + createContainerBtn.style.display = 'none'; + openProjectBtn.style.display = 'block'; + deleteContainerBtn.style.display = 'block'; } } @@ -869,12 +879,31 @@ body: JSON.stringify(postData) }) .then(response => { - response.json().then(data => { + response.json().then(async data => { const responseCode = data.code if (response.ok && responseCode === 0) { - showInformationNotification(`创建容器成功!`) - adjustBtnForRepoItem(repoId, true) + // TODO: 根据中英双语显示 + showInformationNotification(`创建容器成功!项目初始化中,请等待...`) + adjustBtnForRepoItem(repoId, 'creating') console.log('Successfully create dev container!') + + // 此时等待容器准备完成 + try { + await sleep(2000) //先等待2秒 + const projectStatus = await projectCompletionSign(repoId); + + if (projectStatus === 'ok') { + console.log('Project prepared!') + adjustBtnForRepoItem(repoId, 'created') + showInformationNotification(`项目已准备完成!`) + } else { + // projectCompletionSign 抛出了错误或者返回了 'error' + console.warn("项目初始化失败或超时"); + } + } catch (error) { + console.error("项目初始化失败:", error); + adjustBtnForRepoItem(repoId, 'created') + } } else if (response.ok) { console.warn(responseCode) showErrorNotification(`创建容器失败!\nError: ${data.data.ErrorMsg}`) @@ -890,6 +919,63 @@ }); } + function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + + async function projectCompletionSign(repoId) { + return new Promise((resolve, reject) => { + const maxRetries = 60; // 最大重试次数 + let retryCount = 0; + const intervalId = setInterval(async () => { + var url = DEVSTAR_DOMAIN + "/api/devcontainer"; + var token = USERTOKEN; + + const queryParams = new URLSearchParams({ + repoId: repoId, + wait: true + }).toString(); + const urlWithParams = `${url}?${queryParams}`; + + try { + const response = await fetch(urlWithParams, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'token ' + token + }, + }); + + const data = await response.json(); + const responseCode = data.code; + + if (response.ok && responseCode === 0) { + // 项目准备完成 + clearInterval(intervalId); // 清除定时器 + resolve('ok'); + return; + } else if (response.ok) { + // 继续 + } else { + showErrorNotification(`项目初始化失败!\nError: ${data.message}`); + clearInterval(intervalId); + reject(new Error(`项目初始化失败!\nError: ${data.message}`)); + return; + } + } catch (error) { + console.error(error); + // 发生错误时,不清除定时器,继续重试 + } + + retryCount++; + if (retryCount >= maxRetries) { + clearInterval(intervalId); // 清除定时器 + reject(new Error("达到最大重试次数,项目可能未准备好")); // Reject Promise + } + }, 1000); // 每秒检查一次 + }); + } + function deleteDevContainer(repoId) { var url = DEVSTAR_DOMAIN + "/api/devcontainer" var token = USERTOKEN @@ -911,7 +997,7 @@ const responseCode = data.code if (response.ok && responseCode === 0) { showInformationNotification("删除容器成功!") - adjustBtnForRepoItem(repoId, false) + adjustBtnForRepoItem(repoId, 'not create') console.log('Successfully delete dev container belong to repoId:', repoId, data) } else if (response.ok) { showErrorNotification(`删除容器失败!\nError: ${data.data.ErrorMsg}`)