Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,19 @@ <h4>This price has been archived</h4>
<img src="assets/icons/sell.svg" class="icon" alt="Sale tag icon" />
<div>PRICE</div>
</div>
<div
class="flex gap-extra-small align-vert dimmed-extra dimmed-hover"
(click)="priceActions.CopyPriceId(price)"
(keydown.enter)="priceActions.CopyPriceId(price)"
(keydown.space)="priceActions.CopyPriceId(price)"
tabindex="0"
>
<div>{{ price.id }}</div>
<img src="assets/icons/content_copy.svg" class="icon" alt="Copy icon" />
</div>
<app-copy-text [text]="price.id" [opacity]="0.5"></app-copy-text>
</div>

<div class="flex align-vert space-between mb-snug">
@if(price.nickname){
<h1 class="mb-zero">{{ price.nickname }}</h1>
} @else {
<h1 class="mb-zero">Price for {{ price.product }}</h1>
}
<div class="flex align-vert gap-small">
@if(price.nickname){
<h1 class="mb-zero">{{ price.nickname }}</h1>
} @else {
<h1 class="mb-zero">Price for {{ price.product }}</h1>
} @if(!price.active){
<span class="chip grey-chip">Archived</span>
}
</div>
<div class="flex gap-extra-small align-vert">
<button
type="button"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import { PriceActionsHostComponent } from '../../components/price-actions-host/p
import { ActivatedRoute, Router } from '@angular/router';
import { PopupMenuAction, PopupMenuComponent } from '../../../../../shared';
import { EventsListComponent } from '../../../components';
import { MoreInfoHoverComponent } from '../../../../../shared';
import {
MoreInfoHoverComponent,
CopyTextComponent,
} from '../../../../../shared';

import { Subscription } from 'rxjs';

