forked from apex-enterprise-patterns/fflib-apex-common
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added initial versions of base LWCs, including a confirmation dialog …
…and a formatted modal
- Loading branch information
1 parent
78dabd3
commit fad409d
Showing
25 changed files
with
21,458 additions
and
1 deletion.
There are no files selected for viewing
113 changes: 113 additions & 0 deletions
113
...rk/default/ortoo-core/default/lwc/confirmationDialog/__tests__/confirmationDialog.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import { createElement } from 'lwc'; | ||
import ConfirmationDialog from 'c/confirmationDialog'; | ||
|
||
describe('c-confirmation-dialog', () => { | ||
afterEach(() => { | ||
// The jsdom instance is shared across test cases in a single file so reset the DOM | ||
while (document.body.firstChild) { | ||
document.body.removeChild(document.body.firstChild); | ||
} | ||
}); | ||
|
||
it('When set to visible, and with a title contains a div containing the title, directing it to the title slot', () => { | ||
const element = createElement('c-confirmation-dialog', { | ||
is: ConfirmationDialog | ||
}); | ||
element.title = 'The title'; | ||
element.visible = true; | ||
document.body.appendChild(element); | ||
|
||
const expectedElement = element.shadowRoot.querySelector( 'c-formatted-modal div[slot="title"]' ); | ||
expect( expectedElement.innerHTML ).toBe( 'The title' ); | ||
}); | ||
|
||
it('When set to visible, contains a div containing a message slot, directing it to the modal contents slot', () => { | ||
const element = createElement('c-confirmation-dialog', { | ||
is: ConfirmationDialog | ||
}); | ||
element.message = 'The message'; | ||
element.visible = true; | ||
document.body.appendChild(element); | ||
|
||
const expectedElement = element.shadowRoot.querySelector( 'c-formatted-modal div[slot="contents"]' ); | ||
expect( expectedElement ).not.toBe( null ); | ||
}); | ||
|
||
it('When set to visible, contains a div containing cancel and confirm buttons with the specified labels, directing them to the modal footer slot', () => { | ||
const element = createElement('c-confirmation-dialog', { | ||
is: ConfirmationDialog | ||
}); | ||
element.confirmLabel = 'Confirm'; | ||
element.cancelLabel = 'Cancel'; | ||
element.visible = true; | ||
document.body.appendChild(element); | ||
|
||
const expectedElement = element.shadowRoot.querySelector( 'c-formatted-modal div[slot="footer"]' ); | ||
expect( expectedElement ).not.toBe( null ); | ||
|
||
expect( expectedElement.querySelector( '[title="Confirm"]' ) ).not.toBe( null ); | ||
expect( expectedElement.querySelector( '[title="Cancel"]' ) ).not.toBe( null ); | ||
}); | ||
|
||
it('Clicking the confirm button will issue an event containing the confirm message', () => { | ||
|
||
const CONFIRM_MESSAGE = 'The confirm message'; | ||
const CANCEL_MESSAGE = 'The cancel message'; | ||
|
||
const element = createElement('c-confirmation-dialog', { | ||
is: ConfirmationDialog | ||
}); | ||
|
||
element.confirmLabel = 'Confirm'; | ||
element.confirmMessage = CONFIRM_MESSAGE; | ||
element.cancelLabel = 'Cancel'; | ||
element.cancelMessage = CANCEL_MESSAGE; | ||
|
||
element.visible = true; | ||
document.body.appendChild(element); | ||
|
||
const confirmHandler = jest.fn(); | ||
element.addEventListener( 'confirm', confirmHandler ) ; | ||
|
||
const cancelHandler = jest.fn(); | ||
element.addEventListener( 'cancel', cancelHandler ) ; | ||
|
||
element.shadowRoot.querySelector( '[title="Confirm"]' ).click(); | ||
|
||
expect( confirmHandler ).toHaveBeenCalled(); | ||
expect( confirmHandler.mock.calls[0][0].detail ).toBe( CONFIRM_MESSAGE ); | ||
|
||
expect( cancelHandler ).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('Clicking the cancel button will issue an event containing the cancel message', () => { | ||
|
||
const CONFIRM_MESSAGE = 'The confirm message'; | ||
const CANCEL_MESSAGE = 'The cancel message'; | ||
|
||
const element = createElement('c-confirmation-dialog', { | ||
is: ConfirmationDialog | ||
}); | ||
|
||
element.confirmLabel = 'Confirm'; | ||
element.confirmMessage = CONFIRM_MESSAGE; | ||
element.cancelLabel = 'Cancel'; | ||
element.cancelMessage = CANCEL_MESSAGE; | ||
|
||
element.visible = true; | ||
document.body.appendChild(element); | ||
|
||
const confirmHandler = jest.fn(); | ||
element.addEventListener( 'confirm', confirmHandler ) ; | ||
|
||
const cancelHandler = jest.fn(); | ||
element.addEventListener( 'cancel', cancelHandler ) ; | ||
|
||
element.shadowRoot.querySelector( '[title="Cancel"]' ).click(); | ||
|
||
expect( cancelHandler ).toHaveBeenCalled(); | ||
expect( cancelHandler.mock.calls[0][0].detail ).toBe( CANCEL_MESSAGE ); | ||
|
||
expect( confirmHandler ).not.toHaveBeenCalled(); | ||
}); | ||
}); |
30 changes: 30 additions & 0 deletions
30
framework/default/ortoo-core/default/lwc/confirmationDialog/confirmationDialog.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<template> | ||
<c-formatted-modal visible={visible}> | ||
<div slot="title"> | ||
{title} | ||
</div> | ||
|
||
<div slot="contents"> | ||
<slot name="message"></slot> | ||
</div> | ||
|
||
<div slot="footer"> | ||
<lightning-button-group> | ||
<lightning-button | ||
variant="neutral" | ||
name="cancel" | ||
label={cancelLabel} | ||
title={cancelLabel} | ||
onclick={handleCancel} | ||
></lightning-button> | ||
<lightning-button | ||
variant="brand" | ||
name="confirm" | ||
label={confirmLabel} | ||
title={confirmLabel} | ||
onclick={handleConfirm} | ||
></lightning-button> | ||
</lightning-button-group> | ||
</div> | ||
</c-formatted-modal> | ||
</template> |
27 changes: 27 additions & 0 deletions
27
framework/default/ortoo-core/default/lwc/confirmationDialog/confirmationDialog.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { LightningElement, api } from 'lwc'; | ||
|
||
export default class ConfirmationDialog extends LightningElement { | ||
|
||
@api title; | ||
@api name; | ||
// TODO: default labels | ||
// TODO: consider standard variations - No / *Yes ; Cancel / *Confirm ; Cancel / *Save | ||
@api confirmLabel; | ||
@api cancelLabel; | ||
|
||
// The message to send back to the parent component when the confirmation button is clicked | ||
@api confirmMessage; | ||
|
||
// The message to send back to the parent component when the cancel button is clicked | ||
@api cancelMessage; | ||
|
||
@api visible; | ||
|
||
handleCancel( event ) { | ||
this.dispatchEvent( new CustomEvent( 'cancel', { detail: this.cancelMessage } ) ); | ||
} | ||
|
||
handleConfirm( event ) { | ||
this.dispatchEvent( new CustomEvent( 'confirm', { detail: this.confirmMessage } ) ); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
framework/default/ortoo-core/default/lwc/confirmationDialog/confirmationDialog.js-meta.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> | ||
<apiVersion>52.0</apiVersion> | ||
<description>Provides a modal dialog box that will request confirmation or cancellation. Both events can have a 'message' provided to them by the consumer, allowing the dialog to state what has been confirmed or cancelled.</description> | ||
<masterLabel>Confirmation Dialog</masterLabel> | ||
<isExposed>false</isExposed> | ||
</LightningComponentBundle> |
112 changes: 112 additions & 0 deletions
112
framework/default/ortoo-core/default/lwc/formattedModal/__tests__/formattedModal.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import { createElement } from 'lwc'; | ||
import FormattedModal from 'c/formattedModal'; | ||
|
||
describe('c-formatted-modal', () => { | ||
afterEach(() => { | ||
// The jsdom instance is shared across test cases in a single file so reset the DOM | ||
while (document.body.firstChild) { | ||
document.body.removeChild(document.body.firstChild); | ||
} | ||
}); | ||
it('Will use a c-modal to render the modal', () => { | ||
const element = createElement('c-formatted-modal', { | ||
is: FormattedModal | ||
}); | ||
document.body.appendChild(element); | ||
element.visible = true; | ||
|
||
return Promise.resolve() | ||
.then( () => { | ||
const modal = element.shadowRoot.querySelector( 'c-modal' ); | ||
expect( modal ).not.toBe( null ); | ||
}); | ||
}); | ||
|
||
it('Will create a contents slot in the c-modal', () => { | ||
const element = createElement('c-formatted-modal', { | ||
is: FormattedModal | ||
}); | ||
document.body.appendChild(element); | ||
element.visible = true; | ||
|
||
return Promise.resolve() // we need this because we set the element to visible *after* adding it to the dom. | ||
// this means we need to wait for a render cycle to complete. | ||
.then( () => { | ||
const modalContentsSlot = element.shadowRoot.querySelector( 'c-modal [slot="contents"]' ); | ||
expect( modalContentsSlot ).not.toBe( null ); | ||
}); | ||
}); | ||
|
||
it('Will populate the contents of the c-modal with slots that are exposed externally', () => { | ||
const element = createElement('c-formatted-modal', { | ||
is: FormattedModal | ||
}); | ||
document.body.appendChild(element); | ||
element.visible = true; | ||
|
||
return Promise.resolve() | ||
.then( () => { | ||
const titleSlot = element.shadowRoot.querySelector( 'c-modal [slot="contents"] slot[name="title"]' ) | ||
const contentsSlot = element.shadowRoot.querySelector( 'c-modal [slot="contents"] slot[name="contents"]' ) | ||
const footerSlot = element.shadowRoot.querySelector( 'c-modal [slot="contents"] slot[name="footer"]' ) | ||
expect( titleSlot ).not.toBe( null ); | ||
expect( contentsSlot ).not.toBe( null ); | ||
expect( footerSlot ).not.toBe( null ); | ||
}); | ||
}); | ||
|
||
it('When the modal is set to be not visible, will not render the slots', () => { | ||
const element = createElement('c-formatted-modal', { | ||
is: FormattedModal | ||
}); | ||
document.body.appendChild(element); | ||
element.visible = false; | ||
|
||
return Promise.resolve() | ||
.then( () => { | ||
const titleSlot = element.shadowRoot.querySelector( 'c-modal [slot="contents"] slot[name="title"]' ) | ||
const contentsSlot = element.shadowRoot.querySelector( 'c-modal [slot="contents"] slot[name="contents"]' ) | ||
const footerSlot = element.shadowRoot.querySelector( 'c-modal [slot="contents"] slot[name="footer"]' ) | ||
expect( titleSlot ).toBe( null ); | ||
expect( contentsSlot ).toBe( null ); | ||
expect( footerSlot ).toBe( null ); | ||
}); | ||
}); | ||
|
||
it('will default the modal to be non visible', () => { | ||
const element = createElement('c-formatted-modal', { | ||
is: FormattedModal | ||
}); | ||
document.body.appendChild(element); | ||
|
||
return Promise.resolve() | ||
.then( () => { | ||
const titleSlot = element.shadowRoot.querySelector( 'c-modal [slot="contents"] slot[name="title"]' ) | ||
const contentsSlot = element.shadowRoot.querySelector( 'c-modal [slot="contents"] slot[name="contents"]' ) | ||
const footerSlot = element.shadowRoot.querySelector( 'c-modal [slot="contents"] slot[name="footer"]' ) | ||
expect( titleSlot ).toBe( null ); | ||
expect( contentsSlot ).toBe( null ); | ||
expect( footerSlot ).toBe( null ); | ||
}); | ||
}); | ||
|
||
it('will forward the cancel event on the c-modal, if one it issued', () => { | ||
const element = createElement('c-formatted-modal', { | ||
is: FormattedModal | ||
}); | ||
element.visible = true; | ||
document.body.appendChild(element); | ||
|
||
let cancelHandler = jest.fn(); | ||
element.addEventListener( 'cancel', cancelHandler ); | ||
|
||
return Promise.resolve() | ||
.then( () => { | ||
const modal = element.shadowRoot.querySelector( 'c-modal' ); | ||
modal.dispatchEvent( new CustomEvent( 'cancel' ) ); | ||
}) | ||
.then( () => { | ||
expect( cancelHandler ).toHaveBeenCalled(); | ||
}) | ||
}); | ||
}); |
20 changes: 20 additions & 0 deletions
20
framework/default/ortoo-core/default/lwc/formattedModal/formattedModal.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<template> | ||
<c-modal | ||
visible={visible} | ||
oncancel={handleCancel} | ||
> | ||
<div slot="contents"> | ||
<header class="slds-modal__header"> | ||
<h2 id="modal-heading-01" class="slds-text-heading_medium slds-hyphenate"> | ||
<slot name="title"></slot> | ||
</h2> | ||
</header> | ||
<div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1"> | ||
<slot name="contents"></slot> | ||
</div> | ||
<footer class="slds-modal__footer"> | ||
<slot name="footer"></slot> | ||
</footer> | ||
</div> | ||
</c-modal> | ||
</template> |
14 changes: 14 additions & 0 deletions
14
framework/default/ortoo-core/default/lwc/formattedModal/formattedModal.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { LightningElement, api } from 'lwc'; | ||
|
||
export default class FormattedModal extends LightningElement { | ||
@api visible; | ||
|
||
handleCancel() { | ||
this.dispatchCancel(); | ||
} | ||
|
||
dispatchCancel() { | ||
const event = new CustomEvent( 'cancel' ); | ||
this.dispatchEvent( event ); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
framework/default/ortoo-core/default/lwc/formattedModal/formattedModal.js-meta.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> | ||
<apiVersion>52.0</apiVersion> | ||
<description>A modal that follows the standard Lightning Card rendering convention of providing title, content and footer slots.</description> | ||
<masterLabel>Formatted Modal</masterLabel> | ||
<isExposed>false</isExposed> | ||
</LightningComponentBundle> |
37 changes: 37 additions & 0 deletions
37
framework/default/ortoo-core/default/lwc/layoutConstants/layoutConstants.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
const DISPLAY_DENSITY = Object.freeze({ | ||
COMFY : 'comfy', | ||
COMPACT : 'compact', | ||
DEFAULT : 'comfy', | ||
}); | ||
|
||
const getKeyForDisplayDensity = displayDensity => { | ||
for ( let key in DISPLAY_DENSITY ) { | ||
if ( DISPLAY_DENSITY[ key ] == displayDensity ) { | ||
return key; | ||
} | ||
} | ||
} | ||
|
||
const LABEL_PROPERTIES = Object.freeze({ | ||
COMFY : { | ||
VARIANT : 'standard', | ||
CLASSES : 'slds-form-element slds-form-element_stacked' | ||
}, | ||
COMPACT : { | ||
VARIANT : 'label-inline', | ||
CLASSES : 'slds-form-element slds-form-element_horizontal' | ||
}, | ||
HIDDEN : { | ||
VARIANT : 'label-hidden', | ||
CLASSES : '' | ||
}, | ||
}); | ||
|
||
const CONSTANTS = Object.freeze({ | ||
DISPLAY_DENSITY : DISPLAY_DENSITY, | ||
LABEL_PROPERTIES : LABEL_PROPERTIES, | ||
getLabelVariant : displayDensity => LABEL_PROPERTIES[ getKeyForDisplayDensity( displayDensity ) ].VARIANT, | ||
getLabelClasses : displayDensity => LABEL_PROPERTIES[ getKeyForDisplayDensity( displayDensity ) ].CLASSES | ||
}); | ||
|
||
export default CONSTANTS; |
7 changes: 7 additions & 0 deletions
7
framework/default/ortoo-core/default/lwc/layoutConstants/layoutConstants.js-meta.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> | ||
<apiVersion>52.0</apiVersion> | ||
<description>A service modal that provides constants relating to layouts (e.g. display density and classes for labels) as well as functions for returning the correct constants in certain circumstances.</description> | ||
<masterLabel>Layout Constants</masterLabel> | ||
<isExposed>false</isExposed> | ||
</LightningComponentBundle> |
Oops, something went wrong.