-
Notifications
You must be signed in to change notification settings - Fork 100
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
Create Product::Avatar
component
#394
Changes from 10 commits
4c93e39
eb2a9e0
08ae24d
a9f5054
a2068e0
58980e1
8c4360b
048bcc7
5fcf37a
8ffe69f
33558e8
28590d1
1df9ef0
6ec08e4
98bb18b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import Component from "@glimmer/component"; | ||
import getProductID from "hermes/utils/get-product-id"; | ||
import { inject as service } from "@ember/service"; | ||
import FlightIcon from "@hashicorp/ember-flight-icons/components/flight-icon"; | ||
import ProductAreasService from "hermes/services/product-areas"; | ||
import { assert } from "@ember/debug"; | ||
import { HermesAvatarSize } from "hermes/types/avatar-size"; | ||
|
||
interface ProductAvatarComponentSignature { | ||
Element: HTMLDivElement; | ||
Args: { | ||
product: string; | ||
size?: `${HermesAvatarSize}`; | ||
}; | ||
Blocks: { | ||
default: []; | ||
}; | ||
} | ||
|
||
export default class ProductAvatarComponent extends Component<ProductAvatarComponentSignature> { | ||
@service declare productAreas: ProductAreasService; | ||
|
||
private get productID(): string { | ||
const productID = getProductID(this.args.product); | ||
assert("productID must edxist", productID); | ||
return productID; | ||
} | ||
|
||
private get sizeIsMedium() { | ||
return this.args.size === HermesAvatarSize.Medium; | ||
} | ||
|
||
private get sizeIsLarge() { | ||
return this.args.size === HermesAvatarSize.Large; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Curious about this pattern vs. checking the value in the template using a more generic getter that just returns the size (like was added in the thumbnail component in this PR) - seems like that could be more scalable? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Most of it was the convenience of having everything in one file in the early phase. But it's worth noting that Tailwind's dynamic class rules limit our efficiency a bit.* Still, we're past the early phase, so we can be smarter here. I refactored to use CSS classes. * Of course, there are workarounds. I think safe-listing the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool, sounds good 👍 |
||
|
||
<template> | ||
<div | ||
data-test-product-avatar | ||
class="product-badge relative flex shrink-0 shrink-0 items-center justify-center rounded-md | ||
{{this.productID}} | ||
{{if | ||
this.sizeIsLarge | ||
'h-8 w-8' | ||
(if this.sizeIsMedium 'h-7 w-7' 'h-5 w-5') | ||
}} | ||
" | ||
...attributes | ||
> | ||
<FlightIcon @name={{this.productID}} class="h-4 w-4" /> | ||
</div> | ||
</template> | ||
} | ||
|
||
declare module "@glint/environment-ember-loose/registry" { | ||
export default interface Registry { | ||
"Product::Avatar": typeof ProductAvatarComponent; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export enum HermesAvatarSize { | ||
Small = "small", | ||
Medium = "medium", | ||
Large = "large", | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { TestContext, render } from "@ember/test-helpers"; | ||
import { hbs } from "ember-cli-htmlbars"; | ||
import { setupRenderingTest } from "ember-qunit"; | ||
import ProductAreasService from "hermes/services/product-areas"; | ||
import { module, test } from "qunit"; | ||
|
||
const AVATAR = "[data-test-product-avatar]"; | ||
const ICON = ".flight-icon"; | ||
|
||
interface ProductAvatarTestContext extends TestContext { | ||
product: string; | ||
} | ||
|
||
module("Integration | Component | product/avatar", function (hooks) { | ||
setupRenderingTest(hooks); | ||
|
||
hooks.beforeEach(async function (this: ProductAvatarTestContext) { | ||
const productAreasService = this.owner.lookup( | ||
"service:product-areas", | ||
) as ProductAreasService; | ||
}); | ||
|
||
test("it renders the product icon", async function (this: ProductAvatarTestContext, assert) { | ||
this.set("product", "Terraform"); | ||
|
||
await render<ProductAvatarTestContext>(hbs` | ||
<Product::Avatar | ||
@product={{this.product}} | ||
/> | ||
`); | ||
|
||
assert.dom(AVATAR).hasClass("terraform"); | ||
assert.dom(ICON).hasAttribute("data-test-icon", "terraform"); | ||
|
||
this.set("product", "Vault"); | ||
|
||
assert.dom(AVATAR).hasClass("vault"); | ||
assert.dom(ICON).hasAttribute("data-test-icon", "vault"); | ||
|
||
// expect an error if the product is not found | ||
assert.throws(() => { | ||
this.set("product", "foo"); | ||
}); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we still need
sizeIsLarge()
with this?