Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions src/assets/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -1450,6 +1450,58 @@ body.config {
transition: color var(--transition-speed) ease;
}

.editor-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}

.label-with-copy {
display: flex;
align-items: center;
gap: 8px;
}

.copy-icon-button {
background: none;
border: none;
cursor: pointer;
padding: 2px;
color: var(--text-secondary);
opacity: 0.7;
transition: all var(--transition-speed) ease;
border-radius: 3px;
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 20px;
height: 20px;
}

.copy-icon-button svg {
width: 16px;
height: 16px;
stroke: currentColor;
}

.copy-icon-button:hover:not(:disabled) {
opacity: 1;
color: var(--text-primary);
background: var(--bg-hover);
transform: scale(1.1);
}

.copy-icon-button:disabled {
opacity: 0.3;
cursor: not-allowed;
}

.copy-icon-button:focus-visible {
outline: 2px solid var(--input-focus-border);
outline-offset: 1px;
}

.code-editor {
width: 100%;
height: 400px;
Expand Down
103 changes: 101 additions & 2 deletions src/components/Rules.vue
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,30 @@
<div class="rule-editor">
<div class="editor-panel">
<div class="editor-header">
<label for="detectEditor">Detect Logic</label>
<div class="label-with-copy">
<label for="detectEditor">Detect Logic</label>
<button
class="copy-icon-button"
title="Copy detect logic to clipboard"
:disabled="!currentRule.detectLogic.trim()"
@click="copyDetectLogicToClipboard"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<rect width="14" height="14" x="8" y="8" rx="2" ry="2"></rect>
<path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path>
</svg>
</button>
</div>
</div>
<textarea
id="detectEditor"
Expand All @@ -81,7 +104,30 @@
</div>
<div class="editor-panel">
<div class="editor-header">
<label for="respondEditor">Respond Logic</label>
<div class="label-with-copy">
<label for="respondEditor">Respond Logic</label>
<button
class="copy-icon-button"
title="Copy respond logic to clipboard"
:disabled="!currentRule.respondLogic.trim()"
@click="copyRespondLogicToClipboard"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<rect width="14" height="14" x="8" y="8" rx="2" ry="2"></rect>
<path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path>
</svg>
</button>
</div>
<div v-if="hasUnsavedChanges" class="draft-indicator-inline">
<span class="draft-badge">πŸ“ Unsaved Changes</span>
</div>
Expand Down Expand Up @@ -5557,6 +5603,59 @@ async function copyFieldPathToClipboard(fieldPath: string) {
}
}

// Clipboard functions for rule logic
async function copyDetectLogicToClipboard() {
if (!currentRule.detectLogic.trim()) {
appStore.addNotification('warning', 'No detect logic to copy')
return
}

try {
await navigator.clipboard.writeText(currentRule.detectLogic)
appStore.addNotification('success', 'Detect logic copied to clipboard')
} catch (error) {
// Fallback for browsers that don't support clipboard API
try {
const textArea = document.createElement('textarea')
textArea.value = currentRule.detectLogic
document.body.appendChild(textArea)
textArea.select()
document.execCommand('copy')
document.body.removeChild(textArea)
appStore.addNotification('success', 'Detect logic copied to clipboard')
} catch (_fallbackError) {
appStore.addNotification('error', 'Failed to copy detect logic to clipboard')
logger.error('Clipboard error:', error)
}
}
}

async function copyRespondLogicToClipboard() {
if (!currentRule.respondLogic.trim()) {
appStore.addNotification('warning', 'No respond logic to copy')
return
}

try {
await navigator.clipboard.writeText(currentRule.respondLogic)
appStore.addNotification('success', 'Respond logic copied to clipboard')
} catch (error) {
// Fallback for browsers that don't support clipboard API
try {
const textArea = document.createElement('textarea')
textArea.value = currentRule.respondLogic
document.body.appendChild(textArea)
textArea.select()
document.execCommand('copy')
document.body.removeChild(textArea)
appStore.addNotification('success', 'Respond logic copied to clipboard')
} catch (_fallbackError) {
appStore.addNotification('error', 'Failed to copy respond logic to clipboard')
logger.error('Clipboard error:', error)
}
}
}

// Import from IaC functionality
function clearIaCImport() {
iacImportContent.value = ''
Expand Down