Skip to content

Commit

Permalink
feat: Plugins to NavBar (#63)
Browse files Browse the repository at this point in the history
* feat: Plugins to NavBar

* fix: No plugins message
  • Loading branch information
brancoder authored Dec 22, 2021
1 parent 3fb5e59 commit 8d20359
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 222 deletions.
14 changes: 7 additions & 7 deletions src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ReactComponent as MoonIcon } from "../assets/moon.svg";
import { ReactComponent as PadlockUnlockedIcon } from "../assets/padlock-unlocked.svg";
import { ReactComponent as PadlockIcon } from "../assets/padlock.svg";
import { ReactComponent as PeersIcon } from "../assets/peers.svg";
import { ReactComponent as SettingsIcon } from "../assets/settings.svg";
import { ReactComponent as PluginsIcon } from "../assets/plugins.svg";
import { ReactComponent as SunIcon } from "../assets/sun.svg";
import { ReactComponent as VisualizerIcon } from "../assets/visualizer.svg";
import { ServiceFactory } from "../factories/serviceFactory";
Expand Down Expand Up @@ -44,9 +44,9 @@ import Login from "./routes/Login";
import Peer from "./routes/Peer";
import { PeerRouteProps } from "./routes/PeerRouteProps";
import Peers from "./routes/Peers";
import Plugins from "./routes/Plugins";
import Search from "./routes/Search";
import { SearchRouteProps } from "./routes/SearchRouteProps";
import Settings from "./routes/Settings";
import Unavailable from "./routes/Unavailable";
import Visualizer from "./routes/Visualizer";

