refactor: 💡 Refactor session-recordings routes (#222)
* refactor: 💡 Refactor session-recordings routes
This commit is contained in:
1 parent
451fcdbfeb
commit
0d9602f4ba
11 files changed
+240
-191
No files matched your search
@@ -10,6 +10,6 @@ export default class ScopesScopeSessionRecordingsSessionRecordingController exte
|
||||
* Session recording breadcrumb
|
||||
*/
|
||||
get breadCrumb() {
|
||||
return this.model.sessionRecording.displayName;
|
||||
return this.model.displayName;
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,4 @@ export default class ScopesScopeSessionRecordingsRoute extends Route {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// =actions
|
||||
}
|
||||
@@ -17,32 +17,15 @@ export default class ScopesScopeSessionRecordingsSessionRecordingRoute extends R
|
||||
}
|
||||
|
||||
/**
|
||||
* Load session recording, sorted connections and channels,
|
||||
* and related storage bucket if present
|
||||
* @return {{sessionRecording: SessionRecordingModel, sortedConnections: [ConnectionRecordingModel], storageBucket: ?StorageBucketModel}}
|
||||
* Load session recording.
|
||||
* @return {sessionRecording: SessionRecordingModel}
|
||||
*/
|
||||
async model({ session_recording_id }) {
|
||||
let storageBucket = null;
|
||||
const sessionRecording = await this.store.findRecord(
|
||||
'session-recording',
|
||||
session_recording_id
|
||||
);
|
||||
|
||||
try {
|
||||
if (sessionRecording.target?.storage_bucket_id) {
|
||||
const { storage_bucket_id } = sessionRecording.target;
|
||||
storageBucket = await this.store.findRecord(
|
||||
'storage-bucket',
|
||||
storage_bucket_id
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
// no op
|
||||
}
|
||||
|
||||
return {
|
||||
sessionRecording,
|
||||
storageBucket,
|
||||
};
|
||||
return sessionRecording;
|
||||
}
|
||||
}
|
||||
+44
-1
@@ -1,3 +1,46 @@
|
||||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default class ScopesScopeSessionRecordingsSessionRecordingChannelsByConnectionRoute extends Route {}
|
||||
export default class ScopesScopeSessionRecordingsSessionRecordingChannelsByConnectionRoute extends Route {
|
||||
// =services
|
||||
@service store;
|
||||
@service session;
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* If arriving here unauthenticated, redirect to index for further processing.
|
||||
*/
|
||||
beforeModel() {
|
||||
if (!this.session.isAuthenticated) this.router.transitionTo('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Load session recording (already in store) and related storage bucket if present
|
||||
* @return {{sessionRecording: SessionRecordingModel, storageBucket: ?StorageBucketModel}}
|
||||
*/
|
||||
async model() {
|
||||
let storageBucket = null;
|
||||
|
||||
const sessionRecording = this.modelFor(
|
||||
'scopes.scope.session-recordings.session-recording'
|
||||
);
|
||||
|
||||
try {
|
||||
if (sessionRecording.target?.storage_bucket_id) {
|
||||
const { storage_bucket_id } = sessionRecording.target;
|
||||
storageBucket = await this.store.findRecord(
|
||||
'storage-bucket',
|
||||
storage_bucket_id
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
// no op
|
||||
}
|
||||
|
||||
return {
|
||||
sessionRecording,
|
||||
storageBucket,
|
||||
};
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -7,10 +7,15 @@ export default class ScopesScopeSessionRecordingsSessionRecordingChannelsByConne
|
||||
@service can;
|
||||
|
||||
// =methods
|
||||
/**
|
||||
*
|
||||
* @param {*} channel_id
|
||||
* @returns {channelRecording: Object, sessionRecording: Object, storageBucket: Object, asciicast: Object}
|
||||
*/
|
||||
async model({ channel_id }) {
|
||||
let asciicast;
|
||||
const { sessionRecording, storageBucket } = await this.modelFor(
|
||||
'scopes.scope.session-recordings.session-recording'
|
||||
'scopes.scope.session-recordings.session-recording.channels-by-connection'
|
||||
);
|
||||
const channelRecording = await this.store.peekRecord(
|
||||
'channel-recording',
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default class ScopesScopeSessionRecordingsSessionRecordingIndexRoute extends Route {}
|
||||
export default class ScopesScopeSessionRecordingsSessionRecordingIndexRoute extends Route {
|
||||
// =services
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Redirects to the sessionRecording type specific screen,
|
||||
* for now just SSH types are supported.
|
||||
* @param {SessionRecordingModel} sessionRecording
|
||||
*/
|
||||
async afterModel(sessionRecording) {
|
||||
if (sessionRecording.isSSH) {
|
||||
this.router.transitionTo(
|
||||
'scopes.scope.session-recordings.session-recording.channels-by-connection',
|
||||
sessionRecording.id
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@
|
||||
@iconPosition='trailing'
|
||||
@color='secondary'
|
||||
@text={{t 'actions.view'}}
|
||||
@route='scopes.scope.session-recordings.session-recording'
|
||||
@route='scopes.scope.session-recordings.session-recording.channels-by-connection'
|
||||
@model={{B.data.id}}
|
||||
/>
|
||||
{{/if}}
|
||||
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
<Rose::Layout::Page as |page|>
|
||||
<page.breadcrumbs>
|
||||
<BreadCrumbs />
|
||||
</page.breadcrumbs>
|
||||
|
||||
<page.header>
|
||||
<h2>{{t 'resources.session-recording.session.title'}}</h2>
|
||||
</page.header>
|
||||
|
||||
<page.body>
|
||||
<div class='channels-by-connection'>
|
||||
<Layout::Sidebar as |sb|>
|
||||
<sb.Body>
|
||||
{{#each
|
||||
@model.sessionRecording.sortedConnectionsByStartTimeDesc
|
||||
as |connection|
|
||||
}}
|
||||
<div class='channels-by-connection-connection-header'>
|
||||
<p class='hds-typography-display-300 hds-font-weight-semibold'>
|
||||
{{t 'resources.session-recording.connection.title'}}
|
||||
{{connection.id}}
|
||||
</p>
|
||||
</div>
|
||||
<Hds::Table
|
||||
@model={{connection.sortedChannelsByStartTimeDesc}}
|
||||
@density='tall'
|
||||
@columns={{array
|
||||
(hash
|
||||
label=(t
|
||||
'resources.session-recording.connection.form.channel.label'
|
||||
)
|
||||
)
|
||||
(hash
|
||||
label=(t
|
||||
'resources.session-recording.connection.form.summary.label'
|
||||
)
|
||||
)
|
||||
(hash label='' align='right')
|
||||
}}
|
||||
>
|
||||
<:body as |B|>
|
||||
<B.Tr>
|
||||
<B.Td>
|
||||
<span>{{B.data.id}}</span>
|
||||
</B.Td>
|
||||
<B.Td>
|
||||
<MetadataList as |list|>
|
||||
{{! Bytes up }}
|
||||
<list.Item @icon='arrow-up' @color='success'>
|
||||
{{format-bytes-size B.data.bytes_up}}
|
||||
</list.Item>
|
||||
{{! Bytes down }}
|
||||
<list.Item @icon='arrow-down' @color='action'>
|
||||
{{format-bytes-size B.data.bytes_down}}
|
||||
</list.Item>
|
||||
{{! Duration }}
|
||||
<list.Item @icon='clock' @color='faint'>
|
||||
{{format-time-duration B.data.duration}}
|
||||
</list.Item>
|
||||
</MetadataList>
|
||||
</B.Td>
|
||||
<B.Td align='right'>
|
||||
<Hds::Button
|
||||
@icon='play'
|
||||
@color='secondary'
|
||||
@text='Play'
|
||||
@route='scopes.scope.session-recordings.session-recording.channels-by-connection.channel'
|
||||
@model={{B.data.id}}
|
||||
/>
|
||||
</B.Td>
|
||||
</B.Tr>
|
||||
</:body>
|
||||
</Hds::Table>
|
||||
{{/each}}
|
||||
</sb.Body>
|
||||
<sb.Sidebar>
|
||||
<div>
|
||||
<h3>{{t 'resources.session-recording.details'}}</h3>
|
||||
|
||||
<MetadataList @orientation='vertical' as |list|>
|
||||
{{! Start time }}
|
||||
<list.Item @icon='calendar' @color='faint'>
|
||||
{{t 'form.started.label'}}
|
||||
<time
|
||||
datetime={{format-date-iso
|
||||
@model.sessionRecording.start_time
|
||||
}}
|
||||
>
|
||||
{{format-date-iso-human @model.sessionRecording.start_time}}
|
||||
</time>
|
||||
</list.Item>
|
||||
{{! Duration }}
|
||||
<list.Item @icon='clock' @color='faint'>
|
||||
{{format-time-duration @model.sessionRecording.duration}}
|
||||
</list.Item>
|
||||
{{! Bytes up }}
|
||||
<list.Item @icon='arrow-up' @color='success'>
|
||||
{{format-bytes-size @model.sessionRecording.bytes_up}}
|
||||
</list.Item>
|
||||
{{! Bytes down }}
|
||||
<list.Item @icon='arrow-down' @color='action'>
|
||||
{{format-bytes-size @model.sessionRecording.bytes_down}}
|
||||
</list.Item>
|
||||
</MetadataList>
|
||||
</div>
|
||||
|
||||
{{! Related information }}
|
||||
<div>
|
||||
<h3>{{t 'resources.session-recording.related'}}</h3>
|
||||
<LinkListPanel as |list|>
|
||||
{{! User name }}
|
||||
{{#if @model.sessionRecording.user}}
|
||||
<list.Item
|
||||
@icon='user'
|
||||
@color='boundary'
|
||||
@route='scopes.scope.users.user'
|
||||
@model={{array
|
||||
@model.sessionRecording.user.scopeId
|
||||
@model.sessionRecording.user.id
|
||||
}}
|
||||
@text={{@model.sessionRecording.userDisplayName}}
|
||||
/>
|
||||
{{/if}}
|
||||
{{! Target name }}
|
||||
{{#if @model.sessionRecording.target}}
|
||||
<list.Item
|
||||
@icon='target'
|
||||
@color='boundary'
|
||||
@route='scopes.scope.targets.target'
|
||||
@model={{array
|
||||
@model.sessionRecording.target.scopeId
|
||||
@model.sessionRecording.target.id
|
||||
}}
|
||||
@text={{@model.sessionRecording.target.name}}
|
||||
>
|
||||
{{#if @model.sessionRecording.target.type}}
|
||||
<Hds::Badge @text={{@model.sessionRecording.target.type}} />
|
||||
{{/if}}
|
||||
</list.Item>
|
||||
{{/if}}
|
||||
{{! Bucket name }}
|
||||
{{#if @model.storageBucket}}
|
||||
<list.Item
|
||||
@icon='cloud-check'
|
||||
@color='boundary'
|
||||
@route='scopes.scope.storage-buckets.storage-bucket'
|
||||
@model={{array
|
||||
@model.storageBucket.scope.id
|
||||
@model.storageBucket.id
|
||||
}}
|
||||
@text={{@model.storageBucket.name}}
|
||||
/>
|
||||
{{/if}}
|
||||
</LinkListPanel>
|
||||
</div>
|
||||
</sb.Sidebar>
|
||||
</Layout::Sidebar>
|
||||
</div>
|
||||
</page.body>
|
||||
</Rose::Layout::Page>
|
||||
@@ -1,160 +0,0 @@
|
||||
<Rose::Layout::Page as |page|>
|
||||
<page.breadcrumbs>
|
||||
<BreadCrumbs />
|
||||
</page.breadcrumbs>
|
||||
|
||||
<page.header>
|
||||
<h2>{{t 'resources.session-recording.session.title'}}</h2>
|
||||
</page.header>
|
||||
|
||||
<page.body>
|
||||
<div class='channels-by-connection'>
|
||||
<Layout::Sidebar as |sb|>
|
||||
<sb.Body>
|
||||
{{#each
|
||||
@model.sessionRecording.sortedConnectionsByStartTimeDesc
|
||||
as |connection|
|
||||
}}
|
||||
<div class='channels-by-connection-connection-header'>
|
||||
<p class='hds-typography-display-300 hds-font-weight-semibold'>
|
||||
{{t 'resources.session-recording.connection.title'}}
|
||||
{{connection.id}}
|
||||
</p>
|
||||
</div>
|
||||
<Hds::Table
|
||||
@model={{connection.sortedChannelsByStartTimeDesc}}
|
||||
@density='tall'
|
||||
@columns={{array
|
||||
(hash
|
||||
label=(t
|
||||
'resources.session-recording.connection.form.channel.label'
|
||||
)
|
||||
)
|
||||
(hash
|
||||
label=(t
|
||||
'resources.session-recording.connection.form.summary.label'
|
||||
)
|
||||
)
|
||||
(hash label='' align='right')
|
||||
}}
|
||||
>
|
||||
<:body as |B|>
|
||||
<B.Tr>
|
||||
<B.Td>
|
||||
<span>{{B.data.id}}</span>
|
||||
</B.Td>
|
||||
<B.Td>
|
||||
<MetadataList as |list|>
|
||||
{{! Bytes up }}
|
||||
<list.Item @icon='arrow-up' @color='success'>
|
||||
{{format-bytes-size B.data.bytes_up}}
|
||||
</list.Item>
|
||||
{{! Bytes down }}
|
||||
<list.Item @icon='arrow-down' @color='action'>
|
||||
{{format-bytes-size B.data.bytes_down}}
|
||||
</list.Item>
|
||||
{{! Duration }}
|
||||
<list.Item @icon='clock' @color='faint'>
|
||||
{{format-time-duration B.data.duration}}
|
||||
</list.Item>
|
||||
</MetadataList>
|
||||
</B.Td>
|
||||
<B.Td align='right'>
|
||||
<Hds::Button
|
||||
@icon='play'
|
||||
@color='secondary'
|
||||
@text='Play'
|
||||
@route='scopes.scope.session-recordings.session-recording.channels-by-connection.channel'
|
||||
@model={{B.data.id}}
|
||||
/>
|
||||
</B.Td>
|
||||
</B.Tr>
|
||||
</:body>
|
||||
</Hds::Table>
|
||||
{{/each}}
|
||||
</sb.Body>
|
||||
<sb.Sidebar>
|
||||
<div>
|
||||
<h3>{{t 'resources.session-recording.details'}}</h3>
|
||||
|
||||
<MetadataList @orientation='vertical' as |list|>
|
||||
{{! Start time }}
|
||||
<list.Item @icon='calendar' @color='faint'>
|
||||
{{t 'form.started.label'}}
|
||||
<time
|
||||
datetime={{format-date-iso
|
||||
@model.sessionRecording.start_time
|
||||
}}
|
||||
>
|
||||
{{format-date-iso-human @model.sessionRecording.start_time}}
|
||||
</time>
|
||||
</list.Item>
|
||||
{{! Duration }}
|
||||
<list.Item @icon='clock' @color='faint'>
|
||||
{{format-time-duration @model.sessionRecording.duration}}
|
||||
</list.Item>
|
||||
{{! Bytes up }}
|
||||
<list.Item @icon='arrow-up' @color='success'>
|
||||
{{format-bytes-size @model.sessionRecording.bytes_up}}
|
||||
</list.Item>
|
||||
{{! Bytes down }}
|
||||
<list.Item @icon='arrow-down' @color='action'>
|
||||
{{format-bytes-size @model.sessionRecording.bytes_down}}
|
||||
</list.Item>
|
||||
</MetadataList>
|
||||
</div>
|
||||
|
||||
{{! Related information }}
|
||||
<div>
|
||||
<h3>{{t 'resources.session-recording.related'}}</h3>
|
||||
<LinkListPanel as |list|>
|
||||
{{! User name }}
|
||||
{{#if @model.sessionRecording.user}}
|
||||
<list.Item
|
||||
@icon='user'
|
||||
@color='boundary'
|
||||
@route='scopes.scope.users.user'
|
||||
@model={{array
|
||||
@model.sessionRecording.user.scopeId
|
||||
@model.sessionRecording.user.id
|
||||
}}
|
||||
@text={{@model.sessionRecording.userDisplayName}}
|
||||
/>
|
||||
{{/if}}
|
||||
{{! Target name }}
|
||||
{{#if @model.sessionRecording.target}}
|
||||
<list.Item
|
||||
@icon='target'
|
||||
@color='boundary'
|
||||
@route='scopes.scope.targets.target'
|
||||
@model={{array
|
||||
@model.sessionRecording.target.scopeId
|
||||
@model.sessionRecording.target.id
|
||||
}}
|
||||
@text={{@model.sessionRecording.target.name}}
|
||||
>
|
||||
{{#if @model.sessionRecording.target.type}}
|
||||
<Hds::Badge @text={{@model.sessionRecording.target.type}} />
|
||||
{{/if}}
|
||||
</list.Item>
|
||||
{{/if}}
|
||||
{{! Bucket name }}
|
||||
{{#if @model.storageBucket}}
|
||||
<list.Item
|
||||
@icon='cloud-check'
|
||||
@color='boundary'
|
||||
@route='scopes.scope.storage-buckets.storage-bucket'
|
||||
@model={{array
|
||||
@model.storageBucket.scope.id
|
||||
@model.storageBucket.id
|
||||
}}
|
||||
@text={{@model.storageBucket.name}}
|
||||
/>
|
||||
{{/if}}
|
||||
</LinkListPanel>
|
||||
</div>
|
||||
</sb.Sidebar>
|
||||
</Layout::Sidebar>
|
||||
</div>
|
||||
</page.body>
|
||||
</Rose::Layout::Page>
|
||||
@@ -50,8 +50,8 @@ module('Acceptance | session recordings | read', function (hooks) {
|
||||
});
|
||||
urls.globalScope = `/scopes/global`;
|
||||
urls.sessionRecordings = `${urls.globalScope}/session-recordings`;
|
||||
urls.sessionRecording = `${urls.sessionRecordings}/${instances.sessionRecording.id}`;
|
||||
urls.channelRecording = `${urls.sessionRecording}/channels-by-connection/${instances.channelRecording.id}`;
|
||||
urls.sessionRecording = `${urls.sessionRecordings}/${instances.sessionRecording.id}/channels-by-connection`;
|
||||
urls.channelRecording = `${urls.sessionRecording}/${instances.channelRecording.id}`;
|
||||
authenticateSession({});
|
||||
featuresService = this.owner.lookup('service:features');
|
||||
});
|
||||
|
||||
+2
-2
@@ -48,8 +48,8 @@ module(
|
||||
});
|
||||
urls.globalScope = `/scopes/global`;
|
||||
urls.sessionRecordings = `${urls.globalScope}/session-recordings`;
|
||||
urls.sessionRecording = `${urls.sessionRecordings}/${instances.sessionRecording.id}`;
|
||||
urls.connectionRecording = `${urls.sessionRecording}/channels-by-connection/${instances.channelRecording.id}`;
|
||||
urls.sessionRecording = `${urls.sessionRecordings}/${instances.sessionRecording.id}/channels-by-connection`;
|
||||
urls.connectionRecording = `${urls.sessionRecording}/${instances.channelRecording.id}`;
|
||||
authenticateSession({});
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user