diff --git a/.storybook/preview-head.html b/.storybook/preview-head.html
index aa62527ab..7f0b8485c 100644
--- a/.storybook/preview-head.html
+++ b/.storybook/preview-head.html
@@ -1,4 +1,4 @@
-
+
diff --git a/assets/js/app.js b/assets/js/app.js
index 6e135c4d4..b3013f5d7 100644
--- a/assets/js/app.js
+++ b/assets/js/app.js
@@ -24,8 +24,21 @@ window.app = new Vue({
methods: {
raise: function (msg) {
console[msg.type](msg);
- const withoutThisMsg = this.notifications.filter((m) => m.message !== msg.message);
- this.notifications = [msg, ...withoutThisMsg];
+ const now = new Date();
+ const latestMsg = this.notifications[0];
+ if (latestMsg && latestMsg.message === msg.message) {
+ latestMsg.count++;
+ latestMsg.time = now;
+ } else {
+ this.notifications = [
+ {
+ ...msg,
+ count: 1,
+ time: now,
+ },
+ ...this.notifications,
+ ];
+ }
},
clear: function () {
this.notifications = [];
diff --git a/assets/js/components/Notifications.stories.js b/assets/js/components/Notifications.stories.js
index f82af9234..a00d194d0 100644
--- a/assets/js/components/Notifications.stories.js
+++ b/assets/js/components/Notifications.stories.js
@@ -14,21 +14,53 @@ const Template = (args, { argTypes }) => ({
template: '',
});
+function timeAgo(hours = 0, minutes = 0, seconds = 0) {
+ const date = new Date();
+ date.setHours(date.getHours() - hours);
+ date.setMinutes(date.getMinutes() - minutes);
+ date.setSeconds(date.getSeconds() - seconds);
+ return date;
+}
+
export const Base = Template.bind({});
Base.args = {
notifications: [
{
message: "Server unavailable",
type: "error",
+ time: timeAgo(),
+ count: 1,
},
{
message: "charger out of sync: expected disabled, got enabled",
type: "warn",
+ count: 4,
+ time: timeAgo(0, 0, 42),
+ },
+ {
+ message: "Sponsortoken: x509: certificate has expired",
+ type: "error",
+ count: 1,
+ time: timeAgo(1, 12, 44),
+ },
+ {
+ message: "charger out of sync: expected disabled, got enabled",
+ type: "warn",
+ count: 4,
+ time: timeAgo(1, 22, 0),
+ },
+ {
+ message: "vehicle remote charge start: invalid character '<' looking for beginning of value",
+ type: "warn",
+ count: 3,
+ time: timeAgo(4, 2, 0),
},
{
message:
"Amet irure quis incididunt voluptate esse. Commodo ea sunt est ipsum tempor nisi laboris voluptate labore elit laborum. Ex irure commodo reprehenderit consequat consequat do ad tempor aliquip deserunt eu. Laboris minim nostrud quis nisi. Dolor occaecat reprehenderit velit dolore exercitation cupidatat et voluptate. Nulla pariatur deserunt esse minim nisi nisi nulla. Sit eiusmod do incididunt sint minim pariatur aute.",
type: "warn",
+ count: 1,
+ time: timeAgo(5, 2, 44),
},
],
};
diff --git a/assets/js/components/Notifications.vue b/assets/js/components/Notifications.vue
index 7bcef52b8..59646fae7 100644
--- a/assets/js/components/Notifications.vue
+++ b/assets/js/components/Notifications.vue
@@ -29,21 +29,30 @@
>
-
-
- {{ notification.message }}
-
+
+
+ {{ fmtTimeAgo(msg.time) }}
+
+
+
+
+ {{ msg.message }}
+
+
+ {{ msg.count }}
+
+
+