Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
9 changes: 6 additions & 3 deletions src/app/core/auth/auth.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,10 +266,13 @@ export class AuthEffects {
filter((action: Action) => !IDLE_TIMER_IGNORE_TYPES.includes(action.type)),
// Using switchMap the effect will stop subscribing to the previous timer if a new action comes
// in, and start a new timer
switchMap(() =>
switchMap(() => {
// Calculate the timeout: timeUntilIdle minus warningTimeBeforeIdle (if configured)
const warningTime = environment.auth.ui.warningTimeBeforeIdle || 0;
const timeout = Math.max(environment.auth.ui.timeUntilIdle - warningTime, 0);
// Start a timer outside of Angular's zone
timer(environment.auth.ui.timeUntilIdle, new LeaveZoneScheduler(this.zone, asyncScheduler))
),
return timer(timeout, new LeaveZoneScheduler(this.zone, asyncScheduler));
}),
// Re-enter the zone to dispatch the action
observeOn(new EnterZoneScheduler(this.zone, queueScheduler)),
map(() => new SetUserAsIdleAction()),
Expand Down
11 changes: 9 additions & 2 deletions src/app/shared/idle-modal/idle-modal.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { IdleModalComponent } from './idle-modal.component';
import { AuthService } from '../../core/auth/auth.service';
import { By } from '@angular/platform-browser';
import { Store } from '@ngrx/store';
import { LogOutAction } from '../../core/auth/auth.actions';
import { LogOutAction, RefreshTokenAction } from '../../core/auth/auth.actions';

describe('IdleModalComponent', () => {
let component: IdleModalComponent;
Expand All @@ -19,7 +19,8 @@ describe('IdleModalComponent', () => {

beforeEach(waitForAsync(() => {
modalStub = jasmine.createSpyObj('modalStub', ['close']);
authServiceStub = jasmine.createSpyObj('authService', ['setIdle']);
authServiceStub = jasmine.createSpyObj('authService', ['setIdle', 'getToken']);
authServiceStub.getToken.and.returnValue({ access_token: 'test-token' });
storeStub = jasmine.createSpyObj('store', ['dispatch']);
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot()],
Expand Down Expand Up @@ -49,6 +50,9 @@ describe('IdleModalComponent', () => {
spyOn(component.response, 'emit');
component.extendSessionPressed();
}));
it('should dispatch RefreshTokenAction', () => {
expect(storeStub.dispatch).toHaveBeenCalledWith(jasmine.any(RefreshTokenAction));
});
it('should set idle to false', () => {
expect(authServiceStub.setIdle).toHaveBeenCalledWith(false);
});
Expand Down Expand Up @@ -77,6 +81,9 @@ describe('IdleModalComponent', () => {
spyOn(component.response, 'emit');
component.closePressed();
}));
it('should dispatch RefreshTokenAction', () => {
expect(storeStub.dispatch).toHaveBeenCalledWith(jasmine.any(RefreshTokenAction));
});
it('should set idle to false', () => {
expect(authServiceStub.setIdle).toHaveBeenCalledWith(false);
});
Expand Down
7 changes: 6 additions & 1 deletion src/app/shared/idle-modal/idle-modal.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { AuthService } from '../../core/auth/auth.service';
import { hasValue } from '../empty.util';
import { Store } from '@ngrx/store';
import { AppState } from '../../app.reducer';
import { LogOutAction } from '../../core/auth/auth.actions';
import { LogOutAction, RefreshTokenAction } from '../../core/auth/auth.actions';

@Component({
selector: 'ds-idle-modal',
Expand Down Expand Up @@ -74,6 +74,11 @@ export class IdleModalComponent implements OnInit {
if (hasValue(this.graceTimer)) {
clearTimeout(this.graceTimer);
}
// Refresh the token to extend session
const token = this.authService.getToken();
if (hasValue(token)) {
this.store.dispatch(new RefreshTokenAction(token));
}
this.authService.setIdle(false);
this.closeModal();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,33 +24,41 @@
</div>
</div>
<div class="ml-2 space-children-mr">
<button type="button"
class="btn btn-secondary"
id="save"
[attr.data-test]="'save' | dsBrowserOnly"
[dsBtnDisabled]="(processingSaveStatus | async) || !(hasUnsavedModification | async)"
(click)="save($event)">
<span><i class="fas fa-save"></i> {{'submission.general.save' | translate}}</span>
</button>
<button type="button"
[class.btn-primary]="!(showDepositAndDiscard | async)"
[class.btn-secondary]="(showDepositAndDiscard | async)"
class="btn"
id="saveForLater"
[attr.data-test]="'save-for-later' | dsBrowserOnly"
[dsBtnDisabled]="(processingSaveStatus | async) || (processingDepositStatus | async)"
(click)="saveLater($event)">
<span><i class="fas fa-save"></i> {{'submission.general.save-later' | translate}}</span>
</button>
<button *ngIf="(showDepositAndDiscard | async)"
type="button"
id="deposit"
[attr.data-test]="'deposit' | dsBrowserOnly"
class="btn btn-success"
[dsBtnDisabled]="(processingSaveStatus | async) || (processingDepositStatus | async)"
(click)="deposit($event)">
<span><i class="fas fa-plus"></i> {{'submission.general.deposit' | translate}}</span>
</button>
<!-- Save button: saves progress and continues editing -->
<span [ngbTooltip]="!(hasUnsavedModification | async) ? ('submission.buttons.save.disabled.tooltip' | translate) : ('submission.buttons.save.tooltip' | translate)">
<button type="button"
class="btn btn-secondary"
id="save"
[attr.data-test]="'save' | dsBrowserOnly"
[dsBtnDisabled]="(processingSaveStatus | async) || !(hasUnsavedModification | async)"
(click)="save($event)">
<span><i class="fas fa-save"></i> {{'submission.general.save' | translate}}</span>
</button>
</span>
<!-- Save & Exit button: saves progress and exits the form -->
<span [ngbTooltip]="'submission.buttons.save-exit.tooltip' | translate">
<button type="button"
[class.btn-primary]="!(showDepositAndDiscard | async)"
[class.btn-secondary]="(showDepositAndDiscard | async)"
class="btn"
id="saveAndExit"
Comment thread
amadulhaxxani marked this conversation as resolved.
[attr.data-test]="'save-and-exit' | dsBrowserOnly"
Comment thread
amadulhaxxani marked this conversation as resolved.
[dsBtnDisabled]="(processingSaveStatus | async) || (processingDepositStatus | async)"
(click)="saveLater($event)">
<span><i class="fas fa-door-open"></i> {{'submission.general.save-and-exit' | translate}}</span>
</button>
</span>
<!-- Submit for Review button: sends entry to editor for review -->
<span *ngIf="(showDepositAndDiscard | async)" [ngbTooltip]="'submission.buttons.submit.tooltip' | translate">
<button type="button"
id="deposit"
[attr.data-test]="'deposit' | dsBrowserOnly"
class="btn btn-success"
[dsBtnDisabled]="(processingSaveStatus | async) || (processingDepositStatus | async)"
(click)="deposit($event)">
<span><i class="fas fa-check"></i> {{'submission.general.submit-review' | translate}}</span>
</button>
</span>
</div>
</div>
</div>
Expand Down
26 changes: 22 additions & 4 deletions src/assets/i18n/cs.json5
Original file line number Diff line number Diff line change
Expand Up @@ -6372,6 +6372,24 @@
// "submission.general.save-later": "Save for later",
"submission.general.save-later": "Uložit na později",

// "submission.general.save-and-exit": "Save & Exit",
"submission.general.save-and-exit": "Uložit a Ukončit",

// "submission.general.submit-review": "Submit for Review",
"submission.general.submit-review": "Odeslat ke Kontrole",

// "submission.buttons.save.tooltip": "Save progress and continue editing",
"submission.buttons.save.tooltip": "Uložit průběh a pokračovat v úpravách",

// "submission.buttons.save.disabled.tooltip": "The autosave is active, there are no pending changes to save",
"submission.buttons.save.disabled.tooltip": "Automatické ukládání je aktivní, nejsou žádné neuložené změny",

// "submission.buttons.save-exit.tooltip": "Save progress and exit the form",
"submission.buttons.save-exit.tooltip": "Uložit průběh a ukončit formulář",

// "submission.buttons.submit.tooltip": "Submit to editor for review",
"submission.buttons.submit.tooltip": "Odeslat editorovi ke kontrole",

// "submission.import-external.page.title": "Import metadata from an external source",
"submission.import-external.page.title": "Importovat metadata z externího zdroje",

Expand Down Expand Up @@ -6972,8 +6990,8 @@
// "submission.sections.general.deposit_error_notice": "There was an issue when submitting the item, please try again later.",
"submission.sections.general.deposit_error_notice": "Při odesílání záznamu došlo k problému, zkuste to prosím později.",

// "submission.sections.general.deposit_success_notice": "Submission deposited successfully.",
"submission.sections.general.deposit_success_notice": "Příspěvek úspěšně uložen.",
// "submission.sections.general.deposit_success_notice": "Submission successful! Your entry has been sent to the editor for review and will be published after approval.",
"submission.sections.general.deposit_success_notice": "Odeslání úspěšné! Váš příspěvek byl odeslán editorovi ke kontrole a bude publikován po schválení.",

// "submission.sections.general.discard_error_notice": "There was an issue when discarding the item, please try again later.",
"submission.sections.general.discard_error_notice": "Při vyřazování záznamu došlo k problému, zkuste to prosím později.",
Expand Down Expand Up @@ -9600,8 +9618,8 @@
// "submission.sections.clarin-license.head.license-more-details": "See more details for the licenses",
"submission.sections.clarin-license.head.license-more-details": "Více podrobností o licencích",

// "submission.sections.clarin-license.head.license-do-not-suits-needs": "None of these licenses suits your needs",
"submission.sections.clarin-license.head.license-do-not-suits-needs": "Žádná z těchto licencí nevyhovuje vašim potřebám",
// "submission.sections.clarin-license.head.license-do-not-suits-needs": "If none of these licenses suit your needs:",
"submission.sections.clarin-license.head.license-do-not-suits-needs": "Pokud vám žádná z těchto licencí nevyhovuje:",

// "submission.sections.clarin-license.head.license-not-offer-proceeds": "If you need to use a license we currently do not offer, proceed as follows:",
"submission.sections.clarin-license.head.license-not-offer-proceeds": "Pokud potřebujete použít licenci, kterou v současné době nenabízíme, postupujte následovně:",
Expand Down
17 changes: 15 additions & 2 deletions src/assets/i18n/en.json5
Original file line number Diff line number Diff line change
Expand Up @@ -4249,6 +4249,19 @@

"submission.general.save-later": "Save for later",

"submission.general.save-and-exit": "Save & Exit",

"submission.general.submit-review": "Submit for Review",

// Button tooltips (Issue #2 - UX Improvement)
"submission.buttons.save.tooltip": "Save progress and continue editing",

"submission.buttons.save.disabled.tooltip": "The autosave is active, there are no pending changes to save",

"submission.buttons.save-exit.tooltip": "Save progress and exit the form",

"submission.buttons.submit.tooltip": "Submit to editor for review",

"submission.import-external.page.title": "Import metadata from an external source",

"submission.import-external.title": "Import metadata from an external source",
Expand Down Expand Up @@ -4649,7 +4662,7 @@

"submission.sections.general.deposit_error_notice": "There was an issue when submitting the item, please try again later.",

"submission.sections.general.deposit_success_notice": "Submission deposited successfully.",
"submission.sections.general.deposit_success_notice": "Submission successful! Your entry has been sent to the editor for review and will be published after approval.",

"submission.sections.general.discard_error_notice": "There was an issue when discarding the item, please try again later.",

Expand Down Expand Up @@ -6362,7 +6375,7 @@

"submission.sections.clarin-license.head.license-more-details": "See more details for the licenses",

"submission.sections.clarin-license.head.license-do-not-suits-needs": "None of these licenses suits your needs",
"submission.sections.clarin-license.head.license-do-not-suits-needs": "If none of these licenses suit your needs:",

"submission.sections.clarin-license.head.license-not-offer-proceeds": "If you need to use a license we currently do not offer, proceed as follows:",

Expand Down
2 changes: 2 additions & 0 deletions src/config/auth-config.interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export interface AuthConfig extends Config {
ui: {
// The amount of time before the idle warning is shown
timeUntilIdle: number;
// The amount of time before timeUntilIdle to show a warning
warningTimeBeforeIdle?: number;
// The amount of time the user has to react after the idle warning is shown before they are logged out.
idleGracePeriod: number;
};
Expand Down
2 changes: 2 additions & 0 deletions src/config/default-app-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ export class DefaultAppConfig implements AppConfig {
ui: {
// the amount of time before the idle warning is shown
timeUntilIdle: 15 * 60 * 1000, // 15 minutes
// the amount of time before timeUntilIdle to show a warning
warningTimeBeforeIdle: 1 * 60 * 1000, // 1 minute
// the amount of time the user has to react after the idle warning is shown before they are logged out.
idleGracePeriod: 5 * 60 * 1000 // 5 minutes
},
Expand Down
Loading