Changeset 0.22.4 (#146)
This commit is contained in:
@@ -409,6 +409,26 @@ function _registerProjectPanel() {
|
||||
</div>
|
||||
<div class="project-panel-hint">Workspace files are available to AI in all project chats. Enables the Editor surface.</div>
|
||||
</div>
|
||||
<div class="project-panel-section" id="projectGitSection" style="display:none">
|
||||
<label class="project-panel-label">Git Settings</label>
|
||||
<div style="display:flex;flex-direction:column;gap:6px">
|
||||
<input type="text" id="projectGitRemote" class="project-panel-input" placeholder="Git remote URL (https://...)" spellcheck="false">
|
||||
<input type="text" id="projectGitBranch" class="project-panel-input" placeholder="Branch (default: main)" spellcheck="false">
|
||||
<select id="projectGitCredential" class="project-panel-select">
|
||||
<option value="">No credential</option>
|
||||
</select>
|
||||
<button class="btn-small" id="projectGitSave">Save Git Config</button>
|
||||
</div>
|
||||
<div class="project-panel-hint">Configure git remote to sync workspace files with a repository.</div>
|
||||
</div>
|
||||
<div class="project-panel-section" id="projectFilesSection">
|
||||
<label class="project-panel-label">Project Files</label>
|
||||
<div id="projectFileList" class="project-panel-list"></div>
|
||||
<div style="margin-top:6px">
|
||||
<input type="file" id="projectFileInput" style="display:none" multiple>
|
||||
<button class="btn-small" id="projectFileUploadBtn">Upload File</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="project-panel-section project-panel-footer">
|
||||
<label class="project-panel-checkbox">
|
||||
<input type="checkbox" id="projectArchiveToggle">
|
||||
@@ -434,6 +454,15 @@ function _registerProjectPanel() {
|
||||
el.querySelector('#projectWsSelect').addEventListener('change', _saveProjectWorkspace);
|
||||
el.querySelector('#projectWsCreate').addEventListener('click', _createProjectWorkspace);
|
||||
|
||||
// Wire git settings (v0.22.4)
|
||||
el.querySelector('#projectGitSave').addEventListener('click', _saveProjectGitConfig);
|
||||
|
||||
// Wire project files (v0.22.4)
|
||||
el.querySelector('#projectFileUploadBtn').addEventListener('click', () => {
|
||||
document.getElementById('projectFileInput').click();
|
||||
});
|
||||
el.querySelector('#projectFileInput').addEventListener('change', _handleProjectFileUpload);
|
||||
|
||||
PanelRegistry.register('project', {
|
||||
element: el,
|
||||
label: 'Project',
|
||||
@@ -481,6 +510,12 @@ async function _loadProjectPanel(projectId) {
|
||||
|
||||
// Load workspace picker (v0.21.5)
|
||||
await _renderProjectWorkspace(projectId);
|
||||
|
||||
// Load git settings (v0.22.4) — depends on workspace being loaded
|
||||
await _renderProjectGitSettings(projectId);
|
||||
|
||||
// Load project files (v0.22.4)
|
||||
await _renderProjectFiles(projectId);
|
||||
}
|
||||
|
||||
async function _saveProjectPrompt() {
|
||||
@@ -700,6 +735,8 @@ async function _saveProjectWorkspace() {
|
||||
UI.toast(wsId ? 'Workspace linked' : 'Workspace unlinked', 'success');
|
||||
// Trigger editor surface check
|
||||
if (typeof EditorMode !== 'undefined') EditorMode.check();
|
||||
// Refresh git settings (v0.22.4)
|
||||
await _renderProjectGitSettings(_projectPanelId);
|
||||
} catch (e) {
|
||||
UI.toast('Failed to update workspace', 'error');
|
||||
}
|
||||
@@ -731,6 +768,106 @@ async function _createProjectWorkspace() {
|
||||
|
||||
// ── Channel workspace picker (v0.21.5) ───────
|
||||
|
||||
// ── Workspace Git Config (v0.22.4) ───────────
|
||||
|
||||
async function _renderProjectGitSettings(projectId) {
|
||||
const gitSection = document.getElementById('projectGitSection');
|
||||
const wsId = document.getElementById('projectWsSelect')?.value;
|
||||
if (!wsId) {
|
||||
gitSection.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
gitSection.style.display = '';
|
||||
|
||||
try {
|
||||
const ws = await API.getWorkspace(wsId);
|
||||
document.getElementById('projectGitRemote').value = ws.git_remote_url || '';
|
||||
document.getElementById('projectGitBranch').value = ws.git_branch || '';
|
||||
|
||||
// Load git credentials
|
||||
const credSel = document.getElementById('projectGitCredential');
|
||||
credSel.innerHTML = '<option value="">No credential</option>';
|
||||
try {
|
||||
const creds = await API.listGitCredentials();
|
||||
const list = Array.isArray(creds) ? creds : (creds?.data || []);
|
||||
for (const c of list) {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = c.id;
|
||||
opt.textContent = c.name || c.id.slice(0, 8);
|
||||
if (c.id === ws.git_credential_id) opt.selected = true;
|
||||
credSel.appendChild(opt);
|
||||
}
|
||||
} catch (_) {}
|
||||
} catch (_) {
|
||||
gitSection.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
async function _saveProjectGitConfig() {
|
||||
const wsId = document.getElementById('projectWsSelect')?.value;
|
||||
if (!wsId) return;
|
||||
|
||||
const remote = document.getElementById('projectGitRemote').value.trim();
|
||||
const branch = document.getElementById('projectGitBranch').value.trim() || null;
|
||||
const credId = document.getElementById('projectGitCredential').value || null;
|
||||
|
||||
try {
|
||||
await API.updateWorkspace(wsId, {
|
||||
git_remote_url: remote || null,
|
||||
git_branch: branch,
|
||||
git_credential_id: credId,
|
||||
});
|
||||
UI.toast('Git config saved', 'success');
|
||||
} catch (e) {
|
||||
UI.toast('Failed to save git config: ' + (e.message || e), 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// ── Project Files (v0.22.4) ──────────────────
|
||||
|
||||
async function _renderProjectFiles(projectId) {
|
||||
const list = document.getElementById('projectFileList');
|
||||
if (!list) return;
|
||||
|
||||
try {
|
||||
const resp = await API.projectListFiles(projectId);
|
||||
const files = resp?.files || [];
|
||||
if (!files.length) {
|
||||
list.innerHTML = '<div class="project-panel-empty">No files uploaded</div>';
|
||||
return;
|
||||
}
|
||||
list.innerHTML = files.map(f => {
|
||||
const size = f.size_bytes > 1024 * 1024
|
||||
? (f.size_bytes / 1024 / 1024).toFixed(1) + ' MB'
|
||||
: (f.size_bytes / 1024).toFixed(1) + ' KB';
|
||||
return `<div class="project-panel-item" style="display:flex;justify-content:space-between;align-items:center">
|
||||
<span title="${esc(f.filename)}">${esc(f.filename)}</span>
|
||||
<span class="text-muted" style="font-size:11px">${size}</span>
|
||||
</div>`;
|
||||
}).join('');
|
||||
} catch (e) {
|
||||
list.innerHTML = '<div class="project-panel-empty">Failed to load files</div>';
|
||||
}
|
||||
}
|
||||
|
||||
async function _handleProjectFileUpload() {
|
||||
const input = document.getElementById('projectFileInput');
|
||||
if (!input.files?.length || !_projectPanelId) return;
|
||||
|
||||
for (const file of input.files) {
|
||||
try {
|
||||
await API.projectUploadFile(_projectPanelId, file);
|
||||
UI.toast(`Uploaded ${file.name}`, 'success');
|
||||
} catch (e) {
|
||||
UI.toast(`Upload failed: ${e.message || e}`, 'error');
|
||||
}
|
||||
}
|
||||
input.value = '';
|
||||
await _renderProjectFiles(_projectPanelId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function showWorkspacePicker(chatId) {
|
||||
let workspaces = [];
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user