diff --git a/app/components/events/logs-page-main.hbs b/app/components/events/logs-page-main.hbs new file mode 100644 index 00000000..392f53f0 --- /dev/null +++ b/app/components/events/logs-page-main.hbs @@ -0,0 +1,39 @@ +
+

+ Event logs +

+
+ {{#if @isLogsLoading}} +
+ Loading... +
+ {{else}} + {{#if @isNoLogsPresent}} +
+ No logs available, for the event! +
+ {{else}} + {{#each @eventLogsData as |log|}} +
+ [{{log.timestamp}}] + {{log.peerName}} + was removed by + {{log.removedByUsername}} +
+ {{/each}} + {{/if}} + {{/if}} +
+
\ No newline at end of file diff --git a/app/components/events/logs-page.hbs b/app/components/events/logs-page.hbs index 08a0b491..7d13a24d 100644 --- a/app/components/events/logs-page.hbs +++ b/app/components/events/logs-page.hbs @@ -1,26 +1,5 @@ -
-

- Event logs -

-
- {{!TODO added dummy cards as of now, will integrate api for data }} - {{#each this.EVENT_LOGS_DATA as |data|}} -
- {{data.time}} - {{data.removedPeer}} - was - removed by - {{data.removedBy}} -
- {{/each}} -
-
\ No newline at end of file + \ No newline at end of file diff --git a/app/components/events/logs-page.js b/app/components/events/logs-page.js index 06d564bf..22d5917c 100644 --- a/app/components/events/logs-page.js +++ b/app/components/events/logs-page.js @@ -1,85 +1,76 @@ +import { registerDestructor } from '@ember/destroyable'; +import { inject as service } from '@ember/service'; import Component from '@glimmer/component'; +import { tracked } from '@glimmer/tracking'; +import { removePeerLogsTransformer } from '../../utils/logsTransformer'; +import { + EVENTS_LOGS_POLL_TIME, + EVENTS_LOGS_TYPE, + GET_API_CONFIGS, +} from '../../constants/live'; +import { APPS } from '../../constants/urls'; export default class LogsPageComponent extends Component { - // TODO added dummy data as of now, will integrate api for data - EVENT_LOGS_DATA = [ - { - id: 1, - time: '[9:00PM]', - removedPeer: 'xyz', - removedBy: 'Satyam Bajpai', - }, - { - id: 2, - time: '[9:00PM]', - removedPeer: 'xyz', - removedBy: 'Satyam Bajpai', - }, - { - id: 3, - time: '[9:00PM]', - removedPeer: 'xyz', - removedBy: 'Satyam Bajpai', - }, - { - id: 4, - time: '[9:00PM]', - removedPeer: 'xyz', - removedBy: 'Satyam Bajpai', - }, - { - id: 5, - time: '[9:00PM]', - removedPeer: 'xyz', - removedBy: 'Satyam Bajpai', - }, - { - id: 6, - time: '[9:00PM]', - removedPeer: 'xyz', - removedBy: 'Satyam Bajpai', - }, - { - id: 7, - time: '[9:00PM]', - removedPeer: 'xyz', - removedBy: 'Satyam Bajpai', - }, - { - id: 8, - time: '[9:00PM]', - removedPeer: 'xyz', - removedBy: 'Satyam Bajpai', - }, - { - id: 9, - time: '[9:00PM]', - removedPeer: 'xyz', - removedBy: 'Satyam Bajpai', - }, - { - id: 10, - time: '[9:00PM]', - removedPeer: 'xyz', - removedBy: 'Satyam Bajpai', - }, - { - id: 11, - time: '[9:00PM]', - removedPeer: 'xyz', - removedBy: 'Satyam Bajpai', - }, - { - id: 12, - time: '[9:00PM]', - removedPeer: 'xyz', - removedBy: 'Satyam Bajpai', - }, - { - id: 13, - time: '[9:00PM]', - removedPeer: 'xyz', - removedBy: 'Satyam Bajpai', - }, - ]; + @service store; + @service live; + @tracked eventLogsData; + @tracked isLogsLoading; + @tracked isInitialLoading = true; + logsPollingInterval; + LOGS_TYPE_EVENTS_REMOVE_PEER = EVENTS_LOGS_TYPE.EVENTS_REMOVE_PEER; + @tracked isNoLogsPresent; + + constructor(...args) { + super(...args); + + (async () => { + await this.getLogs(); + })(); + + this.logsPollingInterval = setInterval(async () => { + await this.getLogs(); + }, EVENTS_LOGS_POLL_TIME); + + registerDestructor(this, () => { + clearInterval(this.logsPollingInterval); + }); + } + + async getLogs() { + if (this.isInitialLoading) { + this.isLogsLoading = true; + } + + try { + const logsResponse = await fetch( + `${APPS.API_BACKEND}/logs/${this.LOGS_TYPE_EVENTS_REMOVE_PEER}`, + { + ...GET_API_CONFIGS, + credentials: 'include', + } + ); + + const logsFromApi = removePeerLogsTransformer( + (await logsResponse.json())?.logs + ); + + // filtering logs of current active event + this.eventLogsData = logsFromApi.filter((log) => { + return this.live.activeRoomId === log.eventId; + }); + + if (this.eventLogsData.length === 0) { + this.isNoLogsPresent = true; + } else { + this.isNoLogsPresent = false; + } + } catch (err) { + console.error('Something went wrong ', err); + } finally { + if (this.isInitialLoading) { + this.isLogsLoading = false; + this.isInitialLoading = false; + } + } + } } diff --git a/app/components/live-header.hbs b/app/components/live-header.hbs index b218de69..40d8e018 100644 --- a/app/components/live-header.hbs +++ b/app/components/live-header.hbs @@ -13,17 +13,27 @@ {{@activeTab}} -
+
{{#each @tabs as |tab|}} - + {{#if (eq tab.label 'Logs')}} + {{#if this.live.userData.roles.super_user}} + + {{/if}} + {{else}} + + {{/if}} {{/each}}
\ No newline at end of file diff --git a/app/components/live-header.js b/app/components/live-header.js index 095fca01..e359cd19 100644 --- a/app/components/live-header.js +++ b/app/components/live-header.js @@ -1,10 +1,11 @@ import Component from '@glimmer/component'; import { action } from '@ember/object'; import { tracked } from '@glimmer/tracking'; +import { inject as service } from '@ember/service'; export default class LiveHeaderComponent extends Component { + @service live; @tracked isTabOpen = false; - @action toggleTabs() { this.isTabOpen = !this.isTabOpen; } diff --git a/app/constants/live.js b/app/constants/live.js index a11d0474..501cfcc5 100644 --- a/app/constants/live.js +++ b/app/constants/live.js @@ -34,3 +34,8 @@ export const GET_API_CONFIGS = { 'Content-Type': 'application/json', }, }; + +export const EVENTS_LOGS_POLL_TIME = 40000; +export const EVENTS_LOGS_TYPE = { + EVENTS_REMOVE_PEER: 'EVENTS_REMOVE_PEER', +}; diff --git a/app/controllers/live.js b/app/controllers/live.js index eb3bb1e0..55d89c41 100644 --- a/app/controllers/live.js +++ b/app/controllers/live.js @@ -15,7 +15,6 @@ export default class LiveController extends Controller { { id: 1, label: 'Screenshare', active: true }, { id: 2, label: 'Previous Events', active: false }, { id: 3, label: 'Real Dev Squad', active: false }, - // TODO: uncomment this line when logs feature is integrated with API { id: 4, label: 'Logs', active: false }, ]; @tracked activeTab = 'Screenshare'; diff --git a/app/styles/app.css b/app/styles/app.css index 88e51a38..7a7ce06d 100644 --- a/app/styles/app.css +++ b/app/styles/app.css @@ -27,7 +27,7 @@ @import 'room-code-modal.module.css'; @import 'intro.module.css'; @import 'onboarding-card.module.css'; -@import 'logs-page.module.css'; +@import 'logs-page-main.module.css'; @import 'events.module.css'; * { @@ -61,4 +61,4 @@ button { #toast-container>div { opacity: 1; -} +} \ No newline at end of file diff --git a/app/styles/logs-page.module.css b/app/styles/logs-page-main.module.css similarity index 100% rename from app/styles/logs-page.module.css rename to app/styles/logs-page-main.module.css diff --git a/app/templates/live.hbs b/app/templates/live.hbs index 817e9359..38e94fe7 100644 --- a/app/templates/live.hbs +++ b/app/templates/live.hbs @@ -1,11 +1,13 @@ {{page-title 'Live'}}
- + {{#if this.liveService.isJoined}} + + {{/if}} { + const transformedData = logs?.map((log) => { + return { + eventId: log?.body?.event_id, + removedById: log?.meta?.removed_by_id, + removedByUsername: log?.meta?.removed_by_username, + peerId: log?.body?.peer_id, + peerName: log?.body?.peer_name, + reason: log?.body?.reason, + timestamp: new Date(log?.timestamp?._seconds * 1000).toUTCString(), + timestampInSeconds: log?.timestamp?._seconds, + }; + }); + return transformedData; +}; diff --git a/tests/constants/event-logs-data.js b/tests/constants/event-logs-data.js new file mode 100644 index 00000000..593b9db0 --- /dev/null +++ b/tests/constants/event-logs-data.js @@ -0,0 +1,42 @@ +export const EVENTS_LOGS_DATA = [ + { + eventId: 'event-id-1', + removedById: 'removed-by-1', + removedByUsername: 'removed-by-username-1', + peerId: 'peer-id-1', + peerName: 'peer-name-1', + reason: 'reason-1', + timestamp: new Date(1699022859 * 1000).toUTCString(), + timestampInSeconds: 1699022859 + 1000, + }, + { + eventId: 'event-id-2', + removedById: 'removed-by-2', + removedByUsername: 'removed-by-username-2', + peerId: 'peer-id-2', + peerName: 'peer-name-2', + reason: 'reason-2', + timestamp: new Date(1699022859 * 1000 + 2000).toUTCString(), + timestampInSeconds: 1699022859 + 2000, + }, + { + eventId: 'event-id-3', + removedById: 'removed-by-3', + removedByUsername: 'removed-by-username-3', + peerId: 'peer-id-3', + peerName: 'peer-name-3', + reason: 'reason-3', + timestamp: new Date(1699022859 * 1000 + 3000).toUTCString(), + timestampInSeconds: 1699022859 + 3000, + }, + { + eventId: 'event-id-4', + removedById: 'removed-by-4', + removedByUsername: 'removed-by-username-4', + peerId: 'peer-id-4', + peerName: 'peer-name-4', + reason: 'reason-4', + timestamp: new Date(1699022859 * 1000 + 4000).toUTCString(), + timestampInSeconds: 1699022859 + 4000, + }, +]; diff --git a/tests/integration/components/events/logs-page-main-test.js b/tests/integration/components/events/logs-page-main-test.js new file mode 100644 index 00000000..29ab134c --- /dev/null +++ b/tests/integration/components/events/logs-page-main-test.js @@ -0,0 +1,82 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'website-www/tests/helpers'; +import { render } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; +import { EVENTS_LOGS_DATA } from '../../../constants/event-logs-data'; + +module('Integration | Component | events/logs-page-main', function (hooks) { + setupRenderingTest(hooks); + + test('it should render Events::LogsPageMain', async function (assert) { + await render(hbs` + + `); + + assert.dom('[data-test-logs-page-container]').exists(); + assert.dom('[data-test-logs-heading]').exists(); + assert.dom('[data-test-logs-main]').exists(); + }); + + test('it should show loader if isLoading is true otherwise false', async function (assert) { + await render(hbs` + + `); + + assert.dom('[data-test-logs-loader]').exists(); + + await render(hbs` + + `); + + assert.dom('[data-test-logs-loader]').doesNotExist(); + }); + + test('it should show fallback if isNoLogsPresent is true otherwise false', async function (assert) { + await render(hbs` + + `); + + assert.dom('[data-test-logs-fallback]').exists(); + + await render(hbs` + + `); + + assert.dom('[data-test-logs-fallback]').doesNotExist(); + }); + + test('it should show logs if data is present', async function (assert) { + this.set('logsData', EVENTS_LOGS_DATA); + await render(hbs` + + `); + + EVENTS_LOGS_DATA.forEach((log) => { + assert.dom(`[data-test-log-card="${log.timestampInSeconds}"]`).exists(); + assert + .dom(`[data-test-log-card-time="${log.timestampInSeconds}"]`) + .exists(); + assert + .dom(`[data-test-log-card-text="${log.timestampInSeconds}"]`) + .exists(); + assert + .dom(`[data-test-log-card-removed-peer="${log.timestampInSeconds}"]`) + .exists(); + assert + .dom(`[data-test-log-removed-by="${log.timestampInSeconds}"]`) + .exists(); + }); + }); +}); diff --git a/tests/integration/components/events/logs-page-test.js b/tests/integration/components/events/logs-page-test.js index 9d4e5af1..f2362e71 100644 --- a/tests/integration/components/events/logs-page-test.js +++ b/tests/integration/components/events/logs-page-test.js @@ -10,15 +10,6 @@ module('Integration | Component | events/logs-page', function (hooks) { await render(hbs` `); - assert.dom('[data-test-logs-page-container]').exists(); - assert.dom('[data-test-logs-heading]').exists(); - assert.dom('[data-test-logs-main]').exists(); - assert.dom('[data-test-log-card]').exists(); - - // TODO : will add tests for this when we integrate API to this - // data-test-log-card-time='{{data.id}}' - // data-test-log-card-removed-peer='{{data.id}}' - // data-test-log-card='{{data.id}}' - // data-test-log-removed-by='{{data.id}}' + assert.ok(true); }); });