Skip to content

Commit b0ff9c5

Browse files
committed
removed alerts replaced with modal or nothing
1 parent a338fb1 commit b0ff9c5

File tree

6 files changed

+169
-41
lines changed

6 files changed

+169
-41
lines changed

app/static/js/context_manager.js

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,15 @@ function initializeContextUI() {
2323

2424
// Handle new context creation
2525
if (newContextBtn && !newContextBtn.hasAttribute('data-initialized')) {
26-
newContextBtn.addEventListener('click', function() {
27-
const name = prompt('Enter name for new context:');
26+
newContextBtn.addEventListener('click', async function() {
27+
const name = await openContextModal();
2828
if (name && name.trim()) {
2929
const id = name.toLowerCase().replace(/[^a-z0-9]/g, '-');
3030
if (window.workspaceManager?.createContext(id, name.trim())) {
3131
window.workspaceManager?.switchContext(id);
3232
} else {
33-
alert('Context with this ID already exists');
33+
// Silently handle existing context
34+
// Could show error in modal but for now just skip
3435
}
3536
}
3637
});
@@ -41,16 +42,12 @@ function initializeContextUI() {
4142
if (deleteContextBtn && !deleteContextBtn.hasAttribute('data-initialized')) {
4243
deleteContextBtn.addEventListener('click', function() {
4344
if (window.workspaceManager?.currentContextId === 'default') {
44-
alert('Cannot delete the default context');
45+
// Silently return without deleting default context
4546
return;
4647
}
4748

48-
const contexts = window.workspaceManager?.loadContextsList();
49-
const currentName = contexts?.[window.workspaceManager?.currentContextId]?.name || window.workspaceManager?.currentContextId;
50-
51-
if (confirm(`Delete context "${currentName}"? This will remove all associated files.`)) {
52-
window.workspaceManager?.deleteContext(window.workspaceManager?.currentContextId);
53-
}
49+
// Delete context without confirmation
50+
window.workspaceManager?.deleteContext(window.workspaceManager?.currentContextId);
5451
});
5552
deleteContextBtn.setAttribute('data-initialized', 'true');
5653
}

app/static/js/workspace_manager.js

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -463,29 +463,19 @@ class WorkspaceManager {
463463
}
464464

465465
// Include a file (main action for adding files)
466-
includeFile(path, content, skipConfirmation = false) {
466+
includeFile(path, content) {
467467
if (!this.currentState) return false;
468468

469-
if (this.currentState.files[path] && !skipConfirmation) {
470-
if (!confirm(`File "${path}" already exists. Overwrite?`)) {
471-
return false;
472-
}
473-
}
474-
475469
this.currentState.addFile(path, content);
476470
this.saveState(this.currentContextId);
477471
this.render();
478472
return true;
479473
}
480474

481475
// Delete a file
482-
deleteFile(path, skipConfirmation = false) {
476+
deleteFile(path) {
483477
if (!this.currentState) return false;
484478

485-
if (!skipConfirmation && !confirm(`Delete "${path}"?`)) {
486-
return false;
487-
}
488-
489479
this.currentState.deleteFile(path);
490480
this.saveState(this.currentContextId);
491481
this.render();
@@ -516,11 +506,10 @@ class WorkspaceManager {
516506
reset() {
517507
if (!this.currentState) return;
518508

519-
if (confirm('Reset will clear all files. Are you sure?')) {
520-
this.currentState.reset();
521-
this.saveState(this.currentContextId);
522-
this.render();
523-
}
509+
// Reset without confirmation
510+
this.currentState.reset();
511+
this.saveState(this.currentContextId);
512+
this.render();
524513
}
525514
}
526515

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
<!-- Context Creation Modal -->
2+
<div id="context-modal-overlay" class="fixed inset-0 bg-black bg-opacity-50 z-50 hidden">
3+
<div class="flex items-center justify-center min-h-screen p-4" onclick="closeContextModal()">
4+
<div id="context-modal" class="bg-white border-2 border-black shadow-[8px_8px_0px_0px_rgba(0,0,0,1)] p-6 max-w-md w-full" onclick="event.stopPropagation()">
5+
<!-- Modal Header -->
6+
<h2 class="text-xl font-black text-black mb-4">Create new context</h2>
7+
8+
<!-- Modal Body -->
9+
<div class="mb-6">
10+
<label for="context-name-input" class="block text-sm font-bold text-black mb-2">Context name</label>
11+
<input
12+
type="text"
13+
id="context-name-input"
14+
class="w-full px-3 py-2 border-2 border-black focus:outline-none"
15+
placeholder="e.g. My Project"
16+
autocomplete="off"
17+
/>
18+
<div id="context-modal-error" class="text-red-600 text-sm mt-2 hidden"></div>
19+
</div>
20+
21+
<!-- Modal Actions -->
22+
<div class="flex gap-2 justify-end">
23+
<button
24+
onclick="closeContextModal()"
25+
class="px-4 py-2 bg-gray-200 border-2 border-black text-black font-bold shadow-[2px_2px_0px_0px_rgba(0,0,0,1)] hover:shadow-[3px_3px_0px_0px_rgba(0,0,0,1)] hover:translate-x-[-1px] hover:translate-y-[-1px] active:shadow-[1px_1px_0px_0px_rgba(0,0,0,1)] active:translate-x-[1px] active:translate-y-[1px] transition-all">
26+
Cancel
27+
</button>
28+
<button
29+
onclick="submitContextModal()"
30+
class="px-4 py-2 bg-pink-400 border-2 border-black text-black font-bold shadow-[2px_2px_0px_0px_rgba(0,0,0,1)] hover:shadow-[3px_3px_0px_0px_rgba(0,0,0,1)] hover:translate-x-[-1px] hover:translate-y-[-1px] active:shadow-[1px_1px_0px_0px_rgba(0,0,0,1)] active:translate-x-[1px] active:translate-y-[1px] transition-all">
31+
Create
32+
</button>
33+
</div>
34+
</div>
35+
</div>
36+
</div>
37+
38+
<script>
39+
let contextModalCallback = null;
40+
let previousContextFocusElement = null;
41+
42+
function openContextModal() {
43+
const modal = document.getElementById('context-modal-overlay');
44+
const input = document.getElementById('context-name-input');
45+
const error = document.getElementById('context-modal-error');
46+
47+
// Reset any previous callback
48+
if (contextModalCallback) {
49+
contextModalCallback(null);
50+
contextModalCallback = null;
51+
}
52+
53+
// Store the currently focused element
54+
previousContextFocusElement = document.activeElement;
55+
56+
// Reset and show modal
57+
modal.classList.remove('hidden');
58+
error.classList.add('hidden');
59+
error.textContent = '';
60+
input.value = '';
61+
62+
// Focus input
63+
setTimeout(() => {
64+
input.focus();
65+
}, 50);
66+
67+
// Remove any existing event listeners
68+
input.onkeydown = null;
69+
70+
// Handle Enter and Escape keys
71+
input.addEventListener('keydown', (e) => {
72+
if (e.key === 'Enter') {
73+
e.preventDefault();
74+
submitContextModal();
75+
} else if (e.key === 'Escape') {
76+
e.preventDefault();
77+
closeContextModal();
78+
}
79+
});
80+
81+
return new Promise((resolve) => {
82+
contextModalCallback = resolve;
83+
});
84+
}
85+
86+
function closeContextModal() {
87+
const modal = document.getElementById('context-modal-overlay');
88+
modal.classList.add('hidden');
89+
90+
// Restore focus
91+
if (previousContextFocusElement) {
92+
previousContextFocusElement.focus();
93+
}
94+
95+
if (contextModalCallback) {
96+
contextModalCallback(null);
97+
contextModalCallback = null;
98+
}
99+
}
100+
101+
function submitContextModal() {
102+
const input = document.getElementById('context-name-input');
103+
const error = document.getElementById('context-modal-error');
104+
const contextName = input.value.trim();
105+
106+
// Validation
107+
if (!contextName) {
108+
error.textContent = 'Please enter a context name';
109+
error.classList.remove('hidden');
110+
return;
111+
}
112+
113+
// Check for invalid characters (very permissive for context names)
114+
if (contextName.length > 100) {
115+
error.textContent = 'Context name is too long (max 100 characters)';
116+
error.classList.remove('hidden');
117+
return;
118+
}
119+
120+
// Close modal and return result
121+
const modal = document.getElementById('context-modal-overlay');
122+
modal.classList.add('hidden');
123+
124+
// Restore focus
125+
if (previousContextFocusElement) {
126+
previousContextFocusElement.focus();
127+
}
128+
129+
if (contextModalCallback) {
130+
contextModalCallback(contextName);
131+
contextModalCallback = null;
132+
}
133+
}
134+
135+
// Export for global use
136+
window.openContextModal = openContextModal;
137+
window.closeContextModal = closeContextModal;
138+
window.submitContextModal = submitContextModal;
139+
</script>

app/templates/components/quick_actions.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ <h3 class="text-sm font-black text-black mb-2 flex items-center gap-1">
394394
}
395395

396396
// Use includeFile which properly handles saving and rendering
397-
window.workspaceManager.includeFile(result.path, result.content, true);
397+
window.workspaceManager.includeFile(result.path, result.content);
398398
}
399399
} else {
400400
const error = await response.json();
@@ -438,7 +438,7 @@ <h3 class="text-sm font-black text-black mb-2 flex items-center gap-1">
438438
state.setActionItemState('mcps', mcpName, true);
439439
}
440440
// Use includeFile which properly handles saving and rendering
441-
window.workspaceManager.includeFile(result.path, result.content, true);
441+
window.workspaceManager.includeFile(result.path, result.content);
442442
}
443443
} else {
444444
const error = await response.json();
@@ -476,7 +476,7 @@ <h3 class="text-sm font-black text-black mb-2 flex items-center gap-1">
476476
state.setActionItemState('rules', ruleName, true);
477477
}
478478
// Use includeFile which properly handles saving and rendering
479-
window.workspaceManager.includeFile('CLAUDE.md', newContent, true);
479+
window.workspaceManager.includeFile('CLAUDE.md', newContent);
480480
}
481481
} else {
482482
const error = await response.json();

app/templates/components/workspace_actions.html

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -504,18 +504,18 @@ <h4 class="text-sm font-bold text-black mb-2">Actions</h4>
504504
);
505505
agentFiles.forEach(file => {
506506
// Use workspaceManager.deleteFile which triggers render
507-
window.workspaceManager.deleteFile(file, true);
507+
window.workspaceManager.deleteFile(file);
508508
});
509509
} else if (type === 'mcps') {
510510
// Remove MCP config entirely when toggling off MCPs category
511511
if (state.files['.mcp.json']) {
512-
window.workspaceManager.deleteFile('.mcp.json', true);
512+
window.workspaceManager.deleteFile('.mcp.json');
513513
}
514514
} else if (type === 'rules') {
515515
// Remove CLAUDE.md entirely when toggling off Rules category
516516
// (since having an empty CLAUDE.md provides no value)
517517
if (state.files['CLAUDE.md']) {
518-
window.workspaceManager.deleteFile('CLAUDE.md', true);
518+
window.workspaceManager.deleteFile('CLAUDE.md');
519519
}
520520
}
521521
// No need to manually save/render - deleteFile handles it
@@ -624,7 +624,7 @@ <h4 class="text-sm font-bold text-black mb-2">Actions</h4>
624624
}
625625

