mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[AAE-10777] Move in common service the real common services (#8203)
* Move in common service the real common services remove Pagination js-api dependencies move search-input component in content * fix unit * fix lint * fix * fix
This commit is contained in:
@@ -15,16 +15,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Pagination } from '@alfresco/js-api';
|
||||
import { Observable } from 'rxjs';
|
||||
import { IdentityGroupModel } from '../models/identity-group.model';
|
||||
import { IdentityRoleModel } from '../models/identity-role.model';
|
||||
import { IdentityUserModel } from '../models/identity-user.model';
|
||||
import { PaginationModel } from '../../models/pagination.model';
|
||||
|
||||
export interface IdentityUserQueryResponse {
|
||||
|
||||
entries: IdentityUserModel[];
|
||||
pagination: Pagination;
|
||||
pagination: PaginationModel;
|
||||
}
|
||||
|
||||
export interface IdentityUserPasswordModel {
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Pagination } from '@alfresco/js-api';
|
||||
import { PaginationModel } from '../../models/pagination.model';
|
||||
|
||||
export interface IdentityGroupModel {
|
||||
id?: string;
|
||||
@@ -35,7 +35,7 @@ export interface IdentityGroupSearchParam {
|
||||
export interface IdentityGroupQueryResponse {
|
||||
|
||||
entries: IdentityGroupModel[];
|
||||
pagination: Pagination;
|
||||
pagination: PaginationModel;
|
||||
}
|
||||
|
||||
export interface IdentityGroupQueryCloudRequestModel {
|
||||
|
@@ -19,14 +19,14 @@ import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { throwError as observableThrowError, Observable, of } from 'rxjs';
|
||||
import { catchError, map } from 'rxjs/operators';
|
||||
import { Pagination } from '@alfresco/js-api';
|
||||
import { PaginationModel } from '../../models/pagination.model';
|
||||
import { IdentityRoleModel } from '../models/identity-role.model';
|
||||
import { AppConfigService } from '../../app-config/app-config.service';
|
||||
import { LogService } from '../../common/services/log.service';
|
||||
|
||||
export interface IdentityRoleResponseModel {
|
||||
entries: IdentityRoleModel[];
|
||||
pagination: Pagination;
|
||||
pagination: PaginationModel;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
|
@@ -30,7 +30,7 @@ import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { BaseCardView } from '../base-card-view';
|
||||
import { ClipboardService } from '../../../clipboard/clipboard.service';
|
||||
import { TranslationService } from '../../../services/translation.service';
|
||||
import { TranslationService } from '../../../translation/translation.service';
|
||||
|
||||
@Component({
|
||||
providers: [
|
||||
|
@@ -21,7 +21,7 @@ import { CardViewUpdateService } from '../../services/card-view-update.service';
|
||||
import { BaseCardView } from '../base-card-view';
|
||||
import { MatChipInputEvent } from '@angular/material/chips';
|
||||
import { ClipboardService } from '../../../clipboard/clipboard.service';
|
||||
import { TranslationService } from '../../../services/translation.service';
|
||||
import { TranslationService } from '../../../translation/translation.service';
|
||||
import { CardViewItemValidator } from '../../interfaces/card-view-item-validator.interface';
|
||||
import { UntypedFormControl } from '@angular/forms';
|
||||
import { debounceTime, takeUntil, filter } from 'rxjs/operators';
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { CardViewItem } from '../interfaces/card-view-item.interface';
|
||||
import { DynamicComponentModel } from '../../services/dynamic-component-mapper.service';
|
||||
import { DynamicComponentModel } from '../../common/services/dynamic-component-mapper.service';
|
||||
import { CardViewBaseItemModel } from './card-view-baseitem.model';
|
||||
import { Observable } from 'rxjs';
|
||||
import { CardViewArrayItemProperties } from '../interfaces/card-view-arrayitem-properties.interface';
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { CardViewItem } from '../interfaces/card-view-item.interface';
|
||||
import { DynamicComponentModel } from '../../services/dynamic-component-mapper.service';
|
||||
import { DynamicComponentModel } from '../../common/services/dynamic-component-mapper.service';
|
||||
import { CardViewBaseItemModel } from './card-view-baseitem.model';
|
||||
import { CardViewBoolItemProperties } from '../interfaces/card-view.interfaces';
|
||||
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { CardViewItem } from '../interfaces/card-view-item.interface';
|
||||
import { DynamicComponentModel } from '../../services/dynamic-component-mapper.service';
|
||||
import { DynamicComponentModel } from '../../common/services/dynamic-component-mapper.service';
|
||||
import { CardViewBaseItemModel } from './card-view-baseitem.model';
|
||||
import { CardViewDateItemProperties } from '../interfaces/card-view.interfaces';
|
||||
import { LocalizedDatePipe } from '../../pipes/localized-date.pipe';
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { CardViewItem } from '../interfaces/card-view-item.interface';
|
||||
import { DynamicComponentModel } from '../../services/dynamic-component-mapper.service';
|
||||
import { DynamicComponentModel } from '../../common/services/dynamic-component-mapper.service';
|
||||
import { CardViewDateItemModel } from './card-view-dateitem.model';
|
||||
import { CardViewDateItemProperties } from '../interfaces/card-view.interfaces';
|
||||
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { CardViewItem } from '../interfaces/card-view-item.interface';
|
||||
import { DynamicComponentModel } from '../../services/dynamic-component-mapper.service';
|
||||
import { DynamicComponentModel } from '../../common/services/dynamic-component-mapper.service';
|
||||
import { CardViewTextItemModel } from './card-view-textitem.model';
|
||||
import { CardViewTextItemProperties } from '../interfaces/card-view.interfaces';
|
||||
import { CardViewItemFloatValidator } from '../validators/card-view.validators';
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { CardViewItem } from '../interfaces/card-view-item.interface';
|
||||
import { DynamicComponentModel } from '../../services/dynamic-component-mapper.service';
|
||||
import { DynamicComponentModel } from '../../common/services/dynamic-component-mapper.service';
|
||||
import { CardViewTextItemModel } from './card-view-textitem.model';
|
||||
import { CardViewTextItemProperties } from '../interfaces/card-view.interfaces';
|
||||
import { CardViewItemIntValidator } from '../validators/card-view.validators';
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { CardViewItem } from '../interfaces/card-view-item.interface';
|
||||
import { DynamicComponentModel } from '../../services/dynamic-component-mapper.service';
|
||||
import { DynamicComponentModel } from '../../common/services/dynamic-component-mapper.service';
|
||||
import { CardViewBaseItemModel } from './card-view-baseitem.model';
|
||||
import { CardViewKeyValuePairsItemProperties } from '../interfaces/card-view.interfaces';
|
||||
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { CardViewItem } from '../interfaces/card-view-item.interface';
|
||||
import { DynamicComponentModel } from '../../services/dynamic-component-mapper.service';
|
||||
import { DynamicComponentModel } from '../../common/services/dynamic-component-mapper.service';
|
||||
import { CardViewBaseItemModel } from './card-view-baseitem.model';
|
||||
|
||||
export class CardViewMapItemModel extends CardViewBaseItemModel implements CardViewItem, DynamicComponentModel {
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { CardViewItem } from '../interfaces/card-view-item.interface';
|
||||
import { DynamicComponentModel } from '../../services/dynamic-component-mapper.service';
|
||||
import { DynamicComponentModel } from '../../common/services/dynamic-component-mapper.service';
|
||||
import { CardViewBaseItemModel } from './card-view-baseitem.model';
|
||||
import { CardViewSelectItemProperties, CardViewSelectItemOption } from '../interfaces/card-view.interfaces';
|
||||
import { Observable, of } from 'rxjs';
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { CardViewItem } from '../interfaces/card-view-item.interface';
|
||||
import { DynamicComponentModel } from '../../services/dynamic-component-mapper.service';
|
||||
import { DynamicComponentModel } from '../../common/services/dynamic-component-mapper.service';
|
||||
import { CardViewBaseItemModel } from './card-view-baseitem.model';
|
||||
import { CardViewTextItemPipeProperty, CardViewTextItemProperties } from '../interfaces/card-view.interfaces';
|
||||
|
||||
|
@@ -27,6 +27,7 @@ export {
|
||||
SelectFilterInputComponent
|
||||
} from './components/card-view.components';
|
||||
|
||||
export * from './interfaces/card-view.interfaces';
|
||||
export * from './interfaces/card-view.interfaces';
|
||||
export * from './validators/card-view.validators';
|
||||
export * from './models/card-view.models';
|
||||
|
@@ -22,7 +22,7 @@ import { CardViewTextItemComponent } from '../components/card-view-textitem/card
|
||||
import { CardViewSelectItemComponent } from '../components/card-view-selectitem/card-view-selectitem.component';
|
||||
import { CardViewBoolItemComponent } from '../components/card-view-boolitem/card-view-boolitem.component';
|
||||
import { CardViewKeyValuePairsItemComponent } from '../components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component';
|
||||
import { DynamicComponentMapper, DynamicComponentResolveFunction, DynamicComponentResolver } from '../../services/dynamic-component-mapper.service';
|
||||
import { DynamicComponentMapper, DynamicComponentResolveFunction, DynamicComponentResolver } from '../../common/services/dynamic-component-mapper.service';
|
||||
import { CardViewArrayItemComponent } from '../components/card-view-arrayitem/card-view-arrayitem.component';
|
||||
|
||||
@Injectable({
|
||||
|
@@ -20,6 +20,11 @@ export * from './services/log.service';
|
||||
export * from './services/storage.service';
|
||||
export * from './services/user-preferences.service';
|
||||
export * from './services/language-item.interface';
|
||||
export * from './services/dynamic-component-mapper.service';
|
||||
export * from './services/highlight-transform.service';
|
||||
export * from './services/page-title.service';
|
||||
export * from './services/thumbnail.service';
|
||||
export * from './services/sort-by-category.service';
|
||||
|
||||
export * from './models/log-levels.model';
|
||||
|
||||
|
@@ -16,11 +16,11 @@
|
||||
*/
|
||||
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { CoreTestingModule } from '../testing/core.testing.module';
|
||||
import { setupTestBed } from '../testing/setup-test-bed';
|
||||
import { UserPreferencesService } from '../common/services/user-preferences.service';
|
||||
import { CoreTestingModule } from '../../testing/core.testing.module';
|
||||
import { setupTestBed } from '../../testing/setup-test-bed';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreModule } from '../core.module';
|
||||
import { CoreModule } from '../../core.module';
|
||||
|
||||
describe('DirectionalityConfigService', () => {
|
||||
let userPreferencesService: UserPreferencesService;
|
@@ -17,7 +17,7 @@
|
||||
|
||||
import { Injectable, Inject, Renderer2, RendererFactory2 } from '@angular/core';
|
||||
import { Directionality, Direction } from '@angular/cdk/bidi';
|
||||
import { UserPreferencesService } from '../common/services/user-preferences.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
|
||||
@Injectable({
|
@@ -16,7 +16,8 @@
|
||||
*/
|
||||
|
||||
import { Type } from '@angular/core';
|
||||
import { getType } from './get-type';
|
||||
|
||||
const getType = (type: any): any => () => type;
|
||||
|
||||
export interface DynamicComponentModel { type: string }
|
||||
export type DynamicComponentResolveFunction = (model: DynamicComponentModel) => Type<any>;
|
@@ -17,8 +17,8 @@
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { TranslationService } from './translation.service';
|
||||
import { AppConfigService } from '../../app-config/app-config.service';
|
||||
import { TranslationService } from '../../translation/translation.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
@@ -17,8 +17,8 @@
|
||||
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { ThumbnailService } from './thumbnail.service';
|
||||
import { setupTestBed } from '../testing/setup-test-bed';
|
||||
import { CoreTestingModule } from '../testing/core.testing.module';
|
||||
import { setupTestBed } from '../../testing/setup-test-bed';
|
||||
import { CoreTestingModule } from '../../testing/core.testing.module';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
describe('ThumbnailService', () => {
|
@@ -19,7 +19,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MatIconRegistry } from '@angular/material/icon';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { AlfrescoApiService } from '../../services/alfresco-api.service';
|
||||
import { ContentApi, NodeEntry } from '@alfresco/js-api';
|
||||
|
||||
const DEFAULT_ICON = './assets/images/ft_ic_miscellaneous.svg';
|
@@ -47,15 +47,14 @@ import { DownloadZipDialogModule } from './dialogs/download-zip/download-zip.dia
|
||||
import { PipeModule } from './pipes/pipe.module';
|
||||
|
||||
import { AlfrescoApiService } from './services/alfresco-api.service';
|
||||
import { TranslationService } from './services/translation.service';
|
||||
import { TranslationService } from './translation/translation.service';
|
||||
import { startupServiceFactory } from './services/startup-service-factory';
|
||||
import { SortingPickerModule } from './sorting-picker/sorting-picker.module';
|
||||
import { IconModule } from './icon/icon.module';
|
||||
import { TranslateLoaderService } from './services/translate-loader.service';
|
||||
import { TranslateLoaderService } from './translation/translate-loader.service';
|
||||
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 { directionalityConfigFactory } from './common/services/directionality-config-factory';
|
||||
import { DirectionalityConfigService } from './common/services/directionality-config.service';
|
||||
import { AlfrescoJsClientsModule } from '@alfresco/adf-core/api';
|
||||
import { AuthenticationInterceptor, Authentication } from '@alfresco/adf-core/auth';
|
||||
import { LegacyApiClientModule } from './api-factories/legacy-api-client.module';
|
||||
@@ -95,7 +94,6 @@ import { MAT_SNACK_BAR_DEFAULT_OPTIONS } from '@angular/material/snack-bar';
|
||||
IconModule,
|
||||
SortingPickerModule,
|
||||
NotificationHistoryModule,
|
||||
SearchTextModule,
|
||||
BlankPageModule,
|
||||
LegacyApiClientModule,
|
||||
AlfrescoJsClientsModule,
|
||||
@@ -136,7 +134,6 @@ import { MAT_SNACK_BAR_DEFAULT_OPTIONS } from '@angular/material/snack-bar';
|
||||
SortingPickerModule,
|
||||
IconModule,
|
||||
NotificationHistoryModule,
|
||||
SearchTextModule,
|
||||
BlankPageModule,
|
||||
RichTextEditorModule
|
||||
]
|
||||
|
@@ -18,7 +18,7 @@
|
||||
import { Component, ViewChildren } from '@angular/core';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { HighlightTransformService } from '../services/highlight-transform.service';
|
||||
import { HighlightTransformService } from '../common/services/highlight-transform.service';
|
||||
import { HighlightDirective } from './highlight.directive';
|
||||
import { setupTestBed } from '../testing/setup-test-bed';
|
||||
import { CoreTestingModule } from '../testing/core.testing.module';
|
||||
|
@@ -18,7 +18,7 @@
|
||||
/* eslint-disable @angular-eslint/no-input-rename */
|
||||
|
||||
import { Directive, ElementRef, Input, Renderer2, AfterViewChecked } from '@angular/core';
|
||||
import { HighlightTransformService, HighlightTransformResult } from '../services/highlight-transform.service';
|
||||
import { HighlightTransformService, HighlightTransformResult } from '../common/services/highlight-transform.service';
|
||||
|
||||
@Directive({
|
||||
selector: '[adf-highlight]'
|
||||
|
@@ -1,27 +0,0 @@
|
||||
/*!
|
||||
* @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 { NodeEntry } from '@alfresco/js-api';
|
||||
|
||||
export interface FolderCreatedEvent {
|
||||
|
||||
name: string;
|
||||
relativePath?: string;
|
||||
parentId?: string;
|
||||
node?: NodeEntry;
|
||||
|
||||
}
|
@@ -17,5 +17,4 @@
|
||||
|
||||
export * from './base.event';
|
||||
export * from './base-ui.event';
|
||||
export * from './folder-created.event';
|
||||
export * from './file.event';
|
||||
|
@@ -23,7 +23,7 @@ import { CheckboxWidgetComponent } from './checkbox.widget';
|
||||
import { setupTestBed } from '../../../../testing/setup-test-bed';
|
||||
import { FormBaseModule } from '../../../form-base.module';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { TranslateLoaderService } from '../../../../services/translate-loader.service';
|
||||
import { TranslateLoaderService } from '../../../../translation/translate-loader.service';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { CoreTestingModule } from '../../../../testing';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
|
@@ -24,9 +24,7 @@ import { FormFieldModel } from './form-field.model';
|
||||
import { FormOutcomeModel } from './form-outcome.model';
|
||||
import { FormModel } from './form.model';
|
||||
import { TabModel } from './tab.model';
|
||||
import { fakeMetadataForm, fakeViewerForm } from '../../mock/form.mock';
|
||||
import { Node } from '@alfresco/js-api';
|
||||
import { UploadWidgetContentLinkModel } from './upload-widget-content-link.model';
|
||||
import { fakeMetadataForm } from '../../mock/form.mock';
|
||||
import { CoreTestingModule, setupTestBed } from '../../../../testing';
|
||||
|
||||
describe('FormModel', () => {
|
||||
@@ -609,37 +607,4 @@ describe('FormModel', () => {
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('setNodeIdValueForViewersLinkedToUploadWidget', () => {
|
||||
const fakeNodeWithProperties: Node = {
|
||||
id: 'fake-properties',
|
||||
name: 'fake-properties-name',
|
||||
content: {
|
||||
mimeType: 'application/pdf'
|
||||
},
|
||||
properties: {
|
||||
'pfx:property_one': 'testValue',
|
||||
'pfx:property_two': true
|
||||
}
|
||||
} as Node;
|
||||
let form: FormModel;
|
||||
|
||||
it('should set the node id to the viewers linked to the upload widget in the event', () => {
|
||||
form = new FormModel(fakeMetadataForm);
|
||||
const uploadWidgetContentLinkModel = new UploadWidgetContentLinkModel(fakeNodeWithProperties, 'content_form_nodes');
|
||||
|
||||
form.setNodeIdValueForViewersLinkedToUploadWidget(uploadWidgetContentLinkModel);
|
||||
|
||||
expect(form.values['cmfb85b2a7295ba41209750bca176ccaf9a']).toBe(fakeNodeWithProperties.id);
|
||||
});
|
||||
|
||||
it('should not set the node id to the viewers when they are not linked', () => {
|
||||
form = new FormModel(fakeViewerForm);
|
||||
const uploadWidgetContentLinkModel = new UploadWidgetContentLinkModel(fakeNodeWithProperties, 'upload_widget');
|
||||
|
||||
form.setNodeIdValueForViewersLinkedToUploadWidget(uploadWidgetContentLinkModel);
|
||||
|
||||
expect(form.values['cmfb85b2a7295ba41209750bca176ccaf9a']).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { DynamicComponentMapper, DynamicComponentResolveFunction, DynamicComponentResolver } from '../../services/dynamic-component-mapper.service';
|
||||
import { DynamicComponentMapper, DynamicComponentResolveFunction, DynamicComponentResolver } from '../../common/services/dynamic-component-mapper.service';
|
||||
import { Injectable, Type } from '@angular/core';
|
||||
import * as widgets from '../components/widgets';
|
||||
|
||||
|
@@ -21,7 +21,7 @@ import { LanguageMenuComponent } from './language-menu.component';
|
||||
import { CoreTestingModule } from '../testing/core.testing.module';
|
||||
import { UserPreferencesService } from '../common/services/user-preferences.service';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { LanguageService } from '../services/language.service';
|
||||
import { LanguageService } from './service/language.service';
|
||||
|
||||
describe('LanguageMenuComponent', () => {
|
||||
|
||||
|
@@ -21,7 +21,7 @@ import { CoreStoryModule } from '../testing/core.story.module';
|
||||
import { LanguageMenuModule } from './language-menu.module';
|
||||
import { LanguageMenuComponent } from './language-menu.component';
|
||||
|
||||
import { LanguageService } from '../services/language.service';
|
||||
import { LanguageService } from './service/language.service';
|
||||
import { LanguageServiceMock } from '../mock/language.service.mock';
|
||||
|
||||
export default {
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Component, EventEmitter, Output } from '@angular/core';
|
||||
import { LanguageService } from '../services/language.service';
|
||||
import { LanguageService } from './service/language.service';
|
||||
import { Observable } from 'rxjs';
|
||||
import { LanguageItem } from '../common/services/language-item.interface';
|
||||
|
||||
|
@@ -21,7 +21,7 @@ import { CoreStoryModule } from '../testing/core.story.module';
|
||||
import { LanguageMenuModule } from './language-menu.module';
|
||||
import { LanguagePickerComponent } from './language-picker.component';
|
||||
|
||||
import { LanguageService } from '../services/language.service';
|
||||
import { LanguageService } from './service/language.service';
|
||||
import { LanguageServiceMock } from '../mock/language.service.mock';
|
||||
|
||||
export default {
|
||||
|
@@ -15,6 +15,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './service/language.service';
|
||||
|
||||
export * from './language-menu.component';
|
||||
export * from './language-menu.module';
|
||||
export * from './language-picker.component';
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
import { LanguageItem } from '../common/services/language-item.interface';
|
||||
import { LanguageItem } from '../../common/services/language-item.interface';
|
||||
|
||||
export interface LanguageServiceInterface {
|
||||
|
@@ -18,9 +18,9 @@
|
||||
import { LanguageServiceInterface } from './language.service.interface';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { AppConfigService, AppConfigValues } from '../app-config/app-config.service';
|
||||
import { LanguageItem } from '../common/services/language-item.interface';
|
||||
import { UserPreferencesService } from '../common/services/user-preferences.service';
|
||||
import { AppConfigService, AppConfigValues } from '../../app-config/app-config.service';
|
||||
import { LanguageItem } from '../../common/services/language-item.interface';
|
||||
import { UserPreferencesService } from '../../common/services/user-preferences.service';
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class LanguageService implements LanguageServiceInterface {
|
@@ -23,7 +23,7 @@ import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } fro
|
||||
import { Router, ActivatedRoute, Params } from '@angular/router';
|
||||
import { AuthenticationService } from '../../auth/services/authentication.service';
|
||||
import { OauthConfigModel } from '../../auth/models/oauth-config.model';
|
||||
import { TranslationService } from '../../services/translation.service';
|
||||
import { TranslationService } from '../../translation/translation.service';
|
||||
import { UserPreferencesService } from '../../common/services/user-preferences.service';
|
||||
import { AlfrescoApiService } from '../../services/alfresco-api.service';
|
||||
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { LanguageServiceInterface } from '../services/language.service.interface';
|
||||
import { LanguageServiceInterface } from '../language-menu/service/language.service.interface';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { LanguageItem } from '../common/services/language-item.interface';
|
||||
|
@@ -17,7 +17,7 @@
|
||||
|
||||
import { EventEmitter, Injectable } from '@angular/core';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { TranslationService } from '../services/translation.service';
|
||||
import { TranslationService } from '../translation/translation.service';
|
||||
|
||||
export interface LangChangeEvent {
|
||||
lang: string;
|
||||
|
@@ -27,7 +27,6 @@ export * from './request-pagination.model';
|
||||
export * from './decimal-number.model';
|
||||
export * from './bpm-user.model';
|
||||
export * from './ecm-user.model';
|
||||
export * from './search-text-input.model';
|
||||
export * from './node-metadata.model';
|
||||
export * from './application-access.model';
|
||||
export * from './user-access.model';
|
||||
|
@@ -1,37 +0,0 @@
|
||||
/*!
|
||||
* @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.
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line no-shadow
|
||||
export enum SearchTextStateEnum {
|
||||
expanded = 'expanded',
|
||||
collapsed = 'collapsed'
|
||||
}
|
||||
|
||||
export interface SearchAnimationState {
|
||||
value: string;
|
||||
params?: any;
|
||||
}
|
||||
|
||||
export interface SearchAnimationControl {
|
||||
active: SearchAnimationState;
|
||||
inactive: SearchAnimationState;
|
||||
}
|
||||
|
||||
export interface SearchAnimationDirection {
|
||||
ltr: SearchAnimationControl;
|
||||
rtl: SearchAnimationControl;
|
||||
}
|
@@ -22,7 +22,7 @@ import { MatMenuTrigger, MenuPositionX, MenuPositionY } from '@angular/material/
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Subject } from 'rxjs';
|
||||
import { StorageService } from '../../common/services/storage.service';
|
||||
import { Pagination } from '@alfresco/js-api';
|
||||
import { PaginationModel } from '../../models/pagination.model';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-notification-history',
|
||||
@@ -53,7 +53,7 @@ export class NotificationHistoryComponent implements OnDestroy, OnInit, AfterVie
|
||||
onDestroy$ = new Subject<boolean>();
|
||||
notifications: NotificationModel[] = [];
|
||||
paginatedNotifications = [];
|
||||
pagination: Pagination;
|
||||
pagination: PaginationModel;
|
||||
|
||||
constructor(
|
||||
private notificationService: NotificationService,
|
||||
|
@@ -22,7 +22,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MatSnackBar, MatSnackBarConfig, MatSnackBarModule } from '@angular/material/snack-bar';
|
||||
import { NotificationService } from './notification.service';
|
||||
import { TranslationService } from '../../services/translation.service';
|
||||
import { TranslationService } from '../../translation/translation.service';
|
||||
import { setupTestBed } from '../../testing/setup-test-bed';
|
||||
import { CoreTestingModule } from '../../testing/core.testing.module';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
@@ -17,7 +17,7 @@
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MatSnackBar, MatSnackBarRef, MatSnackBarConfig } from '@angular/material/snack-bar';
|
||||
import { TranslationService } from '../../services/translation.service';
|
||||
import { TranslationService } from '../../translation/translation.service';
|
||||
import { Subject } from 'rxjs';
|
||||
import { NotificationModel } from '../models/notification.model';
|
||||
import { info, warning, error } from '../helpers/notification.factory';
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { TranslationService } from '../services/translation.service';
|
||||
import { TranslationService } from '../translation/translation.service';
|
||||
|
||||
@Pipe({
|
||||
name: 'adfFileSize',
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { TranslationService } from '../services/translation.service';
|
||||
import { TranslationService } from '../translation/translation.service';
|
||||
|
||||
@Pipe({
|
||||
name: 'adfLocalizedRole'
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { ThumbnailService } from '../services/thumbnail.service';
|
||||
import { ThumbnailService } from '../common/services/thumbnail.service';
|
||||
|
||||
@Pipe({
|
||||
name: 'adfMimeTypeIcon'
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { HighlightTransformService, HighlightTransformResult } from '../services/highlight-transform.service';
|
||||
import { HighlightTransformService, HighlightTransformResult } from '../common/services/highlight-transform.service';
|
||||
|
||||
@Pipe({
|
||||
name: 'highlight'
|
||||
|
@@ -1,33 +0,0 @@
|
||||
/*!
|
||||
* @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 { trigger, transition, animate, style, state, AnimationTriggerMetadata } from '@angular/animations';
|
||||
|
||||
export const searchAnimation: AnimationTriggerMetadata = trigger('transitionMessages', [
|
||||
state('active', style({
|
||||
'margin-left': '{{ margin-left }}px',
|
||||
'margin-right': '{{ margin-right }}px',
|
||||
transform: '{{ transform }}'
|
||||
}), { params: { 'margin-left': 0, 'margin-right': 0, transform: 'translateX(0%)' } }),
|
||||
state('inactive', style({
|
||||
'margin-left': '{{ margin-left }}px',
|
||||
'margin-right': '{{ margin-right }}px',
|
||||
transform: '{{ transform }}'
|
||||
}), { params: { 'margin-left': 0, 'margin-right': 0, transform: 'translateX(0%)' } }),
|
||||
state('no-animation', style({ transform: 'translateX(0%)', width: '100%' })),
|
||||
transition('active <=> inactive', animate('400ms cubic-bezier(0.25, 0.8, 0.25, 1)'))
|
||||
]);
|
@@ -1,48 +0,0 @@
|
||||
/*!
|
||||
* @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 { QueryBody, NodePaging } from '@alfresco/js-api';
|
||||
import { Subject } from 'rxjs';
|
||||
import { ElementRef } from '@angular/core';
|
||||
|
||||
export interface SearchConfigurationInterface {
|
||||
|
||||
/**
|
||||
* Generates a QueryBody object with custom search parameters.
|
||||
*
|
||||
* @param searchTerm Term text to search for
|
||||
* @param maxResults Maximum number of search results to show in a page
|
||||
* @param skipCount The offset of the start of the page within the results list
|
||||
* @returns Query body defined by the parameters
|
||||
*/
|
||||
generateQueryBody(searchTerm: string, maxResults: number, skipCount: number): QueryBody;
|
||||
|
||||
}
|
||||
|
||||
export interface SearchComponentInterface {
|
||||
|
||||
panel: ElementRef;
|
||||
showPanel: boolean;
|
||||
results: NodePaging;
|
||||
isOpen: boolean;
|
||||
keyPressedStream: Subject<string>;
|
||||
displayWith: ((value: any) => string) | null;
|
||||
|
||||
resetResults(): void;
|
||||
hidePanel(): void;
|
||||
setVisibility(): void;
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
/*!
|
||||
* @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.
|
||||
*/
|
||||
|
||||
export * from './animations';
|
||||
export * from './search-text-input.component';
|
||||
export * from './search-trigger.directive';
|
||||
export * from './search-text-input.module';
|
||||
|
||||
export * from './interfaces/search-configuration.interface';
|
@@ -1,38 +0,0 @@
|
||||
<div class="adf-search-container" [attr.state]="subscriptAnimationState.value">
|
||||
<div [@transitionMessages]="subscriptAnimationState"
|
||||
(@transitionMessages.done)="applySearchFocus($event)">
|
||||
<button mat-icon-button
|
||||
*ngIf="expandable"
|
||||
id="adf-search-button"
|
||||
class="adf-search-button"
|
||||
[title]="'SEARCH.BUTTON.TOOLTIP' | translate"
|
||||
(click)="toggleSearchBar()"
|
||||
(keyup.enter)="toggleSearchBar()">
|
||||
<mat-icon [attr.aria-label]="'SEARCH.BUTTON.ARIA-LABEL' | translate">search</mat-icon>
|
||||
</button>
|
||||
<mat-form-field class="adf-input-form-field-divider" [hintLabel]="hintLabel">
|
||||
<input matInput
|
||||
#searchInput
|
||||
[attr.aria-label]="'SEARCH.INPUT.ARIA-LABEL' | translate"
|
||||
[attr.type]="inputType"
|
||||
[autocomplete]="getAutoComplete()"
|
||||
id="adf-control-input"
|
||||
[(ngModel)]="searchTerm"
|
||||
[placeholder]="placeholder"
|
||||
(focus)="activateToolbar()"
|
||||
(blur)="onBlur($event)"
|
||||
(keyup.escape)="toggleSearchBar()"
|
||||
(keyup.arrowdown)="selectFirstResult($event)"
|
||||
(ngModelChange)="inputChange($event)"
|
||||
[searchAutocomplete]="searchAutocomplete ? searchAutocomplete : null"
|
||||
(keyup.enter)="searchSubmit($event)">
|
||||
<button mat-icon-button matSuffix
|
||||
data-automation-id="adf-clear-search-button"
|
||||
class="adf-clear-search-button"
|
||||
*ngIf="canShowClearSearch()"
|
||||
(mousedown)="resetSearch()">
|
||||
<mat-icon>clear</mat-icon>
|
||||
</button>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
@@ -1,37 +0,0 @@
|
||||
.adf-search-container {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
.adf-search-button {
|
||||
left: -13px;
|
||||
}
|
||||
|
||||
[dir='rtl'] .adf-search-button {
|
||||
right: -13px;
|
||||
}
|
||||
|
||||
[dir='ltr'] .adf-search-button {
|
||||
left: -13px;
|
||||
}
|
||||
|
||||
.adf {
|
||||
&-search-fixed-text {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
&-input-form-field-divider {
|
||||
.mat-form-field-underline {
|
||||
background-color: var(--adf-search-input-bg-color);
|
||||
|
||||
.mat-form-field-ripple {
|
||||
background-color: var(--adf-search-input-bg-color);
|
||||
}
|
||||
}
|
||||
|
||||
font-size: var(--theme-subheading-2-font-size);
|
||||
}
|
||||
}
|
||||
|
||||
.adf-highlight {
|
||||
color: var(--adf-search-input-highlight-color);
|
||||
}
|
@@ -1,386 +0,0 @@
|
||||
/*!
|
||||
* @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 { ComponentFixture, TestBed, discardPeriodicTasks, fakeAsync, tick } from '@angular/core/testing';
|
||||
import { CoreTestingModule } from '../testing/core.testing.module';
|
||||
import { SearchTextInputComponent } from './search-text-input.component';
|
||||
import { DebugElement } from '@angular/core';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { Subject } from 'rxjs';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { UserPreferencesService } from '../common/services/user-preferences.service';
|
||||
import { setupTestBed } from '../testing/setup-test-bed';
|
||||
|
||||
describe('SearchTextInputComponent', () => {
|
||||
|
||||
let fixture: ComponentFixture<SearchTextInputComponent>;
|
||||
let component: SearchTextInputComponent;
|
||||
let debugElement: DebugElement;
|
||||
let element: HTMLElement;
|
||||
let userPreferencesService: UserPreferencesService;
|
||||
|
||||
setupTestBed({
|
||||
imports: [
|
||||
TranslateModule.forRoot(),
|
||||
CoreTestingModule
|
||||
]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SearchTextInputComponent);
|
||||
component = fixture.componentInstance;
|
||||
debugElement = fixture.debugElement;
|
||||
element = fixture.nativeElement;
|
||||
userPreferencesService = TestBed.inject(UserPreferencesService);
|
||||
component.focusListener = new Subject<any>();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
describe('component rendering', () => {
|
||||
|
||||
it('should display a search input field when specified', async () => {
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
component.inputType = 'search';
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(element.querySelectorAll('input[type="search"]').length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('expandable option false', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
component.expandable = false;
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
||||
describe('search button', () => {
|
||||
|
||||
it('should NOT display a autocomplete list control when configured not to', fakeAsync(() => {
|
||||
fixture.detectChanges();
|
||||
|
||||
tick(100);
|
||||
|
||||
const searchButton: DebugElement = debugElement.query(By.css('#adf-search-button'));
|
||||
component.subscriptAnimationState.value = 'active';
|
||||
fixture.detectChanges();
|
||||
|
||||
tick(100);
|
||||
|
||||
expect(component.subscriptAnimationState.value).toBe('active');
|
||||
|
||||
searchButton.triggerEventHandler('click', null);
|
||||
fixture.detectChanges();
|
||||
tick(100);
|
||||
fixture.detectChanges();
|
||||
|
||||
tick(100);
|
||||
|
||||
expect(component.subscriptAnimationState.value).toBe('inactive');
|
||||
discardPeriodicTasks();
|
||||
}));
|
||||
|
||||
it('click on the search button should open the input box when is close', fakeAsync(() => {
|
||||
fixture.detectChanges();
|
||||
|
||||
tick(100);
|
||||
|
||||
const searchButton: DebugElement = debugElement.query(By.css('#adf-search-button'));
|
||||
searchButton.triggerEventHandler('click', null);
|
||||
|
||||
tick(100);
|
||||
fixture.detectChanges();
|
||||
|
||||
tick(100);
|
||||
|
||||
expect(component.subscriptAnimationState.value).toBe('active');
|
||||
discardPeriodicTasks();
|
||||
}));
|
||||
|
||||
it('Search button should not change the input state too often', fakeAsync(() => {
|
||||
fixture.detectChanges();
|
||||
|
||||
tick(100);
|
||||
|
||||
const searchButton: DebugElement = debugElement.query(By.css('#adf-search-button'));
|
||||
component.subscriptAnimationState.value = 'active';
|
||||
fixture.detectChanges();
|
||||
|
||||
tick(100);
|
||||
|
||||
expect(component.subscriptAnimationState.value).toBe('active');
|
||||
searchButton.triggerEventHandler('click', null);
|
||||
fixture.detectChanges();
|
||||
|
||||
tick(100);
|
||||
|
||||
searchButton.triggerEventHandler('click', null);
|
||||
fixture.detectChanges();
|
||||
|
||||
tick(100);
|
||||
fixture.detectChanges();
|
||||
|
||||
tick(100);
|
||||
|
||||
expect(component.subscriptAnimationState.value).toBe('inactive');
|
||||
discardPeriodicTasks();
|
||||
}));
|
||||
|
||||
it('Search bar should close when user press ESC button', fakeAsync(() => {
|
||||
fixture.detectChanges();
|
||||
|
||||
tick(100);
|
||||
|
||||
const inputDebugElement = debugElement.query(By.css('#adf-control-input'));
|
||||
component.subscriptAnimationState.value = 'active';
|
||||
fixture.detectChanges();
|
||||
|
||||
tick(100);
|
||||
|
||||
expect(component.subscriptAnimationState.value).toBe('active');
|
||||
|
||||
inputDebugElement.triggerEventHandler('keyup.escape', {});
|
||||
|
||||
tick(100);
|
||||
fixture.detectChanges();
|
||||
|
||||
tick(100);
|
||||
|
||||
expect(component.subscriptAnimationState.value).toBe('inactive');
|
||||
discardPeriodicTasks();
|
||||
}));
|
||||
});
|
||||
|
||||
describe('toggle animation', () => {
|
||||
beforeEach(() => {
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should have margin-left set when active and direction is ltr', fakeAsync(() => {
|
||||
userPreferencesService.setWithoutStore('textOrientation', 'ltr');
|
||||
fixture.detectChanges();
|
||||
|
||||
const searchButton: DebugElement = debugElement.query(By.css('#adf-search-button'));
|
||||
|
||||
searchButton.triggerEventHandler('click', null);
|
||||
tick(100);
|
||||
fixture.detectChanges();
|
||||
tick(100);
|
||||
|
||||
expect(component.subscriptAnimationState.params).toEqual({ 'margin-left': 13 });
|
||||
discardPeriodicTasks();
|
||||
}));
|
||||
|
||||
it('should have positive transform translateX set when inactive and direction is ltr', fakeAsync(() => {
|
||||
userPreferencesService.setWithoutStore('textOrientation', 'ltr');
|
||||
component.subscriptAnimationState.value = 'active';
|
||||
|
||||
fixture.detectChanges();
|
||||
const searchButton: DebugElement = debugElement.query(By.css('#adf-search-button'));
|
||||
|
||||
searchButton.triggerEventHandler('click', null);
|
||||
tick(100);
|
||||
fixture.detectChanges();
|
||||
tick(100);
|
||||
|
||||
expect(component.subscriptAnimationState.params).toEqual({ transform: 'translateX(82%)' });
|
||||
discardPeriodicTasks();
|
||||
}));
|
||||
|
||||
it('should have margin-right set when active and direction is rtl', fakeAsync(() => {
|
||||
userPreferencesService.setWithoutStore('textOrientation', 'rtl');
|
||||
fixture.detectChanges();
|
||||
|
||||
const searchButton: DebugElement = debugElement.query(By.css('#adf-search-button'));
|
||||
|
||||
searchButton.triggerEventHandler('click', null);
|
||||
tick(100);
|
||||
fixture.detectChanges();
|
||||
tick(100);
|
||||
|
||||
expect(component.subscriptAnimationState.params).toEqual({ 'margin-right': 13 });
|
||||
discardPeriodicTasks();
|
||||
}));
|
||||
|
||||
it('should have negative transform translateX set when inactive and direction is rtl', fakeAsync(() => {
|
||||
userPreferencesService.setWithoutStore('textOrientation', 'rtl');
|
||||
component.subscriptAnimationState.value = 'active';
|
||||
|
||||
fixture.detectChanges();
|
||||
const searchButton: DebugElement = debugElement.query(By.css('#adf-search-button'));
|
||||
|
||||
searchButton.triggerEventHandler('click', null);
|
||||
tick(100);
|
||||
fixture.detectChanges();
|
||||
tick(100);
|
||||
|
||||
expect(component.subscriptAnimationState.params).toEqual({ transform: 'translateX(-82%)' });
|
||||
discardPeriodicTasks();
|
||||
}));
|
||||
|
||||
it('should set browser autocomplete to on when configured', async () => {
|
||||
component.autocomplete = true;
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(element.querySelector('#adf-control-input').getAttribute('autocomplete')).toBe('on');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Search visibility', () => {
|
||||
beforeEach(() => {
|
||||
userPreferencesService.setWithoutStore('textOrientation', 'ltr');
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should emit an event when the search becomes active', fakeAsync(() => {
|
||||
const searchVisibilityChangeSpy = spyOn(component.searchVisibility, 'emit');
|
||||
component.toggleSearchBar();
|
||||
tick(200);
|
||||
|
||||
expect(searchVisibilityChangeSpy).toHaveBeenCalledWith(true);
|
||||
}));
|
||||
|
||||
it('should emit an event when the search becomes inactive', fakeAsync(() => {
|
||||
component.toggleSearchBar();
|
||||
tick(200);
|
||||
expect(component.subscriptAnimationState.value).toEqual('active');
|
||||
|
||||
const searchVisibilityChangeSpy = spyOn(component.searchVisibility, 'emit');
|
||||
component.toggleSearchBar();
|
||||
tick(200);
|
||||
|
||||
expect(component.subscriptAnimationState.value).toEqual('inactive');
|
||||
expect(searchVisibilityChangeSpy).toHaveBeenCalledWith(false);
|
||||
}));
|
||||
|
||||
it('should reset emit when the search becomes inactive', fakeAsync(() => {
|
||||
const resetSpy = spyOn(component.reset, 'emit');
|
||||
|
||||
component.toggleSearchBar();
|
||||
tick(200);
|
||||
expect(component.subscriptAnimationState.value).toEqual('active');
|
||||
component.searchTerm = 'fake-search-term';
|
||||
|
||||
component.toggleSearchBar();
|
||||
tick(200);
|
||||
|
||||
expect(resetSpy).toHaveBeenCalled();
|
||||
expect(component.searchTerm).toEqual('');
|
||||
}));
|
||||
|
||||
describe('Clear button', () => {
|
||||
beforeEach(fakeAsync(() => {
|
||||
fixture.detectChanges();
|
||||
component.subscriptAnimationState.value = 'active';
|
||||
fixture.detectChanges();
|
||||
tick(200);
|
||||
}));
|
||||
|
||||
it('should clear button be visible when showClearButton is set to true', async () => {
|
||||
component.showClearButton = true;
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
const clearButton = fixture.debugElement.query(By.css('[data-automation-id="adf-clear-search-button"]'));
|
||||
|
||||
expect(clearButton).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should clear button not be visible when showClearButton is set to false', () => {
|
||||
component.showClearButton = false;
|
||||
fixture.detectChanges();
|
||||
const clearButton = fixture.debugElement.query(By.css('[data-automation-id="adf-clear-search-button"]'));
|
||||
|
||||
expect(clearButton).toBeNull();
|
||||
});
|
||||
|
||||
it('should reset the search when clicking the clear button', async () => {
|
||||
const resetEmitSpy = spyOn(component.reset, 'emit');
|
||||
const searchVisibilityChangeSpy = spyOn(component.searchVisibility, 'emit');
|
||||
|
||||
component.searchTerm = 'fake-search-term';
|
||||
component.showClearButton = true;
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
const clearButton = fixture.debugElement.query(By.css('[data-automation-id="adf-clear-search-button"]'));
|
||||
clearButton.nativeElement.dispatchEvent(new MouseEvent('mousedown'));
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(resetEmitSpy).toHaveBeenCalled();
|
||||
expect(searchVisibilityChangeSpy).toHaveBeenCalledWith(false);
|
||||
expect(component.subscriptAnimationState.value).toEqual('inactive');
|
||||
expect(component.searchTerm).toEqual('');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Collapse on blur', () => {
|
||||
beforeEach(fakeAsync(() => {
|
||||
fixture.detectChanges();
|
||||
component.toggleSearchBar();
|
||||
tick(200);
|
||||
}));
|
||||
|
||||
it('should collapse search on blur when the collapseOnBlur is set to true', fakeAsync (() => {
|
||||
const searchVisibilityChangeSpy = spyOn(component.searchVisibility, 'emit');
|
||||
const resetEmitSpy = spyOn(component.reset, 'emit');
|
||||
component.collapseOnBlur = true;
|
||||
component.searchTerm = 'fake-search-term';
|
||||
component.onBlur({ relatedTarget: null });
|
||||
tick(200);
|
||||
|
||||
expect(searchVisibilityChangeSpy).toHaveBeenCalledWith(false);
|
||||
expect(component.subscriptAnimationState.value).toEqual('inactive');
|
||||
expect(component.searchTerm).toEqual('');
|
||||
expect(resetEmitSpy).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should not collapse search on blur when the collapseOnBlur is set to false', () => {
|
||||
const searchVisibilityChangeSpy = spyOn(component.searchVisibility, 'emit');
|
||||
component.searchTerm = 'fake-search-term';
|
||||
component.collapseOnBlur = false;
|
||||
component.onBlur({ relatedTarget: null });
|
||||
|
||||
expect(searchVisibilityChangeSpy).not.toHaveBeenCalled();
|
||||
expect(component.subscriptAnimationState.value).toEqual('active');
|
||||
expect(component.searchTerm).toEqual('fake-search-term');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@@ -1,196 +0,0 @@
|
||||
/*!
|
||||
* @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 { Meta, moduleMetadata, Story } from '@storybook/angular';
|
||||
import { CoreStoryModule } from '../testing/core.story.module';
|
||||
|
||||
import { SearchTextInputComponent } from './search-text-input.component';
|
||||
import { SearchTextModule } from './search-text-input.module';
|
||||
|
||||
export default {
|
||||
component: SearchTextInputComponent,
|
||||
title: 'Core/Search Text Input/Search Text Input',
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
imports: [CoreStoryModule, SearchTextModule]
|
||||
})
|
||||
],
|
||||
argTypes: {
|
||||
autocomplete: {
|
||||
control: 'boolean',
|
||||
description: 'Toggles auto-completion of the search input field.',
|
||||
defaultValue: false,
|
||||
table: {
|
||||
type: { summary: 'boolean' },
|
||||
defaultValue: { summary: 'false' }
|
||||
}
|
||||
},
|
||||
expandable: {
|
||||
control: 'boolean',
|
||||
description: 'Toggles whether to use an expanding search control. If false, a regular input is used.',
|
||||
defaultValue: true,
|
||||
table: {
|
||||
type: { summary: 'boolean' },
|
||||
defaultValue: { summary: 'true' }
|
||||
}
|
||||
},
|
||||
inputType: {
|
||||
control: 'radio',
|
||||
options: ['date', 'month', 'number', 'search', 'text', 'time'],
|
||||
description: 'Type of the input field to render, e.g. "search" or "text" (default).',
|
||||
defaultValue: 'text',
|
||||
table: {
|
||||
category: 'HTML input attributes',
|
||||
type: { summary: 'string' },
|
||||
defaultValue: { summary: 'text' }
|
||||
}
|
||||
},
|
||||
liveSearchEnabled: {
|
||||
control: 'boolean',
|
||||
description: 'Toggles "find-as-you-type" suggestions for possible matches.',
|
||||
defaultValue: true,
|
||||
table: {
|
||||
type: { summary: 'boolean' },
|
||||
defaultValue: { summary: 'true' }
|
||||
}
|
||||
},
|
||||
searchAutocomplete: {
|
||||
control: 'boolean',
|
||||
description: 'Trigger autocomplete results on input change.',
|
||||
defaultValue: false,
|
||||
table: {
|
||||
type: { summary: 'boolean' },
|
||||
defaultValue: { summary: 'false' }
|
||||
}
|
||||
},
|
||||
searchTerm: {
|
||||
control: 'text',
|
||||
description: 'Search term preselected.',
|
||||
defaultValue: '',
|
||||
table: {
|
||||
category: 'HTML input attributes',
|
||||
type: { summary: 'string' },
|
||||
defaultValue: { summary: '' }
|
||||
}
|
||||
},
|
||||
debounceTime: {
|
||||
control: 'number',
|
||||
description: 'Debounce time in milliseconds.',
|
||||
defaultValue: 0,
|
||||
table: {
|
||||
type: { summary: 'number' },
|
||||
defaultValue: { summary: '0' }
|
||||
}
|
||||
},
|
||||
focusListener: {
|
||||
control: 'object',
|
||||
description: 'Listener for results-list events (focus, blur and focusout).',
|
||||
table: {
|
||||
type: { summary: 'Observable<FocusEvent>' }
|
||||
}
|
||||
},
|
||||
collapseOnSubmit: {
|
||||
control: 'boolean',
|
||||
description: 'Collapse search bar on submit.',
|
||||
defaultValue: true,
|
||||
table: {
|
||||
type: { summary: 'boolean' },
|
||||
defaultValue: { summary: 'true' }
|
||||
}
|
||||
},
|
||||
defaultState: {
|
||||
control: 'inline-radio',
|
||||
options: ['collapsed', 'expanded'],
|
||||
description: 'Default state.',
|
||||
defaultValue: 'collapsed',
|
||||
table: {
|
||||
type: { summary: 'string' },
|
||||
defaultValue: { summary: 'collapsed' }
|
||||
}
|
||||
},
|
||||
collapseOnBlur: {
|
||||
control: 'boolean',
|
||||
description: 'Collapse search bar on blur.',
|
||||
defaultValue: true,
|
||||
table: {
|
||||
type: { summary: 'boolean' },
|
||||
defaultValue: { summary: 'true' }
|
||||
}
|
||||
},
|
||||
showClearButton: {
|
||||
control: 'boolean',
|
||||
description: 'Toggles whether to show a clear button that closes the search.',
|
||||
defaultValue: false,
|
||||
table: {
|
||||
type: { summary: 'boolean' },
|
||||
defaultValue: { summary: 'false' }
|
||||
}
|
||||
},
|
||||
placeholder: {
|
||||
control: 'text',
|
||||
description: 'Placeholder text to show in the input field.',
|
||||
defaultValue: '',
|
||||
table: {
|
||||
category: 'HTML input attributes',
|
||||
type: { summary: 'string' },
|
||||
defaultValue: { summary: '' }
|
||||
}
|
||||
},
|
||||
hintLabel: {
|
||||
control: 'text',
|
||||
description: 'Hint label.',
|
||||
defaultValue: '',
|
||||
table: {
|
||||
category: 'HTML input attributes',
|
||||
type: { summary: 'string' },
|
||||
defaultValue: { summary: '' }
|
||||
}
|
||||
},
|
||||
searchChange: {
|
||||
action: 'searchChange',
|
||||
description: 'Emitted when the search term is changed. The search term is provided in the "value" property of the returned object. If the term is less than three characters in length then it is truncated to an empty string.',
|
||||
table: { category: 'Actions' }
|
||||
},
|
||||
submit: {
|
||||
action: 'submit',
|
||||
description: 'Emitted when the search is submitted by pressing the ENTER key.',
|
||||
table: { category: 'Actions' }
|
||||
},
|
||||
selectResult: {
|
||||
action: 'selectResult',
|
||||
description: 'Emitted when the result list is selected.',
|
||||
table: { category: 'Actions' }
|
||||
},
|
||||
reset: {
|
||||
action: 'reset',
|
||||
description: 'Emitted when the result list is reset.',
|
||||
table: { category: 'Actions' }
|
||||
},
|
||||
searchVisibility: {
|
||||
action: 'searchVisibility',
|
||||
description: 'Emitted when the search visibility changes. True when the search is active, false when it is inactive.',
|
||||
table: { category: 'Actions' }
|
||||
}
|
||||
}
|
||||
} as Meta;
|
||||
|
||||
const template: Story<SearchTextInputComponent> = (args: SearchTextInputComponent) => ({
|
||||
props: args
|
||||
});
|
||||
|
||||
export const searchTextInput = template.bind({});
|
||||
searchTextInput.parameters = { layout: 'centered' };
|
@@ -1,323 +0,0 @@
|
||||
/*!
|
||||
* @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 { ViewEncapsulation, Component, Input, OnDestroy, ViewChild, ElementRef, Output, EventEmitter, OnInit } from '@angular/core';
|
||||
import { Subject, Observable, Subscription } from 'rxjs';
|
||||
import { debounceTime, takeUntil, filter } from 'rxjs/operators';
|
||||
import { Direction } from '@angular/cdk/bidi';
|
||||
import { searchAnimation } from './animations';
|
||||
import { UserPreferencesService } from '../common/services/user-preferences.service';
|
||||
import { SearchTextStateEnum, SearchAnimationState, SearchAnimationDirection } from '../models/search-text-input.model';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-search-text-input',
|
||||
templateUrl: './search-text-input.component.html',
|
||||
styleUrls: ['./search-text-input.component.scss'],
|
||||
animations: [searchAnimation],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
host: {
|
||||
class: 'adf-search-text-input'
|
||||
}
|
||||
})
|
||||
export class SearchTextInputComponent implements OnInit, OnDestroy {
|
||||
|
||||
/** Toggles auto-completion of the search input field. */
|
||||
@Input()
|
||||
autocomplete: boolean = false;
|
||||
|
||||
/** Toggles whether to use an expanding search control. If false
|
||||
* then a regular input is used.
|
||||
*/
|
||||
@Input()
|
||||
expandable: boolean = true;
|
||||
|
||||
/** Type of the input field to render, e.g. "search" or "text" (default). */
|
||||
@Input()
|
||||
inputType: string = 'text';
|
||||
|
||||
/** Toggles "find-as-you-type" suggestions for possible matches. */
|
||||
@Input()
|
||||
liveSearchEnabled: boolean = true;
|
||||
|
||||
/** Trigger autocomplete results on input change. */
|
||||
@Input()
|
||||
searchAutocomplete: any = false;
|
||||
|
||||
/** Search term preselected */
|
||||
@Input()
|
||||
searchTerm: string = '';
|
||||
|
||||
/** Debounce time in milliseconds. */
|
||||
@Input()
|
||||
debounceTime: number = 0;
|
||||
|
||||
/** Listener for results-list events (focus, blur and focusout). */
|
||||
@Input()
|
||||
focusListener: Observable<FocusEvent>;
|
||||
|
||||
/** Collapse search bar on submit. */
|
||||
@Input()
|
||||
collapseOnSubmit: boolean = true;
|
||||
|
||||
/** Default state expanded or Collapsed. */
|
||||
@Input()
|
||||
defaultState: SearchTextStateEnum = SearchTextStateEnum.collapsed;
|
||||
|
||||
/** Toggles whether to collapse the search on blur. */
|
||||
@Input()
|
||||
collapseOnBlur: boolean = true;
|
||||
|
||||
/** Toggles whether to show a clear button that closes the search */
|
||||
@Input()
|
||||
showClearButton: boolean = false;
|
||||
|
||||
/** Placeholder text to show in the input field */
|
||||
@Input()
|
||||
placeholder: string = '';
|
||||
|
||||
/** Hint label */
|
||||
@Input()
|
||||
hintLabel = '';
|
||||
|
||||
/** Emitted when the search term is changed. The search term is provided
|
||||
* in the 'value' property of the returned object. If the term is less
|
||||
* than three characters in length then it is truncated to an empty
|
||||
* string.
|
||||
*/
|
||||
@Output()
|
||||
searchChange: EventEmitter<string> = new EventEmitter();
|
||||
|
||||
/** Emitted when the search is submitted by pressing the ENTER key.
|
||||
* The search term is provided as the value of the event.
|
||||
*/
|
||||
@Output()
|
||||
submit: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
/** Emitted when the result list is selected */
|
||||
@Output()
|
||||
selectResult: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
/** Emitted when the result list is reset */
|
||||
@Output()
|
||||
reset: EventEmitter<boolean> = new EventEmitter();
|
||||
|
||||
/** Emitted when the search visibility changes. True when the search is active, false when it is inactive */
|
||||
@Output()
|
||||
searchVisibility: EventEmitter<boolean> = new EventEmitter<boolean>();
|
||||
|
||||
@ViewChild('searchInput', { static: true })
|
||||
searchInput: ElementRef;
|
||||
|
||||
subscriptAnimationState: any;
|
||||
|
||||
animationStates: SearchAnimationDirection = {
|
||||
ltr : {
|
||||
active: { value: 'active', params: { 'margin-left': 13 } },
|
||||
inactive: { value: 'inactive', params: { transform: 'translateX(82%)' } }
|
||||
},
|
||||
rtl: {
|
||||
active: { value: 'active', params: { 'margin-right': 13 } },
|
||||
inactive: { value: 'inactive', params: { transform: 'translateX(-82%)' } }
|
||||
}
|
||||
};
|
||||
|
||||
private dir = 'ltr';
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
private toggleSearch = new Subject<any>();
|
||||
private focusSubscription: Subscription;
|
||||
private valueChange = new Subject<string>();
|
||||
|
||||
constructor(
|
||||
private userPreferencesService: UserPreferencesService
|
||||
) {
|
||||
this.toggleSearch
|
||||
.pipe(
|
||||
debounceTime(200),
|
||||
takeUntil(this.onDestroy$)
|
||||
)
|
||||
.subscribe(() => {
|
||||
if (this.expandable) {
|
||||
this.subscriptAnimationState = this.toggleAnimation();
|
||||
if (this.subscriptAnimationState.value === 'inactive') {
|
||||
this.searchTerm = '';
|
||||
this.reset.emit(true);
|
||||
if (document.activeElement.id === this.searchInput.nativeElement.id) {
|
||||
this.searchInput.nativeElement.blur();
|
||||
}
|
||||
}
|
||||
this.emitVisibilitySearch();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.userPreferencesService
|
||||
.select('textOrientation')
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe((direction: Direction) => {
|
||||
this.dir = direction;
|
||||
this.subscriptAnimationState = this.getDefaultState(this.dir);
|
||||
});
|
||||
|
||||
this.subscriptAnimationState = this.getDefaultState(this.dir);
|
||||
this.setValueChangeHandler();
|
||||
this.setupFocusEventHandlers();
|
||||
}
|
||||
|
||||
applySearchFocus(animationDoneEvent) {
|
||||
if (animationDoneEvent.toState === 'active' && this.isDefaultStateCollapsed()) {
|
||||
this.searchInput.nativeElement.focus();
|
||||
}
|
||||
}
|
||||
|
||||
getAutoComplete(): string {
|
||||
return this.autocomplete ? 'on' : 'off';
|
||||
}
|
||||
|
||||
private toggleAnimation() {
|
||||
if (this.dir === 'ltr') {
|
||||
return this.subscriptAnimationState.value === 'inactive' ?
|
||||
{ value: 'active', params: { 'margin-left': 13 } } :
|
||||
{ value: 'inactive', params: { transform: 'translateX(82%)' } };
|
||||
} else {
|
||||
return this.subscriptAnimationState.value === 'inactive' ?
|
||||
{ value: 'active', params: { 'margin-right': 13 } } :
|
||||
{ value: 'inactive', params: { transform: 'translateX(-82%)' } };
|
||||
}
|
||||
}
|
||||
|
||||
private getDefaultState(dir: string): SearchAnimationState {
|
||||
if (this.dir) {
|
||||
return this.getAnimationState(dir);
|
||||
}
|
||||
return this.animationStates.ltr.inactive;
|
||||
}
|
||||
|
||||
private getAnimationState(dir: string): SearchAnimationState {
|
||||
if (this.expandable && this.isDefaultStateExpanded()) {
|
||||
return this.animationStates[dir].active;
|
||||
} else if ( this.expandable ) {
|
||||
return this.animationStates[dir].inactive;
|
||||
} else {
|
||||
return { value: 'no-animation' };
|
||||
}
|
||||
}
|
||||
|
||||
private setupFocusEventHandlers() {
|
||||
if ( this.focusListener ) {
|
||||
const focusEvents: Observable<FocusEvent> = this.focusListener
|
||||
.pipe(
|
||||
debounceTime(50),
|
||||
filter(($event: any) => this.isSearchBarActive() && ($event.type === 'blur' || $event.type === 'focusout' || $event.type === 'focus')),
|
||||
takeUntil(this.onDestroy$)
|
||||
);
|
||||
|
||||
this.focusSubscription = focusEvents.subscribe( (event: FocusEvent) => {
|
||||
if ( event.type === 'focus') {
|
||||
this.searchInput.nativeElement.focus();
|
||||
} else {
|
||||
this.toggleSearchBar();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private setValueChangeHandler() {
|
||||
this.valueChange.pipe(
|
||||
debounceTime(this.debounceTime),
|
||||
takeUntil(this.onDestroy$)
|
||||
).subscribe( (value: string) => {
|
||||
this.searchChange.emit(value);
|
||||
});
|
||||
}
|
||||
|
||||
selectFirstResult($event) {
|
||||
this.selectResult.emit($event);
|
||||
}
|
||||
|
||||
onBlur($event) {
|
||||
if (this.collapseOnBlur && !$event.relatedTarget) {
|
||||
this.resetSearch();
|
||||
}
|
||||
}
|
||||
|
||||
inputChange($event: any) {
|
||||
this.valueChange.next($event);
|
||||
}
|
||||
|
||||
toggleSearchBar() {
|
||||
if (this.toggleSearch) {
|
||||
this.toggleSearch.next();
|
||||
}
|
||||
}
|
||||
|
||||
searchSubmit(event: any) {
|
||||
this.submit.emit(event);
|
||||
if (this.collapseOnSubmit) {
|
||||
this.toggleSearchBar();
|
||||
}
|
||||
}
|
||||
|
||||
activateToolbar(): boolean {
|
||||
if (!this.isSearchBarActive()) {
|
||||
this.toggleSearchBar();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
isSearchBarActive(): boolean {
|
||||
return this.subscriptAnimationState.value === 'active';
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.toggleSearch) {
|
||||
this.toggleSearch.complete();
|
||||
this.toggleSearch = null;
|
||||
}
|
||||
|
||||
if (this.focusSubscription) {
|
||||
this.focusSubscription.unsubscribe();
|
||||
this.focusSubscription = null;
|
||||
this.focusListener = null;
|
||||
}
|
||||
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
canShowClearSearch(): boolean {
|
||||
return this.showClearButton && this.isSearchBarActive();
|
||||
}
|
||||
|
||||
resetSearch() {
|
||||
if (this.isSearchBarActive()) {
|
||||
this.toggleSearchBar();
|
||||
}
|
||||
}
|
||||
|
||||
private isDefaultStateCollapsed(): boolean {
|
||||
return this.defaultState === SearchTextStateEnum.collapsed;
|
||||
}
|
||||
|
||||
private isDefaultStateExpanded(): boolean {
|
||||
return this.defaultState === SearchTextStateEnum.expanded;
|
||||
}
|
||||
|
||||
private emitVisibilitySearch() {
|
||||
this.searchVisibility.emit(this.isSearchBarActive());
|
||||
}
|
||||
}
|
@@ -1,42 +0,0 @@
|
||||
/*!
|
||||
* @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 { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MaterialModule } from '../material.module';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { SearchTextInputComponent } from './search-text-input.component';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { SearchTriggerDirective } from './search-trigger.directive';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
SearchTextInputComponent,
|
||||
SearchTriggerDirective
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
TranslateModule,
|
||||
MaterialModule,
|
||||
FormsModule
|
||||
],
|
||||
exports: [
|
||||
SearchTextInputComponent,
|
||||
SearchTriggerDirective
|
||||
]
|
||||
})
|
||||
export class SearchTextModule {}
|
@@ -1,222 +0,0 @@
|
||||
/*!
|
||||
* @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.
|
||||
*/
|
||||
|
||||
/* eslint-disable @angular-eslint/no-input-rename, @typescript-eslint/no-use-before-define, @angular-eslint/no-input-rename */
|
||||
|
||||
import { ENTER, ESCAPE } from '@angular/cdk/keycodes';
|
||||
import {
|
||||
ChangeDetectorRef,
|
||||
Directive,
|
||||
ElementRef,
|
||||
forwardRef,
|
||||
Inject,
|
||||
Input,
|
||||
NgZone,
|
||||
OnDestroy,
|
||||
Optional
|
||||
} from '@angular/core';
|
||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Observable, Subject, Subscription, merge, of, fromEvent } from 'rxjs';
|
||||
import { filter, switchMap, takeUntil } from 'rxjs/operators';
|
||||
import { SearchComponentInterface } from './interfaces/search-configuration.interface';
|
||||
|
||||
export const SEARCH_AUTOCOMPLETE_VALUE_ACCESSOR: any = {
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: forwardRef(() => SearchTriggerDirective),
|
||||
multi: true
|
||||
};
|
||||
|
||||
/**
|
||||
* Directive selectors without adf- prefix will be deprecated on 3.0.0
|
||||
*/
|
||||
@Directive({
|
||||
// eslint-disable-next-line @angular-eslint/directive-selector
|
||||
selector: `input[searchAutocomplete], textarea[searchAutocomplete]`,
|
||||
host: {
|
||||
role: 'combobox',
|
||||
'[attr.autocomplete]': 'autocomplete',
|
||||
'aria-autocomplete': 'list',
|
||||
'[attr.aria-expanded]': 'panelOpen.toString()',
|
||||
'(blur)': 'onTouched()',
|
||||
'(input)': 'handleInput($event)',
|
||||
'(keydown)': 'handleKeydown($event)'
|
||||
},
|
||||
providers: [SEARCH_AUTOCOMPLETE_VALUE_ACCESSOR]
|
||||
})
|
||||
export class SearchTriggerDirective implements ControlValueAccessor, OnDestroy {
|
||||
private onDestroy$: Subject<boolean> = new Subject<boolean>();
|
||||
|
||||
@Input('searchAutocomplete')
|
||||
searchPanel: SearchComponentInterface;
|
||||
|
||||
@Input()
|
||||
autocomplete: string = 'off';
|
||||
|
||||
private _panelOpen: boolean = false;
|
||||
private closingActionsSubscription: Subscription;
|
||||
private escapeEventStream = new Subject<void>();
|
||||
|
||||
onChange: (value: any) => void = () => { };
|
||||
|
||||
onTouched = () => { };
|
||||
|
||||
constructor(private element: ElementRef,
|
||||
private ngZone: NgZone,
|
||||
private changeDetectorRef: ChangeDetectorRef,
|
||||
@Optional() @Inject(DOCUMENT) private document: any) { }
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
|
||||
if (this.escapeEventStream) {
|
||||
this.escapeEventStream = null;
|
||||
}
|
||||
if ( this.closingActionsSubscription ) {
|
||||
this.closingActionsSubscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
get panelOpen(): boolean {
|
||||
return this._panelOpen && this.searchPanel.showPanel;
|
||||
}
|
||||
|
||||
openPanel(): void {
|
||||
this.searchPanel.isOpen = this._panelOpen = true;
|
||||
this.closingActionsSubscription = this.subscribeToClosingActions();
|
||||
}
|
||||
|
||||
closePanel(): void {
|
||||
if (this._panelOpen) {
|
||||
this.closingActionsSubscription.unsubscribe();
|
||||
this._panelOpen = false;
|
||||
this.searchPanel.resetResults();
|
||||
this.searchPanel.hidePanel();
|
||||
this.changeDetectorRef.detectChanges();
|
||||
}
|
||||
}
|
||||
|
||||
get panelClosingActions(): Observable<any> {
|
||||
return merge(
|
||||
this.escapeEventStream,
|
||||
this.outsideClickStream
|
||||
);
|
||||
}
|
||||
|
||||
private get outsideClickStream(): Observable<any> {
|
||||
if (!this.document) {
|
||||
return of(null);
|
||||
}
|
||||
|
||||
return merge(
|
||||
fromEvent(this.document, 'click'),
|
||||
fromEvent(this.document, 'touchend')
|
||||
).pipe(
|
||||
filter((event: MouseEvent | TouchEvent) => {
|
||||
const clickTarget = event.target as HTMLElement;
|
||||
return this._panelOpen && clickTarget !== this.element.nativeElement;
|
||||
}),
|
||||
takeUntil(this.onDestroy$)
|
||||
);
|
||||
}
|
||||
|
||||
writeValue(value: any): void {
|
||||
Promise.resolve(null).then(() => this.setTriggerValue(value));
|
||||
}
|
||||
|
||||
registerOnChange(fn: (value: any) => any): void {
|
||||
this.onChange = fn;
|
||||
}
|
||||
|
||||
registerOnTouched(fn: () => any) {
|
||||
this.onTouched = fn;
|
||||
}
|
||||
|
||||
handleKeydown(event: KeyboardEvent): void {
|
||||
const keyCode = event.keyCode;
|
||||
|
||||
if (keyCode === ESCAPE && this.panelOpen) {
|
||||
this.escapeEventStream.next();
|
||||
event.stopPropagation();
|
||||
} else if (keyCode === ENTER) {
|
||||
this.escapeEventStream.next();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
handleInput(event: KeyboardEvent): void {
|
||||
if (document.activeElement === event.target ) {
|
||||
const inputValue: string = (event.target as HTMLInputElement).value;
|
||||
this.onChange(inputValue);
|
||||
if (inputValue && this.searchPanel) {
|
||||
this.searchPanel.keyPressedStream.next(inputValue);
|
||||
this.openPanel();
|
||||
} else if (this.searchPanel) {
|
||||
this.searchPanel.resetResults();
|
||||
this.closePanel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private isPanelOptionClicked(event: MouseEvent) {
|
||||
let isPanelOption: boolean = false;
|
||||
if ( event && this.searchPanel ) {
|
||||
const clickTarget = event.target as HTMLElement;
|
||||
isPanelOption = !this.isNoResultOption() &&
|
||||
!!this.searchPanel.panel &&
|
||||
!!this.searchPanel.panel.nativeElement.contains(clickTarget);
|
||||
}
|
||||
return isPanelOption;
|
||||
}
|
||||
|
||||
private isNoResultOption(): boolean {
|
||||
return this.searchPanel && this.searchPanel.results.list ? this.searchPanel.results.list.entries.length === 0 : true;
|
||||
}
|
||||
|
||||
private subscribeToClosingActions(): Subscription {
|
||||
const firstStable = this.ngZone.onStable.asObservable();
|
||||
const optionChanges = this.searchPanel.keyPressedStream.asObservable();
|
||||
|
||||
return merge(firstStable, optionChanges)
|
||||
.pipe(
|
||||
switchMap(() => {
|
||||
this.searchPanel.setVisibility();
|
||||
return this.panelClosingActions;
|
||||
}),
|
||||
takeUntil(this.onDestroy$)
|
||||
)
|
||||
.subscribe((event) => this.setValueAndClose(event));
|
||||
}
|
||||
|
||||
private setTriggerValue(value: any): void {
|
||||
const toDisplay = this.searchPanel && this.searchPanel.displayWith ?
|
||||
this.searchPanel.displayWith(value) : value;
|
||||
const inputValue = toDisplay != null ? toDisplay : '';
|
||||
this.element.nativeElement.value = inputValue;
|
||||
}
|
||||
|
||||
private setValueAndClose(event: any | null): void {
|
||||
if (this.isPanelOptionClicked(event) && !event.defaultPrevented) {
|
||||
this.setTriggerValue(event.target.textContent.trim());
|
||||
this.onChange(event.target.textContent.trim());
|
||||
this.element.nativeElement.focus();
|
||||
}
|
||||
this.closePanel();
|
||||
}
|
||||
}
|
@@ -19,7 +19,6 @@ import { Injectable } from '@angular/core';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { ContentApi, MinimalNode, Node, NodeEntry, NodesApi } from '@alfresco/js-api';
|
||||
import { Observable, Subject, from, throwError } from 'rxjs';
|
||||
import { FolderCreatedEvent } from '../events/folder-created.event';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { AuthenticationService } from '../auth/services/authentication.service';
|
||||
import { LogService } from '../common/services/log.service';
|
||||
@@ -27,7 +26,14 @@ import { catchError } from 'rxjs/operators';
|
||||
import { PermissionsEnum } from '../models/permissions.enum';
|
||||
import { AllowableOperationsEnum } from '../models/allowable-operations.enum';
|
||||
import { DownloadService } from './download.service';
|
||||
import { ThumbnailService } from './thumbnail.service';
|
||||
import { ThumbnailService } from '../common/services/thumbnail.service';
|
||||
|
||||
export interface FolderCreatedEvent {
|
||||
name: string;
|
||||
relativePath?: string;
|
||||
parentId?: string;
|
||||
node?: NodeEntry;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
@@ -1,85 +0,0 @@
|
||||
/*!
|
||||
* @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 { Injectable } from '@angular/core';
|
||||
import {
|
||||
AlfrescoApiCompatibility,
|
||||
ContentApi,
|
||||
Node, NodesApi
|
||||
} from '@alfresco/js-api';
|
||||
import { ReplaySubject, Subject } from 'rxjs';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ExternalAlfrescoApiService {
|
||||
|
||||
/**
|
||||
* Publish/subscribe to events related to node updates.
|
||||
*/
|
||||
nodeUpdated = new Subject<Node>();
|
||||
|
||||
alfrescoApiInitialized: ReplaySubject<boolean> = new ReplaySubject(1);
|
||||
|
||||
protected alfrescoApi: AlfrescoApiCompatibility;
|
||||
_nodesApi: NodesApi;
|
||||
|
||||
getInstance(): AlfrescoApiCompatibility {
|
||||
return this.alfrescoApi;
|
||||
}
|
||||
|
||||
get contentApi(): ContentApi {
|
||||
return this.getInstance().content;
|
||||
}
|
||||
|
||||
get nodesApi(): NodesApi {
|
||||
this._nodesApi = this._nodesApi ?? new NodesApi(this.getInstance());
|
||||
return this._nodesApi;
|
||||
}
|
||||
|
||||
init(ecmHost: string, contextRoot: string) {
|
||||
|
||||
const domainPrefix = this.createPrefixFromHost(ecmHost);
|
||||
|
||||
const config = {
|
||||
provider: 'ECM',
|
||||
hostEcm: ecmHost,
|
||||
authType: 'BASIC',
|
||||
contextRoot,
|
||||
domainPrefix
|
||||
};
|
||||
this.initAlfrescoApi(config);
|
||||
this.alfrescoApiInitialized.next(true);
|
||||
}
|
||||
|
||||
protected initAlfrescoApi(config) {
|
||||
if (this.alfrescoApi) {
|
||||
this.alfrescoApi.configureJsApi(config);
|
||||
} else {
|
||||
this.alfrescoApi = new AlfrescoApiCompatibility(config);
|
||||
}
|
||||
}
|
||||
|
||||
private createPrefixFromHost(url: string): string {
|
||||
const match = url.match(/:\/\/(www[0-9]?\.)?(.[^/:]+)/i);
|
||||
let result = null;
|
||||
if (match != null && match.length > 2 && typeof match[2] === 'string' && match[2].length > 0) {
|
||||
result = match[2];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
@@ -17,27 +17,16 @@
|
||||
|
||||
export * from './alfresco-api.service';
|
||||
export * from './content.service';
|
||||
export * from './page-title.service';
|
||||
export * from './renditions.service';
|
||||
export * from './translation.service';
|
||||
export * from './translate-loader.service';
|
||||
export * from './thumbnail.service';
|
||||
export * from './upload.service';
|
||||
export * from './dynamic-component-mapper.service';
|
||||
export * from './highlight-transform.service';
|
||||
export * from './deleted-nodes-api.service';
|
||||
export * from './nodes-api.service';
|
||||
export * from './people-content.service';
|
||||
export * from './people-process.service';
|
||||
export * from './discovery-api.service';
|
||||
export * from './external-alfresco-api.service';
|
||||
export * from './download-zip.service';
|
||||
export * from './automation.service';
|
||||
export * from './automation.service';
|
||||
export * from './download.service';
|
||||
export * from './bpm-user.service';
|
||||
export * from './ecm-user.service';
|
||||
export * from './language.service';
|
||||
export * from './sort-by-category.service';
|
||||
export * from './user-access.service';
|
||||
export * from './user-info-resolver.service';
|
||||
|
@@ -18,7 +18,7 @@
|
||||
import { TestBed, ComponentFixture } from '@angular/core/testing';
|
||||
import { CoreTestingModule } from '../../testing/core.testing.module';
|
||||
import { ErrorContentComponent } from './error-content.component';
|
||||
import { TranslationService } from '../../services/translation.service';
|
||||
import { TranslationService } from '../../translation/translation.service';
|
||||
import { setupTestBed } from '../../testing/setup-test-bed';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { of } from 'rxjs';
|
||||
|
@@ -23,7 +23,7 @@ import {
|
||||
OnInit
|
||||
} from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { TranslationService } from '../../services/translation.service';
|
||||
import { TranslationService } from '../../translation/translation.service';
|
||||
@Component({
|
||||
selector: 'adf-error-content',
|
||||
templateUrl: './error-content.component.html',
|
||||
|
@@ -17,7 +17,7 @@
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { AlfrescoApiService } from '../services/alfresco-api.service';
|
||||
import { StorageService } from '../common/services/storage.service';
|
||||
import { UserPreferencesService } from '../common/services/user-preferences.service';
|
||||
import { DemoForm } from '../mock/form/demo-form.mock';
|
@@ -19,7 +19,7 @@ import { NgModule } from '@angular/core';
|
||||
import { CoreModule } from '../core.module';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { TRANSLATION_PROVIDER } from '../services/translation.service';
|
||||
import { TRANSLATION_PROVIDER } from '../translation/translation.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
@@ -24,14 +24,14 @@ import { AlfrescoApiService } from '../services/alfresco-api.service';
|
||||
import { AlfrescoApiServiceMock } from '../mock/alfresco-api.service.mock';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { AppConfigServiceMock } from '../common/mock/app-config.service.mock';
|
||||
import { TranslationService } from '../services/translation.service';
|
||||
import { TranslationService } from '../translation/translation.service';
|
||||
import { TranslationMock } from '../mock/translation.service.mock';
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { CookieService } from '../common/services/cookie.service';
|
||||
import { CookieServiceMock } from '../mock/cookie.service.mock';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { directionalityConfigFactory } from '../services/directionality-config-factory';
|
||||
import { DirectionalityConfigService } from '../services/directionality-config.service';
|
||||
import { directionalityConfigFactory } from '../common/services/directionality-config-factory';
|
||||
import { DirectionalityConfigService } from '../common/services/directionality-config.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
@@ -17,3 +17,4 @@
|
||||
|
||||
export * from './setup-test-bed';
|
||||
export * from './core.testing.module';
|
||||
export * from './automation.service';
|
||||
|
@@ -15,4 +15,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export const getType = (type: any): any => () => type;
|
||||
export * from './translation.service';
|
||||
export * from './translate-loader.service';
|
@@ -24,7 +24,7 @@ import { TranslateLoaderService } from './translate-loader.service';
|
||||
import { TRANSLATION_PROVIDER, TranslationService } from './translation.service';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { AppConfigServiceMock } from '../common/mock/app-config.service.mock';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { AlfrescoApiService } from '../services/alfresco-api.service';
|
||||
import { AlfrescoApiServiceMock } from '../mock/alfresco-api.service.mock';
|
||||
|
||||
declare let jasmine: any;
|
@@ -21,7 +21,7 @@ import { AlfrescoApiService } from '../../services/alfresco-api.service';
|
||||
import { LogService } from '../../common/services/log.service';
|
||||
import { Subject } from 'rxjs';
|
||||
import { Track } from '../models/viewer.model';
|
||||
import { TranslationService } from '../../services/translation.service';
|
||||
import { TranslationService } from '../../translation/translation.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
@@ -41,10 +41,10 @@ export * from './lib/clipboard/index';
|
||||
export * from './lib/dialogs/index';
|
||||
export * from './lib/icon/index';
|
||||
export * from './lib/notifications/index';
|
||||
export * from './lib/search-text/index';
|
||||
export * from './lib/blank-page/index';
|
||||
export * from './lib/rich-text-editor/index';
|
||||
export * from './lib/snackbar-content/index';
|
||||
export * from './lib/translation/index';
|
||||
|
||||
export * from './lib/common/utils/index';
|
||||
export * from './lib/interface/index';
|
||||
|
Reference in New Issue
Block a user