Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ADF-5158] ECM Version Directive #5779

Merged
merged 12 commits into from
Jun 23, 2020
56 changes: 56 additions & 0 deletions docs/core/directives/version-compatibility.directive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# [Version Compatibility Directive](../../../lib/core/directives/version-compatibility.directive.ts "Defined in version-compatibility.directive.ts")

Enables/disables components based on ACS version in use.

## Basic usage

```html
<button *adf-acs-version="'6.0.0'">
My Action
</button>
```

## Class members

### Properties

| Name | Type | Default value | Description |
| ---- | ---- | ------------- | ----------- |
| adf-acs-version | `string` | | The minimum version required for a given component to work propertly. |

## Details

Add the directive to a component or HTML element to enable or disable it based on the version of ACS running in the app.

The directive takes the version specified in the html and compares it to the version of Alfresco Content Services running in the app.

This will allow certain features to be only present under specific versions.

#### Major version
```html
<button *adf-acs-version="'7'">
My Action
</button>
```

#### Major and minor version
```html
<button *adf-acs-version="'6.2'">
My Action
</button>
```

#### Major, minor and patch version
```html
<button *adf-acs-version="'6.0.1'">
My Action
</button>
```

It can be set to match major, minor and patches of ACS versions. Fox example, if the version `6` is specifed it will enable the component from `6.0.0` onwards.

If the minimum version required is not matched the component will not be initialized and will disappear from the DOM tree.

```
Note, if you don’t place the * in front, the app won’t be able to inject the TemplateRef and ViewContainerRef required for this directive to work.
```
8 changes: 8 additions & 0 deletions lib/core/core.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ import { ExtensionsModule } from '@alfresco/adf-extensions';
import { directionalityConfigFactory } from './services/directionality-config-factory';
import { DirectionalityConfigService } from './services/directionality-config.service';
import { SearchTextModule } from './search-text/search-text-input.module';
import { versionCompatibilityFactory } from './services/version-compatibility-factory';
import { VersionCompatibilityService } from './services/version-compatibility.service';