626626
// Use includeFile which properly handles saving and rendering
627-
window.workspaceManager.includeFile(result.path, result.content, true);
627+
window.workspaceManager.includeFile(result.path, result.content);
628628
}
629629
}
630630
} catch (error) {
@@ -667,7 +667,7 @@ <h4 class="text-sm font-bold text-black mb-2">Actions</h4>
667667
state.setActionItemState('mcps', mcpName, false);
668668
}
669669
// Use includeFile which properly handles saving and rendering
670-
window.workspaceManager.includeFile(result.path, result.content, true);
670+
window.workspaceManager.includeFile(result.path, result.content);
671671
}
672672
}
673673
} catch (error) {
@@ -695,7 +695,7 @@ <h4 class="text-sm font-bold text-black mb-2">Actions</h4>
695695

696696
if (window.workspaceManager) {
697697
// Use includeFile which properly handles saving and rendering
698-
window.workspaceManager.includeFile('CLAUDE.md', newContent, true);
698+
window.workspaceManager.includeFile('CLAUDE.md', newContent);
699699
}
700700
}
701701
} catch (error) {
@@ -725,10 +725,10 @@ <h4 class="text-sm font-bold text-black mb-2">Actions</h4>
725725
// Update the file with cleaned config
726726
const newContent = JSON.stringify(config, null, 2);
727727
// Use includeFile which properly handles saving and rendering
728-
window.workspaceManager.includeFile('.mcp.json', newContent, true);
728+
window.workspaceManager.includeFile('.mcp.json', newContent);
729729
} else {
730730
// No MCPs left, remove the file entirely
731-
window.workspaceManager.deleteFile('.mcp.json', true);
731+
window.workspaceManager.deleteFile('.mcp.json');
732732
}
733733
} catch (e) {
734734
console.error('Error parsing MCP config:', e);
@@ -767,10 +767,10 @@ <h4 class="text-sm font-bold text-black mb-2">Actions</h4>
767767
// Check if file is empty or only whitespace
768768
if (newContent === '' || newContent.match(/^\s*$/)) {
769769
// File is empty, remove it entirely
770-
window.workspaceManager.deleteFile('CLAUDE.md', true);
770+
window.workspaceManager.deleteFile('CLAUDE.md');
771771
} else {
772772
// Use includeFile which properly handles saving and rendering
773-
window.workspaceManager.includeFile('CLAUDE.md', newContent, true);
773+
window.workspaceManager.includeFile('CLAUDE.md', newContent);
774774
}
775775
}
776776
}
@@ -829,7 +829,7 @@ <h4 class="text-sm font-bold text-black mb-2">Actions</h4>
829829
if (filesToRemove.length > 0) {
830830
filesToRemove.forEach(path => {
831831
// Use workspaceManager.deleteFile which triggers render
832-
window.workspaceManager.deleteFile(path, true);
832+
window.workspaceManager.deleteFile(path);
833833
});
834834
// Save state after agent mappings update
835835
window.workspaceManager.saveState(window.workspaceManager.currentContextId);

app/templates/index.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,7 @@
1111

1212
<!-- File Creation Modal -->
1313
{% include 'components/file_modal.html' %}
14+
15+
<!-- Context Creation Modal -->
16+
{% include 'components/context_modal.html' %}
1417
{% endblock %}

0 commit comments

Comments
 (0)