-
-
-
All team members succesfully deleted
-
-
-
-
+
\ No newline at end of file
+
diff --git a/web/satellite/src/components/notifications/NotificationArea.vue b/web/satellite/src/components/notifications/NotificationArea.vue
new file mode 100644
index 000000000..463fea64e
--- /dev/null
+++ b/web/satellite/src/components/notifications/NotificationArea.vue
@@ -0,0 +1,46 @@
+// Copyright (C) 2018 Storj Labs, Inc.
+// See LICENSE for copying information.
+
+
+
+
+
+
+
+
+
+
diff --git a/web/satellite/src/store/index.ts b/web/satellite/src/store/index.ts
index 4ec18bca0..4cddd58ab 100644
--- a/web/satellite/src/store/index.ts
+++ b/web/satellite/src/store/index.ts
@@ -4,8 +4,9 @@
import Vue from 'vue';
import Vuex from 'vuex';
-import {authModule} from "@/store/modules/users";
-import {projectsModule} from "@/store/modules/projects";
+import { authModule } from "@/store/modules/users";
+import { projectsModule } from "@/store/modules/projects";
+import { notificationsModule } from '@/store/modules/notifications';
Vue.use(Vuex);
@@ -13,8 +14,9 @@ Vue.use(Vuex);
const store = new Vuex.Store({
modules: {
authModule,
- projectsModule
- }
+ projectsModule,
+ notificationsModule,
+ },
});
export default store;
diff --git a/web/satellite/src/store/modules/notifications.ts b/web/satellite/src/store/modules/notifications.ts
new file mode 100644
index 000000000..e17db5f7d
--- /dev/null
+++ b/web/satellite/src/store/modules/notifications.ts
@@ -0,0 +1,87 @@
+// Copyright (C) 2018 Storj Labs, Inc.
+// See LICENSE for copying information.
+
+import { NOTIFICATION_MUTATIONS } from '../mutationConstants';
+import { NOTIFICATION_TYPES } from '@/utils/constants/notification';
+import { DelayedNotification } from '@/utils/entities/DelayedNotification';
+
+export const notificationsModule = {
+ state: {
+ // Dynamic queue for displaying notifications
+ notificationQueue: [],
+ },
+ mutations: {
+ // Mutaion for adding notification to queue
+ [NOTIFICATION_MUTATIONS.ADD](state: any, notification: any): void {
+ state.notificationQueue.push(notification);
+
+ // Pause current notification if it`s not first
+ if (state.notificationQueue.length > 1) {
+ notification.pause();
+ }
+ },
+ // Mutaion for deleting notification to queue
+ [NOTIFICATION_MUTATIONS.DELETE](state: any): void {
+ state.notificationQueue[0].pause();
+ state.notificationQueue.shift();
+
+ // Starts next notification in queue if it exist
+ if (state.notificationQueue[0]) {
+ state.notificationQueue[0].start();
+ }
+ },
+ [NOTIFICATION_MUTATIONS.PAUSE](state: any): void {
+ state.notificationQueue[0].pause();
+ },
+ [NOTIFICATION_MUTATIONS.RESUME](state: any): void {
+ state.notificationQueue[0].start();
+ },
+ },
+ actions: {
+ // Commits muttation for adding success notification
+ success: function({commit}: any, message: string): void {
+ const notification = new DelayedNotification(
+ () => commit(NOTIFICATION_MUTATIONS.DELETE),
+ NOTIFICATION_TYPES.SUCCESS,
+ message,
+ );
+
+ commit(NOTIFICATION_MUTATIONS.ADD, notification);
+ },
+ // Commits muttation for adding info notification
+ notify: function({commit}: any, message: string): void {
+
+ const notification = new DelayedNotification(
+ () => commit(NOTIFICATION_MUTATIONS.DELETE),
+ NOTIFICATION_TYPES.NOTIFICATION,
+ message,
+ );
+
+ commit(NOTIFICATION_MUTATIONS.ADD, notification);
+ },
+ // Commits muttation for adding error notification
+ error: function({commit}: any, message: string): void {
+ const notification = new DelayedNotification(
+ () => commit(NOTIFICATION_MUTATIONS.DELETE),
+ NOTIFICATION_TYPES.ERROR,
+ message,
+ );
+
+ commit(NOTIFICATION_MUTATIONS.ADD, notification);
+ },
+ deleteNotification: function({commit}: any): void {
+ commit(NOTIFICATION_MUTATIONS.DELETE);
+ },
+ pauseNotification: function({commit}: any): void {
+ commit(NOTIFICATION_MUTATIONS.PAUSE);
+ },
+ resumeNotification: function({commit}: any): void {
+ commit(NOTIFICATION_MUTATIONS.RESUME);
+ },
+ },
+ getters: {
+ currentNotification: (state: any) => {
+ return state.notificationQueue[0] ? state.notificationQueue[0] : null;
+ },
+ },
+};
diff --git a/web/satellite/src/store/mutationConstants.ts b/web/satellite/src/store/mutationConstants.ts
index c36a926de..556575834 100644
--- a/web/satellite/src/store/mutationConstants.ts
+++ b/web/satellite/src/store/mutationConstants.ts
@@ -15,3 +15,10 @@ export const PROJECTS_MUTATIONS = {
FETCH: "FETCH_PROJECTS",
SELECT: "SELECT_PROJECT",
};
+
+export const NOTIFICATION_MUTATIONS = {
+ ADD: 'ADD_NOTIFICATION',
+ DELETE: 'DELETE_NOTIFICATION',
+ PAUSE: 'PAUSE_NOTIFICATION',
+ RESUME: 'RESUME_NOTIFICATION',
+};
diff --git a/web/satellite/src/utils/constants/notification.ts b/web/satellite/src/utils/constants/notification.ts
new file mode 100644
index 000000000..caa49d767
--- /dev/null
+++ b/web/satellite/src/utils/constants/notification.ts
@@ -0,0 +1,33 @@
+// Copyright (C) 2018 Storj Labs, Inc.
+// See LICENSE for copying information.
+
+export const NOTIFICATION_IMAGES = {
+ NOTIFICATION: `
+
+
+
+ `,
+ SUCCESS: `
+
+
+
+ `,
+ ERROR: `
+
+
+
+
+ `,
+ CLOSE: `
+
+
+ `
+
+
+};
+
+export const NOTIFICATION_TYPES = {
+ SUCCESS: 'SUCCESS',
+ NOTIFICATION: 'NOTIFICATION',
+ ERROR: 'ERROR',
+};
diff --git a/web/satellite/src/utils/entities/DelayedNotification.ts b/web/satellite/src/utils/entities/DelayedNotification.ts
new file mode 100644
index 000000000..8c2044557
--- /dev/null
+++ b/web/satellite/src/utils/entities/DelayedNotification.ts
@@ -0,0 +1,31 @@
+// Copyright (C) 2018 Storj Labs, Inc.
+// See LICENSE for copying information.
+
+export class DelayedNotification {
+ public type: string;
+ public message: string;
+ public id: string;
+ private timerId: any = null;
+ private startTime: any;
+ private remainingTime: any;
+ private callback: Function;
+
+ constructor(callback: Function, type: string, message: string) {
+ this.callback = callback;
+ this.type = type;
+ this.message = message;
+ this.id = Date.now().toString();
+ this.remainingTime = 3000;
+ this.start();
+ }
+
+ public pause(): void {
+ clearTimeout(this.timerId);
+ this.remainingTime -= new Date().getMilliseconds() - this.startTime;
+ }
+
+ public start(): void {
+ this.startTime = new Date().getMilliseconds();
+ this.timerId = setTimeout(this.callback, this.remainingTime);
+ }
+}
diff --git a/web/satellite/src/utils/idGenerator.ts b/web/satellite/src/utils/idGenerator.ts
new file mode 100644
index 000000000..80f48b1d3
--- /dev/null
+++ b/web/satellite/src/utils/idGenerator.ts
@@ -0,0 +1,7 @@
+// Copyright (C) 2018 Storj Labs, Inc.
+// See LICENSE for copying information.
+
+// Custom string id generator
+export function getId(): string {
+ return '_' + Math.random().toString(36).substr(2, 9);
+}
diff --git a/web/satellite/tests/unit/notifications/Notification.spec.ts b/web/satellite/tests/unit/notifications/Notification.spec.ts
new file mode 100644
index 000000000..9eeeedc5e
--- /dev/null
+++ b/web/satellite/tests/unit/notifications/Notification.spec.ts
@@ -0,0 +1,43 @@
+// Copyright (C) 2018 Storj Labs, Inc.
+// See LICENSE for copying information.
+
+import { shallowMount, mount } from '@vue/test-utils';
+import Notification from '@/components/notifications/Notification.vue';
+import { NOTIFICATION_TYPES } from '@/utils/constants/notification';
+
+describe('Notification.vue', () => {
+
+ it('renders correctly', () => {
+ const wrapper = shallowMount(Notification);
+
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it('renders correctly with props', () => {
+ const testMessage = 'testMessage';
+
+ const wrapper = mount(Notification, {
+ propsData: {
+ type: NOTIFICATION_TYPES.SUCCESS,
+ message: testMessage,
+ },
+ });
+
+ expect(wrapper).toMatchSnapshot();
+ expect(wrapper.find(".notification-wrap__text").text()).toMatch(testMessage);
+
+ wrapper.setProps({
+ type: NOTIFICATION_TYPES.ERROR,
+ message: testMessage,
+ });
+
+ expect(wrapper).toMatchSnapshot();
+
+ wrapper.setProps({
+ type: NOTIFICATION_TYPES.NOTIFICATION,
+ message: testMessage,
+ });
+
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/web/satellite/tests/unit/notifications/NotificationArea.spec.ts b/web/satellite/tests/unit/notifications/NotificationArea.spec.ts
new file mode 100644
index 000000000..86ac5563d
--- /dev/null
+++ b/web/satellite/tests/unit/notifications/NotificationArea.spec.ts
@@ -0,0 +1,44 @@
+// Copyright (C) 2018 Storj Labs, Inc.
+// See LICENSE for copying information.
+
+import { shallowMount, mount } from '@vue/test-utils';
+import NotificationArea from '@/components/notifications/NotificationArea.vue';
+import { NOTIFICATION_TYPES } from '@/utils/constants/notification';
+import { DelayedNotification } from '@/utils/entities/DelayedNotification';
+import Vuex from 'vuex';
+import { createLocalVue } from 'vue-test-utils';
+
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('Notification.vue', () => {
+
+ it('renders correctly', () => {
+ const wrapper = shallowMount(NotificationArea,{
+ computed: {
+ currentNotification: jest.fn(),
+ },
+ });
+
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it('renders correctly with notification', () => {
+ const testMessage = 'testMessage';
+ const notification = new DelayedNotification(
+ jest.fn(),
+ NOTIFICATION_TYPES.SUCCESS,
+ testMessage
+ );
+
+ const wrapper = mount(NotificationArea, {
+ localVue,
+ computed: {
+ currentNotification: () => notification,
+ }
+ });
+
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/web/satellite/tests/unit/notifications/__snapshots__/Notification.spec.ts.snap b/web/satellite/tests/unit/notifications/__snapshots__/Notification.spec.ts.snap
new file mode 100644
index 000000000..96469c895
--- /dev/null
+++ b/web/satellite/tests/unit/notifications/__snapshots__/Notification.spec.ts.snap
@@ -0,0 +1,70 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Notification.vue renders correctly 1`] = `
+
+`;
+
+exports[`Notification.vue renders correctly with props 1`] = `
+
+`;
+
+exports[`Notification.vue renders correctly with props 2`] = `
+
+`;
+
+exports[`Notification.vue renders correctly with props 3`] = `
+
+`;
diff --git a/web/satellite/tests/unit/notifications/__snapshots__/NotificationArea.spec.ts.snap b/web/satellite/tests/unit/notifications/__snapshots__/NotificationArea.spec.ts.snap
new file mode 100644
index 000000000..cd38770fa
--- /dev/null
+++ b/web/satellite/tests/unit/notifications/__snapshots__/NotificationArea.spec.ts.snap
@@ -0,0 +1,22 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Notification.vue renders correctly 1`] = ``;
+
+exports[`Notification.vue renders correctly with notification 1`] = `
+
+`;