diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 75372a2..2679791 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -35,6 +35,7 @@ const auditMode = ref("all"); const tokens = ref([]); const newToken = ref(null); +const showCreateModal = ref(false); const showDeleteConfirm = ref(false); const editing = ref(false); const editFields = ref(false); @@ -58,10 +59,11 @@ tags: "", allow_ui: true, allow_rest_api: true, - allow_mcp: false, - fieldsText: "username=\npassword=*" + allow_mcp: false }); +const formFields = ref(defaultCreateFields()); + const editForm = reactive({ title: "", purpose: "", @@ -92,10 +94,7 @@ ); const activeSecrets = computed(() => secrets.value.filter((secret) => !secret.archived).length); const mcpSecrets = computed(() => secrets.value.filter((secret) => secret.allow_mcp).length); - -function parseFields() { - return parseFieldsText(form.fieldsText); -} +const canCreateSecret = computed(() => Boolean(form.title.trim() && parseCreateFields().length)); function parseFieldsText(value) { return value @@ -117,6 +116,60 @@ .filter(Boolean); } +function defaultCreateFields() { + return [ + { id: crypto.randomUUID(), name: "username", value: "", encrypted: false }, + { id: crypto.randomUUID(), name: "password", value: "", encrypted: true } + ]; +} + +function openCreateModal() { + showCreateModal.value = true; +} + +function addCreateField() { + formFields.value.push({ + id: crypto.randomUUID(), + name: "", + value: "", + encrypted: true + }); +} + +function removeCreateField(index) { + if (formFields.value.length === 1) return; + formFields.value.splice(index, 1); +} + +function parseCreateFields() { + return formFields.value + .map((field, index) => { + const name = field.name.trim(); + if (!name) return null; + return { + name, + value: field.value, + encrypted: Boolean(field.encrypted), + masked: Boolean(field.encrypted), + position: index + }; + }) + .filter(Boolean); +} + +function resetCreateForm() { + form.title = ""; + form.purpose = ""; + form.category = ""; + form.source = ""; + form.notes = ""; + form.tags = ""; + form.allow_ui = true; + form.allow_rest_api = true; + form.allow_mcp = false; + formFields.value = defaultCreateFields(); +} + function serializeFields(fields) { return fields .map((field) => `${field.name}=${field.encrypted ? "*" : ""}${field.value || ""}`) @@ -170,6 +223,7 @@ } async function createSecret() { + const fields = parseCreateFields(); await api.createSecret({ title: form.title, purpose: form.purpose || null, @@ -180,14 +234,10 @@ allow_ui: form.allow_ui, allow_rest_api: form.allow_rest_api, allow_mcp: form.allow_mcp, - fields: parseFields() + fields }); - form.title = ""; - form.purpose = ""; - form.category = ""; - form.source = ""; - form.notes = ""; - form.tags = ""; + resetCreateForm(); + showCreateModal.value = false; await loadSecrets(); } @@ -425,7 +475,15 @@
{{ error }}