Skip to content

Commit

Permalink
feat(configs): let users create new configs
Browse files Browse the repository at this point in the history
Closes #73

Signed-off-by: Lukas Mertens <[email protected]>

commit-id:68e323f6
  • Loading branch information
lukas-mertens committed Apr 15, 2024
1 parent 680c64e commit 585706e
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 12 deletions.
4 changes: 3 additions & 1 deletion cypress/e2e/module-selection.cy.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2020 - 2024 Pionix GmbH and Contributors to EVerest

import {faker} from "@faker-js/faker";

describe('Module Selection', () => {
it('should be possible to search for EvseManager', () => {
cy.connectToSimulator();
cy.get('[data-cy="modules-expansion-panel"]').click();
cy.createConfig(faker.word.words(1));
cy.get('[data-cy="modules-search"]').type("EvseManager");
cy.get('[data-cy="module-list-item"]').contains("EvseManager").should('be.visible');
cy.get('[data-cy="modules-search"]').type("{selectall}{backspace}LoremIpsumDolorModule");
Expand Down
9 changes: 8 additions & 1 deletion cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ declare global {
namespace Cypress {
interface Chainable {
connectToSimulator(): Chainable<void>;
createConfig(name: string): Chainable<void>;
}
}
}
Expand All @@ -15,4 +16,10 @@ Cypress.Commands.add('connectToSimulator', () => {
cy.visit('/');
cy.get('[data-cy="server-list-item').contains('Simulator').click();
cy.get('[data-cy="hamburger-menu"]').should('be.visible');
})
});

Cypress.Commands.add('createConfig', (name) => {
cy.get('[data-cy="plus-create-config-btn"]').click();
cy.get('[data-cy="config-name-input"]').type(name);
cy.get('[data-cy="accept-create-config-btn"]').click();
});
107 changes: 107 additions & 0 deletions src/components/CreateConfig.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<!-- SPDX-License-Identifier: Apache-2.0 -->
<!-- Copyright 2020 - 2024 Pionix GmbH and Contributors to EVerest -->

<template>
<div class="btn-container">
<v-tooltip location="right" open-delay="500" v-if="state == ComponentStates.DEFAULT">
<template v-slot:activator="{ props }">
<v-btn color="default"
variant="flat"
density="compact"
icon="mdi-plus"
data-cy="plus-create-config-btn"
v-bind="props"
@click="state = ComponentStates.ASK_USER_FOR_CONFIG_NAME"
></v-btn>
</template>
<span>Create Config</span>
</v-tooltip>
<v-tooltip location="right" open-delay="500" v-if="state == ComponentStates.ASK_USER_FOR_CONFIG_NAME">
<template v-slot:activator="{ props }">
<v-btn color="default"
variant="flat"
density="compact"
data-cy="abort-create-config-btn"
icon="mdi-close"
v-bind="props"
@click="abortConfigCreation()"
></v-btn>
</template>
<span>Abort</span>
</v-tooltip>
<v-tooltip location="right" open-delay="500" v-if="state == ComponentStates.ASK_USER_FOR_CONFIG_NAME">
<template v-slot:activator="{ props }">
<v-btn color="default"
variant="flat"
density="compact"
icon="mdi-check"
data-cy="accept-create-config-btn"
v-bind="props"
:disabled="!configNameValid"
@click="createConfig()"
></v-btn>
</template>
<span>Create Config</span>
</v-tooltip>
</div>
<v-text-field
density="compact"
v-model="configName"
v-if="state === ComponentStates.ASK_USER_FOR_CONFIG_NAME"
data-cy="config-name-input"
placeholder="config name"
:rules="[validateConfigName]"
></v-text-field>
</template>

<script setup lang="ts">
import {computed, ref} from "vue";

enum ComponentStates {
DEFAULT,
ASK_USER_FOR_CONFIG_NAME,
}
const state = ref<ComponentStates>(ComponentStates.DEFAULT);
const configName = ref<string>("");
const configNameValid = computed<boolean>(() => validateConfigName() === true);
const emit = defineEmits<{
createConfig: [name: string],
}>();

function createConfig() {
if (validateConfigName() === true) {
emit("createConfig", configName.value);
state.value = ComponentStates.DEFAULT;
configName.value = "";
}
}

function abortConfigCreation() {
state.value = ComponentStates.DEFAULT;
configName.value = "";
}

/**
* A config name must not be empty, must not contain the extension and must be a valid filename
*/
function validateConfigName() {
if (configName.value.trim().length === 0) {
return "Please enter a name";
} else if (/.*(\.json|\.ya?ml)$/.test(configName.value)) {
return "The name must not contain the file extension";
} else if (!/^[a-zA-Z0-9-_]+$/.test(configName.value)) {
return "The name must only contain letters, numbers, dashes and underscores";
} else {
return true;
}
}
</script>


<style scoped lang="scss">
.btn-container {
display: flex;
justify-content: end;
width: 100%;
}
</style>
28 changes: 18 additions & 10 deletions src/components/EvModuleList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
Copyright 2020 - 2024 Pionix GmbH and Contributors to EVerest -->

<template>
<v-expansion-panels class="ma-0">
<v-expansion-panel data-cy="modules-expansion-panel">
<v-expansion-panels class="ma-0" v-model="expansionPanelState">
<v-expansion-panel data-cy="modules-expansion-panel" value="modules" :disabled="!current_config">
<v-expansion-panel-title> Available modules</v-expansion-panel-title>
<v-expansion-panel-text>
<v-text-field v-model="search"
Expand Down Expand Up @@ -34,15 +34,16 @@
</v-list>
</v-expansion-panel-text>
</v-expansion-panel>
<v-expansion-panel :disabled="config_list.length == 0">
<v-expansion-panel-title>
<v-expansion-panel value="configs">
<v-expansion-panel-title data-cy="configs-expansion-panel">
{{ config_list.length == 0 ? "No configs available" : "Available configs" }}
</v-expansion-panel-title>
<v-expansion-panel-text>
<create-config @create-config="create_config"></create-config>
<v-list class="ma-0">
<v-tooltip location="right" v-for="config in config_list" :key="config" open-delay="500">
<template v-slot:activator="{ props }">
<v-list-item :title="config" v-bind="props" @click="load_config_if_empty(config)">
<v-list-item :title="config" v-bind="props" @click="load_config_if_empty(config)" data-cy="config-list-item">
<template v-slot:append>
<v-icon>mdi-upload</v-icon>
</template>
Expand All @@ -62,7 +63,7 @@
@deny="close_dialog()"
/>
</v-expansion-panel>
<v-expansion-panel>
<v-expansion-panel value="commands">
<v-expansion-panel-title> Issue commands</v-expansion-panel-title>
<v-expansion-panel-text>
<v-list>
Expand All @@ -84,6 +85,7 @@ import EVBackendClient from "@/modules/evbc/client";
import EvDialog from "@/components/EvDialog.vue";
import EVConfigModel from "@/modules/evbc/config_model";
import {Notyf} from "notyf";
import CreateConfig from "@/components/CreateConfig.vue";

let evbcStore: ReturnType<typeof useEvbcStore>;
let evbc: EVBackendClient;
Expand All @@ -95,18 +97,20 @@ export default defineComponent({
show_dialog: false,
config_to_load: null,
search: "",
expansionPanelState: ["configs"],
} as {
show_dialog: boolean;
config_to_load: string | null;
search: string;
expansionPanelState: string[];
};
},
created() {
evbcStore = useEvbcStore();
evbc = inject<EVBackendClient>('evbc') as EVBackendClient;
notyf = inject<Notyf>('notyf');
},
components: {EvDialog},
components: {CreateConfig, EvDialog},
computed: {
current_config(): EVConfigModel | null {
return evbcStore.current_config;
Expand Down Expand Up @@ -152,9 +156,7 @@ export default defineComponent({
if (evbcStore.current_config) {
added_module_id = evbcStore.current_config.add_new_module_instance(type);
} else {
const new_config = evbc.create_empty_config("test_config");
added_module_id = new_config.add_new_module_instance(type);
evbcStore.setOpenedConfig(new_config);
throw new Error("No config loaded");
}
if (evbcStore.get_selected_terminal()) {
const selectedTerminal = evbcStore.get_selected_terminal();
Expand All @@ -169,6 +171,11 @@ export default defineComponent({
evbcStore.get_config_context().clicked_terminal(terminalToClick, added_module_id);
}
},
create_config(name: string) {
const new_config = evbc.create_empty_config(name);
evbcStore.setOpenedConfig(new_config);
this.expansionPanelState = ["modules"];
},
load_config_if_empty(name: string) {
if (!this.current_config) {
this.load_config(name);
Expand All @@ -182,6 +189,7 @@ export default defineComponent({
this.show_dialog = false;
const new_config = evbc.load_config(name);
evbcStore.setOpenedConfig(new_config)
this.expansionPanelState = ["modules"];
},
restart_modules() {
evbc._cxn.rpc_issuer.restart_modules().then(() => {
Expand Down

0 comments on commit 585706e

Please sign in to comment.