From c0ca744d177f17647eb481e9e8fb5b3866567f94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Popovics=20Andr=C3=A1s?= Date: Mon, 12 Jun 2017 14:10:54 +0100 Subject: [PATCH] [ADF-589] Login component different bug fixes (#1953) * Basic style changes * Further design changes * Responsive design fixes * Different sign in button style for the different login steps --- ng2-components/ng2-alfresco-login/index.ts | 5 +- .../components/alfresco-login.component.css | 191 +++++++++++++++--- .../components/alfresco-login.component.html | 42 +++- .../alfresco-login.component.spec.ts | 84 ++++++-- .../components/alfresco-login.component.ts | 11 + .../ng2-alfresco-login/src/i18n/en.json | 4 +- ng2-components/package-lock.json | 24 +-- 7 files changed, 291 insertions(+), 70 deletions(-) diff --git a/ng2-components/ng2-alfresco-login/index.ts b/ng2-components/ng2-alfresco-login/index.ts index eee122fd3b..d31899a9e0 100644 --- a/ng2-components/ng2-alfresco-login/index.ts +++ b/ng2-components/ng2-alfresco-login/index.ts @@ -17,7 +17,7 @@ import { NgModule, ModuleWithProviders } from '@angular/core'; import { CoreModule } from 'ng2-alfresco-core'; -import { MdInputModule, MdIconModule, MdCheckboxModule } from '@angular/material'; +import { MdInputModule, MdIconModule, MdCheckboxModule, MdProgressSpinnerModule } from '@angular/material'; import { LoginHeaderDirective } from './src/directives/login-header.directive'; import { LoginFooterDirective } from './src/directives/login-footer.directive'; @@ -39,7 +39,8 @@ export const ALFRESCO_LOGIN_DIRECTIVES: any[] = [ CoreModule, MdInputModule, MdIconModule, - MdCheckboxModule + MdCheckboxModule, + MdProgressSpinnerModule ], declarations: [ ...ALFRESCO_LOGIN_DIRECTIVES diff --git a/ng2-components/ng2-alfresco-login/src/components/alfresco-login.component.css b/ng2-components/ng2-alfresco-login/src/components/alfresco-login.component.css index 3ba3b8801a..4b583d7c13 100644 --- a/ng2-components/ng2-alfresco-login/src/components/alfresco-login.component.css +++ b/ng2-components/ng2-alfresco-login/src/components/alfresco-login.component.css @@ -24,25 +24,62 @@ :host .content-layout { background-size: cover; background-position: center; - height: 100%; + min-height: 100%; padding: 0; + + -webkit-box-orient: vertical; + -moz-box-orient: vertical; + box-orient: vertical; + flex-direction: column; + + align-items: center; + justify-content: center; } :host .login-card-wide.mdl-card { - align-self: center; - margin: auto; border-radius: 8px; background-color: #ffffff; box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.24), 0 0 2px 0 rgba(0, 0, 0, 0.12); + width: 450px; + min-width: 350px; + min-height: 450px; + padding: 21px 64px 34px 64px; + box-sizing: border-box; +} + +@media (max-width: 482px) { + :host .login-card-wide.mdl-card { + width: calc(100% - 32px); + } } :host .error { + display: -webkit-box; + display: -moz-box; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + + -webkit-box-orient: horizontal; + -moz-box-orient: horizontal; + box-orient: horizontal; + flex-direction: row; + + -webkit-box-pack: flex-start; + -moz-box-pack: flex-start; + box-pack: flex-start; + justify-content: flex-start; + color: red; - padding: 8px; + padding: 0px; margin-bottom: 4px; font-size: 13px; } +:host .error .error-icon { + margin-right: 10px; +} + :host .center { display: block; margin-left: auto; @@ -50,7 +87,7 @@ } :host .alfresco-logo { - margin-top: 5px; + padding: 24px 16px 24px 16px; } :host .alfresco-logo img { @@ -58,15 +95,70 @@ } :host .mdl-button--raised.mdl-button--colored { - width: 98%; + width: 100%; height: 36px; + line-height: 38px; border-radius: 4px; + box-shadow: none; } -:host .mdl-button--raised.mdl-button--colored { +.login-button-label { color: rgb(255, 255, 255); } +:host .mdl-button--raised.mdl-button--colored[disabled] { + background-color: rgba(0, 0, 0, 0.07); +} + +:host .mdl-button--raised.mdl-button--colored[disabled] .login-button-label { + color: rgb(175, 175, 175); +} + +.adf-login-button.isChecking { + background-color: #e0f7fa; +} + +.adf-login-button.isChecking .login-button-label{ + color: #00bcd4; +} + +.adf-login-button.isWelcome { + background-color: #00bcd4; + color: #ffffff; +} + +.adf-login-button.isWelcome .welcome-icon { + margin: 5px 0 0 10px; +} + +.adf-interactive-login-label { + display: -webkit-box; + display: -moz-box; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + + -webkit-box-orient: horizontal; + -moz-box-orient: horizontal; + box-orient: horizontal; + flex-direction: row; + + -webkit-box-pack: center; + -moz-box-pack: center; + box-pack: center; + justify-content: center; +} + +.adf-login-checking-spinner { + height: 30px; + width: 20px; + margin-left: 10px; +} + +.adf-login-checking-spinner.mat-spinner >>> path { + stroke: #00bcd4; +} + :host .login-card-wide > .mdl-card__menu { color: #000; } @@ -81,19 +173,43 @@ color: #ff9100; } +:host .login-controls { + padding: 0 0 26px 0; + overflow: visible; + width: 100%; +} + :host .login-action { - margin: 20px; - margin-bottom: 50px; + margin-top: 20px; + display: -webkit-box; + display: -moz-box; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + + -webkit-box-orient: horizontal; + -moz-box-orient: horizontal; + box-orient: horizontal; + flex-direction: row; + + -webkit-box-pack: space-between; + -moz-box-pack: space-between; + box-pack: space-between; + justify-content: space-between; } -:host .login-action-left { - float: left; - margin-left: 10px; +:host .login-action-left a, +:host .login-action-right a { + text-decoration: none; } -:host .login-action-right { - float: right; - margin-right: 10px; +/* Known issue in angular material design module in betas */ +:host >>> .rememberme-cb label > div { + margin-right: 8px; +} + +:host .mat-input-underline .mat-input-ripple { + background-color: #ffab40; } .ng-invalid.ng-invalid.ng-touched { @@ -124,6 +240,15 @@ color: #ff1744; } +:host .copyright { + width: 450px; + text-align: center; + padding-top: 16px; + font-size: 12px; + color: #000; + opacity: 0.54; +} + .ng-invalid.ng-touched:not(:focus) + label::before { font-family: 'Material Icons'; font-weight: normal; @@ -188,20 +313,29 @@ bottom: 20px; } -.alfresco-login__password { - padding-right: 25px; -} - -.alfresco-login__password-icon { - float: right; - margin-right: -30px; - margin-top: 14px; +.mat-input-container .alfresco-login__password-icon.mat-icon { + font-size: 24px; cursor: pointer; - user-select: none; -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; + position: relative; + top: -6px; + height: 20px; +} + +.adf-login__field >>> .mat-input-wrapper { + margin: 1em 0 0 0; + font-size: 16px; +} + +.adf-login__field >>> input { + color: rgba(0, 0, 0, 0.87); +} + +.adf-login__field .mat-focused >>> .mat-input-placeholder { + color: rgba(0, 0, 0, 0.38); } .alfresco-login__container { @@ -232,12 +366,17 @@ } .adf-login__remember-me { - padding-top: 15px; + padding-top: 22px; +} + +.adf-login__remember-me >>> .mat-checkbox-label { + color: #000000; + opacity: 0.87; } .adf-login__field { display: block; margin-left: auto; margin-right: auto; - padding-bottom: 24px; + padding-bottom: 18px; } diff --git a/ng2-components/ng2-alfresco-login/src/components/alfresco-login.component.html b/ng2-components/ng2-alfresco-login/src/components/alfresco-login.component.html index 6aad3b8ff7..95277447e3 100644 --- a/ng2-components/ng2-alfresco-login/src/components/alfresco-login.component.html +++ b/ng2-components/ng2-alfresco-login/src/components/alfresco-login.component.html @@ -10,18 +10,21 @@ {{'LOGIN.LOGO' | translate }} -
+ + +
diff --git a/ng2-components/ng2-alfresco-login/src/components/alfresco-login.component.spec.ts b/ng2-components/ng2-alfresco-login/src/components/alfresco-login.component.spec.ts index c3f0a77399..2268c54dfc 100644 --- a/ng2-components/ng2-alfresco-login/src/components/alfresco-login.component.spec.ts +++ b/ng2-components/ng2-alfresco-login/src/components/alfresco-login.component.spec.ts @@ -32,6 +32,9 @@ describe('AlfrescoLogin', () => { let usernameInput, passwordInput; + const getLoginErrorElement = () => element.querySelector('#login-error'); + const getLoginErrorMessage = () => element.querySelector('#login-error .login-error-message').innerText; + beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ @@ -61,6 +64,52 @@ describe('AlfrescoLogin', () => { fixture.detectChanges(); }); + describe('Login button', () => { + + const getLoginButton = () => element.querySelector('#login-button'); + const getLoginButtonText = () => element.querySelector('#login-button span.login-button-label').innerText; + + function loginWithCredentials(username, password) { + component.providers = 'ECM'; + usernameInput.value = username; + passwordInput.value = password; + + usernameInput.dispatchEvent(new Event('input')); + passwordInput.dispatchEvent(new Event('input')); + fixture.detectChanges(); + + element.querySelector('button').click(); + fixture.detectChanges(); + } + + it('should be rendered with the proper key by default', () => { + expect(getLoginButton()).not.toBeNull(); + expect(getLoginButtonText()).toEqual('LOGIN.BUTTON.LOGIN'); + }); + + it('should be changed to the "checking key" after a login attempt', () => { + const authService = TestBed.get(AlfrescoAuthenticationService); + spyOn(authService, 'login').and.returnValue({ subscribe: () => { } }); + + loginWithCredentials('fake-username', 'fake-password'); + + expect(element.querySelector('#checking-spinner')).not.toBeNull(); + expect(getLoginButtonText()).toEqual('LOGIN.BUTTON.CHECKING'); + }); + + it('should be changed back to the default after a failed login attempt', () => { + loginWithCredentials('fake-wrong-username', 'fake-wrong-password'); + + expect(getLoginButtonText()).toEqual('LOGIN.BUTTON.LOGIN'); + }); + + it('should be changed to the "welcome key" after a successful login attempt', () => { + loginWithCredentials('fake-username', 'fake-password'); + + expect(getLoginButtonText()).toEqual('LOGIN.BUTTON.WELCOME'); + }); + }); + it('should render Login form with all the keys to be translated', () => { expect(element.querySelector('[for="username"]')).toBeDefined(); expect(element.querySelector('[for="username"]').innerText).toEqual('LOGIN.LABEL.USERNAME'); @@ -71,9 +120,6 @@ describe('AlfrescoLogin', () => { expect(element.querySelector('[for="password"]')).toBeDefined(); expect(element.querySelector('[for="password"]').innerText).toEqual('LOGIN.LABEL.PASSWORD'); - expect(element.querySelector('#login-button')).toBeDefined(); - expect(element.querySelector('#login-button').innerText).toEqual('LOGIN.BUTTON.LOGIN'); - expect(element.querySelector('#login-action-help')).toBeDefined(); expect(element.querySelector('#login-action-help').innerText).toEqual('LOGIN.ACTION.HELP'); @@ -245,8 +291,8 @@ describe('AlfrescoLogin', () => { expect(component.error).toBe(true); expect(component.success).toBe(false); - expect(element.querySelector('#login-error')).toBeDefined(); - expect(element.querySelector('#login-error').innerText).toEqual('LOGIN.MESSAGES.LOGIN-ERROR-CREDENTIALS'); + expect(getLoginErrorElement()).toBeDefined(); + expect(getLoginErrorMessage()).toEqual('LOGIN.MESSAGES.LOGIN-ERROR-CREDENTIALS'); }); it('should return error with a wrong password', () => { @@ -268,8 +314,8 @@ describe('AlfrescoLogin', () => { expect(component.error).toBe(true); expect(component.success).toBe(false); - expect(element.querySelector('#login-error')).toBeDefined(); - expect(element.querySelector('#login-error').innerText).toEqual('LOGIN.MESSAGES.LOGIN-ERROR-CREDENTIALS'); + expect(getLoginErrorElement()).toBeDefined(); + expect(getLoginErrorMessage()).toEqual('LOGIN.MESSAGES.LOGIN-ERROR-CREDENTIALS'); }); it('should return error with a wrong username and password', () => { @@ -291,8 +337,8 @@ describe('AlfrescoLogin', () => { expect(component.error).toBe(true); expect(component.success).toBe(false); - expect(element.querySelector('#login-error')).toBeDefined(); - expect(element.querySelector('#login-error').innerText).toEqual('LOGIN.MESSAGES.LOGIN-ERROR-CREDENTIALS'); + expect(getLoginErrorElement()).toBeDefined(); + expect(getLoginErrorMessage()).toEqual('LOGIN.MESSAGES.LOGIN-ERROR-CREDENTIALS'); }); it('should return CORS error when server CORS error occurs', () => { @@ -314,8 +360,8 @@ describe('AlfrescoLogin', () => { expect(component.error).toBe(true); expect(component.success).toBe(false); - expect(element.querySelector('#login-error')).toBeDefined(); - expect(element.querySelector('#login-error').innerText).toEqual('ERROR: the network is offline, Origin is not allowed by Access-Control-Allow-Origin'); + expect(getLoginErrorElement()).toBeDefined(); + expect(getLoginErrorMessage()).toEqual('ERROR: the network is offline, Origin is not allowed by Access-Control-Allow-Origin'); }); it('should return CSRF error when server CSRF error occurs', () => { @@ -337,8 +383,8 @@ describe('AlfrescoLogin', () => { expect(component.error).toBe(true); expect(component.success).toBe(false); - expect(element.querySelector('#login-error')).toBeDefined(); - expect(element.querySelector('#login-error').innerText).toEqual('LOGIN.MESSAGES.LOGIN-ERROR-CSRF'); + expect(getLoginErrorElement()).toBeDefined(); + expect(getLoginErrorMessage()).toEqual('LOGIN.MESSAGES.LOGIN-ERROR-CSRF'); }); it('should return ECOM read-oly error when error occurs', () => { @@ -360,8 +406,8 @@ describe('AlfrescoLogin', () => { expect(component.error).toBe(true); expect(component.success).toBe(false); - expect(element.querySelector('#login-error')).toBeDefined(); - expect(element.querySelector('#login-error').innerText).toEqual('LOGIN.MESSAGES.LOGIN-ECM-LICENSE'); + expect(getLoginErrorElement()).toBeDefined(); + expect(getLoginErrorMessage()).toEqual('LOGIN.MESSAGES.LOGIN-ECM-LICENSE'); }); it('should emit onSuccess event after the login has succeeded', () => { @@ -415,8 +461,8 @@ describe('AlfrescoLogin', () => { expect(component.error).toBe(true); expect(component.success).toBe(false); - expect(element.querySelector('#login-error')).toBeDefined(); - expect(element.querySelector('#login-error').innerText).toEqual('LOGIN.MESSAGES.LOGIN-ERROR-CREDENTIALS'); + expect(getLoginErrorElement()).toBeDefined(); + expect(getLoginErrorMessage()).toEqual('LOGIN.MESSAGES.LOGIN-ERROR-CREDENTIALS'); expect(component.onError.emit).toHaveBeenCalledWith('Fake server error'); }); @@ -460,8 +506,8 @@ describe('AlfrescoLogin', () => { expect(component.error).toBe(true); expect(component.success).toBe(false); - expect(element.querySelector('#login-error')).toBeDefined(); - expect(element.querySelector('#login-error').innerText).toEqual('LOGIN.MESSAGES.LOGIN-ERROR-PROVIDERS'); + expect(getLoginErrorElement()).toBeDefined(); + expect(getLoginErrorMessage()).toEqual('LOGIN.MESSAGES.LOGIN-ERROR-PROVIDERS'); expect(component.onError.emit).toHaveBeenCalledWith('LOGIN.MESSAGES.LOGIN-ERROR-PROVIDERS'); }); }); diff --git a/ng2-components/ng2-alfresco-login/src/components/alfresco-login.component.ts b/ng2-components/ng2-alfresco-login/src/components/alfresco-login.component.ts index d443ed86fb..2d73277847 100644 --- a/ng2-components/ng2-alfresco-login/src/components/alfresco-login.component.ts +++ b/ng2-components/ng2-alfresco-login/src/components/alfresco-login.component.ts @@ -22,6 +22,12 @@ import { FormSubmitEvent } from '../models/form-submit-event.model'; declare let componentHandler: any; +enum LoginSteps { + Landing = 0, + Checking = 1, + Welcome = 2 +} + @Component({ selector: 'alfresco-login', templateUrl: './alfresco-login.component.html', @@ -72,6 +78,8 @@ export class AlfrescoLoginComponent implements OnInit { error: boolean = false; errorMsg: string; success: boolean = false; + actualLoginStep: any = LoginSteps.Landing; + LoginSteps: any = LoginSteps; formError: { [id: string]: string }; minLength: number = 2; footerTemplate: TemplateRef; @@ -162,13 +170,16 @@ export class AlfrescoLoginComponent implements OnInit { * @param values */ private performLogin(values: any) { + this.actualLoginStep = LoginSteps.Checking; this.authService.login(values.username, values.password) .subscribe( (token: any) => { + this.actualLoginStep = LoginSteps.Welcome; this.success = true; this.onSuccess.emit({token: token, username: values.username, password: values.password}); }, (err: any) => { + this.actualLoginStep = LoginSteps.Landing; this.displayErrorMessage(err); this.enableError(); this.onError.emit(err); diff --git a/ng2-components/ng2-alfresco-login/src/i18n/en.json b/ng2-components/ng2-alfresco-login/src/i18n/en.json index 3ca1c4cb95..7e527fed9a 100644 --- a/ng2-components/ng2-alfresco-login/src/i18n/en.json +++ b/ng2-components/ng2-alfresco-login/src/i18n/en.json @@ -19,7 +19,9 @@ "LOGIN-ECM-LICENSE": "Content Services repository is in read-only mode" }, "BUTTON": { - "LOGIN": "SIGN IN" + "LOGIN": "SIGN IN", + "CHECKING": "CHECKING", + "WELCOME": "WELCOME" }, "ACTION": { "HELP": "NEED HELP?", diff --git a/ng2-components/package-lock.json b/ng2-components/package-lock.json index fd48e88e1f..7f08ddff85 100644 --- a/ng2-components/package-lock.json +++ b/ng2-components/package-lock.json @@ -2960,7 +2960,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true }, "lodash": { @@ -3903,7 +3903,7 @@ "joi": { "version": "10.5.2", "resolved": "https://registry.npmjs.org/joi/-/joi-10.5.2.tgz", - "integrity": "sha512-Do/NXTokq86nvFfggE4UbwNnyzvALn3Ay+gMwQSAkrQoWTYc4LvkabhypVZiqDZq0TbtVhUpOphe4dmKB6/Pxg==", + "integrity": "sha1-ZPaFOwgOnfDPTMniBPoSzI95LEg=", "dev": true, "dependencies": { "hoek": { @@ -4016,7 +4016,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true }, "lodash": { @@ -4580,7 +4580,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", "dev": true }, "minimist": { @@ -4846,7 +4846,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true }, "semver": { @@ -4880,7 +4880,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true } } @@ -4924,7 +4924,7 @@ "npmlog": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.0.tgz", - "integrity": "sha512-ocolIkZYZt8UveuiDS0yAkkIjid1o7lPG8cYm05yNYzBn8ykQtaiPMEGp8fY9tKdDgm8okpdKzkvu1y9hUYugA==", + "integrity": "sha1-3Fm+6F9k8A7UJO+yrweD3yXRwLU=", "dev": true }, "nth-check": { @@ -5936,7 +5936,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true } } @@ -6002,7 +6002,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true }, "yargs": { @@ -6576,7 +6576,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true }, "source-map-support": { @@ -6880,7 +6880,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true } } @@ -7375,7 +7375,7 @@ "wide-align": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", - "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "integrity": "sha1-Vx4PGwYEY268DfwhsDObvjE0FxA=", "dev": true }, "widest-line": {