diff --git a/app.vue b/app.vue
index 276aa0ed..2915152a 100644
--- a/app.vue
+++ b/app.vue
@@ -5,7 +5,8 @@
diff --git a/layouts/default.vue b/layouts/default.vue
index dfeb0a9a..b2ef3b9b 100644
--- a/layouts/default.vue
+++ b/layouts/default.vue
@@ -1,18 +1,23 @@
diff --git a/middleware/auth.global.ts b/middleware/auth.global.ts
index 242ae855..cb1236ae 100644
--- a/middleware/auth.global.ts
+++ b/middleware/auth.global.ts
@@ -1,7 +1,6 @@
import { navigateTo, defineNuxtRouteMiddleware } from "#app";
import { useSettings } from "~/src/shared/lib/use-settings";
-import {useSettingsStore} from "~/src/shared/stores";
-import { useProfileStore } from "~/src/shared/stores/profile"
+import {useSettingsStore, useProfileStore} from "~/src/shared/stores";
export default defineNuxtRouteMiddleware(async (to) => {
const { auth} = storeToRefs(useSettingsStore())
diff --git a/package.json b/package.json
index 6dd8e4ad..6b8b08f5 100644
--- a/package.json
+++ b/package.json
@@ -67,6 +67,7 @@
"vue-eslint-parser": "^9.1.0"
},
"dependencies": {
+ "@floating-ui/vue": "^1.1.2",
"@highlightjs/vue-plugin": "^2.1.2",
"@hpcc-js/wasm": "^2.8.0",
"@pinia/nuxt": "^0.5.1",
diff --git a/pages/settings.vue b/pages/settings.vue
index 8cde4d57..57bba1bc 100644
--- a/pages/settings.vue
+++ b/pages/settings.vue
@@ -2,7 +2,7 @@
import { useTitle } from "@vueuse/core";
import { storeToRefs } from "pinia";
import { computed } from "vue";
-import { useSettingsStore, THEME_MODES } from "~/src/shared/stores/settings";
+import { useSettingsStore, THEME_MODES } from "~/src/shared/stores";
import { AppHeader, BadgeNumber, IconSvg } from "~/src/shared/ui";
const settingsStore = useSettingsStore();
diff --git a/src/assets/index.css b/src/assets/index.css
index 23dadcd7..2895d107 100644
--- a/src/assets/index.css
+++ b/src/assets/index.css
@@ -1,7 +1,7 @@
@import "vendor.css";
body {
- @apply bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-50 p-0;
+ @apply bg-gray-50 dark:bg-gray-800 text-gray-800 dark:text-gray-50 p-0;
}
body a:hover {
diff --git a/src/shared/lib/helpers/index.ts b/src/shared/lib/helpers/index.ts
index fb9e2d24..8fc561d6 100644
--- a/src/shared/lib/helpers/index.ts
+++ b/src/shared/lib/helpers/index.ts
@@ -1 +1,2 @@
export * from './htmlEncode';
+export * from './textToColors';
diff --git a/src/shared/lib/helpers/textToColors.ts b/src/shared/lib/helpers/textToColors.ts
new file mode 100644
index 00000000..3bd242f5
--- /dev/null
+++ b/src/shared/lib/helpers/textToColors.ts
@@ -0,0 +1,17 @@
+export const textToColors = (input: string): string[] => {
+ // Utility function to convert a character to a base hue value
+ const charToHue = (char: string): number => {
+ const code = char.toLowerCase().charCodeAt(0);
+ return (code - 97) * 20 % 360; // Map 'a' to 'z' to a hue value between 0 and 360
+ };
+
+ // Function to generate an HSL color based on a base hue
+ const getHslColor = (hue: number) => `hsl(${hue}, 70%, 50%)`;
+
+ // Extract up to three characters from the input string
+ const chars = input.length >= 3 ? input.slice(0, 3).split('') : input.padEnd(3, input[0]).slice(0, 3).split('');
+
+ // Calculate the hue for each character
+ // Generate the HSL colors list
+ return chars.map(charToHue).map(getHslColor);
+}
diff --git a/src/shared/lib/io/use-events-requests.ts b/src/shared/lib/io/use-events-requests.ts
index 9090f0f5..0f3b1dd9 100644
--- a/src/shared/lib/io/use-events-requests.ts
+++ b/src/shared/lib/io/use-events-requests.ts
@@ -1,4 +1,5 @@
-import {useProfileStore} from "../../stores/profile";
+import {storeToRefs} from "pinia";
+import {useEventsStore, useProfileStore} from "../../stores";
import type { EventId, EventType, ServerEvent } from '../../types';
import { REST_API_URL } from "./constants";
@@ -16,10 +17,13 @@ type TUseEventsRequests = () => {
export const useEventsRequests: TUseEventsRequests = () => {
const { token } = storeToRefs(useProfileStore())
+ const { activeProjectKey: project } = storeToRefs(useEventsStore())
+
const headers = {"X-Auth-Token": token.value }
- const getEventRestUrl = (param?: string): string => `${REST_API_URL}/api/event${param ? `/${param}` : 's'}`
+ const getEventRestUrl = (param: string): string => `${REST_API_URL}/api/event/${param}${project.value ? `?project=${project.value}` : ''}`
+ const getEventsRestUrl = (): string => `${REST_API_URL}/api/events${project.value ? `?project=${project.value}` : ''}`
- const getAll = () => fetch(getEventRestUrl(), { headers })
+ const getAll = () => fetch(getEventsRestUrl(), { headers })
.then((response) => response.json())
.then((response) => {
if (response?.data) {
@@ -46,17 +50,25 @@ export const useEventsRequests: TUseEventsRequests = () => {
return null;
})
- const deleteSingle = (id: EventId) => fetch(getEventRestUrl(id), {method: 'DELETE', headers})
+ const deleteSingle = (id: EventId) => fetch(getEventRestUrl(id), {
+ method: 'DELETE',
+ headers,
+ ...(project.value ? { body: JSON.stringify({project: project.value }) } : null)
+ })
.catch((err) => {
console.error('Fetch Error', err)
})
- const deleteAll = () => fetch(getEventRestUrl(), {method: 'DELETE', headers})
+ const deleteAll = () => fetch(getEventsRestUrl(), {
+ method: 'DELETE',
+ headers,
+ ...(project.value ? { body: JSON.stringify({project: project.value}) } : null)
+ })
.catch((err) => {
console.error('Fetch Error', err)
})
- const deleteList = (uuids: EventId[]) => fetch(getEventRestUrl(), {
+ const deleteList = (uuids: EventId[]) => fetch(getEventsRestUrl(), {
method: 'DELETE',
headers,
body: JSON.stringify({uuids})
@@ -65,10 +77,13 @@ export const useEventsRequests: TUseEventsRequests = () => {
console.error('Fetch Error', err)
})
- const deleteByType = (type: EventType) => fetch(getEventRestUrl(), {
+ const deleteByType = (type: EventType) => fetch(getEventsRestUrl(), {
method: 'DELETE',
headers,
- body: JSON.stringify({type})
+ body: JSON.stringify({
+ type,
+ ...(project.value ? { project: project.value } : null),
+ })
})
.catch((err) => {
console.error('Fetch Error', err)
diff --git a/src/shared/lib/io/use-smtp-requests.ts b/src/shared/lib/io/use-smtp-requests.ts
index 7360d9ac..c8b51366 100644
--- a/src/shared/lib/io/use-smtp-requests.ts
+++ b/src/shared/lib/io/use-smtp-requests.ts
@@ -1,4 +1,4 @@
-import {useProfileStore} from "../../stores/profile";
+import {useProfileStore} from "../../stores";
import type { EventId, Attachment } from "../../types";
import { REST_API_URL } from "./constants";
diff --git a/src/shared/lib/use-api-transport/use-api-transport.ts b/src/shared/lib/use-api-transport/use-api-transport.ts
index dd8ac501..69241746 100644
--- a/src/shared/lib/use-api-transport/use-api-transport.ts
+++ b/src/shared/lib/use-api-transport/use-api-transport.ts
@@ -7,6 +7,18 @@ let isEventsEmitted = false
export const useApiTransport = () => {
const { token } = storeToRefs(useProfileStore())
+ const { activeProjectKey: project } = storeToRefs(useEventsStore())
+
+ const createPayload = (additional?: Record) => {
+ const payload = {
+ token: token.value,
+ project: project.value
+ }
+ if (additional) {
+ Object.assign(payload, additional)
+ }
+ return payload
+ }
const {centrifuge} = useCentrifuge()
const eventsStore = useEventsStore()
@@ -50,9 +62,12 @@ export const useApiTransport = () => {
centrifuge.on('publication', (ctx) => {
// We need to handle only events from the channel 'events' with event name 'event.received'
- if (ctx.channel === 'events' && ctx.data?.event === 'event.received') {
+ if (ctx.data?.event === 'event.received') {
const event = ctx?.data?.data || null
- eventsStore.addList([event]);
+
+ if (event && event.project === project) {
+ eventsStore.addList([event]);
+ }
}
});
}
@@ -71,7 +86,7 @@ export const useApiTransport = () => {
const deleteEvent = (eventId: EventId) => {
if (getWSConnection()) {
- return centrifuge.rpc(`delete:api/event/${eventId}`, {token: token.value})
+ return centrifuge.rpc(`delete:api/event/${eventId}`, createPayload())
}
return deleteSingle(eventId);
@@ -79,7 +94,7 @@ export const useApiTransport = () => {
const deleteEventsAll = () => {
if (getWSConnection()) {
- return centrifuge.rpc(`delete:api/events`, {token: token.value})
+ return centrifuge.rpc(`delete:api/events`, createPayload())
}
return deleteAll();
@@ -95,7 +110,7 @@ export const useApiTransport = () => {
}
if (getWSConnection()) {
- return centrifuge.rpc(`delete:api/events`, {uuids, token: token.value})
+ return centrifuge.rpc(`delete:api/events`, createPayload({ uuids }))
}
return deleteList(uuids);
@@ -103,7 +118,7 @@ export const useApiTransport = () => {
const deleteEventsByType = (type: EventType) => {
if (getWSConnection()) {
- return centrifuge.rpc(`delete:api/events`, {type, token: token.value})
+ return centrifuge.rpc(`delete:api/events`, createPayload())
}
return deleteByType(type);
@@ -111,15 +126,12 @@ export const useApiTransport = () => {
// NOTE: works only with ws
const rayStopExecution = (hash: RayContentLock["name"]) => {
- centrifuge.rpc(`post:api/ray/locks/${hash}`, {
- stop_execution: true,
- token: token.value
- })
+ centrifuge.rpc(`post:api/ray/locks/${hash}`, createPayload({ stop_execution: true }))
}
// NOTE: works only with ws
const rayContinueExecution = (hash: RayContentLock["name"]) => {
- centrifuge.rpc(`post:api/ray/locks/${hash}`, {token: token.value})
+ centrifuge.rpc(`post:api/ray/locks/${hash}`, createPayload())
}
return {
diff --git a/src/shared/lib/use-events/use-events-api.ts b/src/shared/lib/use-events/use-events-api.ts
index 78d4c7a2..71aa07ad 100644
--- a/src/shared/lib/use-events/use-events-api.ts
+++ b/src/shared/lib/use-events/use-events-api.ts
@@ -81,7 +81,7 @@ export const useEventsApi = (): TUseEventsApi => {
const getAll = () => {
getEventsAll().then((eventsList: ServerEvent[]) => {
if (eventsList.length) {
- eventsStore.initialize(eventsList);
+ eventsStore.initializeEvents(eventsList);
} else {
// NOTE: clear cached events hardly
eventsStore.removeAll();
diff --git a/src/shared/lib/use-settings/use-settings.ts b/src/shared/lib/use-settings/use-settings.ts
index 75cc7f44..1ee1adef 100644
--- a/src/shared/lib/use-settings/use-settings.ts
+++ b/src/shared/lib/use-settings/use-settings.ts
@@ -1,12 +1,13 @@
-import {useProfileStore} from "../../stores/profile";
-import type { TProfile, TSettings } from "../../types";
-import { REST_API_URL } from "../io";
+import {useProfileStore} from "../../stores/profile/profile-store";
+import type {TProfile, TSettings, TProjects} from "../../types";
+import { REST_API_URL } from "../io/constants";
type TUseSettings = {
api: {
getProfile: () => Promise
getSettings: () => Promise
+ getProjects: () => Promise
}
}
@@ -28,12 +29,22 @@ export const useSettings = (): TUseSettings => {
.catch((e) => {
console.error(e);
+ return null
+ });
+ const getProjects = () => fetch(`${REST_API_URL}/api/projects`, {
+ headers: {"X-Auth-Token": token.value || ""}
+ })
+ .then((response) => response.json())
+ .catch((e) => {
+ console.error(e);
+
return null
});
return {
api: {
getProfile,
+ getProjects,
getSettings: getAppSettings
}
}
diff --git a/src/shared/stores/connections.ts b/src/shared/stores/connections.ts
deleted file mode 100644
index e593981b..00000000
--- a/src/shared/stores/connections.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { defineStore } from "pinia";
-
-export enum CONNECTION_STATUSES {
- CONNECTED= "connected",
- DISCONNECTED = "disconnected",
-}
-
-export const useConnectionStore = defineStore("connectionStore", {
- state: () => ({
- wsConnectionStatus: CONNECTION_STATUSES.DISCONNECTED,
- }),
- getters: {
- isConnectedWS({ wsConnectionStatus }) {
- return wsConnectionStatus === CONNECTION_STATUSES.CONNECTED;
- }
- },
- actions: {
- setStatus(newStatus: CONNECTION_STATUSES) {
- this.wsConnectionStatus = newStatus;
- },
- removeWSConnection() {
- this.setStatus(CONNECTION_STATUSES.DISCONNECTED)
- },
- addWSConnection() {
- this.setStatus(CONNECTION_STATUSES.CONNECTED)
- }
-
- },
-});
diff --git a/src/shared/stores/connections/connections-store.ts b/src/shared/stores/connections/connections-store.ts
new file mode 100644
index 00000000..ee19bc89
--- /dev/null
+++ b/src/shared/stores/connections/connections-store.ts
@@ -0,0 +1,26 @@
+import { defineStore } from "pinia";
+import {ConnectionStatus} from "./types";
+
+
+export const useConnectionStore = defineStore("connectionStore", {
+ state: () => ({
+ wsConnectionStatus: ConnectionStatus.DISCONNECTED,
+ }),
+ getters: {
+ isConnectedWS({ wsConnectionStatus }) {
+ return wsConnectionStatus === ConnectionStatus.CONNECTED;
+ }
+ },
+ actions: {
+ setStatus(newStatus: ConnectionStatus) {
+ this.wsConnectionStatus = newStatus;
+ },
+ removeWSConnection() {
+ this.setStatus(ConnectionStatus.DISCONNECTED)
+ },
+ addWSConnection() {
+ this.setStatus(ConnectionStatus.CONNECTED)
+ }
+
+ },
+});
diff --git a/src/shared/stores/connections/index.ts b/src/shared/stores/connections/index.ts
new file mode 100644
index 00000000..3f9e4cab
--- /dev/null
+++ b/src/shared/stores/connections/index.ts
@@ -0,0 +1 @@
+export { useConnectionStore } from './connections-store'
diff --git a/src/shared/stores/connections/types.ts b/src/shared/stores/connections/types.ts
new file mode 100644
index 00000000..ae4f950e
--- /dev/null
+++ b/src/shared/stores/connections/types.ts
@@ -0,0 +1,4 @@
+export enum ConnectionStatus {
+ CONNECTED = "connected",
+ DISCONNECTED = "disconnected",
+}
diff --git a/src/shared/stores/events/events-store.ts b/src/shared/stores/events/events-store.ts
index 1f105433..5186e835 100644
--- a/src/shared/stores/events/events-store.ts
+++ b/src/shared/stores/events/events-store.ts
@@ -1,8 +1,15 @@
import { defineStore } from "pinia";
import {PAGE_TYPES} from "../../constants";
-import type { EventId, EventType , ServerEvent, TEventsGroup} from '../../types';
+import {useSettings} from "../../lib/use-settings";
+import type {EventId, EventType, ServerEvent, TEventsGroup, TProjects} from '../../types';
import {EVENT_TYPES} from "../../types";
-import { getStoredLockedIds, setStoredCachedIds, setStoredLockedIds, getStoredCachedIds } from "./local-storage-actions";
+import {
+ getStoredLockedIds,
+ setStoredCachedIds,
+ setStoredLockedIds,
+ getStoredCachedIds,
+ setStoredProject, removeStoredProject, getStoredProject
+} from "./local-storage-actions";
import type {TEventsCachedIdsMap} from "./types";
const MAX_EVENTS_COUNT = 500;
@@ -24,6 +31,10 @@ export const useEventsStore = defineStore("eventsStore", {
events: [] as ServerEvent[],
cachedIds: getStoredCachedIds() || initialCachedIds,
lockedIds: getStoredLockedIds() || [],
+ projects: {
+ available: [] as TProjects['data'],
+ activeKey: null as string | null,
+ }
}),
getters: {
eventsCounts: ({events}) => (eventType: EVENT_TYPES | undefined): number => {
@@ -43,14 +54,30 @@ export const useEventsStore = defineStore("eventsStore", {
},
cachedIdsTypesList({ cachedIds }) {
return Object.entries(cachedIds).filter(([_, value]) => value.length > 0).map(([key]) => key as TEventsGroup)
- }
+ },
+ activeProjectKey: ({ projects }) => projects.activeKey,
+ availableProjects: ({ projects }) => projects.available,
},
actions: {
+ async initialize (): Promise {
+ const {api: { getProjects }} = useSettings();
+ this.initActiveProject();
+
+ try {
+ const { data } = await getProjects();
+ if (data) {
+ this.setAvailableProjects(data);
+ }
+ } catch (e) {
+ console.error(e);
+ }
+ },
// events
- initialize(events: ServerEvent[]): void {
+ initializeEvents (events: ServerEvent[]): void {
this.events = events.slice(0, MAX_EVENTS_COUNT);
this.syncCachedWithActive(events.map(({ uuid }) => uuid));
+ this.initActiveProject();
},
addList(events: ServerEvent[]): void {
events.forEach((event) => {
@@ -165,6 +192,31 @@ export const useEventsStore = defineStore("eventsStore", {
this.lockedIds.push(eventUuid);
setStoredLockedIds(this.lockedIds);
+ },
+ // projects
+ initActiveProject() {
+ this.projects.activeKey = getStoredProject();
+ },
+ setAvailableProjects(projects: TProjects['data']) {
+ if (projects.length > 0) {
+ this.projects.available = projects;
+
+ if (this.projects.activeKey === null) {
+ this.setActiveProject(projects[0].key);
+ }
+ } else {
+ this.resetActiveProject();
+ }
+ },
+ setActiveProject(project: string | null) {
+ this.projects.activeKey = project;
+
+ setStoredProject(project);
+ },
+ resetActiveProject() {
+ this.projects.activeKey = null;
+
+ removeStoredProject();
}
},
});
diff --git a/src/shared/stores/events/local-storage-actions.ts b/src/shared/stores/events/local-storage-actions.ts
index 1d00310b..7edc69f6 100644
--- a/src/shared/stores/events/local-storage-actions.ts
+++ b/src/shared/stores/events/local-storage-actions.ts
@@ -1,10 +1,10 @@
-import { type EventId, LOCAL_STORAGE_KEYS} from "../../types";
+import {type EventId, SESSION_STORAGE_KEYS} from "../../types";
import type {TEventsCachedIdsMap} from "./types";
-const { localStorage } = window;
+const { sessionStorage } = window;
export const getStoredCachedIds = (): TEventsCachedIdsMap | null => {
- const storageValue = localStorage?.getItem(LOCAL_STORAGE_KEYS.CACHED_EVENTS);
+ const storageValue = sessionStorage?.getItem(SESSION_STORAGE_KEYS.CACHED_EVENTS);
if (storageValue) {
return JSON.parse(storageValue) as TEventsCachedIdsMap;
@@ -14,12 +14,12 @@ export const getStoredCachedIds = (): TEventsCachedIdsMap | null => {
};
export const setStoredCachedIds = (cachedEventMap: TEventsCachedIdsMap) => {
- localStorage?.setItem(LOCAL_STORAGE_KEYS.CACHED_EVENTS, JSON.stringify(cachedEventMap));
+ sessionStorage?.setItem(SESSION_STORAGE_KEYS.CACHED_EVENTS, JSON.stringify(cachedEventMap));
}
export const getStoredLockedIds = (): EventId[] | null => {
- const storageValue = localStorage?.getItem(LOCAL_STORAGE_KEYS.LOCKED_EVENTS);
+ const storageValue = sessionStorage?.getItem(SESSION_STORAGE_KEYS.LOCKED_EVENTS);
if (storageValue) {
return JSON.parse(storageValue) as EventId[];
@@ -29,5 +29,20 @@ export const getStoredLockedIds = (): EventId[] | null => {
};
export const setStoredLockedIds = (lockedIds: EventId[]) => {
- localStorage?.setItem(LOCAL_STORAGE_KEYS.LOCKED_EVENTS, JSON.stringify(lockedIds));
+ sessionStorage?.setItem(SESSION_STORAGE_KEYS.LOCKED_EVENTS, JSON.stringify(lockedIds));
+}
+
+export const getStoredProject = (): string | null => sessionStorage?.getItem(SESSION_STORAGE_KEYS.PROJECT) || null;
+
+
+export const removeStoredProject = () => {
+ sessionStorage?.removeItem(SESSION_STORAGE_KEYS.PROJECT);
+}
+
+export const setStoredProject = (project: string | null) => {
+ if (project) {
+ sessionStorage?.setItem(SESSION_STORAGE_KEYS.PROJECT, project);
+ } else {
+ removeStoredProject()
+ }
}
diff --git a/src/shared/stores/profile/index.ts b/src/shared/stores/profile/index.ts
new file mode 100644
index 00000000..0401dc4f
--- /dev/null
+++ b/src/shared/stores/profile/index.ts
@@ -0,0 +1 @@
+export { useProfileStore } from './profile-store'
diff --git a/src/shared/stores/profile/local-storage-actions.ts b/src/shared/stores/profile/local-storage-actions.ts
new file mode 100644
index 00000000..aa8182e3
--- /dev/null
+++ b/src/shared/stores/profile/local-storage-actions.ts
@@ -0,0 +1,15 @@
+import {LOCAL_STORAGE_KEYS} from "../../types";
+
+export const getStoredToken = (): string => {
+ const storedCodeEditor = window?.localStorage?.getItem(LOCAL_STORAGE_KEYS.TOKEN);
+
+ return storedCodeEditor || '';
+};
+
+export const setStoredToken = (token: string) => {
+ localStorage?.setItem(LOCAL_STORAGE_KEYS.TOKEN, token);
+}
+
+export const removeStoredToken = () => {
+ localStorage?.removeItem(LOCAL_STORAGE_KEYS.TOKEN);
+}
diff --git a/src/shared/stores/profile.ts b/src/shared/stores/profile/profile-store.ts
similarity index 71%
rename from src/shared/stores/profile.ts
rename to src/shared/stores/profile/profile-store.ts
index dd709dbf..346018b2 100644
--- a/src/shared/stores/profile.ts
+++ b/src/shared/stores/profile/profile-store.ts
@@ -1,7 +1,7 @@
import { defineStore } from "pinia";
-import type {TProfile} from "../types";
+import type {TProfile} from "../../types";
+import {getStoredToken, removeStoredToken, setStoredToken} from "./local-storage-actions";
-const STORAGE_KEY = "token";
export const useProfileStore = defineStore("profileStore", {
state: () => ({
@@ -16,17 +16,17 @@ export const useProfileStore = defineStore("profileStore", {
actions: {
setToken(token: string): void {
this.token = token;
- localStorage?.setItem(STORAGE_KEY, token);
+ setStoredToken(token);
},
setProfile(profile: TProfile): void {
this.profile = profile;
},
fetchToken(): void {
- this.setToken(localStorage?.getItem(STORAGE_KEY) || '');
+ this.setToken(getStoredToken() || '');
},
removeToken(): void {
this.token = '';
- localStorage?.removeItem(STORAGE_KEY);
+ removeStoredToken();
},
},
});
diff --git a/src/shared/types/local-storage.ts b/src/shared/types/local-storage.ts
index 6d86f6ed..ef2b000e 100644
--- a/src/shared/types/local-storage.ts
+++ b/src/shared/types/local-storage.ts
@@ -1,9 +1,14 @@
export enum LOCAL_STORAGE_KEYS {
- CACHED_EVENTS = "cached_events",
- LOCKED_EVENTS = "locked_events",
THEME = "theme",
NAVBAR = "navbar",
EVENT_COUNTS = "event_counts",
CODE_EDITOR = "code_editor",
+ TOKEN = "token",
+}
+
+export enum SESSION_STORAGE_KEYS {
+ PROJECT = "project",
+ CACHED_EVENTS = "cached_events",
+ LOCKED_EVENTS = "locked_events",
}
diff --git a/src/shared/types/settings.ts b/src/shared/types/settings.ts
index 39252090..f5d1bca8 100644
--- a/src/shared/types/settings.ts
+++ b/src/shared/types/settings.ts
@@ -9,5 +9,13 @@ export type TSettings = {
enabled: boolean,
login_url: string,
},
- version: string
+ version: string,
+}
+
+
+export type TProjects = {
+ data: {
+ name: string,
+ key: string
+ }[]
}
diff --git a/src/widgets/ui/layout-sidebar/layout-sidebar.vue b/src/widgets/ui/layout-sidebar/layout-sidebar.vue
index c418ea89..05e95490 100644
--- a/src/widgets/ui/layout-sidebar/layout-sidebar.vue
+++ b/src/widgets/ui/layout-sidebar/layout-sidebar.vue
@@ -1,25 +1,62 @@
@@ -83,13 +141,41 @@ const serverVersion = computed(() =>
to="/"
title="Dashboard"
class="layout-sidebar__link layout-sidebar__link--logo"
+ tabindex="1"
>
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-