Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resolve #1912 | Add buttons for switching between different environments #1919

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
12 changes: 11 additions & 1 deletion hermes-console/json-server/db.json
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,17 @@
"title": "hermes console",
"contactLink": "https://google.com",
"environmentName": "LOCAL",
"criticalEnvironment": false
"criticalEnvironment": false,
"knownEnvironments": [
{
"name": "local",
"url": "localhost:5173"
},
{
"name": "also-local",
"url": "127.0.0.1:5173"
}
]
},
"dashboard": {
"metrics": "http://localhost:8082",
Expand Down
6 changes: 6 additions & 0 deletions hermes-console/src/api/app-configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ export interface ConsoleConfiguration {
contactLink: string;
environmentName: string;
criticalEnvironment: boolean;
knownEnvironments: ConsoleEnvironment[];
}

export interface ConsoleEnvironment {
name: string;
url: string;
}

export interface DashboardConfiguration {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { useRouter } from 'vue-router';
import { useTheme } from 'vuetify';
import EnvironmentBadge from '@/components/environment-badge/EnviromentBadge.vue';
import EnvironmentSwitch from '@/components/environment-switch/EnvironmentSwitch.vue';
import ThemeSwitch from '@/components/theme-switch/ThemeSwitch.vue';

const { t } = useI18n();
Expand All @@ -17,6 +18,9 @@
const authStore = useAuthStore();

const isLoggedIn = computed(() => authStore.isUserAuthorized);
const knownEnvironments = computed(
() => configStore.appConfig?.console.knownEnvironments || [],
);

function logIn() {
authStore.login(window.location.pathname);
Expand Down Expand Up @@ -57,6 +61,8 @@
configStore.appConfig?.console.criticalEnvironment || false
"
/>
<v-divider vertical v-if="knownEnvironments.length > 0"></v-divider>
<environment-switch :known-environments="knownEnvironments" />
</div>
<div>
<theme-switch />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import { expect } from 'vitest';
import { fireEvent } from '@testing-library/vue';
import { render } from '@/utils/test-utils';
import EnvironmentSwitch from '@/components/environment-switch/EnvironmentSwitch.vue';
import userEvent from '@testing-library/user-event';

const mockReplace = vi.fn();
const mockHref = vi.fn();
const mockOpen = vi.fn();

Object.defineProperty(window, 'location', {
value: {
get href() {
return mockHref();
},
replace: mockReplace,
},
});

window.open = mockOpen;

const TEST_URL_ENV_1 =
'http://localhost:3000/ui/groups/pl.example.hermes/topics/pl.example.hermes.TemperatureChanged';
const TEST_URL_ENV_2 =
'http://127.0.0.1:3000/ui/groups/pl.example.hermes/topics/pl.example.hermes.TemperatureChanged';

describe('EnvironmentSwitch', () => {
it('should highlight the button for the selected environment', () => {
// given
mockHref.mockReturnValue(TEST_URL_ENV_1);

// when
const { getByText } = render(EnvironmentSwitch, {
props: {
knownEnvironments: [
{
name: 'env1',
url: 'localhost:3000',
},
{
name: 'env2',
url: '127.0.0.1:3000',
},
],
},
});

// then
expect(location.href).toBe(
'http://localhost:3000/ui/groups/pl.example.hermes/topics/pl.example.hermes.TemperatureChanged',
);
expect(getByText('env1')).toBeVisible();
expect(getByText('env2')).toBeVisible();
expect(getByText('env1').closest('button')).toHaveClass('v-btn--active', {
exact: false,
});
expect(getByText('env2').closest('button')).not.toHaveClass(
'v-btn--active',
{ exact: false },
);
});

it('should switch between urls without changing the rest of the path', async () => {
// given
mockHref.mockReturnValue(TEST_URL_ENV_1);

// and
const { getByText } = render(EnvironmentSwitch, {
props: {
knownEnvironments: [
{
name: 'env1',
url: 'localhost:3000',
},
{
name: 'env2',
url: '127.0.0.1:3000',
},
],
},
});

// when
await fireEvent.click(getByText('env2').closest('button'));

// then
expect(mockReplace).toHaveBeenCalledWith(TEST_URL_ENV_2);
});

it('should open the new tab on holding ctrl and clicking', async () => {
// given
mockHref.mockReturnValue(TEST_URL_ENV_1);

// and
const { getByText } = render(EnvironmentSwitch, {
props: {
knownEnvironments: [
{
name: 'env1',
url: 'localhost:3000',
},
{
name: 'env2',
url: '127.0.0.1:3000',
},
],
},
});

// when
const user = userEvent.setup();
await user.keyboard('[ControlLeft>]');
await user.click(getByText('env2').closest('button'));

// then
expect(mockOpen).toHaveBeenCalledWith(TEST_URL_ENV_2, '_blank');
});

it('should open the new tab on holding cmd and clicking', async () => {
// given
mockHref.mockReturnValue(TEST_URL_ENV_1);

// and
const { getByText } = render(EnvironmentSwitch, {
props: {
knownEnvironments: [
{
name: 'env1',
url: 'localhost:3000',
},
{
name: 'env2',
url: '127.0.0.1:3000',
},
],
},
});

// when
const user = userEvent.setup();
await user.keyboard('[MetaLeft>]');
await user.click(getByText('env2').closest('button'));

// then
expect(mockOpen).toHaveBeenCalledWith(TEST_URL_ENV_2, '_blank');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<script setup lang="ts">
import { computed } from 'vue';
import type { ConsoleEnvironment } from '@/api/app-configuration';

const props = defineProps<{
knownEnvironments: ConsoleEnvironment[];
}>();

const selectedEnv = computed(() =>
props.knownEnvironments.indexOf(getCurrentEnv()),
);

function getCurrentEnv(): ConsoleEnvironment {
const url = location.href;
const envs = props.knownEnvironments;
return envs.find(
(env) =>
url.startsWith(env.url) ||
url.startsWith(`http://${env.url}`) ||
url.startsWith(`https://${env.url}`),
);
}

function switchToEnv(env: ConsoleEnvironment, event): string {
const currentUrl = location.href;
const currentEnv: ConsoleEnvironment = getCurrentEnv();
const switchedUrl = currentUrl.replace(currentEnv.url, env.url);
if (event.ctrlKey || event.metaKey) {
window.open(switchedUrl, '_blank');
} else {
window.location.replace(switchedUrl);
}
}
</script>

<template>
<v-btn-toggle color="primary" rounded="0" v-model="selectedEnv" group>
<v-btn
v-for="env in knownEnvironments"
min-width="100"
v-bind:key="env.name"
@click="switchToEnv(env, $event)"
>
{{ env.name }}
</v-btn>
</v-btn-toggle>
</template>

<style scoped lang="scss"></style>
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ public static final class Console {

private boolean criticalEnvironment = false;

private List<ConsoleEnvironment> knownEnvironments = Collections.emptyList();

public String getTitle() {
return title;
}
Expand Down Expand Up @@ -129,6 +131,35 @@ public String getEnvironmentName() {
public void setEnvironmentName(String environmentName) {
this.environmentName = environmentName;
}

public List<ConsoleEnvironment> getKnownEnvironments() {
return knownEnvironments;
}

public void setKnownEnvironments(List<ConsoleEnvironment> knownEnvironments) {
this.knownEnvironments = knownEnvironments;
}
}

public static final class ConsoleEnvironment {
private String name;
private String url;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getUrl() {
return url;
}

public void setUrl(String url) {
this.url = url;
}
}

public Owner getOwner() {
Expand Down
7 changes: 6 additions & 1 deletion hermes-management/src/main/resources/application-local.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
console:
console:
title: hermes console
knownEnvironments:
- name: localhost
url: http://localhost:8090
- name: also-localhost
url: http://127.0.0.1:8090
dashboard:
metrics: http://localhost:8082
docs: http://hermes-pubsub.rtfd.org
Expand Down Expand Up @@ -51,4 +56,4 @@ spring:
order: 2147483647
mvc:
servlet:
path: /
path: /
12 changes: 11 additions & 1 deletion hermes-management/src/main/resources/console/config-local.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
{
"console": {
"title": "hermes console"
"title": "hermes console",
"knownEnvironments": [
{
"name": "local",
"url": "localhost:8090"
},
{
"name": "also-local",
"url": "127.0.0.1:8090"
}
]
},
"dashboard": {
"metrics": "http://localhost:8082",
Expand Down
Loading