Skip to content

Commit

Permalink
fix: store favorites locally
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewinci committed Nov 30, 2022
1 parent 7301bd0 commit 056e1af
Show file tree
Hide file tree
Showing 19 changed files with 106 additions and 50 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
"prettier-plugin-rust": "^0.1.8",
"rimraf": "^3.0.2",
"semantic-release": "^19.0.5",
"typescript": "^4.9.3",
"typescript": "<4.9.0",
"vite": "^3.2.4",
"vitest": "^0.25.1"
},
Expand Down
2 changes: 2 additions & 0 deletions src-tauri/src/lib/configuration/config_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,15 @@ mod test {
username: Some("username".into()),
password: Some("password".into()),
}),
..Default::default()
});
config.clusters.push(crate::lib::configuration::ClusterConfig {
id: "1213059c-c744-45ef-a380-3f6997b44377".into(),
name: "test_cluster_2".into(),
endpoint: "localhost:9092".into(),
authentication: crate::lib::configuration::AuthenticationConfig::None,
schema_registry: None,
..Default::default()
});
let sut = ConfigStore::from_config_path(&get_test_config_path());
let res = sut.write_configuration(&InsulatorConfig::default());
Expand Down
1 change: 1 addition & 0 deletions src-tauri/src/lib/configuration/legacy_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ impl TryFrom<LegacyConfiguration> for InsulatorConfig {
endpoint: c.endpoint.clone(),
authentication,
schema_registry,
..Default::default()
})
} else {
warn!("Unable to parse cluster config. {:?}", authentication);
Expand Down
5 changes: 4 additions & 1 deletion src-tauri/src/lib/configuration/store_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::collections::HashMap;

use serde::{Deserialize, Serialize};

use super::{AuthenticationConfig, ClusterConfig, InsulatorConfig, SchemaRegistryConfig, Theme};
use super::{AuthenticationConfig, ClusterConfig, Favorites, InsulatorConfig, SchemaRegistryConfig, Theme};

#[derive(Serialize, Deserialize, Debug, Default, PartialEq, Eq)]
pub struct StoreConfig {
Expand All @@ -21,6 +21,7 @@ pub struct StoreCluster {
pub authentication: StoreAuthentication,
#[serde(rename = "schemaRegistry")]
pub schema_registry: Option<SchemaRegistryConfig>,
pub favorites: Option<Favorites>,
}

#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq)]
Expand Down Expand Up @@ -77,6 +78,7 @@ fn store_cluster_to_config(id: String, store: StoreCluster) -> ClusterConfig {
endpoint: store.endpoint,
authentication: store.authentication.into(),
schema_registry: store.schema_registry,
favorites: store.favorites.unwrap_or_default(),
}
}

Expand Down Expand Up @@ -137,6 +139,7 @@ impl From<ClusterConfig> for StoreCluster {
endpoint: config.endpoint,
authentication: config.authentication.into(),
schema_registry: config.schema_registry,
favorites: Some(config.favorites),
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions src-tauri/src/lib/configuration/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub struct ClusterConfig {
pub authentication: AuthenticationConfig,
#[serde(rename = "schemaRegistry")]
pub schema_registry: Option<SchemaRegistryConfig>,
pub favorites: Favorites,
}

#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq)]
Expand All @@ -51,3 +52,10 @@ pub struct SchemaRegistryConfig {
pub username: Option<String>,
pub password: Option<String>,
}

#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
pub struct Favorites {
pub topics: Vec<String>,
pub schemas: Vec<String>,
pub consumers: Vec<String>,
}
4 changes: 2 additions & 2 deletions webapp/components/code-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Editor, { useMonaco } from "@monaco-editor/react";
import { useEffect } from "react";

type CodeEditorProps = {
height?: string | number;
height: number | string;
language?: string;
value?: string;
readOnly?: boolean;
Expand Down Expand Up @@ -32,7 +32,7 @@ export const CodeEditor = ({ height, language: defaultLanguage, value, readOnly,
return (
<Editor
saveViewState={false}
height={height}
height={height || 0}
defaultLanguage={defaultLanguage}
value={value}
onChange={(v) => {
Expand Down
20 changes: 20 additions & 0 deletions webapp/hooks/use-favorites.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { useQuery } from "@tanstack/react-query";
import { Favorites } from "../models";
import { getFavorites, setFavorites } from "../tauri/configuration";

export const useFavorites = (clusterId: string, key: keyof Favorites) => {
const { data: userFavorites, refetch } = useQuery(["getFavorites", clusterId], () => getFavorites(clusterId));
const toggleFav = async (newItem: string) => {
if (!userFavorites) return;
const favorites = userFavorites[key];
// toggle item from the favorites list
if (favorites?.includes(newItem)) {
await setFavorites(clusterId, { ...userFavorites, [key]: favorites.filter((f) => f != newItem) }); //todo: fix
} else {
await setFavorites(clusterId, { ...userFavorites, [key]: [...favorites, newItem] });
}
refetch();
};

return { favorites: userFavorites ? userFavorites[key] : [], toggleFavorite: toggleFav };
};
7 changes: 7 additions & 0 deletions webapp/models/configurations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export type Cluster = {
endpoint: string;
authentication: ClusterAuthentication;
schemaRegistry: SchemaRegistry | null;
favorites: Favorites;
};

export type ClusterAuthentication =
Expand All @@ -32,3 +33,9 @@ export type SchemaRegistry = {
username?: string;
password?: string;
};

export type Favorites = {
topics: string[];
schemas: string[];
consumers: string[];
};
5 changes: 5 additions & 0 deletions webapp/pages/clusters/edit-clusters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,5 +114,10 @@ function mapFormToCluster(c: ClusterFormType): Cluster {
password: nonEmptyOrUndefined(c.schemaRegistry.password),
}
: null,
favorites: {
consumers: [],
schemas: [],
topics: [],
},
};
}
21 changes: 7 additions & 14 deletions webapp/pages/common/item-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,25 @@ type ItemListProps = {
items: string[];
isLoading: boolean;
isFetching: boolean;
favorites: string[];
onFavToggled: (item: string) => void;
onItemSelected: (item: string) => void;
onRefreshList: () => void;
onAddClick?: () => void;
};

// Common list page component
export const ItemList = (props: ItemListProps) => {
const { onItemSelected, onRefreshList, onAddClick } = props;
const { listId, items, title, isLoading, isFetching } = props;
const { onItemSelected, onRefreshList, onAddClick, onFavToggled } = props;
const { listId, items, title, isLoading, isFetching, favorites } = props;
const [searchText, setSearchText] = useState<string>("");
const [focus, setOnFocus] = useState<string | undefined>(undefined);
const [state, setState] = useSessionStorage<{
recent: string[];
favorites: string[]; //todo: this should be in config
selected?: string;
}>({
key: listId,
defaultValue: {
favorites: [],
recent: [],
},
});
Expand All @@ -65,7 +65,7 @@ export const ItemList = (props: ItemListProps) => {
return {
all: items.filter((t) => test(t)).sort(),
recent: state.recent.filter((t) => items.includes(t) && test(t)).reverse(),
favorites: state.favorites.filter((t) => items.includes(t) && test(t)),
favorites: favorites.filter((f) => items.includes(f)),
};
} catch {
return {
Expand All @@ -74,14 +74,7 @@ export const ItemList = (props: ItemListProps) => {
favorites: [],
};
}
}, [searchText, userSettings.useRegex, items, state.recent, state.favorites]);

const onFavToggled = (newItem: string) => {
// toggle item from the favorites list
if (state.favorites.includes(newItem))
setState((s) => ({ ...s, favorites: s.favorites.filter((f) => f != newItem) }));
else setState((s) => ({ ...s, favorites: [...s.favorites, newItem] }));
};
}, [searchText, userSettings.useRegex, items, state.recent, favorites]);

const onItemSelectedOnTab = (selectedItem: string) => {
// remove any item in focus
Expand Down Expand Up @@ -137,7 +130,7 @@ export const ItemList = (props: ItemListProps) => {
key={title}
title={title}
items={items}
favorites={state.favorites}
favorites={favorites}
isLoading={isLoading}
selected={state.selected}
focus={focus}
Expand Down
1 change: 0 additions & 1 deletion webapp/pages/consumer-groups/consumer-group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ const ConsumerGroupTopicDetails = ({
const lastOffsets = (await getLastOffsets(clusterId, [topicName]))[topicName];
const sumLastOffsets = lastOffsets.map((po) => po.offset).reduce((a, b) => a + b, 0);
const sumOffsets = offsets.map((o) => o.offset).reduce((a, b) => a + b, 0);
console.log(lastOffsets);
return {
lastOffsets,
totalLag: sumLastOffsets - sumOffsets,
Expand Down
6 changes: 5 additions & 1 deletion webapp/pages/consumer-groups/consumer-groups-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { IconTrash } from "@tabler/icons";
import { useQuery } from "@tanstack/react-query";
import { useState } from "react";
import { SingleLineTitle } from "../../components";
import { useFavorites } from "../../hooks/use-favorites";
import { ConsumerSettingsFrom } from "../../models";
import { setConsumerGroup, getConsumerGroups, listTopics } from "../../tauri/admin";
import { ItemList } from "../common";
Expand All @@ -18,6 +19,7 @@ export const ConsumerGroupsList = (props: SchemaListProps) => {
const { isLoading, isFetching, data, refetch } = useQuery(["getConsumerGroups", clusterId], () =>
getConsumerGroups(clusterId)
);
const { favorites, toggleFavorite } = useFavorites(clusterId, "consumers");
return (
<>
<ItemList
Expand All @@ -26,6 +28,8 @@ export const ConsumerGroupsList = (props: SchemaListProps) => {
onAddClick={() => setOpened(true)}
isFetching={isFetching}
isLoading={isLoading}
favorites={favorites}
onFavToggled={toggleFavorite}
items={data ?? []}
onItemSelected={onConsumerSelected}
onRefreshList={refetch}
Expand Down Expand Up @@ -120,7 +124,7 @@ const CreateConsumerGroupModal = ({ clusterId, close }: { clusterId: string; clo
}}
type="submit"
loading={state.isCreating}>
Create 🚀
Create
</Button>
</Group>
</Stack>
Expand Down
5 changes: 4 additions & 1 deletion webapp/pages/schema-registry/schema-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useQuery } from "@tanstack/react-query";
import { AddSchemaModal } from "./add-schema";
import { Modal, Title } from "@mantine/core";
import { useSetState } from "@mantine/hooks";
import { useFavorites } from "../../hooks/use-favorites";

type SchemaListProps = {
clusterId: string;
Expand All @@ -19,14 +20,16 @@ export const SchemaList = (props: SchemaListProps) => {
refetch,
} = useQuery(["getSchemaNamesList", clusterId], () => listSubjects(clusterId));
const [state, setState] = useSetState({ modalOpened: false });

const { favorites, toggleFavorite } = useFavorites(clusterId, "schemas");
return (
<>
<ItemList
title="Schemas"
listId={`schemas-${clusterId}`}
isLoading={isLoading}
isFetching={isFetching}
favorites={favorites}
onFavToggled={toggleFavorite}
items={subjects ?? []}
onAddClick={() => setState((s) => ({ ...s, modalOpened: !s.modalOpened }))}
onItemSelected={onSubjectSelected}
Expand Down
22 changes: 1 addition & 21 deletions webapp/pages/settings/settings.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,10 @@
import { Button, Checkbox, Container, Select, Stack, Text, Center } from "@mantine/core";
import { openConfirmModal } from "@mantine/modals";
import { IconTrash } from "@tabler/icons";
import { Checkbox, Container, Select, Stack, Center } from "@mantine/core";
import { PageHeader } from "../../components";
import { AppTheme } from "../../models";
import { useNotifications } from "../../providers";
import { useUserSettings } from "../../providers/user-settings-provider";

export const Settings = () => {
const { userSettings, setUserSettings } = useUserSettings();
const { success } = useNotifications();
const clearFavorites = () => {
openConfirmModal({
title: "Clear cache",
children: (
<Text size="sm">Are you sure to delete all favorites and recent topics, schemas and consumer groups?</Text>
),
labels: { confirm: "Confirm", cancel: "Cancel" },
onConfirm: () => {
localStorage.clear();
success("Cache cleared", undefined, true);
},
});
};

return (
<Container>
Expand Down Expand Up @@ -52,9 +35,6 @@ export const Settings = () => {
checked={userSettings.useRegex}
onChange={(c) => setUserSettings((s) => ({ ...s, useRegex: c.target.checked }))}
/>
<Button onClick={clearFavorites}>
<IconTrash size={18} /> Clear cache
</Button>
</Stack>
</Center>
</Container>
Expand Down
7 changes: 6 additions & 1 deletion webapp/pages/topics/topic-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Button, Checkbox, Group, NumberInput, Stack, TextInput, Title } from "@
import { openModal, useModals } from "@mantine/modals";
import { useForm } from "@mantine/form";
import { useQuery } from "@tanstack/react-query";
import { useFavorites } from "../../hooks/use-favorites";

type TopicListProps = {
clusterId: string;
Expand All @@ -21,11 +22,15 @@ export const TopicList = (props: TopicListProps) => {
closeOnClickOutside: false,
});

const { favorites, toggleFavorite } = useFavorites(clusterId, "topics");

return (
<ItemList
title="Topics"
listId={`topic-${clusterId}`}
isLoading={isLoading}
favorites={favorites}
onFavToggled={toggleFavorite}
isFetching={isFetching}
items={data ?? []}
onItemSelected={onTopicSelected}
Expand Down Expand Up @@ -72,7 +77,7 @@ const CreateTopicModal = ({ clusterId, updateTopicList }: { clusterId: string; u
<NumberInput min={1} label="In sync replicas" {...form.getInputProps("isr")} />
<Checkbox label="Compacted" {...form.getInputProps("compacted", { type: "checkbox" })} />
<Group mt={10} position="right">
<Button type="submit">Create 🚀</Button>
<Button type="submit">Create</Button>
</Group>
</Stack>
</form>
Expand Down
2 changes: 1 addition & 1 deletion webapp/pages/topics/topic/consumer-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ const ModalBody = ({ clusterId, topicName }: ConsumerModalProps) => {
</Stack>
</Stack>
<Group mt={10} position="right">
<Button type="submit">Start 🚀</Button>
<Button type="submit">Start</Button>
</Group>
</Stack>
</form>
Expand Down
2 changes: 1 addition & 1 deletion webapp/pages/topics/topic/topic-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const TopicPageMenu = ({
https://www.sqlite.org/json1.html
</Anchor>
</Text>
<CodeEditor height={height} language="sql" value={query} onChange={(v) => onQueryChange(v)} />
<CodeEditor height={height ?? 20} language="sql" value={query} onChange={(v) => onQueryChange(v)} />
<Group mt={5} position="apart">
<Group>
<Button
Expand Down
Loading

0 comments on commit 056e1af

Please sign in to comment.