Skip to content

Commit

Permalink
Add conditional "rejected" badge (#580)
Browse files Browse the repository at this point in the history
* Add `has-rejected-doc` helper

* Refactor out helpers

* Grammar tweaks

* Badge logic refactor
  • Loading branch information
jeffdaley authored Feb 6, 2024
1 parent 181e317 commit f4ef0f9
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 96 deletions.
8 changes: 3 additions & 5 deletions web/app/components/editable-field/read-value.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@
<ol data-test-person-list class="person-list">
{{#each this.emails as |email|}}
<li>
<Person
@badge={{if
(and @document (has-approved-doc this.document email))
"approved"
}}
<EditableField::ReadValue::Person
@email={{email}}
@document={{@document}}
/>

</li>
{{/each}}
</ol>
Expand Down
51 changes: 51 additions & 0 deletions web/app/components/editable-field/read-value/person.gts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import Component from "@glimmer/component";
import { HermesDocument } from "hermes/types/document";
import Person from "hermes/components/person";

interface EditableFieldReadValuePersonSignature {
Args: {
email: string;
document?: HermesDocument;
};
}

export default class EditableFieldReadValuePerson extends Component<EditableFieldReadValuePersonSignature> {
/**
* Whether the document has been approved by the user.
* True if the email is in the approvedBy list.
* Dictates the badge on the Person component.
*/
protected get hasApprovedDoc(): boolean {
const { document, email } = this.args;
return !!document?.approvedBy?.some((e) => e === email);
}

/**
* Whether the document has been rejected by the user.
* True if the email is in the changesRequestedBy list.
* Dictates the badge on the Person component.
*/
protected get hasRejectedDoc(): boolean {
const { document, email } = this.args;
return !!document?.changesRequestedBy?.some((e) => e === email);
}

/**
* The conditional badge value to pass to the Person component.
* Return badges for "approved" and "rejected" scenarios.
*/
protected get maybeBadgeValue(): string | undefined {
if (this.hasApprovedDoc) return "approved";
if (this.hasRejectedDoc) return "rejected";
}

<template>
<Person @badge={{this.maybeBadgeValue}} @email={{@email}} />
</template>
}

declare module "@glint/environment-ember-loose/registry" {
export default interface Registry {
"EditableField::ReadValue::Person": typeof EditableFieldReadValuePerson;
}
}
10 changes: 6 additions & 4 deletions web/app/components/person/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
<div class="flex w-full space-x-2" ...attributes>
<div class="relative shrink-0">
<Person::Avatar @size="small" @email={{@email}} />
{{#if (eq @badge "approved")}}
{{#if this.badgeIsShown}}
<div
data-test-person-approved-badge
data-test-person-badge
data-test-person-badge-type={{@badge}}
class="absolute -bottom-1.5 -right-1.5 flex origin-bottom-right scale-[70%] rounded-full bg-color-page-faint p-0.5"
>
<FlightIcon
@name="check-circle-fill"
class="text-color-palette-green-200"
data-test-person-badge-icon
@name={{this.badgeIcon}}
class={{this.badgeIconColor}}
/>
</div>
{{/if}}
Expand Down
35 changes: 35 additions & 0 deletions web/app/components/person/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,41 @@ export default class PersonComponent extends Component<PersonComponentSignature>
"Unknown"
);
}

/**
* Whether the badge should be shown.
* True if the badge is either "approved" or "rejected".
*/
protected get badgeIsShown() {
const { badge } = this.args;
return badge === "approved" || badge === "rejected";
}

/**
* The icon to use in the badge, when shown.
* Reflects either the "approved" or "rejected" state.
*/
protected get badgeIcon() {
switch (this.args.badge) {
case "approved":
return "check-circle-fill";
case "rejected":
return "x-circle-fill";
}
}

/**
* The color to use for the badge icon, when shown.
* Reflects either the "approved" or "rejected" state.
*/
protected get badgeIconColor() {
switch (this.badgeIcon) {
case "check-circle-fill":
return "text-color-palette-green-200";
case "x-circle-fill":
return "text-color-foreground-faint";
}
}
}

declare module "@glint/environment-ember-loose/registry" {
Expand Down
27 changes: 0 additions & 27 deletions web/app/helpers/has-approved-doc.ts

This file was deleted.

2 changes: 1 addition & 1 deletion web/tests/acceptance/authenticated/document-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const TITLE_SELECTOR = "[data-test-document-title]";
const SUMMARY_SELECTOR = "[data-test-document-summary]";
const CONTRIBUTORS_SELECTOR = "[data-test-document-contributors]";
const APPROVERS_SELECTOR = "[data-test-document-approvers]";
const APPROVED_BADGE_SELECTOR = "[data-test-person-approved-badge]";
const APPROVED_BADGE_SELECTOR = "[data-test-person-badge-type='approved']";
const PRODUCT_SELECT_SELECTOR = "[data-test-product-select]";
const PRODUCT_SELECT_PRODUCT_NAME = "[data-test-product-value]";
const POPOVER = "[data-test-x-dropdown-list-content]";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { MirageTestContext, setupMirage } from "ember-cli-mirage/test-support";
import { setupRenderingTest } from "ember-qunit";
import { TEST_USER_EMAIL, authenticateTestUser } from "hermes/mirage/utils";
import { HermesDocument } from "hermes/types/document";
import { module, test } from "qunit";

const BADGE = "[data-test-person-badge]";
const APPROVED_BADGE = '[data-test-person-badge-type="approved"]';
const REJECTED_BADGE = '[data-test-person-badge-type="rejected"]';
const ICON = "[data-test-person-badge-icon]";

interface Context extends MirageTestContext {
document: HermesDocument;
email: string;
}

module(
"Integration | Component | editable-field/read-value/person",
function (hooks) {
setupRenderingTest(hooks);
setupMirage(hooks);

hooks.beforeEach(function (this: Context) {
authenticateTestUser(this);
});

test("it renders a conditional badge", async function (this: Context, assert) {
this.set("document", {
approvedBy: [],
changesRequestedBy: [],
});

this.set("email", TEST_USER_EMAIL);

await render<Context>(hbs`
<EditableField::ReadValue::Person
@email={{this.email}}
@document={{this.document}}
/>
`);

assert.dom(BADGE).doesNotExist();

this.set("document", {
approvedBy: [TEST_USER_EMAIL],
});

assert.dom(APPROVED_BADGE).exists();

assert
.dom(ICON)
.hasClass("text-color-palette-green-200")
.hasAttribute("data-test-icon", "check-circle-fill");

this.set("document", {
changesRequestedBy: [TEST_USER_EMAIL],
});

assert.dom(REJECTED_BADGE).exists();

assert
.dom(ICON)
.hasClass("text-color-foreground-faint")
.hasAttribute("data-test-icon", "x-circle-fill");
});
},
);
22 changes: 0 additions & 22 deletions web/tests/integration/components/person-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import {
pushMirageIntoStore,
} from "hermes/mirage/utils";

const APPROVED_BADGE = "[data-test-person-approved-badge]";

interface PersonComponentTestContext extends MirageTestContext {
ignoreUnknown: boolean;
email: string;
Expand Down Expand Up @@ -66,26 +64,6 @@ module("Integration | Component | person", function (hooks) {
assert.dom(".person").doesNotExist();
});

test("it renders a contextual checkmark", async function (this: PersonComponentTestContext, assert) {
this.set("badge", undefined);

await render<PersonComponentTestContext>(hbs`
<Person @email="" @badge={{this.badge}} />
`);

assert.dom(APPROVED_BADGE).doesNotExist();

this.set("badge", "approved");

assert.dom(APPROVED_BADGE).exists();

this.set("badge", "pending");

assert
.dom(APPROVED_BADGE)
.doesNotExist("only shows a badge if the correct value is passed in");
});

test(`the person is labeled "Me" if it's them`, async function (this: PersonComponentTestContext, assert) {
this.set("email", TEST_USER_EMAIL);

Expand Down
37 changes: 0 additions & 37 deletions web/tests/integration/helpers/has-approved-doc-test.ts

This file was deleted.

0 comments on commit f4ef0f9

Please sign in to comment.