Skip to content
Merged
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
11 changes: 7 additions & 4 deletions app/components/data-stores/create/DataStoreHelpPanel.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<script setup lang="ts">
<script lang="ts" setup>
import Panel from "primevue/panel";

defineProps<{ header: string }>();
Expand All @@ -11,16 +11,19 @@ const emit = defineEmits(["closeHelp"]);
<slot />
<template #icons>
<Button
v-tooltip.top="'Close help box'"
:size="'small'"
aria-label="Close help box"
class="p-panel-header-icon p-link mr-2 help-box-close-btn"
icon="pi pi-times"
rounded
severity="contrast"
v-tooltip.top="'Close help box'"
aria-label="Close help box"
variant="text"
@click="emit('closeHelp')"
/>
</template>
</Panel>
</div>
</template>

<style scoped lang="scss"></style>
<style lang="scss" scoped></style>
78 changes: 55 additions & 23 deletions app/components/data-stores/create/DataStoreProjectInitializer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,9 @@ import InputNumber from "primevue/inputnumber";
import InputGroupAddon from "primevue/inputgroupaddon";
import InputGroup from "primevue/inputgroup";
import DataStoreHelpBox from "~/components/data-stores/create/DataStoreHelpBox.vue";
import {
type AvailableProject,
HelpTextField,
} from "~/components/data-stores/create/index";
import { type AvailableProject, HelpTextField } from "~/components/data-stores/create/index";
import { useToast } from "primevue/usetoast";
import {
type BodyKongInitializeKongInitializePost,
DataStoreType,
type ProjectNode,
} from "~/services/Api";
import { type BodyKongInitializeKongInitializePost, DataStoreType, type ProjectNode } from "~/services/Api";
import { getProjectNodes } from "~/composables/useAPIFetch";

const loading = ref(false);
Expand Down Expand Up @@ -70,8 +63,8 @@ const dataStoreSettingsMap: Map<string, string> = new Map([
["path", "Data path or bucket name"],
["port", "Port"],
["protocol", "Connection protocol"],
["minio_access_key", "MinIO access key"],
["minio_secret_key", "MinIO secret key"],
["minio_access_key", "S3 access key"],
["minio_secret_key", "S3 secret key"],
]);

// Datastore settings
Expand Down Expand Up @@ -108,12 +101,6 @@ if (typeof preselectedProjectId === "string") {
);
}

watch(selectedDataStoreType, (newDataStoreType) => {
if (newDataStoreType === DataStoreType.S3) {
port.value = 9000;
}
});

function activateHelp(helpField: HelpTextField) {
helpActive.value = helpActive.value === helpField ? undefined : helpField;
}
Expand All @@ -126,6 +113,16 @@ function validatePath(path: string) {
return path.startsWith("/") ? path : `/${path}`;
}

function autofillFields(
afDatastoreType: DataStoreType,
afHostname: string,
afPort: number,
) {
selectedDataStoreType.value = afDatastoreType;
host.value = afHostname;
port.value = afPort;
}

