<div class="container-fluid p-4">
<div class="row d-flex flex-row ps-3">
-
<!-- First Grid to hold Details and Inventory Card-->
- <div class="col-sm-3 d-flex flex-column ps-2">
-
- <!-- Details Card-->
- <cd-card cardTitle="Details"
- i18n-title
- class="details"
- aria-label="Details card">
- <dl class="ms-4 me-4">
+ <div class="col-sm-3 d-flex flex-column ps-2 details-card">
+ <cd-productive-card title="Details"
+ i18n-title>
+ <dl>
<dt>Cluster ID</dt>
<dd>{{ detailsCardData.fsid }}</dd>
<dt>Orchestrator</dt>
<dd>
<a routerLink="/api-docs"
target="_blank">
- {{ origin }}/api-docs
+ {{ origin }}/api-docs
<i class="fa fa-external-link"></i>
</a>
</dd>
</span>
</ng-container>
</dl>
- </cd-card>
+ </cd-productive-card>
<!-- Inventory Card-->
<cd-card cardTitle="Inventory"
max-width: 83vw;
}
}
+
+.details-card {
+ dl,
+ dd:last-of-type {
+ margin-bottom: 0;
+ }
+}
it('should render all cards', () => {
fixture.detectChanges();
const dashboardCards = fixture.debugElement.nativeElement.querySelectorAll('cd-card');
- expect(dashboardCards.length).toBe(5);
+ expect(dashboardCards.length).toBe(4);
});
it('should get corresponding data into detailsCardData', () => {
import { FeedbackComponent } from '../shared/feedback/feedback.component';
import { DashboardComponent } from './dashboard/dashboard.component';
import { HealthPieComponent } from './health-pie/health-pie.component';
-import { InputModule, ModalModule, SelectModule, ToggletipModule } from 'carbon-components-angular';
import { OverviewComponent } from '../overview/overview.component';
+import {
+ InputModule,
+ ModalModule,
+ SelectModule,
+ ThemeModule,
+ ToggletipModule
+} from 'carbon-components-angular';
@NgModule({
imports: [
ModalModule,
InputModule,
SelectModule,
- OverviewComponent
+ OverviewComponent,
+ ThemeModule
],
exports: [OverviewComponent],
declarations: [DashboardComponent, HealthPieComponent, FeedbackComponent],
PopoverModule,
InlineLoadingModule,
TagModule,
- LinkModule
+ LinkModule,
+ LayerModule
} from 'carbon-components-angular';
import EditIcon from '@carbon/icons/es/edit/20';
import CodeIcon from '@carbon/icons/es/code/16';
import IdeaIcon from '@carbon/icons/es/idea/20';
import CloseIcon from '@carbon/icons/es/close/16';
import { TearsheetStepComponent } from './tearsheet-step/tearsheet-step.component';
+import { ProductiveCardComponent } from './productive-card/productive-card.component';
@NgModule({
imports: [
PopoverModule,
InlineLoadingModule,
TagModule,
- LinkModule
+ LinkModule,
+ LayerModule
],
declarations: [
SparklineComponent,
DetailsCardComponent,
ToastComponent,
TearsheetComponent,
- TearsheetStepComponent
+ TearsheetStepComponent,
+ ProductiveCardComponent
],
providers: [provideCharts(withDefaultRegisterables())],
exports: [
DetailsCardComponent,
ToastComponent,
TearsheetComponent,
- TearsheetStepComponent
+ TearsheetStepComponent,
+ ProductiveCardComponent
]
})
export class ComponentsModule {
--- /dev/null
+<cds-tile class="productive-card"
+ [ngClass]="{'productive-card--shadow': applyShadow}"
+ [cdsLayer]="0">
+ <header
+ cdsGrid
+ [useCssGrid]="true"
+ [narrow]="true"
+ class="productive-card-header">
+ <h2 cdsCol
+ [columnNumbers]="{md: headerActionTemplate ? 12 : 16, lg: headerActionTemplate ? 12 : 16}"
+ class="cds--type-heading-compact-02 productive-card-header-title">
+ {{title}}
+ </h2>
+ @if(headerActionTemplate) {
+ <div cdsCol
+ [columnNumbers]="{md: 4, lg: 4}"
+ class="productive-card-header-actions">
+ <ng-container *ngTemplateOutlet="headerActionTemplate"></ng-container>
+ </div>
+ }
+ </header>
+ <section class="productive-card-section cds--type-body-compact-01"
+ [ngClass]="{'productive-card-section--footer': footerTemplate}">
+ <ng-content></ng-content>
+ </section>
+ @if(footerTemplate) {
+ <footer class="productive-card-footer">
+ <ng-container *ngTemplateOutlet="footerTemplate"></ng-container>
+ </footer>
+ }
+</cds-tile>
--- /dev/null
+@use '@carbon/colors';
+
+.productive-card {
+ margin: 0;
+ padding: 0;
+
+ &-header {
+ margin: 0;
+ padding: var(--cds-spacing-05);
+
+ &-title {
+ margin: 0;
+ }
+
+ &-actions {
+ margin: 0;
+ }
+ }
+
+ &-section {
+ margin: 0;
+ padding: var(--cds-spacing-05);
+ padding-top: 0;
+
+ &--footer {
+ padding-bottom: 0;
+ }
+ }
+
+ &-footer {
+ height: var(--cds-spacing-08);
+ padding: var(--cds-spacing-05);
+ }
+
+ &--shadow {
+ background-color: var(--cds-layer);
+ position: relative;
+ overflow: hidden; // ensures proper edge fade
+ background-image:
+ // cyan left edge
+ radial-gradient(120% 60% at -15% 100%, rgba(colors.$cyan-60, 0.13) 0%, transparent 65%),
+ // cyan right edge
+ radial-gradient(120% 60% at 115% 100%, rgba(colors.$cyan-60, 0.1) 0%, transparent 65%),
+ // pink center
+ radial-gradient(120% 60% at 50% 100%, rgba(colors.$magenta-60, 0.11) 0%, transparent 70%);
+ box-shadow: var(--cds-ai-drop-shadow), inset 0 0 0 1px var(--cds-ai-inner-shadow);
+ }
+}
--- /dev/null
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ProductiveCardComponent } from './productive-card.component';
+import { GridModule, LayerModule, TilesModule } from 'carbon-components-angular';
+
+describe('ProductiveCardComponent', () => {
+ let component: ProductiveCardComponent;
+ let fixture: ComponentFixture<ProductiveCardComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ProductiveCardComponent],
+ imports: [GridModule, LayerModule, TilesModule]
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(ProductiveCardComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
--- /dev/null
+import { Component, ContentChild, Input, TemplateRef } from '@angular/core';
+
+/**
+ * A generic productive card component.
+ *
+ * @example
+ * <cd-productive-card title="Card Title"
+ * [applyShadow]="true">
+ * <ng-template #headerAction>...</ng-template>
+ * <ng-template #footer>...</ng-template>
+ * <p>My card body content</p>
+ * </cd-productive-card>
+ */
+@Component({
+ selector: 'cd-productive-card',
+ standalone: false,
+ templateUrl: './productive-card.component.html',
+ styleUrl: './productive-card.component.scss'
+})
+export class ProductiveCardComponent {
+ /* Card Title */
+ @Input() title!: string;
+
+ /* Optional: Applies a tinted-colored background to card */
+ @Input() applyShadow: boolean = false;
+
+ /* Optional: Header action template, appears alongwith title in top-right corner */
+ @ContentChild('headerAction', {
+ read: TemplateRef
+ })
+ headerActionTemplate?: TemplateRef<any>;
+
+ /* Optional: Footer template , otherwise no footer will be used for card.*/
+ @ContentChild('footer', {
+ read: TemplateRef
+ })
+ footerTemplate?: TemplateRef<any>;
+}