mirror of
https://github.com/phishingclub/phishingclub.git
synced 2026-07-09 13:58:25 +02:00
added simple code editor for API sender body
Signed-off-by: Ronni Skansing <rskansing@gmail.com>
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import * as monaco from 'monaco-editor';
|
||||
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
|
||||
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
|
||||
|
||||
export let value = '';
|
||||
export let height = 'medium';
|
||||
export let language = 'json';
|
||||
export let placeholder = '';
|
||||
|
||||
let editor = null;
|
||||
let editorContainer = null;
|
||||
|
||||
const heightClasses = {
|
||||
small: 'h-64',
|
||||
medium: 'h-80',
|
||||
large: 'h-96'
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
self.MonacoEnvironment = {
|
||||
getWorker: function (_, label) {
|
||||
if (label === 'json') {
|
||||
return new jsonWorker();
|
||||
}
|
||||
return new editorWorker();
|
||||
}
|
||||
};
|
||||
|
||||
editor = monaco.editor.create(editorContainer, {
|
||||
value: value || '',
|
||||
language: language,
|
||||
theme: 'vs-dark',
|
||||
automaticLayout: true,
|
||||
minimap: {
|
||||
enabled: false
|
||||
},
|
||||
scrollBeyondLastLine: false,
|
||||
fontSize: 13,
|
||||
lineNumbers: 'on',
|
||||
folding: true,
|
||||
wordWrap: 'on',
|
||||
contextmenu: true,
|
||||
scrollbar: {
|
||||
horizontal: 'hidden'
|
||||
},
|
||||
quickSuggestions: false,
|
||||
parameterHints: {
|
||||
enabled: false
|
||||
},
|
||||
suggestOnTriggerCharacters: false,
|
||||
acceptSuggestionOnEnter: 'off',
|
||||
tabCompletion: 'off',
|
||||
wordBasedSuggestions: 'off'
|
||||
});
|
||||
|
||||
// Update value when editor content changes
|
||||
editor.getModel().onDidChangeContent(() => {
|
||||
value = editor.getValue();
|
||||
});
|
||||
|
||||
return () => {
|
||||
if (editor) {
|
||||
editor.dispose();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// Watch for external value changes
|
||||
$: if (editor && value !== undefined && editor.getValue() !== value) {
|
||||
editor.setValue(value || '');
|
||||
}
|
||||
|
||||
let showExample = false;
|
||||
|
||||
const loadExample = () => {
|
||||
if (editor && placeholder) {
|
||||
editor.setValue(placeholder);
|
||||
value = placeholder;
|
||||
}
|
||||
showExample = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="w-full">
|
||||
<div
|
||||
bind:this={editorContainer}
|
||||
class="border border-gray-300 rounded-md {heightClasses[height]} w-full"
|
||||
></div>
|
||||
{#if placeholder}
|
||||
<div class="mt-2">
|
||||
<button
|
||||
type="button"
|
||||
on:click={() => (showExample = !showExample)}
|
||||
class="text-xs text-blue-600 hover:text-blue-800 underline focus:outline-none"
|
||||
>
|
||||
{showExample ? 'Hide' : 'Show'} example
|
||||
</button>
|
||||
{#if showExample}
|
||||
<div class="mt-2 p-3 bg-gray-50 border border-gray-200 rounded-md">
|
||||
<div class="flex justify-between items-start mb-2">
|
||||
<span class="text-xs font-medium text-gray-700">Example:</span>
|
||||
<button
|
||||
type="button"
|
||||
on:click={loadExample}
|
||||
class="text-xs text-blue-600 hover:text-blue-800 underline"
|
||||
>
|
||||
Load example
|
||||
</button>
|
||||
</div>
|
||||
<pre class="text-xs text-gray-600 whitespace-pre-wrap">{placeholder}</pre>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -30,6 +30,7 @@
|
||||
import { showIsLoading, hideIsLoading } from '$lib/store/loading.js';
|
||||
import TableDropDownEllipsis from '$lib/components/table/TableDropDownEllipsis.svelte';
|
||||
import DeleteAlert from '$lib/components/modal/DeleteAlert.svelte';
|
||||
import SimpleCodeEditor from '$lib/components/editor/SimpleCodeEditor.svelte';
|
||||
|
||||
// services
|
||||
const appStateService = AppStateService.instance;
|
||||
@@ -402,7 +403,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Headers and Body Section -->
|
||||
<div class="mb-6 pt-4 pb-2 border-b border-gray-200 w-full">
|
||||
<div class="mb-6 pt-4 pb-2 w-full">
|
||||
<h3 class="text-base font-medium text-pc-darkblue mb-3">Request Details</h3>
|
||||
<div class="space-y-5">
|
||||
<TextareaField
|
||||
@@ -417,18 +418,25 @@ X-Custom-Header: Hello Friend"
|
||||
toolTipText="Each header should be on a new line in the format 'key: value'"
|
||||
>Request Headers</TextareaField
|
||||
>
|
||||
<TextareaField
|
||||
bind:value={formValues.requestBody}
|
||||
height={'medium'}
|
||||
fullWidth
|
||||
optional
|
||||
placeholder={`{
|
||||
"to": "{.Name}",
|
||||
"from": "{.From}",
|
||||
<div class="flex flex-col py-2 w-full">
|
||||
<div class="flex items-center">
|
||||
<p class="font-bold text-slate-600 py-2">Request Body</p>
|
||||
<div class="bg-gray-100 ml-2 px-2 rounded-md">
|
||||
<p class="text-slate-600 text-xs">optional</p>
|
||||
</div>
|
||||
</div>
|
||||
<SimpleCodeEditor
|
||||
bind:value={formValues.requestBody}
|
||||
height="medium"
|
||||
language="json"
|
||||
placeholder={`{
|
||||
"to": "{{.Name}}",
|
||||
"from": "{{.From}}",
|
||||
"subject": "Important Security Alert",
|
||||
"body": "{.Content}"
|
||||
}`}>Request Body</TextareaField
|
||||
>
|
||||
"body": "{{.Content}}"
|
||||
}`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user