Expand All @@ -26,6 +29,7 @@ import { Subscription } from 'rxjs';
UpperCasePipe,
EventsListComponent,
MoreInfoHoverComponent,
CopyTextComponent,
],
templateUrl: './price-detail.component.html',
styleUrl: './price-detail.component.scss',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,14 +133,14 @@ <h2 class="section-title">Details</h2>
<img src="assets/icons/edit.svg" class="icon" alt="Edit icon" />
</button>
</div>
<div class="attribute">
<div class="attribute-title">Product ID</div>
<div class="attribute-value">{{ p.id }}</div>
<div class="mb">
<div class="bolded mb-small">Product ID</div>
<div class="dimmed"><app-copy-text [text]="p.id"></app-copy-text></div>
</div>
<div class="attribute">
<div class="attribute-title">Marketing feature list</div>
<div class="mb">
<div class="bolded mb-small">Marketing feature list</div>
@if(p.marketing_features.length > 0){
<div class="attribute-value">
<div class="dimmed">
@for(feature of p.marketing_features; track feature.name){
<span>{{ feature.name }}</span>
@if(feature !== p.marketing_features[p.marketing_features.length -
Expand All @@ -149,44 +149,44 @@ <h2 class="section-title">Details</h2>
} }
</div>
} @else {
<div class="attribute-value">—</div>
<div class="dimmed">—</div>
}
</div>
<div class="attribute">
<div class="attribute-title">Description</div>
<div class="attribute-value">
<div class="mb">
<div class="bolded mb-small">Description</div>
<div class="dimmed">
{{ p.description ? p.description : '—' }}
</div>
</div>
<div class="attribute">
<div class="attribute-title">Attributes</div>
<div class="attribute-value">—</div>
<div class="mb">
<div class="bolded mb-small">Attributes</div>
<div class="dimmed">—</div>
</div>
@if (detailsExpanded()) {
<div class="attribute">
<div class="attribute-title">Statement descriptor</div>
<div class="attribute-value">
<div class="mb">
<div class="bolded mb-small">Statement descriptor</div>
<div class="dimmed">
{{ p.statement_descriptor ? p.statement_descriptor : '—' }}
</div>
</div>
<div class="attribute">
<div class="attribute-title">Custom unit label</div>
<div class="attribute-value">
<div class="mb">
<div class="bolded mb-small">Custom unit label</div>
<div class="dimmed">
{{ p.unit_label ? p.unit_label : '—' }}
</div>
</div>
<div class="attribute">
<div class="attribute-title">Created</div>
<div class="attribute-value flex align-vert gap-extra-small">
<div class="mb">
<div class="bolded mb-small">Created</div>
<div class="dimmed flex align-vert gap-extra-small">
<img src="assets/icons/clock.svg" class="icon" alt="Clock icon" />
<span>{{
p.created ? (p.created * 1000 | date : 'd MMM y') : '—'
}}</span>
</div>
</div>
<div class="attribute">
<div class="attribute-title">Updated</div>
<div class="attribute-value flex align-vert gap-extra-small">
<div class="mb">
<div class="bolded mb-small">Updated</div>
<div class="dimmed flex align-vert gap-extra-small">
<img src="assets/icons/clock.svg" class="icon" alt="Clock icon" />
<span>{{
p.updated ? (p.updated * 1000 | date : 'd MMM y') : '—'
Expand Down Expand Up @@ -226,9 +226,9 @@ <h2 class="section-title">Metadata</h2>
</div>
@if (MetadataEntries(p.metadata).length > 0) { @for (entry of
MetadataEntries(p.metadata); track entry.key) {
<div class="attribute">
<div class="attribute-title">{{ entry.key }}</div>
<div class="attribute-value">{{ entry.value }}</div>
<div class="mb">
<div class="bolded mb-small">{{ entry.key }}</div>
<div class="dimmed">{{ entry.value }}</div>
</div>
} } @else {
<div class="dashed-placeholder">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
@use '../../../../../styles/buttons.scss' as *;
@use '../../../../../styles/account.scss' as *;
@use '../../../../../styles/align.scss' as *;
@use '../../../../../styles/spacing.scss' as *;
@use '../../../../../styles/forms.scss' as *;
@use '../../../../../styles/collapsible.scss' as *;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
PopupMenuComponent,
PaginatedListComponent,
PaginatedListColumn,
CopyTextComponent,
} from '../../../../../shared';
import { EventsListComponent } from '../../../components';
import { PriceActionsService } from '../../services/price-actions.service';
Expand All @@ -36,6 +37,7 @@ import { Subscription } from 'rxjs';
PaginatedListComponent,
EventsListComponent,
PriceActionsHostComponent,
CopyTextComponent,
],
templateUrl: './product-detail.component.html',
styleUrl: './product-detail.component.scss',
Expand Down
25 changes: 25 additions & 0 deletions apps/web/src/app/shared/ui/copy-text/copy-text.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<button
type="button"
class="copy-text"
[class.copy-text-copied]="copied()"
[attr.aria-label]="tooltipText"
(click)="Copy()"
>
<span class="copy-text-label" [style.opacity]="opacity">{{
displayText || text
}}</span>
<img
src="assets/icons/content_copy.svg"
class="icon copy-icon"
[style.opacity]="opacity"
alt="Copy icon"
/>

<span class="copy-tooltip copy-tooltip-hover" role="tooltip">
{{ tooltipText }}
</span>
<span class="copy-tooltip copy-tooltip-copied light-shadow" role="status">
<img src="assets/icons/check.svg" class="icon" alt="" />
<span>{{ copiedText }}</span>
</span>
</button>
109 changes: 109 additions & 0 deletions apps/web/src/app/shared/ui/copy-text/copy-text.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
@use '../../../styles/base.scss' as *;

:host {
display: inline-flex;
align-items: center;
line-height: 0;
}

.copy-text {
position: relative;
display: inline-flex;
align-items: center;
gap: $spacing-small;
padding: $spacing-extra-small $spacing-extra-small;
margin: 0;
background-color: transparent;
border: none;
border-radius: $border-radius-small;
font-family: inherit;
font-size: $font-size;
color: $text-color;
cursor: pointer;
transition: background-color $transition-fast ease-out;

&:hover,
&:focus-visible {
background-color: $darker-background-color;
}

&:focus-visible {
outline: 2px solid $base-color;
outline-offset: 2px;
}
}

.copy-text-label {
font-family: inherit;
line-height: 1.2;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

.copy-icon {
flex-shrink: 0;
opacity: $dimmed;
}

.copy-tooltip {
position: absolute;
left: 50%;
top: 100%;
z-index: 30;
display: inline-flex;
align-items: center;
gap: $spacing-small;
padding: $spacing-extra-small $spacing-small;
font-size: $font-size;
line-height: 1.4;
white-space: nowrap;
pointer-events: none;
opacity: 0;
visibility: hidden;
transform: translateX(-50%) translateY(4px);
transition: opacity $transition-fast ease-out,
transform $transition-fast ease-out, visibility 0s linear $transition-fast;
}

.copy-tooltip-hover {
margin-top: $spacing-small;
background-color: #1f2a44;
color: $background-color;
border-radius: $border-radius-small;
}

.copy-tooltip-copied {
margin-top: $spacing-extra-small;
background-color: $background-color;
color: $text-color;
border: 1px solid $darkest-background-color;
border-radius: $border-radius-small;

img {
filter: brightness(0) saturate(100%) invert(43%) sepia(76%) saturate(385%)
hue-rotate(116deg) brightness(94%) contrast(91%);
}
}

.copy-text:hover .copy-tooltip-hover,
.copy-text:focus-visible .copy-tooltip-hover {
opacity: 1;
visibility: visible;
transform: translateX(-50%) translateY(0);
transition: opacity $transition-fast ease-out,
transform $transition-fast ease-out, visibility 0s linear 0s;
}

.copy-text-copied .copy-tooltip-hover {
opacity: 0 !important;
visibility: hidden !important;
}

.copy-text-copied .copy-tooltip-copied {
opacity: 1;
visibility: visible;
transform: translateX(-50%) translateY(0);
transition: opacity $transition-fast ease-out,
transform $transition-fast ease-out, visibility 0s linear 0s;
}
46 changes: 46 additions & 0 deletions apps/web/src/app/shared/ui/copy-text/copy-text.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {
ChangeDetectionStrategy,
Component,
Input,
OnDestroy,
signal,
} from '@angular/core';

@Component({
selector: 'app-copy-text',
imports: [],
templateUrl: './copy-text.component.html',
styleUrl: './copy-text.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CopyTextComponent implements OnDestroy {
/** The value copied to the clipboard when clicked. */
@Input({ required: true }) text = '';
/** Optional override for the visible label. Falls back to [text]. */
@Input() displayText = '';
/** Tooltip shown on hover before copying. */
@Input() tooltipText = 'Copy to clipboard';
/** Confirmation shown briefly after copying. */
@Input() copiedText = 'Copied';

@Input() opacity = 1;

readonly copied = signal(false);
private resetTimer?: ReturnType<typeof setTimeout>;

async Copy(): Promise<void> {
if (!this.text) return;
try {
await navigator.clipboard.writeText(this.text);
} catch {
return;
}
this.copied.set(true);
clearTimeout(this.resetTimer);
this.resetTimer = setTimeout(() => this.copied.set(false), 1500);
}

ngOnDestroy(): void {
clearTimeout(this.resetTimer);
}
}
1 change: 1 addition & 0 deletions apps/web/src/app/shared/ui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export * from './test-mode-banner/test-mode-banner.component';
export * from './confirm-dialog/confirm-dialog.component';
export * from './popup-menu/popup-menu.component';
export * from './more-info-hover/more-info-hover.component';
export * from './copy-text/copy-text.component';
13 changes: 0 additions & 13 deletions apps/web/src/app/styles/account.scss
Original file line number Diff line number Diff line change
Expand Up @@ -142,19 +142,6 @@ h2.section-title {
justify-content: center;
}

.attribute {
margin-bottom: $spacing;
}

.attribute-title {
font-weight: $title-weight;
margin-bottom: $spacing-extra-small;
}

.attribute-value {
opacity: $dimmed;
}

@media only screen and (max-width: 1000px) {
h1 {
font-size: 24px;
Expand Down
Loading