Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve activity dashboard design #233

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/app/activity-dashboard/activity-dashboard.component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.event-tables-wrapper {
display: flex;
overflow-x: auto;
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ <h1 class="mat-headline" style="margin: 0px">Activity</h1>
</mat-grid-list>
</div>

<div style="display: flex">
<div class="event-tables-wrapper">
<app-event-tables
*ngFor="let assignee of assignees"
class="issue-table"
Expand Down
2 changes: 1 addition & 1 deletion src/app/activity-dashboard/activity-dashboard.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { ACTION_BUTTONS, EventTablesComponent } from './event-tables/event-table
})
export class ActivityDashboardComponent implements OnInit {
readonly displayedColumns = [TABLE_COLUMNS.DATE_START, TABLE_COLUMNS.ISSUE_COUNT, TABLE_COLUMNS.PR_COUNT, TABLE_COLUMNS.COMMENT_COUNT];
readonly expandedColumns = [EXPANDED_TABLE_COLUMNS.ID, EXPANDED_TABLE_COLUMNS.TITLE, EXPANDED_TABLE_COLUMNS.DATE];
readonly expandedColumns = [EXPANDED_TABLE_COLUMNS.TITLE, EXPANDED_TABLE_COLUMNS.DATE];
readonly actionButtons: ACTION_BUTTONS[] = [ACTION_BUTTONS.VIEW_IN_WEB];

startMinDate: Date;
Expand Down
3 changes: 2 additions & 1 deletion src/app/activity-dashboard/activity-dashboard.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import { SharedModule } from '../shared/shared.module';
import { ActivityDashboardRoutingModule } from './activity-dashboard-routing.module';
import { ActivityDashboardComponent } from './activity-dashboard.component';
import { EventTablesModule } from './event-tables/event-tables.module';
import { EventWeekDetailsComponent } from './event-week-details/event-week-details.component';

@NgModule({
declarations: [ActivityDashboardComponent],
declarations: [ActivityDashboardComponent, EventWeekDetailsComponent],
imports: [CommonModule, SharedModule, ActivityDashboardRoutingModule, EventTablesModule]
})
export class ActivityDashboardModule {}
115 changes: 105 additions & 10 deletions src/app/activity-dashboard/event-tables/event-tables.component.css
Original file line number Diff line number Diff line change
@@ -1,25 +1,56 @@
.table-container {
min-width: 348px;
display: block;
width: 100%;
margin: 10px;
min-width: 400px;
}

.actor-card {
display: flex;
align-items: center;
padding: 10px;
margin-bottom: 1px;
}

.actor-username {
flex-grow: 1;
font-size: 15px;
margin: 0;
text-align: center;
word-break: break-word;
}

.avatar-container {
margin-right: 10px;
}

.mat-table {
/* flex-wrap: wrap; */
width: 100%;
}

/* ref: https://material.angular.io/components/table/examples#table-expandable-rows */
.example-detail-row {
min-height: 0;
.mat-cell {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
padding: 0;
}

.mat-header-cell {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
padding: 0;
}

.example-element-row:not(.example-expanded-row):hover {
background: whitesmoke;
.mat-header-row {
white-space: nowrap;
}

.example-element-row:not(.example-expanded-row):active {
background: #efefef;
.example-element-row:hover {
border: 3px solid rgba(0, 0, 0, 0.514);
border-radius: 3px;
color: #210749;
}

.example-element-row td {
Expand All @@ -45,3 +76,67 @@
.green {
background-color: green;
}

.scrollable-container {
height: 53vh;
overflow: auto;
margin-bottom: 2px;
scrollbar-width: none;
position: relative;
}

.scrollable-container::-webkit-scrollbar {
display: none;
}

/* Ref: https://css-scroll-shadows.vercel.app */
.scrollable-container::before {
pointer-events: none;
content: '';
position: absolute;
z-index: 2;
height: 6px;
width: 100%;
display: block;
background-image: linear-gradient(to bottom, white 66%, transparent);
}

.scrollable-container::after {
pointer-events: none;
content: '';
position: sticky;
z-index: 2;
top: 100%;
height: 6px;
width: 100%;
display: block;
background-image: linear-gradient(to top, white 66%, transparent);
}

.scrollable-container-wrapper {
position: relative;
}

.scrollable-container-wrapper::before {
pointer-events: none;
content: '';
position: absolute;
z-index: 1;
top: 0;
left: 0;
right: 0;
height: 5px;
background-image: radial-gradient(farthest-side at 50% 0, rgba(0, 0, 0, 0.5), transparent);
}

.scrollable-container-wrapper::after {
pointer-events: none;
content: '';
position: absolute;
z-index: 1;
bottom: 0;
left: 0;
right: 0;
height: 5px;
background-image: radial-gradient(farthest-side at 50% 100%, rgba(0, 0, 0, 0.5), transparent);
}
124 changes: 58 additions & 66 deletions src/app/activity-dashboard/event-tables/event-tables.component.html
Original file line number Diff line number Diff line change
@@ -1,75 +1,67 @@
<div class="table-container">
<h1 *ngIf="this.actor !== undefined">
{{ this.actor.login }}
</h1>

<mat-table [dataSource]="this.githubEvents" matSort multiTemplateDataRows class="mat-elevation-z8">
<ng-container matColumnDef="date_start">
<mat-header-cell *matHeaderCellDef mat-sort-header> Date </mat-header-cell>
<mat-cell *matCellDef="let element">
<span (click)="$event.stopPropagation()" style="cursor: default">
{{ element.date_start }}
</span>
</mat-cell>
</ng-container>

<ng-container matColumnDef="issue_count">
<mat-header-cell *matHeaderCellDef mat-sort-header> Issue # </mat-header-cell>
<mat-cell *matCellDef="let element" [ngClass]="colorCell(element.issue_count)">
<span (click)="$event.stopPropagation()" style="cursor: default">
{{ element.issue_count }}
</span>
</mat-cell>
</ng-container>

<ng-container matColumnDef="pr_count">
<mat-header-cell *matHeaderCellDef mat-sort-header> PR # </mat-header-cell>
<mat-cell *matCellDef="let element" [ngClass]="colorCell(element.pr_count)">
<span (click)="$event.stopPropagation()" style="cursor: default">
{{ element.pr_count }}
</span>
</mat-cell>
</ng-container>
<mat-card class="actor-card">
<div
mat-card-avatar
*ngIf="this.actor"
class="avatar-container"
[ngStyle]="{
background: 'url(' + this.actor.avatar_url + ')',
'background-size': '40px'
}"
></div>
<mat-card-title class="actor-username">
{{ this.actor !== undefined ? this.actor.login : 'Unknown' }}
</mat-card-title>
</mat-card>

<ng-container matColumnDef="comment_count">
<mat-header-cell *matHeaderCellDef mat-sort-header> Comment # </mat-header-cell>
<mat-cell *matCellDef="let element" [ngClass]="colorCell(element.comment_count)">
<span (click)="$event.stopPropagation()" style="cursor: default">
{{ element.comment_count }}
</span>
</mat-cell>
</ng-container>
<div class="scrollable-container-wrapper">
<div class="scrollable-container">
<mat-table [dataSource]="this.githubEvents" matSort multiTemplateDataRows>
<ng-container matColumnDef="date_start">
<mat-header-cell *matHeaderCellDef mat-sort-header> Date </mat-header-cell>
<mat-cell *matCellDef="let element">
<span (click)="$event.stopPropagation()" style="cursor: default">
{{ element.date_start }}
</span>
</mat-cell>
</ng-container>

<!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns
ref: https://material.angular.io/components/table/examples#table-expandable-rows -->
<ng-container matColumnDef="issue_count">
<mat-header-cell *matHeaderCellDef mat-sort-header> Issue # </mat-header-cell>
<mat-cell *matCellDef="let element" [ngClass]="colorCell(element.issue_count)">
<span (click)="$event.stopPropagation()" style="cursor: default">
{{ element.issue_count }}
</span>
</mat-cell>
</ng-container>

<ng-container matColumnDef="expandedDetail">
<mat-cell *matCellDef="let element" [attr.colspan]="columnsToDisplay.length">
<div class="example-element-detail" [@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'">
<mat-table [dataSource]="element.events">
<ng-container matColumnDef="{{ expandableColumn }}" *ngFor="let expandableColumn of expandedColumnsToDisplay">
<mat-header-cell *matHeaderCellDef>{{ expandableColumn }}</mat-header-cell>
<mat-cell *matCellDef="let property">
{{ property[expandableColumn] }}
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="expandedColumnsToDisplay"></mat-header-row>
<mat-row *matRowDef="let property; columns: expandedColumnsToDisplay"></mat-row>
</mat-table>
</div>
</mat-cell>
</ng-container>
<ng-container matColumnDef="pr_count">
<mat-header-cell *matHeaderCellDef mat-sort-header> PR # </mat-header-cell>
<mat-cell *matCellDef="let element" [ngClass]="colorCell(element.pr_count)">
<span (click)="$event.stopPropagation()" style="cursor: default">
{{ element.pr_count }}
</span>
</mat-cell>
</ng-container>

<mat-header-row *matHeaderRowDef="this.columnsToDisplay"></mat-header-row>>
<mat-row
*matRowDef="let element; columns: this.columnsToDisplay"
class="example-element-row"
[class.example-expanded-row]="expandedElement === element"
(click)="showExpandedDetails(element)"
></mat-row>
<ng-container matColumnDef="comment_count">
<mat-header-cell *matHeaderCellDef mat-sort-header> Comment # </mat-header-cell>
<mat-cell *matCellDef="let element" [ngClass]="colorCell(element.comment_count)">
<span (click)="$event.stopPropagation()" style="cursor: default">
{{ element.comment_count }}
</span>
</mat-cell>
</ng-container>

<mat-row *matRowDef="let row; columns: ['expandedDetail']" style="cursor: pointer" class="example-detail-row"></mat-row>
</mat-table>
<mat-header-row *matHeaderRowDef="this.columnsToDisplay"></mat-header-row>
<mat-row
*matRowDef="let eventWeek; columns: this.columnsToDisplay"
class="example-element-row"
(click)="openDialog(eventWeek)"
></mat-row>
</mat-table>
</div>
</div>

<mat-card *ngIf="this.githubEvents.isLoading$ | async" style="display: flex; justify-content: center; align-items: center">
<mat-progress-spinner color="primary" mode="indeterminate" diameter="50" strokeWidth="5"></mat-progress-spinner>
Expand Down
38 changes: 22 additions & 16 deletions src/app/activity-dashboard/event-tables/event-tables.component.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { animate, state, style, transition, trigger } from '@angular/animations';
import { AfterViewInit, Component, Input, OnInit, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { GithubUser } from '../../core/models/github-user.model';
import { ErrorHandlingService } from '../../core/services/error-handling.service';
import { GithubEventService } from '../../core/services/githubevent.service';
import { LoggingService } from '../../core/services/logging.service';
import { EventWeekDetailsComponent } from '../event-week-details/event-week-details.component';
import { EventWeek } from '../event-week.model';
import { GithubEventDataTable } from './GithubEventDataTable';
import { NoEventsError } from './no-events-error.model';

export enum ACTION_BUTTONS {
VIEW_IN_WEB,
Expand All @@ -16,14 +20,7 @@ export enum ACTION_BUTTONS {
@Component({
selector: 'app-event-tables',
templateUrl: './event-tables.component.html',
styleUrls: ['./event-tables.component.css'],
animations: [
trigger('detailExpand', [
state('collapsed', style({ height: '0px', minHeight: '0' })),
state('expanded', style({ height: '*' })),
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)'))
])
]
styleUrls: ['./event-tables.component.css']
})

/**
Expand All @@ -44,10 +41,12 @@ export class EventTablesComponent implements OnInit, AfterViewInit {

public readonly action_buttons = ACTION_BUTTONS;

/** The expanded row */
expandedElement: EventWeek | null;

constructor(public githubEventService: GithubEventService, private logger: LoggingService) {}
constructor(
public githubEventService: GithubEventService,
public dialog: MatDialog,
private logger: LoggingService,
private errorHandling: ErrorHandlingService
) {}

ngOnInit() {
this.githubEvents = new GithubEventDataTable(this.githubEventService, this.logger, this.sort, this.paginator, this.actor, this.filters);
Expand Down Expand Up @@ -90,11 +89,18 @@ export class EventTablesComponent implements OnInit, AfterViewInit {
// window.open('https://github.com/', '_blank');
}

/** Show individual GithubEvents of EventWeek. */
showExpandedDetails(element: EventWeek) {
if (element.events.length > 0) {
this.expandedElement = this.expandedElement === element ? null : element;
/** Opens dialog to show the event details of the selected week. */
openDialog(eventWeek: EventWeek) {
if (eventWeek.events.length <= 0) {
this.errorHandling.handleError(new NoEventsError());
return;
}
this.dialog.open(EventWeekDetailsComponent, {
data: {
eventWeek,
expandedColumnsToDisplay: this.expandedColumnsToDisplay
}
});
}

/** Returns color string of cell. Shade darkens with magnitude of number. */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export class NoEventsError extends Error {
constructor() {
super('No events found for this week.');
Object.setPrototypeOf(this, NoEventsError.prototype);
}
}
Loading
Loading