src/app/modules/right-sidebar/right-sidebar.component.ts
The right sidebar
changeDetection | ChangeDetectionStrategy.OnPush |
selector | ccf-right-sidebar |
styleUrls | ./right-sidebar.component.scss |
templateUrl | ./right-sidebar.component.html |
Properties |
|
Inputs |
Outputs |
HostBindings |
constructor(model: ModelState, registration: RegistrationState, page: PageState, astags: AnatomicalStructureTagState)
|
||||||||||||||||||||
Creates an instance of right sidebar component.
Parameters :
|
modalClosed | |
Type : boolean
|
|
Default value : false
|
|
Whether or not the initial registration modal has been closed |
registrationExpanded | |
Type : EventEmitter
|
|
class |
Type : "ccf-right-sidebar"
|
Default value : 'ccf-right-sidebar'
|
HTML class name |
Readonly clsName |
Type : string
|
Default value : 'ccf-right-sidebar'
|
Decorators :
@HostBinding('class')
|
HTML class name |
import { ChangeDetectionStrategy, Component, EventEmitter, HostBinding, Input, Output } from '@angular/core';
import { AnatomicalStructureTagState } from '../../core/store/anatomical-structure-tags/anatomical-structure-tags.state';
import { ModelState } from '../../core/store/model/model.state';
import { PageState } from '../../core/store/page/page.state';
import { RegistrationState } from '../../core/store/registration/registration.state';
/**
* The right sidebar
*/
@Component({
selector: 'ccf-right-sidebar',
templateUrl: './right-sidebar.component.html',
styleUrls: ['./right-sidebar.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class RightSidebarComponent {
/** HTML class name */
@HostBinding('class') readonly clsName = 'ccf-right-sidebar';
/** Whether or not the initial registration modal has been closed */
@Input() modalClosed = false;
@Output() readonly registrationExpanded = new EventEmitter<boolean>();
/**
* Creates an instance of right sidebar component.
*
* @param model Model state service
* @param registration Registration state service
* @param page The page state
* @param astags The anatomical structure tags state
*/
constructor(
readonly model: ModelState,
readonly registration: RegistrationState,
readonly page: PageState,
readonly astags: AnatomicalStructureTagState,
) {}
}
<div class="info-button-container">
<ccf-info-button
videoID="j4f9_xdBrK0"
infoTitle="CCF Registration User Interface"
documentationUrl="assets/docs/README.md"
></ccf-info-button>
</div>
<div class="scroll-wrapper">
<div class="container">
<mat-expansion-panel
class="registration-metadata-panel"
(opened)="registrationExpanded.emit(true)"
(closed)="registrationExpanded.emit(false)"
>
<mat-expansion-panel-header class="header">
<mat-panel-title matTooltip="">Registration Metadata</mat-panel-title>
</mat-expansion-panel-header>
<ccf-registration-metadata></ccf-registration-metadata>
</mat-expansion-panel>
<mat-divider></mat-divider>
<mat-expansion-panel class="tissue-block-controls-panel" [expanded]="true">
<mat-expansion-panel-header class="header">
<mat-panel-title matTooltip="">Tissue Block Controls</mat-panel-title>
</mat-expansion-panel-header>
<ccf-block-size-input [blockSize]="(model.blockSize$ | async)!" (blockSizeChange)="model.setBlockSize($event)">
</ccf-block-size-input>
<ccf-slices-input
[slicesConfig]="$any(model.slicesConfig$ | async)"
(slicesConfigChange)="model.setSlicesConfig($event)"
>
</ccf-slices-input>
<ccf-rotation-slider [rotation]="$any(model.rotation$ | async)" (rotationChange)="model.setRotation($event)">
</ccf-rotation-slider>
</mat-expansion-panel>
<mat-divider></mat-divider>
<mat-expansion-panel class="tags-container" [expanded]="true">
<mat-expansion-panel-header class="header">
<mat-panel-title matTooltip="Review tags generated via collision detection. Add or delete tags as needed."
>Anatomical Structure Tags</mat-panel-title
>
</mat-expansion-panel-header>
<ccf-tag-search [search]="astags.searchExternal" (added)="astags.addTags($event)"> </ccf-tag-search>
<ccf-tag-list
*ngIf="(model.organ$ | async)?.name; else tagListPlaceholder"
class="tag-list"
[tags]="(astags.tags$ | async) ?? []"
(tagRemoved)="astags.removeTag($event)"
>
</ccf-tag-list>
<ng-template #tagListPlaceholder> </ng-template>
<div class="legend">
<span class="dot assigned"></span>
<span class="text assigned">Assigned</span>
<span class="dot added"></span>
<span class="text added">Added</span>
</div>
</mat-expansion-panel>
<mat-divider></mat-divider>
<div class="filler"></div>
<ccf-review-button
class="review-button"
[registrationCallbackSet]="(page.registrationCallbackSet$ | async) ?? false"
[displayErrors]="(registration.displayErrors$ | async) ?? false"
[userValid]="(registration.valid$ | async) ?? false"
[metaData]="(registration.metadata$ | async) ?? []"
(registerData)="registration.register()"
(enterErrorMode)="registration.setDisplayErrors(!registration.isValid)"
>
</ccf-review-button>
</div>
</div>
./right-sidebar.component.scss
:host {
display: block;
height: calc(100% - 2.5rem);
margin-top: 1rem;
margin-bottom: 1.5rem;
.info-button-container {
height: 3.75rem;
display: flex;
justify-content: flex-end;
}
.scroll-wrapper {
overflow-y: scroll;
height: calc(100% - 6rem);
scrollbar-width: thin;
&::-webkit-scrollbar {
width: 0.75rem;
}
.container {
display: flex;
flex-direction: column;
min-height: 100%;
margin: 0 1.5rem;
.review-button {
position: absolute;
bottom: 1.5rem;
z-index: 999;
width: calc(100% - 3.5rem);
}
mat-divider {
border-top-width: 3px;
}
mat-expansion-panel {
box-shadow: none;
mat-expansion-panel-header {
padding: 0 0.5rem 0 0;
font-weight: bold;
-webkit-user-select: none;
-moz-user-select: none;
font-size: 1rem;
height: 3rem;
}
::ng-deep .mat-expansion-panel-body {
padding-left: 0;
padding-right: 0;
}
}
.tags-container {
// Allow tag search to overflow when displaying results
overflow: visible;
::ng-deep .mat-expansion-panel-body {
padding-left: 0;
padding-right: 0;
}
.header {
height: 3rem;
}
.search {
margin-top: 1rem;
.icon.add {
position: absolute;
// Sizes and offsets found by experimentation
width: 3.625rem;
height: 3.625rem;
font-size: 3.625rem;
top: -1.9375rem;
right: -1.1875rem;
}
}
.tag-list {
max-height: 32rem;
margin-left: -1rem;
}
.tag-list-placeholder {
display: flex;
height: 4rem;
align-items: center;
justify-content: center;
font-weight: 400;
}
.legend {
display: flex;
width: 100%;
margin-top: 1.5rem;
align-items: center;
font-size: 0.9rem;
.dot {
display: inline-block;
width: 1rem;
height: 1rem;
border-radius: 50%;
&.assigned {
margin-left: 0.5rem;
}
&.added {
margin-left: 1rem;
}
}
.text {
margin-left: 0.5rem;
}
}
}
.filler {
flex-grow: 1;
}
}
}
}