393 lines
25 KiB
HTML
393 lines
25 KiB
HTML
<div>
|
|
<div class="flex space-x-2 p-2 border-b border-gray-200 dark:border-gray-800">
|
|
<div class="">
|
|
{% if is_edit|default(false, true) %}
|
|
<div
|
|
class="inline-flex items-center justify-center space-x-1 h-10 py-2 text-gray-600 dark:text-gray-400 justify-between rounded-md text-md font-medium cursor-pointer">
|
|
<span class="font-mono" id="function-name-label" onclick="toggleInput()">{{ name }}</span>
|
|
<input type="text" id="function-name"
|
|
class="hidden bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-1.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 max-w-fit"
|
|
placeholder="foo" required="" value="{{ name }}">
|
|
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
|
stroke="currentColor" class="w-5 h-5" onclick="toggleInput()">
|
|
<path stroke-linecap="round" stroke-linejoin="round"
|
|
d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0 1 15.75 21H5.25A2.25 2.25 0 0 1 3 18.75V8.25A2.25 2.25 0 0 1 5.25 6H10">
|
|
</path>
|
|
</svg>
|
|
|
|
<span class="bg-blue-500 text-white text-xs font-semibold px-2 py-1 rounded ml-2">
|
|
v{{ version_number }}
|
|
</span>
|
|
|
|
</div>
|
|
<script>
|
|
function toggleInput() {
|
|
const textLabel = document.getElementById('function-name-label');
|
|
const textInput = document.getElementById('function-name');
|
|
|
|
if (textLabel.style.display === 'none') {
|
|
textLabel.style.display = 'inline';
|
|
textInput.style.display = 'none';
|
|
textLabel.innerText = textInput.value;
|
|
} else {
|
|
textLabel.style.display = 'none';
|
|
textInput.style.display = 'inline';
|
|
textInput.focus();
|
|
}
|
|
}
|
|
</script>
|
|
{% endif %}
|
|
|
|
{% if is_add|default(false, true) %}
|
|
<label for="function-name" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Function
|
|
name</label>
|
|
<input type="text" id="function-name"
|
|
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
|
placeholder="foo" required="" value="{{ name }}" />
|
|
{% endif %}
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div id="editor" class="relative rounded-lg shadow-lg p-4 text-opacity-0">{{ script }}</div>
|
|
<script>
|
|
var editor = ace.edit("editor");
|
|
editor.setOptions({
|
|
maxLines: 100
|
|
});
|
|
editor.setTheme("ace/theme/github_dark");
|
|
editor.session.setMode("ace/mode/javascript");
|
|
|
|
editor.session.$worker.send("changeOptions", [{ asi: true }]);
|
|
</script>
|
|
|
|
|
|
<div class="flex space-x-2 border-b border-gray-200 dark:border-gray-800 justify-between">
|
|
<button
|
|
class="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 hover:bg-accent hover:text-accent-foreground h-10 px-4 py-2 text-gray-600 dark:text-gray-400 justify-between">
|
|
<span class="sr-only" data-id="4">Bold</span>
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
|
stroke="currentColor" class="w-4 h-4" data-darkreader-inline-stroke=""
|
|
style="--darkreader-inline-stroke: currentColor;">
|
|
<path stroke-linecap="round" stroke-linejoin="round"
|
|
d="M20.25 6.375c0 2.278-3.694 4.125-8.25 4.125S3.75 8.653 3.75 6.375m16.5 0c0-2.278-3.694-4.125-8.25-4.125S3.75 4.097 3.75 6.375m16.5 0v11.25c0 2.278-3.694 4.125-8.25 4.125s-8.25-1.847-8.25-4.125V6.375m16.5 0v3.75m-16.5-3.75v3.75m16.5 0v3.75C20.25 16.153 16.556 18 12 18s-8.25-1.847-8.25-4.125v-3.75m16.5 0c0 2.278-3.694 4.125-8.25 4.125s-8.25-1.847-8.25-4.125">
|
|
</path>
|
|
</svg>
|
|
|
|
<span class="ml-1">Environment</span>
|
|
</button>
|
|
|
|
<!-- Spacer Div -->
|
|
<div class="flex-auto"></div>
|
|
|
|
</div>
|
|
|
|
<div id="editor-environment" class="relative rounded-lg shadow-lg p-4 mb-2 text-opacity-0">{{ environment_info }}
|
|
</div>
|
|
<script>
|
|
var editor_environment = ace.edit("editor-environment");
|
|
editor_environment.setOptions({
|
|
maxLines: 100
|
|
});
|
|
editor_environment.setTheme("ace/theme/github_dark");
|
|
editor_environment.session.setMode("ace/mode/json");
|
|
</script>
|
|
|
|
{% if is_add|default(false, true) or is_edit|default(false, true) %}
|
|
<div class="flex">
|
|
|
|
<div class="inline-flex items-center">
|
|
<label class="relative flex items-center p-3 rounded-full cursor-pointer" htmlFor="is_public">
|
|
<input type="checkbox"
|
|
class="before:content[''] peer relative h-5 w-5 cursor-pointer appearance-none rounded-md border border-blue-gray-200 transition-all before:absolute before:top-2/4 before:left-2/4 before:block before:h-12 before:w-12 before:-translate-y-2/4 before:-translate-x-2/4 before:rounded-full before:bg-blue-gray-500 before:opacity-0 before:transition-opacity checked:border-gray-900 checked:bg-gray-900 checked:before:bg-gray-900 hover:before:opacity-10"
|
|
id="is_public" {% if is_public|default(false, true) %} checked {% endif %} />
|
|
<span
|
|
class="absolute text-white transition-opacity opacity-0 pointer-events-none top-2/4 left-2/4 -translate-y-2/4 -translate-x-2/4 peer-checked:opacity-100">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" viewBox="0 0 20 20" fill="currentColor"
|
|
stroke="currentColor" stroke-width="1">
|
|
<path fill-rule="evenodd"
|
|
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
|
|
clip-rule="evenodd"></path>
|
|
</svg>
|
|
</span>
|
|
</label>
|
|
<label class="mt-px font-light text-gray-200 cursor-pointer select-none" htmlFor="is_public">
|
|
Public
|
|
</label>
|
|
</div>
|
|
|
|
<div class="inline-flex items-center">
|
|
<label class="relative flex items-center p-3 rounded-full cursor-pointer" htmlFor="log_request">
|
|
<input type="checkbox"
|
|
class="before:content[''] peer relative h-5 w-5 cursor-pointer appearance-none rounded-md border border-blue-gray-200 transition-all before:absolute before:top-2/4 before:left-2/4 before:block before:h-12 before:w-12 before:-translate-y-2/4 before:-translate-x-2/4 before:rounded-full before:bg-blue-gray-500 before:opacity-0 before:transition-opacity checked:border-gray-900 checked:bg-gray-900 checked:before:bg-gray-900 hover:before:opacity-10"
|
|
id="log_request" {% if log_request|default(false, true) %} checked {% endif %} />
|
|
<span
|
|
class="absolute text-white transition-opacity opacity-0 pointer-events-none top-2/4 left-2/4 -translate-y-2/4 -translate-x-2/4 peer-checked:opacity-100">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" viewBox="0 0 20 20" fill="currentColor"
|
|
stroke="currentColor" stroke-width="1">
|
|
<path fill-rule="evenodd"
|
|
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
|
|
clip-rule="evenodd"></path>
|
|
</svg>
|
|
</span>
|
|
</label>
|
|
<label class="mt-px font-light text-gray-200 cursor-pointer select-none" htmlFor="log_request">
|
|
Log Request
|
|
</label>
|
|
</div>
|
|
|
|
<div class="inline-flex items-center">
|
|
<label class="relative flex items-center p-3 rounded-full cursor-pointer" htmlFor="log_response">
|
|
<input type="checkbox"
|
|
class="before:content[''] peer relative h-5 w-5 cursor-pointer appearance-none rounded-md border border-blue-gray-200 transition-all before:absolute before:top-2/4 before:left-2/4 before:block before:h-12 before:w-12 before:-translate-y-2/4 before:-translate-x-2/4 before:rounded-full before:bg-blue-gray-500 before:opacity-0 before:transition-opacity checked:border-gray-900 checked:bg-gray-900 checked:before:bg-gray-900 hover:before:opacity-10"
|
|
id="log_response" {% if log_response|default(false, true) %} checked {% endif %} />
|
|
<span
|
|
class="absolute text-white transition-opacity opacity-0 pointer-events-none top-2/4 left-2/4 -translate-y-2/4 -translate-x-2/4 peer-checked:opacity-100">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" viewBox="0 0 20 20" fill="currentColor"
|
|
stroke="currentColor" stroke-width="1">
|
|
<path fill-rule="evenodd"
|
|
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
|
|
clip-rule="evenodd"></path>
|
|
</svg>
|
|
</span>
|
|
</label>
|
|
<label class="mt-px font-light text-gray-200 cursor-pointer select-none" htmlFor="log_response">
|
|
Log Response
|
|
</label>
|
|
</div>
|
|
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="flex">
|
|
<button
|
|
class="bg-transparent hover:bg-green-500 text-green-700 font-semibold hover:text-white py-2 px-4 border border-green-500 hover:border-transparent rounded flex mr-2 items-center"
|
|
id="execute-code-btn">
|
|
<span class="sr-only" data-id="4">Bold</span>
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
|
stroke="currentColor" class="w-4 h-4" data-darkreader-inline-stroke=""
|
|
style="--darkreader-inline-stroke: currentColor;">
|
|
<path stroke-linecap="round" stroke-linejoin="round"
|
|
d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.348a1.125 1.125 0 010 1.971l-11.54 6.347a1.125 1.125 0 01-1.667-.985V5.653z">
|
|
</path>
|
|
</svg>
|
|
<span class="ml-1">Execute</span>
|
|
</button>
|
|
<script>
|
|
document.getElementById('execute-code-btn').addEventListener('click', () => {
|
|
try {
|
|
var code = editor.getValue();
|
|
// Define the request object (modify as needed)
|
|
var requestObject = {
|
|
};
|
|
var environment_info = editor_environment.getValue().trim();
|
|
|
|
var startTime = Date.now(); // Start timing
|
|
|
|
// Send the code and request object to the server
|
|
fetch("{{ url_for('execute_code', playground='true') }}", {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ code: code, request: requestObject, environment_info }),
|
|
})
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
return response.text();
|
|
})
|
|
.then(text => {
|
|
try {
|
|
var endTime = Date.now(); // End timing
|
|
|
|
const data = JSON.parse(text); // Try to parse the response as JSON
|
|
|
|
const output_el = document.querySelector('#output')
|
|
|
|
let output_html =
|
|
`<div class="mt-2 p-1 rounded-md bg-gray-200">
|
|
<div class="flex justify-between items-center">
|
|
<div class="flex space-x-2 text-sm font-medium text-gray-600 ml-2 py-1">
|
|
<div class="flex items-center space-x-1 cursor-pointer border-blue-400" id="response-logs-button" onclick="document.querySelector('#response-logs-button').classList.add('border-b-2','text-blue-400');document.querySelector('#browser-preview-button').classList.remove('border-b-2','text-blue-400');document.querySelector('#browser-preview').classList.add('hidden');document.querySelector('#response-logs').classList.remove('hidden');">
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12H12m-8.25 5.25h16.5"></path>
|
|
</svg>
|
|
<span class="">Logs ${data.logs ? `<span class="text-sm text-gray-400">(${data.logs.length})</span>` : ''}</span>
|
|
</div>
|
|
<div class="flex items-center space-x-1 cursor-pointer border-b-2 text-blue-400 border-blue-400" id="browser-preview-button" onclick="this.classList.add('border-b-2','text-blue-400');document.querySelector('#response-logs-button').classList.remove('border-b-2','text-blue-400');document.querySelector('#browser-preview').classList.remove('hidden');document.querySelector('#response-logs').classList.add('hidden');">
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z"></path>
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"></path>
|
|
</svg>
|
|
<span class="">Browser Preview</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="cursor-pointer text-gray-600 rounded-md hover:bg-gray-300" onclick="document.querySelector('#output').innerHTML = '' ">
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12"></path>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
<div class="p-1">
|
|
<div id="browser-preview" class="min-h-10 h-full rounded-md bg-white p-2 ${data.status != 'SUCCESS' ? 'border-red-700 border-2' : ''}">${data.status == 'SUCCESS' ? data.result.body : data.result}</div>
|
|
<div id="response-logs" class="hidden text-sm font-mono">
|
|
${data.logs ? data.logs.map(log =>
|
|
`<div class="flex items-center break-words">
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" />
|
|
</svg>
|
|
<span>${log}</span>
|
|
</div>`).join('\n') : ''}
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-end">
|
|
<div class="text-sm font-medium text-gray-600">
|
|
Status: <span class='${data.status == 'SUCCESS' ? 'text-green-600' : 'text-red-700'}'>${data?.result?.status || "Error"}</span>
|
|
<span>Time: </span><span class="text-green-600">${endTime - startTime}ms</span>
|
|
</div>
|
|
</div>
|
|
</div>`
|
|
|
|
output_el.innerHTML = output_html;
|
|
} catch (err) {
|
|
document.getElementById('output').innerHTML = text;
|
|
}
|
|
})
|
|
.catch(error => {
|
|
document.getElementById('output').textContent = 'Error: ' + error.message;
|
|
});
|
|
|
|
} catch (e) {
|
|
document.getElementById('output').innerHTML = 'Error: ' + e.message;
|
|
}
|
|
});
|
|
</script>
|
|
|
|
|
|
{% if is_edit|default(false, true) %}
|
|
<button
|
|
class="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded flex mr-2 items-center"
|
|
id="edit-http-function">
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
|
stroke="currentColor" class="w-4 h-4 mr-2">
|
|
<path stroke-linecap="round" stroke-linejoin="round"
|
|
d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5m-13.5-9L12 3m0 0l4.5 4.5M12 3v13.5" />
|
|
</svg>
|
|
|
|
<p> Update</p>
|
|
</button>
|
|
<button
|
|
class="bg-transparent hover:bg-red-500 text-red-700 font-semibold hover:text-white py-2 px-4 border border-red-500 hover:border-transparent rounded flex mr-2 items-center"
|
|
hx-delete="{{ url_for('delete_http_function', function_id=function_id) }}" hx-target="#container"
|
|
hx-swap="innerHTML" hx-confirm="Are you sure you want to delete {{ name }}?" hx-push-url="true">
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
|
stroke="currentColor" class="w-4 h-4 mr-2">
|
|
<path stroke-linecap="round" stroke-linejoin="round"
|
|
d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" />
|
|
</svg>
|
|
|
|
<span>Delete</span>
|
|
</button>
|
|
<script>
|
|
document.querySelector('#edit-http-function').addEventListener('click', () => {
|
|
let name = document.querySelector('#function-name').value;
|
|
let script_content = editor.getValue().trim();
|
|
let environment_info = editor_environment.getValue().trim();
|
|
let is_public = document.querySelector('#is_public').checked
|
|
let log_request = document.querySelector('#log_request').checked
|
|
let log_response = document.querySelector('#log_response').checked
|
|
|
|
fetch("{{ url_for('edit_http_function', function_id=function_id) }}", {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({ name, script_content, environment_info, is_public, log_request, log_response }),
|
|
})
|
|
.then(response => response.json())
|
|
.then(json => {
|
|
htmx.ajax('GET', "{{ url_for('get_http_function_edit_form', function_id=function_id) }}", {
|
|
target: '#container',
|
|
swap: 'innerHTML'
|
|
});
|
|
showAlert(json.message, json.status)
|
|
})
|
|
})
|
|
</script>
|
|
{% endif %}
|
|
|
|
{% if is_add|default(false, true) %}
|
|
<button
|
|
class="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded flex"
|
|
id="add-http-function">
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
|
stroke="currentColor" class="w-6 h-6 mr-2" data-darkreader-inline-stroke=""
|
|
style="--darkreader-inline-stroke: currentColor;">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15"></path>
|
|
</svg>
|
|
|
|
<p> Add</p>
|
|
</button>
|
|
<script>
|
|
document.querySelector('#add-http-function').addEventListener('click', () => {
|
|
let name = document.querySelector('#function-name').value;
|
|
let script_content = editor.getValue().trim();
|
|
let environment_info = editor_environment.getValue().trim();
|
|
let is_public = document.querySelector('#is_public').checked
|
|
let log_request = document.querySelector('#log_request').checked
|
|
let log_response = document.querySelector('#log_response').checked
|
|
|
|
htmx.ajax('POST', "{{ url_for('create_http_function') }}", {
|
|
target: '#container',
|
|
swap: 'innerHTML',
|
|
values: { name, script_content, environment_info, is_public, log_request, log_response }
|
|
});
|
|
|
|
|
|
})
|
|
</script>
|
|
{% endif %}
|
|
|
|
</div>
|
|
|
|
<div id="output" class="">
|
|
<!-- Execution results will appear here -->
|
|
</div>
|
|
|
|
<script>
|
|
function showAlert(message, type = 'success', duration = 1500) {
|
|
// Create a new div element
|
|
var alertContainerDiv = document.createElement('div');
|
|
|
|
// Add the required classes to the alertContainerDiv
|
|
alertContainerDiv.classList.add('fixed', 'top-10', 'right-10', 'z-50');
|
|
|
|
// Append the new div to the body of the document
|
|
document.body.appendChild(alertContainerDiv);
|
|
|
|
const alertContainer = document.getElementById('alert-container');
|
|
const alertDiv = document.createElement('div');
|
|
|
|
const icon = type === 'success'
|
|
? '<svg class="w-6 h-6 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>' // SVG for success icon
|
|
: '<svg class="w-6 h-6 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01"></path></svg>'; // SVG for error icon
|
|
|
|
const baseClasses = "flex items-center p-4 mb-4 text-sm text-white rounded-lg shadow-md transition-opacity duration-300";
|
|
alertDiv.className = `${baseClasses} ${type === 'success' ? 'bg-green-400' : 'bg-red-400'}`;
|
|
alertDiv.innerHTML = `${icon}<span class="ml-3">${message}</span>`;
|
|
|
|
// Append alert div to the container
|
|
alertContainerDiv.appendChild(alertDiv);
|
|
|
|
// Remove the alert after 'duration' milliseconds
|
|
setTimeout(() => {
|
|
alertDiv.style.opacity = '0';
|
|
setTimeout(() => alertContainerDiv.parentElement.removeChild(alertContainerDiv), 300);
|
|
}, duration);
|
|
}
|
|
</script>
|
|
|
|
</div> |