@NgModule({
imports: [
Expand Down Expand Up @@ -149,6 +151,12 @@ export class CoreModule {
useFactory: directionalityConfigFactory,
deps: [ DirectionalityConfigService ],
multi: true
},
{
provide: APP_INITIALIZER,
useFactory: versionCompatibilityFactory,
deps: [ VersionCompatibilityService ],
multi: true
}
]
};
Expand Down
7 changes: 5 additions & 2 deletions lib/core/directives/directive.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { CheckAllowableOperationDirective } from './check-allowable-operation.di
import { NodeRestoreDirective } from './node-restore.directive';
import { UploadDirective } from './upload.directive';
import { NodeDownloadDirective } from './node-download.directive';
import { VersionCompatibilityDirective } from './version-compatibility.directive';

@NgModule({
imports: [
Expand All @@ -41,7 +42,8 @@ import { NodeDownloadDirective } from './node-download.directive';
CheckAllowableOperationDirective,
NodeRestoreDirective,
NodeDownloadDirective,
UploadDirective
UploadDirective,
VersionCompatibilityDirective
],
exports: [
HighlightDirective,
Expand All @@ -51,7 +53,8 @@ import { NodeDownloadDirective } from './node-download.directive';
CheckAllowableOperationDirective,
NodeRestoreDirective,
NodeDownloadDirective,
UploadDirective
UploadDirective,
VersionCompatibilityDirective
]
})
export class DirectiveModule {}
1 change: 1 addition & 0 deletions lib/core/directives/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ export * from './check-allowable-operation.directive';
export * from './node-restore.directive';
export * from './node-download.directive';
export * from './upload.directive';
export * from './version-compatibility.directive';

export * from './directive.module';
95 changes: 95 additions & 0 deletions lib/core/directives/version-compatibility.directive.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { Component } from '@angular/core';
import { By } from '@angular/platform-browser';
import { TranslateModule } from '@ngx-translate/core';
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { setupTestBed } from '../testing/setup-test-bed';
import { CoreTestingModule } from '../testing/core.testing.module';
import { VersionCompatibilityService } from '@alfresco/adf-core';

@Component({
template: `
<div *adf-acs-version="'8'" class="hidden-content-1">
My hidden content 1
</div>
<div *adf-acs-version="'7.1'" class="hidden-content-2">
My hidden content 2
</div>
<div *adf-acs-version="'7.0.2'" class="hidden-content-3">
My hidden content 3
</div>
<div *adf-acs-version="'6.1.5'" class="visible-content-1">
My visible content 1
</div>
<div *adf-acs-version="'6.1'" class="visible-content-2">
My visible content 2
</div>
<div *adf-acs-version="'6'" class="visible-content-3">
My visible content 3
</div>
`
})
class TestComponent { }

describe('VersionCompatibilityDirective', () => {
let fixture: ComponentFixture<TestComponent>;
let versionCompatibilityService: VersionCompatibilityService;

const acsResponceMock = {
display: '7.0.1',
major: '7',
minor: '0',
patch: '1'
};

setupTestBed({
imports: [
TranslateModule.forRoot(),
CoreTestingModule
],
declarations: [TestComponent
]
});

beforeEach(() => {
fixture = TestBed.createComponent(TestComponent);
versionCompatibilityService = TestBed.get(VersionCompatibilityService);
spyOn(versionCompatibilityService, 'getAcsVersion').and.returnValue(acsResponceMock);
});

it('should display component when the version is supported', () => {
fixture.detectChanges();
const element1 = fixture.debugElement.query(By.css('[class="visible-content-1"]'));
const element2 = fixture.debugElement.query(By.css('[class="visible-content-2"]'));
const element3 = fixture.debugElement.query(By.css('[class="visible-content-3"]'));
expect(element1).toBeDefined();
expect(element2).toBeDefined();
expect(element3).toBeDefined();
});

it('should hide component when the version is not supported', () => {
fixture.detectChanges();
const element1 = fixture.debugElement.query(By.css('[class="hidden-content-1"]'));
const element2 = fixture.debugElement.query(By.css('[class="hidden-content-2"]'));
const element3 = fixture.debugElement.query(By.css('[class="hidden-content-3"]'));
expect(element1).toBeNull();
expect(element2).toBeNull();
expect(element3).toBeNull();
});
});
82 changes: 82 additions & 0 deletions lib/core/directives/version-compatibility.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { Directive, Input, ViewContainerRef, TemplateRef } from '@angular/core';
import { VersionCompatibilityService } from '../services/version-compatibility.service';
import { VersionModel } from '../models/product-version.model';

@Directive({
selector: '[adf-acs-version]'
})
export class VersionCompatibilityDirective {

/** Minimum version required for component to work correctly . */
@Input('adf-acs-version')
set version(requiredVersion: string) {
this.validateAcsVersion(requiredVersion);
}

constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef,
private versionCompatibilityService: VersionCompatibilityService
) {
}

private validateAcsVersion(requiredVersion: string) {
if (requiredVersion && this.isVersionSupported(requiredVersion)) {
this.viewContainer.createEmbeddedView(this.templateRef);
} else {
this.viewContainer.clear();
}
}

private parseVersion(version: string): VersionModel {
const major = version.split('.')[0];
const minor = version.split('.')[1] || '0';
const patch = version.split('.')[2] || '0';

return {
major: major,
minor: minor,
patch: patch
} as VersionModel;
}

private isVersionSupported(requiredVersion: string): boolean {
const parsedRequiredVersion = this.parseVersion(requiredVersion);
const currentVersion = this.versionCompatibilityService.getAcsVersion();

let versionSupported = false;

if (currentVersion) {
if (+currentVersion.major > +parsedRequiredVersion.major) {
versionSupported = true;
} else if (currentVersion.major === parsedRequiredVersion.major &&
+currentVersion.minor > +parsedRequiredVersion.minor) {
versionSupported = true;
} else if (currentVersion.major === parsedRequiredVersion.major &&
currentVersion.minor === parsedRequiredVersion.minor &&
+currentVersion.patch >= +parsedRequiredVersion.patch) {
versionSupported = true;
}
}

return versionSupported;
}

}
7 changes: 4 additions & 3 deletions lib/core/search-text/search-text-input.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import { Subject } from 'rxjs';
import { TranslateModule } from '@ngx-translate/core';
import { UserPreferencesService } from '../services/user-preferences.service';
import { setupTestBed } from '../testing/setup-test-bed';
import { CoreModule } from '../core.module';

describe('SearchTextInputComponent', () => {

Expand All @@ -37,7 +36,6 @@ describe('SearchTextInputComponent', () => {
setupTestBed({
imports: [
TranslateModule.forRoot(),
CoreModule.forRoot(),
CoreTestingModule
]
});
Expand All @@ -58,6 +56,7 @@ describe('SearchTextInputComponent', () => {
describe('component rendering', () => {

it('should display a search input field when specified', async(() => {
fixture.detectChanges();
component.inputType = 'search';
fixture.detectChanges();
expect(element.querySelectorAll('input[type="search"]').length).toBe(1);
Expand All @@ -68,15 +67,17 @@ describe('SearchTextInputComponent', () => {

beforeEach(() => {
component.expandable = false;
fixture.detectChanges();
});

it('search button should be hide', () => {
fixture.detectChanges();
const searchButton: any = element.querySelector('#adf-search-button');
expect(searchButton).toBe(null);
});

it('should not have animation', () => {
userPreferencesService.setWithoutStore('textOrientation', 'rtl');
fixture.detectChanges();
expect(component.subscriptAnimationState.value).toBe('no-animation');
});
});
Expand Down
1 change: 1 addition & 0 deletions lib/core/services/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,5 @@ export * from './ecm-user.service';
export * from './identity-user.service';
export * from './identity-group.service';
export * from './identity-role.service';
export * from './version-compatibility.service';
export * from './auth-bearer.interceptor';
22 changes: 22 additions & 0 deletions lib/core/services/version-compatibility-factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { VersionCompatibilityService } from './version-compatibility.service';

export function versionCompatibilityFactory(
versionCompatibilityService: VersionCompatibilityService
): Function { return () => versionCompatibilityService; }