Skip to content

Commit

Permalink
feat: Prevent title duplicates with includeTitleDuplicates (#859)
Browse files Browse the repository at this point in the history
Without includeTitleDuplicates: true
- Multiple duplicates with Title only, allows multiple toasts but stil counts duplicates.
- Multiple duplicates with Message only, wont allow duplicates but doesnt count.
- Two different titles with same message, picks up as duplcate and new title not shown as toast.

With includeTitleDuplicates: true
- Multiple duplicates with Title only, wont display duplicates and counts correctly
- Multiple duplicates with Message only, wont allow duplicates but still doesnt count.
- Two different titles with same message, no longer sees this as duplicate and new toast shown.

Co-authored-by: HarikumarG <harikumarmgp@gmail.com>
Co-authored-by: GOLDSWORTHYSlatford Dominic <GoldsworthySlatfordD@derriford.phnt.swest.nhs.uk>
Co-authored-by: Scott Cooper <scttcper@gmail.com>
  • Loading branch information
4 people committed Oct 6, 2020
1 parent 68b5ac6 commit 4ec9725
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 3 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ options:
| preventDuplicates | boolean | false | Block duplicate messages |
| countDuplicates | boolean | false | Displays a duplicates counter (preventDuplicates must be true). Toast must have a title and duplicate message |
| resetTimeoutOnDuplicate | boolean | false | Reset toast timeout on duplicate (preventDuplicates must be true) |
| includeTitleDuplicates | boolean | false | Include the title of a toast when checking for duplicates (by default only message is compared) |

##### iconClasses defaults

Expand Down Expand Up @@ -212,6 +213,8 @@ imports: [
export interface ActiveToast {
/** Your Toast ID. Use this to close it individually */
toastId: number;
/** the title of your toast. Stored to prevent duplicates if includeTitleDuplicates set */
title: string
/** the message of your toast. Stored to prevent duplicates */
message: string;
/** a reference to the component see portal.ts */
Expand Down
7 changes: 7 additions & 0 deletions src/app/home/home.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@
Reset timeout on duplicate
</label>
</div>
<div class="form-check ml-2">
<input class="form-check-input" type="checkbox" [(ngModel)]="options.includeTitleDuplicates" id="includeTitleDuplicate"
[disabled]="!options.preventDuplicates">
<label class="form-check-label" for="includeTitleDuplicate">
Include title in duplicate checks
</label>
</div>
<div class="form-check">
<input
class="form-check-input"
Expand Down
7 changes: 7 additions & 0 deletions src/lib/toastr/toastr-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ export interface GlobalConfig extends IndividualConfig {
* default: false
*/
resetTimeoutOnDuplicate: boolean;
/**
* consider the title of a toast when checking if duplicate
* default: false
*/
includeTitleDuplicates: boolean;
}

/**
Expand Down Expand Up @@ -200,6 +205,8 @@ export const DefaultNoComponentGlobalConfig: GlobalConfig = {
preventDuplicates: false,
countDuplicates: false,
resetTimeoutOnDuplicate: false,
includeTitleDuplicates: false,

iconClasses: {
error: 'toast-error',
info: 'toast-info',
Expand Down
18 changes: 15 additions & 3 deletions src/lib/toastr/toastr.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
export interface ActiveToast<C> {
/** Your Toast ID. Use this to close it individually */
toastId: number;
/** the title of your toast. Stored to prevent duplicates */
title: string;
/** the message of your toast. Stored to prevent duplicates */
message: string;
/** a reference to the component see portal.ts */
Expand Down Expand Up @@ -128,13 +130,17 @@ export class ToastrService {
/**
* Determines if toast message is already shown
*/
findDuplicate(message = '', resetOnDuplicate = false, countDuplicates = false) {
findDuplicate(title = '', message = '', resetOnDuplicate: boolean, countDuplicates: boolean) {
const { includeTitleDuplicates } = this.toastrConfig;

for (const toast of this.toasts) {
if (toast.message === message) {
const hasDuplicateTitle = includeTitleDuplicates && toast.title === title;
if ((!includeTitleDuplicates || hasDuplicateTitle) && toast.message === message) {
toast.toastRef.onDuplicate(resetOnDuplicate, countDuplicates);
return toast;
}
}

return null;
}

Expand Down Expand Up @@ -187,11 +193,16 @@ export class ToastrService {
// if timeout = 0 resetting it would result in setting this.hideTime = Date.now(). Hence, we only want to reset timeout if there is
// a timeout at all
const duplicate = this.findDuplicate(
title,
message,
this.toastrConfig.resetTimeoutOnDuplicate && config.timeOut > 0,
this.toastrConfig.countDuplicates,
);
if (message && this.toastrConfig.preventDuplicates && duplicate !== null) {
if (
((this.toastrConfig.includeTitleDuplicates && title) || message) &&
this.toastrConfig.preventDuplicates &&
duplicate !== null
) {
return duplicate;
}

Expand Down Expand Up @@ -226,6 +237,7 @@ export class ToastrService {
toastRef.componentInstance = portal.instance;
const ins: ActiveToast<any> = {
toastId: this.index,
title: title || '',
message: message || '',
toastRef,
onShown: toastRef.afterActivate(),
Expand Down

0 comments on commit 4ec9725

Please sign in to comment.