;
if (hidden) return null;
btnProps.className = cssNames('Button', className, {
- waiting, primary, accent, plain, active, big, round,
+ waiting, primary, accent, plain, active, big, round, secondary, action,
});
const btnContent: ReactNode = (
diff --git a/src/renderer/components/notifications/notifications.scss b/src/renderer/components/notifications/notifications.scss
index 37d4990ee5..a39a00b227 100644
--- a/src/renderer/components/notifications/notifications.scss
+++ b/src/renderer/components/notifications/notifications.scss
@@ -25,6 +25,10 @@
margin-bottom: $margin * 2;
}
+ .ButtonPannel button:not(:last-of-type) {
+ margin-right: $margin;
+ }
+
> .message {
white-space: pre-line;
padding-left: $padding;
diff --git a/src/renderer/components/notifications/notifications.store.ts b/src/renderer/components/notifications/notifications.store.tsx
similarity index 54%
rename from src/renderer/components/notifications/notifications.store.ts
rename to src/renderer/components/notifications/notifications.store.tsx
index 1873ae91a4..58f9360e1e 100644
--- a/src/renderer/components/notifications/notifications.store.ts
+++ b/src/renderer/components/notifications/notifications.store.tsx
@@ -4,6 +4,10 @@ import { autobind } from "../../utils";
import isObject from "lodash/isObject"
import uniqueId from "lodash/uniqueId";
import { JsonApiErrorParsed } from "../../api/json-api";
+import logger from "../../../main/logger";
+import { ipcRenderer } from "electron";
+import { IpcChannel, NotificationChannelAdd } from "../../../common/ipc";
+import { Button, ButtonProps } from "../button";
export type IMessageId = string | number;
export type IMessage = React.ReactNode | React.ReactNode[] | JsonApiErrorParsed;
@@ -19,6 +23,38 @@ export interface INotification {
message: IMessage;
status?: NotificationStatus;
timeout?: number; // auto-hiding timeout in milliseconds, 0 = no hide
+ onClose?(): void; // additonal logic on when the notification times out or is closed by the "x"
+}
+
+export interface MainNotification {
+ title: string;
+ body: string;
+ buttons?: ({
+ backchannel: IpcChannel;
+ } & ButtonProps)[];
+ status: NotificationStatus;
+ timeout?: number;
+ closeChannel?: IpcChannel;
+}
+
+function RenderButtons({ id, buttons }: { id: IpcChannel, buttons?: MainNotification["buttons"] }) {
+ if (!buttons) {
+ return null;
+ }
+
+ return (
+ <>
+
+
+ {buttons.map(({ backchannel, ...props}) => (
+
+ >
+ )
}
@autobind()
@@ -27,6 +63,28 @@ export class NotificationsStore {
protected autoHideTimers = new Map();
+ registerIpcListener(): void {
+ logger.info(`[NOTIFICATION-STORE] start to listen for notifications requests from main`);
+ ipcRenderer.on(NotificationChannelAdd, (event, model: MainNotification) => {
+ const id = uniqueId("notification_");
+ this.add({
+ message: (
+ <>
+ {model.title}
+ {model.body}
+
+ >
+ ),
+ id,
+ status: model.status,
+ timeout: model.timeout,
+ onClose: () => {
+ model.closeChannel && ipcRenderer.send(model.closeChannel);
+ }
+ });
+ })
+ }
+
addAutoHideTimer(notification: INotification) {
this.removeAutoHideTimer(notification);
const { id, timeout } = notification;
diff --git a/src/renderer/components/notifications/notifications.tsx b/src/renderer/components/notifications/notifications.tsx
index 35c741505c..6ca687fee4 100644
--- a/src/renderer/components/notifications/notifications.tsx
+++ b/src/renderer/components/notifications/notifications.tsx
@@ -84,7 +84,10 @@ export class Notifications extends React.Component {
remove(notification))}
+ onClick={prevDefault(() => {
+ remove(notification);
+ notification.onClose?.();
+ })}
/>
diff --git a/src/renderer/lens-app.tsx b/src/renderer/lens-app.tsx
index 70b992a910..4ad795fc2a 100644
--- a/src/renderer/lens-app.tsx
+++ b/src/renderer/lens-app.tsx
@@ -12,6 +12,7 @@ import { ErrorBoundary } from "./components/error-boundary";
import { WhatsNew, whatsNewRoute } from "./components/+whats-new";
import { Notifications } from "./components/notifications";
import { ConfirmDialog } from "./components/confirm-dialog";
+import { notificationsStore } from "./components/notifications/notifications.store";
@observer
export class LensApp extends React.Component {
@@ -22,6 +23,8 @@ export class LensApp extends React.Component {
window.addEventListener("online", () => {
ipcRenderer.send("network:online")
})
+
+ notificationsStore.registerIpcListener();
}
render() {
diff --git a/src/renderer/theme.store.ts b/src/renderer/theme.store.ts
index 5245d2a728..992c280f6c 100644
--- a/src/renderer/theme.store.ts
+++ b/src/renderer/theme.store.ts
@@ -29,12 +29,8 @@ export class ThemeStore {
{ id: "kontena-light", type: ThemeType.LIGHT },
];
- @computed get activeThemeId() {
- return userStore.preferences.colorTheme;
- }
-
@computed get activeTheme(): Theme {
- const activeTheme = this.themes.find(theme => theme.id === this.activeThemeId) || this.themes[0];
+ const activeTheme = this.themes.find(theme => theme.id === userStore.preferences.colorTheme) || this.themes[0];
return {
colors: {},
...activeTheme,
@@ -43,9 +39,9 @@ export class ThemeStore {
constructor() {
// auto-apply active theme
- reaction(() => this.activeThemeId, async themeId => {
+ reaction(() => this.activeTheme, async ({ id }) => {
try {
- await this.loadTheme(themeId);
+ await this.loadTheme(id);
this.applyTheme();
} catch (err) {
userStore.resetTheme();
diff --git a/src/renderer/themes/kontena-dark.json b/src/renderer/themes/kontena-dark.json
index a0d0eb9869..493219031a 100644
--- a/src/renderer/themes/kontena-dark.json
+++ b/src/renderer/themes/kontena-dark.json
@@ -26,6 +26,8 @@
"buttonPrimaryBackground": "#3d90ce",
"buttonDefaultBackground": "#414448",
"buttonAccentBackground": "#e85555",
+ "buttonActionBackground": "#1dcc1f",
+ "buttonSecondaryBackground": "#edd70c",
"buttonDisabledBackground": "#808080",
"tableBgcStripe": "#2a2d33",
"tableBgcSelected": "#383c42",
diff --git a/src/renderer/themes/kontena-light.json b/src/renderer/themes/kontena-light.json
index f39fa53d00..292863dbeb 100644
--- a/src/renderer/themes/kontena-light.json
+++ b/src/renderer/themes/kontena-light.json
@@ -27,6 +27,8 @@
"buttonPrimaryBackground": "#3d90ce",
"buttonDefaultBackground": "#414448",
"buttonAccentBackground": "#e85555",
+ "buttonActionBackground": "#1dcc1f",
+ "buttonSecondaryBackground": "#edd70c",
"buttonDisabledBackground": "#808080",
"tableBgcStripe": "#f8f8f8",
"tableBgcSelected": "#f4f5f5",
diff --git a/src/renderer/themes/theme-vars.scss b/src/renderer/themes/theme-vars.scss
index c6c3072b8f..10139b83c5 100644
--- a/src/renderer/themes/theme-vars.scss
+++ b/src/renderer/themes/theme-vars.scss
@@ -35,6 +35,8 @@ $sidebarBackground: var(--sidebarBackground);
$buttonPrimaryBackground: var(--buttonPrimaryBackground);
$buttonDefaultBackground: var(--buttonDefaultBackground);
$buttonAccentBackground: var(--buttonAccentBackground);
+$buttonSecondaryBackground: var(--buttonSecondaryBackground);
+$buttonActionBackground: var(--buttonActionBackground);
$buttonDisabledBackground: var(--buttonDisabledBackground);
// Tables
@@ -125,4 +127,4 @@ $filterAreaBackground: var(--filterAreaBackground);
$selectOptionHoveredColor: var(--selectOptionHoveredColor);
$lineProgressBackground: var(--lineProgressBackground);
$radioActiveBackground: var(--radioActiveBackground);
-$menuActiveBackground: var(--menuActiveBackground);
\ No newline at end of file
+$menuActiveBackground: var(--menuActiveBackground);
diff --git a/webpack.renderer.ts b/webpack.renderer.ts
index 74978bd152..6112d1af36 100755
--- a/webpack.renderer.ts
+++ b/webpack.renderer.ts
@@ -159,4 +159,4 @@ export default function (): webpack.Configuration {
}),
],
}
-}
\ No newline at end of file
+}