v2.2.17: Google Service Control & Astra Office Flow Layer
This commit is contained in:
@@ -132,6 +132,86 @@
|
||||
<div id="tgError" class="error" hidden></div>
|
||||
</section>
|
||||
|
||||
<!-- Google (Calendar + Sheets) -->
|
||||
<section class="section" data-section="google">
|
||||
<h2>Google (Calendar · Sheets)</h2>
|
||||
<p class="hint">회의록·할일을 Google Calendar 에 자동 등록하고 Sheets 를 읽고 쓰려면 OAuth 가 필요합니다. <a href="https://console.cloud.google.com/apis/credentials" target="_blank">Google Cloud Console</a> 에서 Desktop OAuth Client 만들고 Client ID/Secret 을 아래에 붙여넣으세요.</p>
|
||||
|
||||
<div class="row">
|
||||
<label>현재 연결 상태</label>
|
||||
<div class="readout" id="googleConnStatus">—</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label for="gClientId">OAuth Client ID</label>
|
||||
<div class="input-group">
|
||||
<input id="gClientId" type="text" placeholder="xxxxxxxx.apps.googleusercontent.com" autocomplete="off" spellcheck="false" />
|
||||
<button data-save="google.clientId">저장</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label for="gClientSecret">OAuth Client Secret</label>
|
||||
<div class="input-group">
|
||||
<input id="gClientSecret" type="password" placeholder="GOCSPX-..." autocomplete="off" spellcheck="false" />
|
||||
<button data-save="google.clientSecret">저장</button>
|
||||
</div>
|
||||
<small class="hint">Desktop OAuth client 의 secret 은 Google 가이드상 비공개 아님. 그래도 Settings Sync 에는 포함되지 않습니다 (machine scope).</small>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<button id="googleConnect">OAuth 연결 / 재연결</button>
|
||||
<button id="googleDisconnect" class="ghost">연결 해제</button>
|
||||
<span id="googleConnStatusInline" class="status-inline"></span>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label for="gCalendarId">Calendar ID</label>
|
||||
<div class="input-group">
|
||||
<input id="gCalendarId" type="text" placeholder="primary" autocomplete="off" spellcheck="false" />
|
||||
<button data-save="google.calendarId">저장</button>
|
||||
</div>
|
||||
<small class="hint">기본 'primary' (본인 메인 캘린더). 다른 캘린더 ID 입력 가능.</small>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label for="gDefaultDur">기본 일정 길이 (분)</label>
|
||||
<div class="input-group narrow">
|
||||
<input id="gDefaultDur" type="number" min="5" max="720" step="5" />
|
||||
<button data-save="google.defaultEventDurationMinutes">저장</button>
|
||||
</div>
|
||||
<small class="hint">duration / end 안 지정된 일정 생성 시 사용. Default 60.</small>
|
||||
</div>
|
||||
|
||||
<h3 style="margin-top:18px;font-size:13px;color:var(--muted)">iCal 읽기 (선택 사항)</h3>
|
||||
<p class="hint">OAuth 없이 비공개 iCal URL 로 일정만 읽고 싶을 때. OAuth 연결돼 있으면 비워둬도 됩니다.</p>
|
||||
|
||||
<div class="row">
|
||||
<label for="gIcalUrl">iCal URL</label>
|
||||
<div class="input-group">
|
||||
<input id="gIcalUrl" type="password" placeholder="https://calendar.google.com/calendar/ical/.../basic.ics" autocomplete="off" spellcheck="false" />
|
||||
<button data-save="google.icalUrl">저장</button>
|
||||
</div>
|
||||
<small class="hint">URL 자체가 capability 토큰이라 password 처리. Settings Sync 에 안 포함됨.</small>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label for="gIcalDays">iCal 미리 가져올 일수</label>
|
||||
<div class="input-group narrow">
|
||||
<input id="gIcalDays" type="number" min="1" max="90" step="1" />
|
||||
<button data-save="google.icalDaysAhead">저장</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<button id="googleIcalRefresh">지금 iCal 새로고침</button>
|
||||
<span id="googleIcalStatus" class="status-inline"></span>
|
||||
</div>
|
||||
|
||||
<div id="googleFeedback" class="feedback" hidden></div>
|
||||
<div id="googleError" class="error" hidden></div>
|
||||
</section>
|
||||
|
||||
<!-- Advanced -->
|
||||
<section class="section" data-section="advanced">
|
||||
<h2>고급</h2>
|
||||
|
||||
@@ -41,6 +41,22 @@
|
||||
const advAutoSteps = $('advAutoSteps');
|
||||
const advCtxSize = $('advCtxSize');
|
||||
|
||||
// ---- Google (Calendar + Sheets) ----
|
||||
const gClientId = $('gClientId');
|
||||
const gClientSecret = $('gClientSecret');
|
||||
const gCalendarId = $('gCalendarId');
|
||||
const gDefaultDur = $('gDefaultDur');
|
||||
const gIcalUrl = $('gIcalUrl');
|
||||
const gIcalDays = $('gIcalDays');
|
||||
const googleConnStatus = $('googleConnStatus');
|
||||
const googleConnStatusInline = $('googleConnStatusInline');
|
||||
const googleConnectBtn = $('googleConnect');
|
||||
const googleDisconnectBtn = $('googleDisconnect');
|
||||
const googleIcalRefreshBtn = $('googleIcalRefresh');
|
||||
const googleIcalStatus = $('googleIcalStatus');
|
||||
const googleFeedback = $('googleFeedback');
|
||||
const googleError = $('googleError');
|
||||
|
||||
// ---- Banner ----
|
||||
const bannerError = $('bannerError');
|
||||
|
||||
@@ -115,6 +131,32 @@
|
||||
document.querySelector('[data-save="advanced.autoSteps"]').addEventListener('click', () =>
|
||||
vscode.postMessage({ type: 'advanced.update', maxAutoSteps: Number(advAutoSteps.value) })
|
||||
);
|
||||
// ---- Google listeners ----
|
||||
document.querySelector('[data-save="google.clientId"]').addEventListener('click', () =>
|
||||
vscode.postMessage({ type: 'google.update', clientId: gClientId.value })
|
||||
);
|
||||
document.querySelector('[data-save="google.clientSecret"]').addEventListener('click', () => {
|
||||
// 저장 후 입력 필드는 비움 — 다음부터는 placeholder 가 "저장됨" 으로 표시됨.
|
||||
vscode.postMessage({ type: 'google.update', clientSecret: gClientSecret.value });
|
||||
gClientSecret.value = '';
|
||||
});
|
||||
document.querySelector('[data-save="google.calendarId"]').addEventListener('click', () =>
|
||||
vscode.postMessage({ type: 'google.update', calendarId: gCalendarId.value })
|
||||
);
|
||||
document.querySelector('[data-save="google.defaultEventDurationMinutes"]').addEventListener('click', () =>
|
||||
vscode.postMessage({ type: 'google.update', defaultEventDurationMinutes: Number(gDefaultDur.value) })
|
||||
);
|
||||
document.querySelector('[data-save="google.icalUrl"]').addEventListener('click', () => {
|
||||
vscode.postMessage({ type: 'google.update', icalUrl: gIcalUrl.value });
|
||||
gIcalUrl.value = '';
|
||||
});
|
||||
document.querySelector('[data-save="google.icalDaysAhead"]').addEventListener('click', () =>
|
||||
vscode.postMessage({ type: 'google.update', icalDaysAhead: Number(gIcalDays.value) })
|
||||
);
|
||||
googleConnectBtn.addEventListener('click', () => vscode.postMessage({ type: 'google.connect' }));
|
||||
googleDisconnectBtn.addEventListener('click', () => vscode.postMessage({ type: 'google.disconnect' }));
|
||||
googleIcalRefreshBtn.addEventListener('click', () => vscode.postMessage({ type: 'google.icalRefresh' }));
|
||||
|
||||
document.querySelector('[data-save="advanced.ctxSize"]').addEventListener('click', () =>
|
||||
vscode.postMessage({ type: 'advanced.update', maxContextSize: Number(advCtxSize.value) })
|
||||
);
|
||||
@@ -264,6 +306,32 @@
|
||||
advMulti.checked = !!adv.multiAgentEnabled;
|
||||
setIfNotFocused(advAutoSteps, adv.maxAutoSteps);
|
||||
setIfNotFocused(advCtxSize, adv.maxContextSize);
|
||||
|
||||
// ---- Google (Calendar + Sheets) ----
|
||||
const g = state.google;
|
||||
if (g) {
|
||||
setIfNotFocused(gClientId, g.clientId);
|
||||
// Secret 은 값 자체를 화면에 안 그림 — 설정 여부만 placeholder 로 표현.
|
||||
gClientSecret.placeholder = g.hasClientSecret ? '••• 저장됨 (덮어쓰려면 새 값 입력)' : 'GOCSPX-...';
|
||||
setIfNotFocused(gCalendarId, g.calendarId);
|
||||
setIfNotFocused(gDefaultDur, g.defaultEventDurationMinutes);
|
||||
gIcalUrl.placeholder = g.hasIcalUrl ? '••• 저장됨 (덮어쓰려면 새 URL 입력)' : 'https://calendar.google.com/calendar/ical/.../basic.ics';
|
||||
setIfNotFocused(gIcalDays, g.icalDaysAhead);
|
||||
// 연결 상태 readout.
|
||||
if (g.connected) {
|
||||
const at = g.connectedAt ? g.connectedAt.slice(0, 16).replace('T', ' ') : '';
|
||||
googleConnStatus.textContent = `✅ 연결됨${g.connectedAs ? ' · ' + g.connectedAs : ''}${at ? ' (' + at + ')' : ''}`;
|
||||
googleConnStatus.style.color = '#10b981';
|
||||
googleDisconnectBtn.disabled = false;
|
||||
} else {
|
||||
googleConnStatus.textContent = '⛔ OAuth 연결 안됨 — Client ID/Secret 저장 후 [OAuth 연결] 클릭';
|
||||
googleConnStatus.style.color = '';
|
||||
googleDisconnectBtn.disabled = true;
|
||||
}
|
||||
googleIcalStatus.textContent = g.lastIcalFetchAt
|
||||
? `마지막 새로고침: ${g.lastIcalFetchAt.slice(0, 16).replace('T', ' ')}`
|
||||
: '';
|
||||
}
|
||||
}
|
||||
|
||||
vscode.postMessage({ type: 'ready' });
|
||||
|
||||
Reference in New Issue
Block a user