function verifyValuesFilled(settings: object): boolean {
for (const key in settings) {
if (!settings[key]) {
Expand Down Expand Up @@ -235,6 +232,36 @@ async function onSubmitCreateDataStoreAndProject() {
column.
</p>
</div>
<div class="ds-autofill-btns">
<Button
:loading="loading"
:size="'small'"
class="ds-autofill-btn"
label="Autofill FHIR"
outlined
rounded
severity="warn"
@click="
autofillFields(DataStoreType.Fhir, 'node-datastore-blaze', 80)
"
/>
<Button
:loading="loading"
:size="'small'"
class="ds-autofill-btn"
label="Autofill S3"
outlined
rounded
severity="info"
@click="
autofillFields(
DataStoreType.S3,
'node-datastore-seaweedfs-all-in-one',
8333,
)
"
/>
</div>
<div class="data-store-panel">
<div class="data-store-input-fields">
<InputGroup
Expand Down Expand Up @@ -285,9 +312,9 @@ async function onSubmitCreateDataStoreAndProject() {
<Select
v-model="selectedDataStoreType"
:options="dataStoreTypeOptions"
class="data-store-type-picker"
optionLabel="label"
optionValue="value"
class="data-store-type-picker"
/>
</InputGroup>
<div
Expand Down Expand Up @@ -335,22 +362,22 @@ async function onSubmitCreateDataStoreAndProject() {
<div class="flex items-center gap-2">
<RadioButton
v-model="selectedBucketAccessPolicy"
class="bucket-access-policy-radio-btn-private"
inputId="private"
name="accessPolicy"
value="Private"
size="small"
class="bucket-access-policy-radio-btn-private"
value="Private"
/>
<label for="private">Private</label>
</div>
<div class="flex items-center gap-2">
<RadioButton
v-model="selectedBucketAccessPolicy"
class="bucket-access-policy-radio-btn-public"
inputId="public"
name="accessPolicy"
value="Public"
size="small"
class="bucket-access-policy-radio-btn-public"
value="Public"
/>
<label for="public">Public</label>
</div>
Expand Down Expand Up @@ -461,8 +488,8 @@ async function onSubmitCreateDataStoreAndProject() {
</InputGroupAddon>
<InputNumber
v-model="port"
:useGrouping="false"
:invalid="port < 0 || port > 65535"
:useGrouping="false"
placeholder="Port e.g. 443"
/>
</InputGroup>
Expand Down Expand Up @@ -536,6 +563,11 @@ async function onSubmitCreateDataStoreAndProject() {
width: 100%;
}

.ds-autofill-btns {
display: flex;
gap: 0.6rem;
margin-bottom: 1rem;
}
.data-store-input-fields {
width: 80%;
margin-right: 24px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,4 +310,74 @@ describe("DataStoreProjectInitializer.vue", () => {

localWrapper.unmount();
});

describe("Autofill buttons", () => {
it("renders Autofill FHIR and Autofill S3 buttons", () => {
const buttons = wrapper.findAll(".ds-autofill-btn");
expect(buttons).toHaveLength(2);
expect(buttons[0]!.text()).toBe("Autofill FHIR");
expect(buttons[1]!.text()).toBe("Autofill S3");
});

it("Autofill FHIR populates hostname, port, and type with FHIR defaults", async () => {
const fhirBtn = wrapper
.findAll(".ds-autofill-btn")
.find((btn) => btn.text() === "Autofill FHIR");
await fhirBtn!.trigger("click");
await innerVm().$nextTick();

expect(innerVm().selectedDataStoreType).toBe(DataStoreType.Fhir);
expect(innerVm().host).toBe("node-datastore-blaze");
expect(innerVm().port).toBe(80);
});

it("Autofill FHIR shows the FHIR data path field", async () => {
const fhirBtn = wrapper
.findAll(".ds-autofill-btn")
.find((btn) => btn.text() === "Autofill FHIR");
await fhirBtn!.trigger("click");
await innerVm().$nextTick();

expect(wrapper.find(".data-store-path-input-fhir").exists()).toBe(true);
expect(wrapper.find(".s3-name-fields").exists()).toBe(false);
});

it("Autofill S3 populates hostname, port, and type with S3 defaults", async () => {
const s3Btn = wrapper
.findAll(".ds-autofill-btn")
.find((btn) => btn.text() === "Autofill S3");
await s3Btn!.trigger("click");
await innerVm().$nextTick();

expect(innerVm().selectedDataStoreType).toBe(DataStoreType.S3);
expect(innerVm().host).toBe("node-datastore-seaweedfs-all-in-one");
expect(innerVm().port).toBe(8333);
});

it("Autofill S3 shows the S3 bucket fields", async () => {
const s3Btn = wrapper
.findAll(".ds-autofill-btn")
.find((btn) => btn.text() === "Autofill S3");
await s3Btn!.trigger("click");
await innerVm().$nextTick();

expect(wrapper.find(".s3-name-fields").exists()).toBe(true);
expect(wrapper.find(".data-store-path-input-fhir").exists()).toBe(false);
});

it("Autofill FHIR switches back to FHIR after S3 was selected", async () => {
const [fhirBtn, s3Btn] = wrapper.findAll(".ds-autofill-btn");
await s3Btn!.trigger("click");
await innerVm().$nextTick();
expect(innerVm().selectedDataStoreType).toBe(DataStoreType.S3);

await fhirBtn!.trigger("click");
await innerVm().$nextTick();

expect(innerVm().selectedDataStoreType).toBe(DataStoreType.Fhir);
expect(innerVm().host).toBe("node-datastore-blaze");
expect(innerVm().port).toBe(80);
expect(wrapper.find(".data-store-path-input-fhir").exists()).toBe(true);
});
});
});
Loading