Expand Down Expand Up @@ -267,9 +267,9 @@ class App extends AsyncComponent<RouteComponentProps, AppState> {
route: "/visualizer"
},
{
label: "Settings",
icon: <SettingsIcon />,
route: "/settings",
label: "Plugins",
icon: <PluginsIcon />,
route: "/plugins",
hidden: !this.state.isLoggedIn
},
{
Expand Down Expand Up @@ -414,8 +414,8 @@ class App extends AsyncComponent<RouteComponentProps, AppState> {
component={(props: RouteComponentProps) => (<Visualizer {...props} />)}
/>
<Route
path="/settings"
component={() => (<Settings />)}
path="/plugins"
component={() => (<Plugins />)}
/>
<Route
path="/login"
Expand Down
22 changes: 8 additions & 14 deletions src/app/components/plugins/Participation.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import classNames from "classnames";
import React, { ReactNode } from "react";
import { ReactComponent as ParticipationIcon } from "../../../assets/plugins/spammer.svg";
import { ServiceFactory } from "../../../factories/serviceFactory";
import { IParticipationEvent } from "../../../models/plugins/participation/IParticipationEvent";
import { IParticipationEventInfo } from "../../../models/plugins/participation/IParticipationEventInfo";
Expand Down Expand Up @@ -72,14 +71,12 @@ class Participation extends AsyncComponent<unknown, ParticipationState> {
* @returns The plugin details if available.
*/
public static pluginDetails(): {
icon: ReactNode;
title: string;
description: string;
settings: ReactNode;
} | undefined {
if (Participation._isAvailable) {
return {
icon: <ParticipationIcon />,
title: Participation.PLUGIN_TITLE,
description: Participation.PLUGIN_DESCRIPTION,
settings: <Participation />
Expand Down Expand Up @@ -139,21 +136,18 @@ class Participation extends AsyncComponent<unknown, ParticipationState> {
return (
<div className="participation">
<div className="content">
<div className="row spread">
<h2>{Participation.PLUGIN_TITLE}</h2>
<div className="row">
<button
type="button"
className="add-button"
onClick={() => this.setState({
<div className="row end">
<button
type="button"
className="add-button"
onClick={() => this.setState({
dialogType: "add",
dialogStatus: "",
dialogBusy: false
})}
>
Add Event
</button>
</div>
>
Add Event
</button>
</div>
<div className="events-panel">
{this.state.eventIds.length === 0 && (
Expand Down
3 changes: 0 additions & 3 deletions src/app/components/plugins/Spammer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { ReactNode } from "react";
import { ReactComponent as SpammerIcon } from "../../../assets/plugins/spammer.svg";
import { ServiceFactory } from "../../../factories/serviceFactory";
import { ISpammerSettings } from "../../../models/plugins/ISpammerSettings";
import { AuthService } from "../../../services/authService";
Expand Down Expand Up @@ -81,14 +80,12 @@ class Spammer extends AsyncComponent<unknown, SpammerState> {
* @returns The plugin details if available.
*/
public static pluginDetails(): {
icon: ReactNode;
title: string;
description: string;
settings: ReactNode;
} | undefined {
if (Spammer._isAvailable) {
return {
icon: <SpammerIcon />,
title: Spammer.PLUGIN_TITLE,
description: Spammer.PLUGIN_DESCRIPTION,
settings: <Spammer />
Expand Down
11 changes: 10 additions & 1 deletion src/app/routes/Settings.scss → src/app/routes/Plugins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
@import '../../scss/fonts';
@import '../../scss/media-queries';

.settings {
.plugins {
display: flex;
flex: 1;
justify-content: center;
Expand Down Expand Up @@ -37,4 +37,13 @@
}
}
}

a {
color: var(--accent-primary);
text-decoration: none;

&:hover {
text-decoration: underline;
}
}
}
108 changes: 108 additions & 0 deletions src/app/routes/Plugins.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import React, { ReactNode } from "react";
import { ServiceFactory } from "../../factories/serviceFactory";
import { AuthService } from "../../services/authService";
import AsyncComponent from "../components/layout/AsyncComponent";
import TabPanel from "../components/layout/TabPanel";
import Participation from "../components/plugins/Participation";
import Spammer from "../components/plugins/Spammer";
import "./Plugins.scss";
import { PluginsState } from "./PluginsState";

/**
* Plugins panel.
*/
class Plugins extends AsyncComponent<unknown, PluginsState> {
/**
* The auth service.
*/
private readonly _authService: AuthService;

/**
* Create a new instance of Plugins.
* @param props The props.
*/
constructor(props: unknown) {
super(props);

this._authService = ServiceFactory.get<AuthService>("auth");

this.state = {
plugins: []
};
}

/**
* The component did mount.
*/
public async componentDidMount(): Promise<void> {
super.componentDidMount();

const plugins = [];

if (this._authService.isLoggedIn()) {
const pluginDetailsSpammer = Spammer.pluginDetails();
if (pluginDetailsSpammer) {
plugins.push(pluginDetailsSpammer);
}
const pluginDetailsParticipation = Participation.pluginDetails();
if (pluginDetailsParticipation) {
plugins.push(pluginDetailsParticipation);
}
}

if (plugins.length > 0) {
this.setState({
activeTab: plugins[0].title
});
}

this.setState({
plugins
});
}

/**
* Render the component.
* @returns The node to render.
*/
public render(): ReactNode {
return (
<div className="plugins">
<div className="content">
{this.state.plugins.length === 0 && (
<p className="margin-t-s">
No plugins enabled which are supported by the dashboard.<br />
More information about managing plugins can be found on the
{" "}
<a
target="_blank"
rel="noreferrer"
href="https://wiki.iota.org/hornet/post_installation/managing_a_node#plugins"
>
Hornet Developer Documentation.
</a>
</p>
)}
<TabPanel
tabs={this.state.plugins.map(p => p.title)}
activeTab={this.state.activeTab ? this.state.activeTab : ""}
onTabChanged={activeTab => {
this.setState({
activeTab
});
}}
>
{this.state.plugins.map((p, idx) => (
<div data-label={p.title} key={idx}>
{p.settings}
</div>
))}

</TabPanel>
</div>
</div >
);
}
}

export default Plugins;
18 changes: 18 additions & 0 deletions src/app/routes/PluginsState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { ReactNode } from "react";

export interface PluginsState {

/**
* The active tab.
*/
activeTab?: string;

/**
* Plugins.
*/
plugins: {
title: string;
description: string;
settings: ReactNode;
}[];
}
Loading

0 comments on commit 8d20359

Please sign in to comment.