diff --git a/src/app/app.component.scss b/src/app/app.component.scss index fa7e7a873a..7793b7529c 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -1,4 +1,3 @@ -@import '../styles/variables.scss'; @import '../styles/helpers/font_awesome_imports.scss'; @import '../../node_modules/bootstrap/scss/bootstrap.scss'; @import '../../node_modules/nouislider/distribute/nouislider.min'; @@ -48,4 +47,3 @@ ds-admin-sidebar { position: fixed; z-index: $sidebar-z-index; } - diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 37cc791558..52c169e7bc 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -28,10 +28,10 @@ import variables from '../styles/_exposed_variables.scss'; import { CSSVariableService } from './shared/sass-helper/sass-helper.service'; import { MenuService } from './shared/menu/menu.service'; import { MenuID } from './shared/menu/initial-menus-state'; -import { Observable } from 'rxjs/internal/Observable'; +import { combineLatest as combineLatestObservable, Observable, of } from 'rxjs'; import { slideSidebarPadding } from './shared/animations/slide'; -import { combineLatest as combineLatestObservable } from 'rxjs'; import { HostWindowService } from './shared/host-window.service'; +import { Theme } from '../config/theme.inferface'; @Component({ selector: 'ds-app', @@ -47,6 +47,7 @@ export class AppComponent implements OnInit, AfterViewInit { slideSidebarOver: Observable; collapsedSidebarWidth: Observable; totalSidebarWidth: Observable; + theme: Observable = of({} as any); constructor( @Inject(GLOBAL_CONFIG) public config: GlobalConfig, @@ -59,7 +60,7 @@ export class AppComponent implements OnInit, AfterViewInit { private router: Router, private cssService: CSSVariableService, private menuService: MenuService, - private windowService: HostWindowService + private windowService: HostWindowService, ) { // Load all the languages that are defined as active from the config file translate.addLangs(config.languages.filter((LangConfig) => LangConfig.active === true).map((a) => a.code)); @@ -83,6 +84,7 @@ export class AppComponent implements OnInit, AfterViewInit { } ngOnInit() { + const env: string = this.config.production ? 'Production' : 'Development'; const color: string = this.config.production ? 'red' : 'green'; console.info(`Environment: %c${env}`, `color: ${color}; font-weight: bold;`); diff --git a/src/app/core/core.effects.ts b/src/app/core/core.effects.ts index 9ade23e6c5..1aa5d2d0b1 100644 --- a/src/app/core/core.effects.ts +++ b/src/app/core/core.effects.ts @@ -1,4 +1,3 @@ - import { ObjectCacheEffects } from './cache/object-cache.effects'; import { UUIDIndexEffects } from './index/index.effects'; import { RequestEffects } from './data/request.effects'; diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 6550435aa3..418b22351b 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -60,6 +60,7 @@ import { HALEndpointService } from './shared/hal-endpoint.service'; import { FacetValueResponseParsingService } from './data/facet-value-response-parsing.service'; import { FacetValueMapResponseParsingService } from './data/facet-value-map-response-parsing.service'; import { FacetConfigResponseParsingService } from './data/facet-config-response-parsing.service'; +import { ResourcePolicyService } from './data/resource-policy.service'; import { RegistryService } from './registry/registry.service'; import { RegistryMetadataschemasResponseParsingService } from './data/registry-metadataschemas-response-parsing.service'; import { RegistryMetadatafieldsResponseParsingService } from './data/registry-metadatafields-response-parsing.service'; @@ -125,6 +126,7 @@ const PROVIDERS = [ MetadataService, ObjectCacheService, PaginationComponentOptions, + ResourcePolicyService, RegistryService, NormalizedObjectBuildService, RemoteDataBuildService, diff --git a/src/app/core/data/comcol-data.service.spec.ts b/src/app/core/data/comcol-data.service.spec.ts index 7f628fc5b9..b5232b0bff 100644 --- a/src/app/core/data/comcol-data.service.spec.ts +++ b/src/app/core/data/comcol-data.service.spec.ts @@ -89,7 +89,7 @@ describe('ComColDataService', () => { function initMockCommunityDataService(): CommunityDataService { return jasmine.createSpyObj('responseCache', { getEndpoint: hot('--a-', { a: communitiesEndpoint }), - getIDHref: cold('b-', { b: communityEndpoint }) + getIDHref: communityEndpoint }); } diff --git a/src/app/core/data/comcol-data.service.ts b/src/app/core/data/comcol-data.service.ts index 9d82cc5047..68eb3e4880 100644 --- a/src/app/core/data/comcol-data.service.ts +++ b/src/app/core/data/comcol-data.service.ts @@ -31,7 +31,7 @@ export abstract class ComColDataService extends DataS return this.halService.getEndpoint(linkPath); } else { const scopeCommunityHrefObs = this.cds.getEndpoint().pipe( - mergeMap((endpoint: string) => this.cds.getIDHref(endpoint, options.scopeID)), + map((endpoint: string) => this.cds.getIDHref(endpoint, options.scopeID)), filter((href: string) => isNotEmpty(href)), take(1), tap((href: string) => { diff --git a/src/app/core/data/metadata-schema-data.service.ts b/src/app/core/data/metadata-schema-data.service.ts index 1d2bf3b221..5e58d972f7 100644 --- a/src/app/core/data/metadata-schema-data.service.ts +++ b/src/app/core/data/metadata-schema-data.service.ts @@ -13,15 +13,38 @@ import { MetadataSchema } from '../metadata/metadataschema.model'; import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { HttpClient } from '@angular/common/http'; import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { ChangeAnalyzer } from './change-analyzer'; import { DefaultChangeAnalyzer } from './default-change-analyzer.service'; +/* tslint:disable:max-classes-per-file */ +class DataServiceImpl extends DataService { + protected linkPath = 'metadataschemas'; + protected forceBypassCache = false; + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected dataBuildService: NormalizedObjectBuildService, + protected store: Store, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + protected http: HttpClient, + protected comparator: ChangeAnalyzer) { + super(); + } + + getBrowseEndpoint(options: FindAllOptions = {}, linkPath: string = this.linkPath): Observable { + return this.halService.getEndpoint(linkPath); + } +} + /** * A service responsible for fetching/sending data from/to the REST API on the metadataschemas endpoint */ @Injectable() -export class MetadataSchemaDataService extends DataService { - protected linkPath = 'metadataschemas'; - protected forceBypassCache = false; +export class MetadataSchemaDataService { + private dataService: DataServiceImpl; constructor( protected requestService: RequestService, @@ -33,17 +56,6 @@ export class MetadataSchemaDataService extends DataService { protected dataBuildService: NormalizedObjectBuildService, protected http: HttpClient, protected notificationsService: NotificationsService) { - super(); + this.dataService = new DataServiceImpl(requestService, rdbService, dataBuildService, null, objectCache, halService, notificationsService, http, comparator); } - - /** - * Get the endpoint for browsing metadataschemas - * @param {FindAllOptions} options - * @returns {Observable} - */ - public getBrowseEndpoint(options: FindAllOptions = {}, linkPath: string = this.linkPath): Observable { - - return null; - } - } diff --git a/src/app/core/data/resource-policy.service.spec.ts b/src/app/core/data/resource-policy.service.spec.ts new file mode 100644 index 0000000000..35d28684a7 --- /dev/null +++ b/src/app/core/data/resource-policy.service.spec.ts @@ -0,0 +1,77 @@ +import { cold, getTestScheduler } from 'jasmine-marbles'; +import { TestScheduler } from 'rxjs/testing'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { ResourcePolicy } from '../shared/resource-policy.model'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { GetRequest } from './request.models'; +import { RequestService } from './request.service'; +import { ResourcePolicyService } from './resource-policy.service'; +import { ObjectCacheService } from '../cache/object-cache.service'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { HttpClient } from '@angular/common/http'; +import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; + +describe('ResourcePolicyService', () => { + let scheduler: TestScheduler; + let service: ResourcePolicyService; + let requestService: RequestService; + let rdbService: RemoteDataBuildService; + let objectCache: ObjectCacheService; + const testObject = { + uuid: '664184ee-b254-45e8-970d-220e5ccc060b' + } as ResourcePolicy; + const requestURL = `https://rest.api/rest/api/resourcepolicies/${testObject.uuid}`; + const requestUUID = '8b3c613a-5a4b-438b-9686-be1d5b4a1c5a'; + + beforeEach(() => { + scheduler = getTestScheduler(); + + requestService = jasmine.createSpyObj('requestService', { + generateRequestId: requestUUID, + configure: true + }); + rdbService = jasmine.createSpyObj('rdbService', { + buildSingle: cold('a', { + a: { + payload: testObject + } + }) + }); + objectCache = {} as ObjectCacheService; + const halService = {} as HALEndpointService; + const notificationsService = {} as NotificationsService; + const http = {} as HttpClient; + const comparator = {} as any; + const dataBuildService = {} as NormalizedObjectBuildService; + + service = new ResourcePolicyService( + requestService, + rdbService, + dataBuildService, + objectCache, + halService, + notificationsService, + http, + comparator + ) + }); + + describe('findByHref', () => { + it('should configure the proper GetRequest', () => { + scheduler.schedule(() => service.findByHref(requestURL)); + scheduler.flush(); + + expect(requestService.configure).toHaveBeenCalledWith(new GetRequest(requestUUID, requestURL, null), false); + }); + + it('should return a RemoteData for the object with the given URL', () => { + const result = service.findByHref(requestURL); + const expected = cold('a', { + a: { + payload: testObject + } + }); + expect(result).toBeObservable(expected); + }); + }); +}); diff --git a/src/app/core/data/resource-policy.service.ts b/src/app/core/data/resource-policy.service.ts new file mode 100644 index 0000000000..1a6a1afedc --- /dev/null +++ b/src/app/core/data/resource-policy.service.ts @@ -0,0 +1,67 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; + +import { Store } from '@ngrx/store'; +import { Observable } from 'rxjs'; + +import { DataService } from '../data/data.service'; +import { RequestService } from '../data/request.service'; +import { FindAllOptions } from '../data/request.models'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { ResourcePolicy } from '../shared/resource-policy.model'; +import { RemoteData } from '../data/remote-data'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { CoreState } from '../core.reducers'; +import { ObjectCacheService } from '../cache/object-cache.service'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; +import { ChangeAnalyzer } from './change-analyzer'; +import { DefaultChangeAnalyzer } from '../data/default-change-analyzer.service'; +import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; + +/* tslint:disable:max-classes-per-file */ +class DataServiceImpl extends DataService { + protected linkPath = 'resourcepolicies'; + protected forceBypassCache = false; + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected dataBuildService: NormalizedObjectBuildService, + protected store: Store, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + protected http: HttpClient, + protected comparator: ChangeAnalyzer) { + super(); + } + + getBrowseEndpoint(options: FindAllOptions = {}, linkPath: string = this.linkPath): Observable { + return this.halService.getEndpoint(linkPath); + } +} + +/** + * A service responsible for fetching/sending data from/to the REST API on the resourcepolicies endpoint + */ +@Injectable() +export class ResourcePolicyService { + private dataService: DataServiceImpl; + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected dataBuildService: NormalizedObjectBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + protected http: HttpClient, + protected comparator: DefaultChangeAnalyzer) { + this.dataService = new DataServiceImpl(requestService, rdbService, dataBuildService, null, objectCache, halService, notificationsService, http, comparator); + } + + findByHref(href: string, options?: HttpOptions): Observable> { + return this.dataService.findByHref(href, options); + } +} diff --git a/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.ts b/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.ts index a355431100..b584fa3285 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.ts +++ b/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.ts @@ -4,10 +4,7 @@ import { Item } from '../../../../core/shared/item.model'; import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { isNotEmpty } from '../../../../shared/empty.util'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; -import { - filterRelationsByTypeLabel, - relationsToItems -} from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; +import { getRelatedItemsByTypeLabel } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; @rendersItemType('JournalIssue', ItemViewMode.Full) @Component({ @@ -34,12 +31,10 @@ export class JournalIssueComponent extends ItemComponent { if (isNotEmpty(this.resolvedRelsAndTypes$)) { this.volumes$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isJournalVolumeOfIssue'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isJournalVolumeOfIssue') ); this.publications$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isPublicationOfJournalIssue'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isPublicationOfJournalIssue') ); } } diff --git a/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.ts b/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.ts index a851bfebbe..66df0b8104 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.ts +++ b/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.ts @@ -4,10 +4,7 @@ import { Item } from '../../../../core/shared/item.model'; import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { isNotEmpty } from '../../../../shared/empty.util'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; -import { - filterRelationsByTypeLabel, - relationsToItems -} from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; +import { getRelatedItemsByTypeLabel } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; @rendersItemType('JournalVolume', ItemViewMode.Full) @Component({ @@ -34,12 +31,10 @@ export class JournalVolumeComponent extends ItemComponent { if (isNotEmpty(this.resolvedRelsAndTypes$)) { this.journals$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isJournalOfVolume'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isJournalOfVolume') ); this.issues$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isIssueOfJournalVolume'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isIssueOfJournalVolume') ); } } diff --git a/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.ts b/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.ts index 99183651e1..a8f071d78a 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.ts +++ b/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.ts @@ -4,10 +4,7 @@ import { Item } from '../../../../core/shared/item.model'; import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { isNotEmpty } from '../../../../shared/empty.util'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; -import { - filterRelationsByTypeLabel, - relationsToItems -} from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; +import { getRelatedItemsByTypeLabel } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; @rendersItemType('Journal', ItemViewMode.Full) @Component({ @@ -29,8 +26,7 @@ export class JournalComponent extends ItemComponent { if (isNotEmpty(this.resolvedRelsAndTypes$)) { this.volumes$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isVolumeOfJournal'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isVolumeOfJournal') ); } } diff --git a/src/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.ts b/src/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.ts index 7101f05d35..031ca14ebb 100644 --- a/src/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.ts +++ b/src/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.ts @@ -4,10 +4,7 @@ import { Item } from '../../../../core/shared/item.model'; import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { isNotEmpty } from '../../../../shared/empty.util'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; -import { - filterRelationsByTypeLabel, - relationsToItems -} from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; +import { getRelatedItemsByTypeLabel } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; @rendersItemType('OrgUnit', ItemViewMode.Full) @Component({ @@ -39,18 +36,15 @@ export class OrgunitComponent extends ItemComponent implements OnInit { if (isNotEmpty(this.resolvedRelsAndTypes$)) { this.people$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isPersonOfOrgUnit'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isPersonOfOrgUnit') ); this.projects$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isProjectOfOrgUnit'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isProjectOfOrgUnit') ); this.publications$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isPublicationOfOrgUnit'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isPublicationOfOrgUnit') ); } }} diff --git a/src/app/entity-groups/research-entities/item-pages/person/person.component.ts b/src/app/entity-groups/research-entities/item-pages/person/person.component.ts index ec91561eb9..8b36175b96 100644 --- a/src/app/entity-groups/research-entities/item-pages/person/person.component.ts +++ b/src/app/entity-groups/research-entities/item-pages/person/person.component.ts @@ -6,10 +6,7 @@ import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.compo import { SearchFixedFilterService } from '../../../../+search-page/search-filters/search-filter/search-fixed-filter.service'; import { isNotEmpty } from '../../../../shared/empty.util'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; -import { - filterRelationsByTypeLabel, - relationsToItems -} from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; +import { getRelatedItemsByTypeLabel } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; @rendersItemType('Person', ItemViewMode.Full) @Component({ @@ -57,18 +54,15 @@ export class PersonComponent extends ItemComponent { if (isNotEmpty(this.resolvedRelsAndTypes$)) { this.publications$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isPublicationOfAuthor'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isPublicationOfAuthor') ); this.projects$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isProjectOfPerson'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isProjectOfPerson') ); this.orgUnits$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isOrgUnitOfPerson'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isOrgUnitOfPerson') ); this.fixedFilterQuery = this.fixedFilterService.getQueryByRelations('isAuthorOfPublication', this.item.id); diff --git a/src/app/entity-groups/research-entities/item-pages/project/project.component.ts b/src/app/entity-groups/research-entities/item-pages/project/project.component.ts index 46bc7c9f88..13c2b54ba4 100644 --- a/src/app/entity-groups/research-entities/item-pages/project/project.component.ts +++ b/src/app/entity-groups/research-entities/item-pages/project/project.component.ts @@ -5,10 +5,7 @@ import { MetadataRepresentation } from '../../../../core/shared/metadata-represe import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { isNotEmpty } from '../../../../shared/empty.util'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; -import { - filterRelationsByTypeLabel, - relationsToItems -} from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; +import { getRelatedItemsByTypeLabel } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; @rendersItemType('Project', ItemViewMode.Full) @Component({ @@ -47,18 +44,15 @@ export class ProjectComponent extends ItemComponent implements OnInit { this.contributors$ = this.buildRepresentations('OrgUnit', 'project.contributor.other'); this.people$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isPersonOfProject'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isPersonOfProject') ); this.publications$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isPublicationOfProject'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isPublicationOfProject') ); this.orgUnits$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isOrgUnitOfProject'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isOrgUnitOfProject') ); } } diff --git a/src/app/footer/footer.component.scss b/src/app/footer/footer.component.scss index bd141706da..51201774d5 100644 --- a/src/app/footer/footer.component.scss +++ b/src/app/footer/footer.component.scss @@ -1,4 +1,3 @@ -@import '../../styles/variables.scss'; $footer-bg: $gray-100; $footer-border: 1px solid darken($footer-bg, 10%); $footer-padding: $spacer * 1.5; diff --git a/src/app/header-nav-wrapper/header-navbar-wrapper.component.scss b/src/app/header-nav-wrapper/header-navbar-wrapper.component.scss index f514508385..c3eba35b79 100644 --- a/src/app/header-nav-wrapper/header-navbar-wrapper.component.scss +++ b/src/app/header-nav-wrapper/header-navbar-wrapper.component.scss @@ -1,5 +1,3 @@ -@import '../../styles/variables.scss'; - @media screen and (max-width: map-get($grid-breakpoints, md)) { :host.open { background-color: $white; diff --git a/src/app/header/header.component.scss b/src/app/header/header.component.scss index df4c0b8fb8..4d25bd0d43 100644 --- a/src/app/header/header.component.scss +++ b/src/app/header/header.component.scss @@ -1,5 +1,3 @@ -@import '../../styles/variables.scss'; - .navbar-brand img { height: $header-logo-height; @media screen and (max-width: map-get($grid-breakpoints, sm)) { diff --git a/src/app/navbar/expandable-navbar-section/expandable-navbar-section.component.scss b/src/app/navbar/expandable-navbar-section/expandable-navbar-section.component.scss index 1fb78bef0d..f724c3e751 100644 --- a/src/app/navbar/expandable-navbar-section/expandable-navbar-section.component.scss +++ b/src/app/navbar/expandable-navbar-section/expandable-navbar-section.component.scss @@ -1,5 +1,3 @@ -@import '../../../styles/variables.scss'; - .dropdown-menu { overflow: hidden; min-width: 100%; diff --git a/src/app/navbar/navbar.component.scss b/src/app/navbar/navbar.component.scss index 947b785196..d0fa04991d 100644 --- a/src/app/navbar/navbar.component.scss +++ b/src/app/navbar/navbar.component.scss @@ -1,5 +1,3 @@ -@import '../../styles/variables.scss'; - nav.navbar { border-bottom: 1px $gray-400 solid; align-items: baseline; @@ -34,6 +32,4 @@ nav.navbar { } padding: 0; } -} - - +} \ No newline at end of file diff --git a/src/app/navbar/navbar.component.ts b/src/app/navbar/navbar.component.ts index 1a20a6b12f..4c7c3cd030 100644 --- a/src/app/navbar/navbar.component.ts +++ b/src/app/navbar/navbar.component.ts @@ -13,8 +13,8 @@ import { GLOBAL_CONFIG, GlobalConfig } from '../../config'; */ @Component({ selector: 'ds-navbar', - styleUrls: ['navbar.component.scss'], - templateUrl: 'navbar.component.html', + styleUrls: ['./navbar.component.scss'], + templateUrl: './navbar.component.html', animations: [slideMobileNav] }) export class NavbarComponent extends MenuComponent implements OnInit { diff --git a/src/app/pagenotfound/pagenotfound.component.scss b/src/app/pagenotfound/pagenotfound.component.scss index da97dd7a62..e69de29bb2 100644 --- a/src/app/pagenotfound/pagenotfound.component.scss +++ b/src/app/pagenotfound/pagenotfound.component.scss @@ -1 +0,0 @@ -@import '../../styles/variables.scss'; diff --git a/src/app/shared/chips/chips.component.scss b/src/app/shared/chips/chips.component.scss index 9d7eae7edd..76be755920 100644 --- a/src/app/shared/chips/chips.component.scss +++ b/src/app/shared/chips/chips.component.scss @@ -1,5 +1,3 @@ -@import "../../../styles/variables"; - .chip-selected { background-color: map-get($theme-colors, info) !important; } diff --git a/src/app/shared/comcol-page-content/comcol-page-content.component.scss b/src/app/shared/comcol-page-content/comcol-page-content.component.scss index ad84b72f8c..e69de29bb2 100644 --- a/src/app/shared/comcol-page-content/comcol-page-content.component.scss +++ b/src/app/shared/comcol-page-content/comcol-page-content.component.scss @@ -1 +0,0 @@ -@import '../../../styles/variables.scss'; \ No newline at end of file diff --git a/src/app/shared/comcol-page-header/comcol-page-header.component.scss b/src/app/shared/comcol-page-header/comcol-page-header.component.scss index ad84b72f8c..e69de29bb2 100644 --- a/src/app/shared/comcol-page-header/comcol-page-header.component.scss +++ b/src/app/shared/comcol-page-header/comcol-page-header.component.scss @@ -1 +0,0 @@ -@import '../../../styles/variables.scss'; \ No newline at end of file diff --git a/src/app/shared/comcol-page-logo/comcol-page-logo.component.scss b/src/app/shared/comcol-page-logo/comcol-page-logo.component.scss index 50be6f5ad0..e69de29bb2 100644 --- a/src/app/shared/comcol-page-logo/comcol-page-logo.component.scss +++ b/src/app/shared/comcol-page-logo/comcol-page-logo.component.scss @@ -1 +0,0 @@ -@import '../../../styles/variables.scss'; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.scss b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.scss index 3e6536110d..3af258db79 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.scss +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.scss @@ -1,5 +1,3 @@ -@import "../../../../../../../styles/variables"; - .dropdown-toggle::after { display:none } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.scss b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.scss index 7d1160f450..a657d3eeb6 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.scss +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.scss @@ -1,5 +1,3 @@ -@import "../../../../../../../styles/variables"; - /* style fa-spin */ .fa-spin { pointer-events: none; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.scss b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.scss index 7c58c0272f..fe20afe1ce 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.scss +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.scss @@ -1,5 +1,3 @@ -@import "../../../../../../../styles/variables"; - :host /deep/ .dropdown-menu { width: 100% !important; max-height: $dropdown-menu-max-height; diff --git a/src/app/shared/form/form.component.scss b/src/app/shared/form/form.component.scss index 1d5e034290..01cf09576f 100644 --- a/src/app/shared/form/form.component.scss +++ b/src/app/shared/form/form.component.scss @@ -1,5 +1,3 @@ -@import "../../../styles/_variables.scss"; - .ds-form-input-addon { border-top-right-radius: 0 !important; border-bottom-right-radius: 0 !important; diff --git a/src/app/shared/input-suggestions/input-suggestions.component.scss b/src/app/shared/input-suggestions/input-suggestions.component.scss index f2587e1b6f..b04cef2adf 100644 --- a/src/app/shared/input-suggestions/input-suggestions.component.scss +++ b/src/app/shared/input-suggestions/input-suggestions.component.scss @@ -1,5 +1,3 @@ -@import "../../../styles/_variables.scss"; - .autocomplete { width: 100%; .dropdown-item { diff --git a/src/app/shared/log-in/log-in.component.scss b/src/app/shared/log-in/log-in.component.scss index 5e4393edaf..0eda382c0a 100644 --- a/src/app/shared/log-in/log-in.component.scss +++ b/src/app/shared/log-in/log-in.component.scss @@ -1,5 +1,3 @@ -@import '../../../styles/variables.scss'; - .form-login .form-control:focus { z-index: 2; } diff --git a/src/app/shared/notifications/notification/notification.component.scss b/src/app/shared/notifications/notification/notification.component.scss index 1c8f0ae17c..a5ebb72b0b 100644 --- a/src/app/shared/notifications/notification/notification.component.scss +++ b/src/app/shared/notifications/notification/notification.component.scss @@ -1,5 +1,3 @@ -@import '../../../../styles/variables.scss'; - .alert { display: inline-block; min-width: $modal-sm; diff --git a/src/app/shared/notifications/notifications-board/notifications-board.component.scss b/src/app/shared/notifications/notifications-board/notifications-board.component.scss index 47b1dba0c3..1101393e59 100644 --- a/src/app/shared/notifications/notifications-board/notifications-board.component.scss +++ b/src/app/shared/notifications/notifications-board/notifications-board.component.scss @@ -1,6 +1,3 @@ -@import '../../../../styles/variables'; -@import '../../../../styles/mixins'; - .notifications-wrapper { z-index: $zindex-popover; text-align: right; diff --git a/src/app/shared/object-collection/object-collection.component.scss b/src/app/shared/object-collection/object-collection.component.scss index 48e6526dff..e69de29bb2 100644 --- a/src/app/shared/object-collection/object-collection.component.scss +++ b/src/app/shared/object-collection/object-collection.component.scss @@ -1 +0,0 @@ -@import '../../../styles/variables'; diff --git a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.scss b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.scss index 51a7fc6a55..8b13789179 100644 --- a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.scss +++ b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.scss @@ -1,2 +1 @@ -@import '../../../../styles/variables'; diff --git a/src/app/shared/object-grid/community-grid-element/community-grid-element.component.scss b/src/app/shared/object-grid/community-grid-element/community-grid-element.component.scss index 51a7fc6a55..8b13789179 100644 --- a/src/app/shared/object-grid/community-grid-element/community-grid-element.component.scss +++ b/src/app/shared/object-grid/community-grid-element/community-grid-element.component.scss @@ -1,2 +1 @@ -@import '../../../../styles/variables'; diff --git a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.scss b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.scss index 45a533cd01..e69de29bb2 100644 --- a/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.scss +++ b/src/app/shared/object-grid/grid-thumbnail/grid-thumbnail.component.scss @@ -1 +0,0 @@ -@import '../../../../styles/variables'; diff --git a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.scss b/src/app/shared/object-grid/item-grid-element/item-grid-element.component.scss index 51a7fc6a55..8b13789179 100644 --- a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.scss +++ b/src/app/shared/object-grid/item-grid-element/item-grid-element.component.scss @@ -1,2 +1 @@ -@import '../../../../styles/variables'; diff --git a/src/app/shared/object-grid/object-grid.component.scss b/src/app/shared/object-grid/object-grid.component.scss index ff78634863..437dfc3b43 100644 --- a/src/app/shared/object-grid/object-grid.component.scss +++ b/src/app/shared/object-grid/object-grid.component.scss @@ -1,6 +1,3 @@ -@import '../../../styles/variables'; -@import '../../../styles/mixins'; - $ds-wrapper-grid-spacing: $spacer/2; ds-wrapper-grid-element ::ng-deep { diff --git a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.scss b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.scss index 1d0786105c..e69de29bb2 100644 --- a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.scss +++ b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.scss @@ -1 +0,0 @@ -@import '../../../../../styles/variables'; diff --git a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.scss b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.scss index bd63aa6a3a..8b13789179 100644 --- a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.scss +++ b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.scss @@ -1,2 +1 @@ -@import '../../../../../styles/variables'; diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.scss b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.scss index e2751279b6..d61f3ccf55 100644 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.scss +++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.scss @@ -1,5 +1,3 @@ -@import '../../../../../styles/variables'; - .card { a > div { position: relative; diff --git a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.scss b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.scss index e8d681fb32..dc9f9b3969 100644 --- a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.scss +++ b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.scss @@ -1,4 +1,3 @@ - @import '../../../../styles/variables'; :host { /deep/ em { font-weight: bold; diff --git a/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.scss b/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.scss index 51a7fc6a55..8b13789179 100644 --- a/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.scss +++ b/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.scss @@ -1,2 +1 @@ -@import '../../../../styles/variables'; diff --git a/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.scss b/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.scss index 45a533cd01..e69de29bb2 100644 --- a/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.scss +++ b/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.scss @@ -1 +0,0 @@ -@import '../../../../styles/variables'; diff --git a/src/app/shared/object-list/collection-list-element/collection-list-element.component.scss b/src/app/shared/object-list/collection-list-element/collection-list-element.component.scss index 45a533cd01..e69de29bb2 100644 --- a/src/app/shared/object-list/collection-list-element/collection-list-element.component.scss +++ b/src/app/shared/object-list/collection-list-element/collection-list-element.component.scss @@ -1 +0,0 @@ -@import '../../../../styles/variables'; diff --git a/src/app/shared/object-list/community-list-element/community-list-element.component.scss b/src/app/shared/object-list/community-list-element/community-list-element.component.scss index 45a533cd01..e69de29bb2 100644 --- a/src/app/shared/object-list/community-list-element/community-list-element.component.scss +++ b/src/app/shared/object-list/community-list-element/community-list-element.component.scss @@ -1 +0,0 @@ -@import '../../../../styles/variables'; diff --git a/src/app/shared/object-list/item-list-element/item-list-element.component.scss b/src/app/shared/object-list/item-list-element/item-list-element.component.scss index 45a533cd01..e69de29bb2 100644 --- a/src/app/shared/object-list/item-list-element/item-list-element.component.scss +++ b/src/app/shared/object-list/item-list-element/item-list-element.component.scss @@ -1 +0,0 @@ -@import '../../../../styles/variables'; diff --git a/src/app/shared/object-list/item-list-element/item-types/publication/publication-list-element.component.html b/src/app/shared/object-list/item-list-element/item-types/publication/publication-list-element.component.html index aff19aec1d..d467edfb21 100644 --- a/src/app/shared/object-list/item-list-element/item-types/publication/publication-list-element.component.html +++ b/src/app/shared/object-list/item-list-element/item-types/publication/publication-list-element.component.html @@ -12,6 +12,7 @@ class="item-list-authors"> + ; diff --git a/src/app/shared/object-list/object-list.component.scss b/src/app/shared/object-list/object-list.component.scss index 3d2af4d023..e69de29bb2 100644 --- a/src/app/shared/object-list/object-list.component.scss +++ b/src/app/shared/object-list/object-list.component.scss @@ -1 +0,0 @@ -@import '../../../styles/variables'; \ No newline at end of file diff --git a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.scss b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.scss index 1d0786105c..e69de29bb2 100644 --- a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.scss +++ b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.scss @@ -1 +0,0 @@ -@import '../../../../../styles/variables'; diff --git a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.scss b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.scss index 1d0786105c..e69de29bb2 100644 --- a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.scss +++ b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.scss @@ -1 +0,0 @@ -@import '../../../../../styles/variables'; diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.scss b/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.scss index 1d0786105c..e69de29bb2 100644 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.scss +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.scss @@ -1 +0,0 @@ -@import '../../../../../styles/variables'; diff --git a/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.scss b/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.scss index 7134c43dad..efc4d3c414 100644 --- a/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.scss +++ b/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.scss @@ -1,4 +1,3 @@ -@import '../../../../styles/variables'; :host { ::ng-deep em { font-weight: bold; diff --git a/src/app/shared/object-list/wrapper-list-element/wrapper-list-element.component.scss b/src/app/shared/object-list/wrapper-list-element/wrapper-list-element.component.scss index 51a7fc6a55..8b13789179 100644 --- a/src/app/shared/object-list/wrapper-list-element/wrapper-list-element.component.scss +++ b/src/app/shared/object-list/wrapper-list-element/wrapper-list-element.component.scss @@ -1,2 +1 @@ -@import '../../../../styles/variables'; diff --git a/src/app/shared/search-form/search-form.component.scss b/src/app/shared/search-form/search-form.component.scss index d5811186e7..64b97aebd8 100644 --- a/src/app/shared/search-form/search-form.component.scss +++ b/src/app/shared/search-form/search-form.component.scss @@ -1,5 +1,3 @@ -@import '../../../styles/variables.scss'; - // temporary fix for bootstrap 4 beta btn color issue .btn-secondary { background-color: $input-bg; diff --git a/src/app/shared/search-form/search-form.component.ts b/src/app/shared/search-form/search-form.component.ts index 10c3a3ede7..7414dd70e6 100644 --- a/src/app/shared/search-form/search-form.component.ts +++ b/src/app/shared/search-form/search-form.component.ts @@ -15,6 +15,7 @@ import { SearchService } from '../../+search-page/search-service/search.service' @Component({ selector: 'ds-search-form', styleUrls: ['./search-form.component.scss'], + // templateUrl: './search-form.component.html', templateUrl: './search-form.component.html' }) @@ -45,6 +46,16 @@ export class SearchFormComponent { */ @Input() scopes: DSpaceObject[]; + /** + * Whether or not the search button should be displayed large + */ + @Input() large = false; + + /** + * The brand color of the search button + */ + @Input() brandColor = 'primary'; + constructor(private router: Router, private searchService: SearchService) { } diff --git a/src/app/shared/starts-with/date/starts-with-date.component.scss b/src/app/shared/starts-with/date/starts-with-date.component.scss index ceec56c8c2..64b97aebd8 100644 --- a/src/app/shared/starts-with/date/starts-with-date.component.scss +++ b/src/app/shared/starts-with/date/starts-with-date.component.scss @@ -1,5 +1,3 @@ -@import '../../../../styles/variables.scss'; - // temporary fix for bootstrap 4 beta btn color issue .btn-secondary { background-color: $input-bg; diff --git a/src/app/shared/starts-with/text/starts-with-text.component.scss b/src/app/shared/starts-with/text/starts-with-text.component.scss index ceec56c8c2..64b97aebd8 100644 --- a/src/app/shared/starts-with/text/starts-with-text.component.scss +++ b/src/app/shared/starts-with/text/starts-with-text.component.scss @@ -1,5 +1,3 @@ -@import '../../../../styles/variables.scss'; - // temporary fix for bootstrap 4 beta btn color issue .btn-secondary { background-color: $input-bg; diff --git a/src/app/shared/truncatable/truncatable-part/truncatable-part.component.scss b/src/app/shared/truncatable/truncatable-part/truncatable-part.component.scss index 133328fec1..68b6772465 100644 --- a/src/app/shared/truncatable/truncatable-part/truncatable-part.component.scss +++ b/src/app/shared/truncatable/truncatable-part/truncatable-part.component.scss @@ -1,6 +1,3 @@ -@import '../../../../styles/variables'; -@import '../../../../styles/mixins'; - @mixin clamp($lines, $size-factor: 1, $line-height: $line-height-base) { $height: $line-height * $font-size-base * $size-factor; &.fixedHeight { diff --git a/src/app/shared/uploader/uploader.component.scss b/src/app/shared/uploader/uploader.component.scss index 370c3ea280..8835b87b1e 100644 --- a/src/app/shared/uploader/uploader.component.scss +++ b/src/app/shared/uploader/uploader.component.scss @@ -1,5 +1,3 @@ -@import '../../../styles/_variables.scss'; - .ds-base-drop-zone { border: 2px dashed $gray-600; } diff --git a/src/app/shared/view-mode-switch/view-mode-switch.component.scss b/src/app/shared/view-mode-switch/view-mode-switch.component.scss index ad84b72f8c..e69de29bb2 100644 --- a/src/app/shared/view-mode-switch/view-mode-switch.component.scss +++ b/src/app/shared/view-mode-switch/view-mode-switch.component.scss @@ -1 +0,0 @@ -@import '../../../styles/variables.scss'; \ No newline at end of file diff --git a/src/app/submission/form/collection/submission-form-collection.component.scss b/src/app/submission/form/collection/submission-form-collection.component.scss index f91f85677d..deecc39510 100644 --- a/src/app/submission/form/collection/submission-form-collection.component.scss +++ b/src/app/submission/form/collection/submission-form-collection.component.scss @@ -1,5 +1,3 @@ -@import '../../../../styles/variables'; - .scrollable-menu { height: auto; max-height: $dropdown-menu-max-height; diff --git a/src/app/submission/form/collection/submission-form-collection.component.spec.ts b/src/app/submission/form/collection/submission-form-collection.component.spec.ts index 679500a670..598d4a1732 100644 --- a/src/app/submission/form/collection/submission-form-collection.component.spec.ts +++ b/src/app/submission/form/collection/submission-form-collection.component.spec.ts @@ -1,4 +1,10 @@ -import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA, DebugElement, SimpleChange } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + CUSTOM_ELEMENTS_SCHEMA, + DebugElement, + SimpleChange +} from '@angular/core'; import { async, ComponentFixture, fakeAsync, inject, TestBed, tick } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; @@ -10,7 +16,10 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { Store } from '@ngrx/store'; import { SubmissionServiceStub } from '../../../shared/testing/submission-service-stub'; -import { mockSubmissionId, mockSubmissionRestResponse } from '../../../shared/mocks/mock-submission'; +import { + mockSubmissionId, + mockSubmissionRestResponse +} from '../../../shared/mocks/mock-submission'; import { SubmissionService } from '../../submission.service'; import { SubmissionFormCollectionComponent } from './submission-form-collection.component'; import { CommunityDataService } from '../../../core/data/community-data.service'; @@ -25,28 +34,8 @@ import { PageInfo } from '../../../core/shared/page-info.model'; import { Collection } from '../../../core/shared/collection.model'; import { createTestComponent } from '../../../shared/testing/utils'; import { cold } from 'jasmine-marbles'; - -const subcommunities = [Object.assign(new Community(), { - name: 'SubCommunity 1', - id: '123456789-1', - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'SubCommunity 1' - }] -}), - Object.assign(new Community(), { - name: 'SubCommunity 1', - id: '123456789s-1', - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'SubCommunity 1' - }] - }) -]; +import { SearchResult } from '../../../+search-page/search-result.model'; +import { SearchService } from '../../../+search-page/search-service/search.service'; const mockCommunity1Collection1 = Object.assign(new Collection(), { name: 'Community 1-Collection 1', @@ -92,45 +81,20 @@ const mockCommunity2Collection2 = Object.assign(new Collection(), { }] }); -const mockCommunity = Object.assign(new Community(), { - name: 'Community 1', - id: '123456789-1', - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'Community 1' - }], - collections: observableOf(new RemoteData(true, true, true, - undefined, new PaginatedList(new PageInfo(), [mockCommunity1Collection1, mockCommunity1Collection2]))), - subcommunities: observableOf(new RemoteData(true, true, true, - undefined, new PaginatedList(new PageInfo(), subcommunities))), -}); - -const mockCommunity2 = Object.assign(new Community(), { - name: 'Community 2', - id: '123456789-2', - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'Community 2' - }], - collections: observableOf(new RemoteData(true, true, true, - undefined, new PaginatedList(new PageInfo(), [mockCommunity2Collection1, mockCommunity2Collection2]))), - subcommunities: observableOf(new RemoteData(true, true, true, - undefined, new PaginatedList(new PageInfo(), []))), -}); - -const mockCommunityList = observableOf(new RemoteData(true, true, true, - undefined, new PaginatedList(new PageInfo(), [mockCommunity, mockCommunity2]))); +const collectionResults = [mockCommunity1Collection1, mockCommunity1Collection2, mockCommunity2Collection1, mockCommunity2Collection2].map((collection: Collection) => Object.assign(new SearchResult(), { indexableObject: collection })); +const searchService = { + search: () => { + return observableOf(new RemoteData(true, true, true, + undefined, new PaginatedList(new PageInfo(), collectionResults))) + } +}; const mockCollectionList = [ { communities: [ { - id: '123456789-1', - name: 'Community 1' + id: 'c0e4de93-f506-4990-a840-d406f6f2ada7', + name: 'Submission test' } ], collection: { @@ -141,8 +105,8 @@ const mockCollectionList = [ { communities: [ { - id: '123456789-1', - name: 'Community 1' + id: 'c0e4de93-f506-4990-a840-d406f6f2ada7', + name: 'Submission test' } ], collection: { @@ -153,8 +117,8 @@ const mockCollectionList = [ { communities: [ { - id: '123456789-2', - name: 'Community 2' + id: 'c0e4de93-f506-4990-a840-d406f6f2ada7', + name: 'Submission test' } ], collection: { @@ -165,8 +129,8 @@ const mockCollectionList = [ { communities: [ { - id: '123456789-2', - name: 'Community 2' + id: 'c0e4de93-f506-4990-a840-d406f6f2ada7', + name: 'Submission test' } ], collection: { @@ -214,11 +178,15 @@ describe('SubmissionFormCollectionComponent Component', () => { TestComponent ], providers: [ - { provide: SubmissionJsonPatchOperationsService, useClass: SubmissionJsonPatchOperationsServiceStub }, + { + provide: SubmissionJsonPatchOperationsService, + useClass: SubmissionJsonPatchOperationsServiceStub + }, { provide: SubmissionService, useClass: SubmissionServiceStub }, { provide: CommunityDataService, useValue: communityDataService }, { provide: JsonPatchOperationsBuilder, useValue: jsonPatchOpBuilder }, { provide: Store, useValue: store }, + { provide: SearchService, useValue: searchService }, ChangeDetectorRef, SubmissionFormCollectionComponent ], @@ -283,14 +251,11 @@ describe('SubmissionFormCollectionComponent Component', () => { }); it('should init collection list properly', () => { - communityDataService.findAll.and.returnValue(mockCommunityList); - comp.ngOnChanges({ currentCollectionId: new SimpleChange(null, collectionId, true) }); - expect(comp.searchListCollection$).toBeObservable(cold('(ab)', { - a: [], + expect(comp.searchListCollection$).toBeObservable(cold('(b)', { b: mockCollectionList })); @@ -428,6 +393,8 @@ class TestComponent { definitionId = 'traditional'; submissionId = mockSubmissionId; - onCollectionChange = () => { return; } + onCollectionChange = () => { + return; + } } diff --git a/src/app/submission/form/collection/submission-form-collection.component.ts b/src/app/submission/form/collection/submission-form-collection.component.ts index b576834091..e9832985fe 100644 --- a/src/app/submission/form/collection/submission-form-collection.component.ts +++ b/src/app/submission/form/collection/submission-form-collection.component.ts @@ -17,16 +17,13 @@ import { distinctUntilChanged, filter, find, - flatMap, map, mergeMap, - reduce, startWith } from 'rxjs/operators'; import { Collection } from '../../../core/shared/collection.model'; import { CommunityDataService } from '../../../core/data/community-data.service'; -import { Community } from '../../../core/shared/community.model'; import { hasValue, isEmpty, isNotEmpty } from '../../../shared/empty.util'; import { RemoteData } from '../../../core/data/remote-data'; import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner'; @@ -35,6 +32,12 @@ import { PaginatedList } from '../../../core/data/paginated-list'; import { SubmissionService } from '../../submission.service'; import { SubmissionObject } from '../../../core/submission/models/submission-object.model'; import { SubmissionJsonPatchOperationsService } from '../../../core/submission/submission-json-patch-operations.service'; +import { SearchService } from '../../../+search-page/search-service/search.service'; +import { PaginatedSearchOptions } from '../../../+search-page/paginated-search-options.model'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model'; +import { getSucceededRemoteData } from '../../../core/shared/operators'; +import { SearchResult } from '../../../+search-page/search-result.model'; /** * An interface to represent a collection entry @@ -148,12 +151,14 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit { * @param {JsonPatchOperationsBuilder} operationsBuilder * @param {SubmissionJsonPatchOperationsService} operationsService * @param {SubmissionService} submissionService + * @param {SearchService} searchService */ constructor(protected cdr: ChangeDetectorRef, private communityDataService: CommunityDataService, private operationsBuilder: JsonPatchOperationsBuilder, private operationsService: SubmissionJsonPatchOperationsService, - private submissionService: SubmissionService) { + private submissionService: SubmissionService, + private searchService: SearchService) { } /** @@ -190,38 +195,39 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit { && hasValue(changes.currentCollectionId.currentValue)) { this.selectedCollectionId = this.currentCollectionId; - // @TODO replace with search/top browse endpoint - // @TODO implement community/subcommunity hierarchy - const communities$ = this.communityDataService.findAll().pipe( - find((communities: RemoteData>) => isNotEmpty(communities.payload)), - mergeMap((communities: RemoteData>) => communities.payload.page)); + // // @TODO replace with search/top browse endpoint + // // @TODO implement community/subcommunity hierarchy + // const communities$ = this.communityDataService.findAll().pipe( + // find((communities: RemoteData>) => isNotEmpty(communities.payload)), + // mergeMap((communities: RemoteData>) => communities.payload.page)); - const listCollection$ = communities$.pipe( - flatMap((communityData: Community) => { - return communityData.collections.pipe( - find((collections: RemoteData>) => !collections.isResponsePending && collections.hasSucceeded), - mergeMap((collections: RemoteData>) => collections.payload.page), - filter((collectionData: Collection) => isNotEmpty(collectionData)), - map((collectionData: Collection) => ({ - communities: [{ id: communityData.id, name: communityData.name }], - collection: { id: collectionData.id, name: collectionData.name } - })) - ); - }), - reduce((acc: any, value: any) => [...acc, ...value], []), - startWith([]) + const listCollection$: Observable = this.searchService.search( + new PaginatedSearchOptions({ + dsoType: DSpaceObjectType.COLLECTION, + pagination: new PaginationComponentOptions(), + scope: 'c0e4de93-f506-4990-a840-d406f6f2ada7' + }) + ).pipe( + getSucceededRemoteData(), + map((collections: RemoteData>>) => collections.payload.page), + filter((collectionData: Array>) => isNotEmpty(collectionData)), + map((collectionData: Array>) => { + return collectionData.map((collection: SearchResult) => { + return { + communities: [{ + id: 'c0e4de93-f506-4990-a840-d406f6f2ada7', + name: 'Submission test' + }], + collection: { id: collection.indexableObject.id, name: collection.indexableObject.name } + } + }) + }) ); - this.selectedCollectionName$ = communities$.pipe( - flatMap((communityData: Community) => { - return communityData.collections.pipe( - find((collections: RemoteData>) => !collections.isResponsePending && collections.hasSucceeded), - mergeMap((collections: RemoteData>) => collections.payload.page), - filter((collectionData: Collection) => isNotEmpty(collectionData)), - filter((collectionData: Collection) => collectionData.id === this.selectedCollectionId), - map((collectionData: Collection) => collectionData.name) - ); - }), + this.selectedCollectionName$ = listCollection$.pipe( + map((collectionData: CollectionListEntry[]) => collectionData.find((entry: CollectionListEntry) => entry.collection.id === this.selectedCollectionId)), + filter((entry: CollectionListEntry) => hasValue(entry.collection)), + map((entry: CollectionListEntry) => entry.collection.name), startWith('') ); diff --git a/src/app/submission/form/section-add/submission-form-section-add.component.scss b/src/app/submission/form/section-add/submission-form-section-add.component.scss index 628f0f5633..c8fd2073d1 100644 --- a/src/app/submission/form/section-add/submission-form-section-add.component.scss +++ b/src/app/submission/form/section-add/submission-form-section-add.component.scss @@ -1,5 +1,3 @@ -@import '../../../../styles/variables'; - .dropdown-toggle::after { display:none } diff --git a/src/app/submission/form/submission-form.component.scss b/src/app/submission/form/submission-form.component.scss index c9b6872146..44551162cc 100644 --- a/src/app/submission/form/submission-form.component.scss +++ b/src/app/submission/form/submission-form.component.scss @@ -1,5 +1,3 @@ -@import '../../../styles/variables'; - .submission-form-header { background-color: rgba($white, .97); padding: ($spacer / 2) 0 ($spacer / 2) 0; diff --git a/src/app/submission/sections/container/section-container.component.scss b/src/app/submission/sections/container/section-container.component.scss index 2e17794e42..3917280f8c 100644 --- a/src/app/submission/sections/container/section-container.component.scss +++ b/src/app/submission/sections/container/section-container.component.scss @@ -1,5 +1,3 @@ -@import '../../../../styles/variables'; - :host /deep/ .card { margin-bottom: $submission-sections-margin-bottom; overflow: unset; diff --git a/src/app/submission/sections/upload/file/section-upload-file.component.scss b/src/app/submission/sections/upload/file/section-upload-file.component.scss index ce67ef98df..7596652dc2 100644 --- a/src/app/submission/sections/upload/file/section-upload-file.component.scss +++ b/src/app/submission/sections/upload/file/section-upload-file.component.scss @@ -1,5 +1,3 @@ -@import '../../../../../styles/variables'; - .sticky-buttons { position: sticky; top: $dropdown-item-padding-x * 3; diff --git a/src/app/submission/sections/upload/section-upload.component.spec.ts b/src/app/submission/sections/upload/section-upload.component.spec.ts index be8f096964..f84ece4969 100644 --- a/src/app/submission/sections/upload/section-upload.component.spec.ts +++ b/src/app/submission/sections/upload/section-upload.component.spec.ts @@ -30,6 +30,7 @@ import { GroupEpersonService } from '../../../core/eperson/group-eperson.service import { cold, hot } from 'jasmine-marbles'; import { Collection } from '../../../core/shared/collection.model'; import { ResourcePolicy } from '../../../core/shared/resource-policy.model'; +import { ResourcePolicyService } from '../../../core/data/resource-policy.service'; import { RemoteData } from '../../../core/data/remote-data'; import { ConfigData } from '../../../core/config/config-data'; import { PageInfo } from '../../../core/shared/page-info.model'; @@ -47,8 +48,7 @@ function getMockSubmissionUploadsConfigService(): SubmissionFormsConfigService { function getMockCollectionDataService(): CollectionDataService { return jasmine.createSpyObj('CollectionDataService', { - findById: jasmine.createSpy('findById'), - findByHref: jasmine.createSpy('findByHref') + findById: jasmine.createSpy('findById') }); } @@ -59,6 +59,12 @@ function getMockGroupEpersonService(): GroupEpersonService { }); } +function getMockResourcePolicyService(): ResourcePolicyService { + return jasmine.createSpyObj('ResourcePolicyService', { + findByHref: jasmine.createSpy('findByHref') + }); +} + const sectionObject: SectionDataObject = { config: 'https://dspace7.4science.it/or2018/api/config/submissionforms/upload', mandatory: true, @@ -80,6 +86,7 @@ describe('SubmissionSectionUploadComponent test suite', () => { let sectionsServiceStub: SectionsServiceStub; let collectionDataService: any; let groupService: any; + let resourcePolicyService: any; let uploadsConfigService: any; let bitstreamService: any; @@ -120,6 +127,7 @@ describe('SubmissionSectionUploadComponent test suite', () => { providers: [ { provide: CollectionDataService, useValue: getMockCollectionDataService() }, { provide: GroupEpersonService, useValue: getMockGroupEpersonService() }, + { provide: ResourcePolicyService, useValue: getMockResourcePolicyService() }, { provide: SubmissionUploadsConfigService, useValue: getMockSubmissionUploadsConfigService() }, { provide: SectionsService, useClass: SectionsServiceStub }, { provide: SubmissionService, useClass: SubmissionServiceStub }, @@ -166,6 +174,7 @@ describe('SubmissionSectionUploadComponent test suite', () => { sectionsServiceStub = TestBed.get(SectionsService); collectionDataService = TestBed.get(CollectionDataService); groupService = TestBed.get(GroupEpersonService); + resourcePolicyService = TestBed.get(ResourcePolicyService); uploadsConfigService = TestBed.get(SubmissionUploadsConfigService); bitstreamService = TestBed.get(SectionUploadService); }); @@ -184,7 +193,7 @@ describe('SubmissionSectionUploadComponent test suite', () => { new RemoteData(false, false, true, undefined, mockCollection))); - collectionDataService.findByHref.and.returnValue(observableOf( + resourcePolicyService.findByHref.and.returnValue(observableOf( new RemoteData(false, false, true, undefined, mockDefaultAccessCondition) )); @@ -230,7 +239,7 @@ describe('SubmissionSectionUploadComponent test suite', () => { new RemoteData(false, false, true, undefined, mockCollection))); - collectionDataService.findByHref.and.returnValue(observableOf( + resourcePolicyService.findByHref.and.returnValue(observableOf( new RemoteData(false, false, true, undefined, mockDefaultAccessCondition) )); diff --git a/src/app/submission/sections/upload/section-upload.component.ts b/src/app/submission/sections/upload/section-upload.component.ts index 3a79a670ad..826385af45 100644 --- a/src/app/submission/sections/upload/section-upload.component.ts +++ b/src/app/submission/sections/upload/section-upload.component.ts @@ -8,6 +8,7 @@ import { hasValue, isNotEmpty, isNotUndefined, isUndefined } from '../../../shar import { SectionUploadService } from './section-upload.service'; import { CollectionDataService } from '../../../core/data/collection-data.service'; import { GroupEpersonService } from '../../../core/eperson/group-eperson.service'; +import { ResourcePolicyService } from '../../../core/data/resource-policy.service'; import { SubmissionUploadsConfigService } from '../../../core/config/submission-uploads-config.service'; import { SubmissionUploadsModel } from '../../../core/config/models/config-submission-uploads.model'; import { SubmissionFormsModel } from '../../../core/config/models/config-submission-forms.model'; @@ -116,6 +117,7 @@ export class SubmissionSectionUploadComponent extends SectionModelComponent { * @param {ChangeDetectorRef} changeDetectorRef * @param {CollectionDataService} collectionDataService * @param {GroupEpersonService} groupService + * @param {ResourcePolicyService} resourcePolicyService * @param {SectionsService} sectionService * @param {SubmissionService} submissionService * @param {SubmissionUploadsConfigService} uploadsConfigService @@ -126,6 +128,7 @@ export class SubmissionSectionUploadComponent extends SectionModelComponent { private changeDetectorRef: ChangeDetectorRef, private collectionDataService: CollectionDataService, private groupService: GroupEpersonService, + private resourcePolicyService: ResourcePolicyService, protected sectionService: SectionsService, private submissionService: SubmissionService, private uploadsConfigService: SubmissionUploadsConfigService, @@ -155,7 +158,7 @@ export class SubmissionSectionUploadComponent extends SectionModelComponent { find((rd: RemoteData) => isNotUndefined((rd.payload))), tap((collectionRemoteData: RemoteData) => this.collectionName = collectionRemoteData.payload.name), flatMap((collectionRemoteData: RemoteData) => { - return this.collectionDataService.findByHref( + return this.resourcePolicyService.findByHref( (collectionRemoteData.payload as any)._links.defaultAccessConditions ); }), diff --git a/src/app/thumbnail/thumbnail.component.ts b/src/app/thumbnail/thumbnail.component.ts index 9700e01821..e31e907b47 100644 --- a/src/app/thumbnail/thumbnail.component.ts +++ b/src/app/thumbnail/thumbnail.component.ts @@ -20,7 +20,7 @@ export class ThumbnailComponent implements OnInit { /** * The default 'holder.js' image */ - @Input() defaultImage? = 'data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2293%22%20height%3D%22120%22%20viewBox%3D%220%200%2093%20120%22%20preserveAspectRatio%3D%22none%22%3E%3C!--%0ASource%20URL%3A%20holder.js%2F93x120%3Ftext%3DNo%20Thumbnail%0ACreated%20with%20Holder.js%202.8.2.%0ALearn%20more%20at%20http%3A%2F%2Fholderjs.com%0A(c)%202012-2015%20Ivan%20Malopinsky%20-%20http%3A%2F%2Fimsky.co%0A--%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%3C!%5BCDATA%5B%23holder_1543e460b05%20text%20%7B%20fill%3A%23AAAAAA%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A10pt%20%7D%20%5D%5D%3E%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_1543e460b05%22%3E%3Crect%20width%3D%2293%22%20height%3D%22120%22%20fill%3D%22%23EEEEEE%22%2F%3E%3Cg%3E%3Ctext%20x%3D%2235.6171875%22%20y%3D%2257%22%3ENo%3C%2Ftext%3E%3Ctext%20x%3D%2210.8125%22%20y%3D%2272%22%3EThumbnail%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E'; + @Input() defaultImage? = 'data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2293%22%20height%3D%22120%22%20viewBox%3D%220%200%2093%20120%22%20preserveAspectRatio%3D%22none%22%3E%3C!--%0ASource%20URL%3A%20holder.js%2F93x120%3Ftext%3DNo%20Thumbnail%0ACreated%20with%20Holder.js%202.8.2.%0ALearn%20more%20at%20http%3A%2F%2Fholderjs.com%0A(c)%202012-2015%20Ivan%20Malopinsky%20-%20http%3A%2F%2Fimsky.co%0A--%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%3C!%5BCDATA%5B%23holder_1543e460b05%20text%20%7B%20fill%3A%23AAAAAA%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A10pt%20%7D%20%5D%5D%3E%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_1543e460b05%22%3E%3Crect%20width%3D%2293%22%20height%3D%22120%22%20fill%3D%22%23FFFFFF%22%2F%3E%3Cg%3E%3Ctext%20x%3D%2235.6171875%22%20y%3D%2257%22%3ENo%3C%2Ftext%3E%3Ctext%20x%3D%2210.8125%22%20y%3D%2272%22%3EThumbnail%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E'; src: string; errorHandler(event) { diff --git a/src/config.js b/src/config.js new file mode 100644 index 0000000000..269277643c --- /dev/null +++ b/src/config.js @@ -0,0 +1,150 @@ +const path = require('path'); + +let production = false; + +let mergedConfig; + +let envConfigOverride; + +let envConfigFile; + +__webpack + +// check process.env.NODE_ENV to determine which environment config to use +// process.env.NODE_ENV is defined by webpack, else assume development +switch (process.env.NODE_ENV) { + case 'prod': + case 'production': + // webpack.prod.dspace-angular-config.ts defines process.env.NODE_ENV = 'production' + envConfigFile = './environment.prod.js'; + production = true; + break; + case 'test': + // webpack.test.dspace-angular-config.ts defines process.env.NODE_ENV = 'test' + envConfigFile = './environment.test.js'; + break; + default: + // if not using webpack.prod.dspace-angular-config.ts or webpack.test.dspace-angular-config.ts, it must be development + envConfigFile = './environment.dev.js'; +} + +try { + mergedConfig = require(path.resolve(__dirname, '..', 'config', 'environment.default.js')); +} catch (e) { + console.log('e', e); + throw new Error('Cannot find file config/environment.default.js'); +} + +// if envConfigFile set try to get configs +if (envConfigFile) { + try { + envConfigOverride = require(path.resolve(__dirname, '..', 'config', envConfigFile)); + } catch (e) { + console.log('e', e); + console.warn('Cannot find file ' + envConfigFile.substring(2, envConfigFile.length), 'Using default environment'); + } + try { + merge(envConfigOverride); + } catch (e) { + console.warn('Unable to merge the default environment'); + } +} + +// allow to override a few important options by environment variables +function createServerConfig(host, port, nameSpace, ssl) { + const result = { host, nameSpace }; + + if (port !== null && port !== undefined) { + result.port = port * 1; + } + + if (ssl !== null && ssl !== undefined) { + result.ssl = ssl.trim().match(/^(true|1|yes)$/i) ? true : false; + } + + return result; +} + +const processEnv = { + ui: createServerConfig( + process.env.DSPACE_HOST, + process.env.DSPACE_PORT, + process.env.DSPACE_NAMESPACE, + process.env.DSPACE_SSL), + rest: createServerConfig( + process.env.DSPACE_REST_HOST, + process.env.DSPACE_REST_PORT, + process.env.DSPACE_REST_NAMESPACE, + process.env.DSPACE_REST_SSL) +}; + +// merge the environment variables with our configuration. +try { + merge(processEnv) +} catch (e) { + console.warn('Unable to merge environment variable into the configuration') +} + +buildBaseUrls(); + +// set config for whether running in production +mergedConfig.production = production; + +function merge(config) { + innerMerge(mergedConfig, config); +} + +function innerMerge(globalConfig, config) { + for (const key in config) { + if (config.hasOwnProperty(key)) { + if (isObject(config[key])) { + innerMerge(globalConfig[key], config[key]); + } else { + if (isDefined(config[key])) { + globalConfig[key] = config[key]; + } + } + } + } +} + +function buildBaseUrls() { + for (const key in mergedConfig) { + if (mergedConfig.hasOwnProperty(key) && mergedConfig[key].host) { + mergedConfig[key].baseUrl = [ + getProtocol(mergedConfig[key].ssl), + getHost(mergedConfig[key].host), + getPort(mergedConfig[key].port), + getNameSpace(mergedConfig[key].nameSpace) + ].join(''); + } + } +} + +function getProtocol(ssl) { + return ssl ? 'https://' : 'http://'; +} + +function getHost(host) { + return host; +} + +function getPort(port) { + return port ? (port !== 80 && port !== 443) ? ':' + port : '' : ''; +} + +function getNameSpace(nameSpace) { + return nameSpace ? nameSpace.charAt(0) === '/' ? nameSpace : '/' + nameSpace : ''; +} + +function isDefined(value) { + return typeof value !== 'undefined' && value !== null; +} + +function isObject(item) { + return item && typeof item === 'object' && !Array.isArray(item); +} + +module.exports = { + mergedConfig: mergedConfig +}; diff --git a/src/config/global-config.interface.ts b/src/config/global-config.interface.ts index d83ec6e4d8..22b4b0500f 100644 --- a/src/config/global-config.interface.ts +++ b/src/config/global-config.interface.ts @@ -8,6 +8,7 @@ import { FormConfig } from './form-config.interfaces'; import {LangConfig} from './lang-config.interface'; import { BrowseByConfig } from './browse-by-config.interface'; import { ItemPageConfig } from './item-page-config.interface'; +import { Theme } from './theme.inferface'; export interface GlobalConfig extends Config { ui: ServerConfig; @@ -25,4 +26,5 @@ export interface GlobalConfig extends Config { languages: LangConfig[]; browseBy: BrowseByConfig; item: ItemPageConfig; + themes: Theme[]; } diff --git a/src/config/theme.inferface.ts b/src/config/theme.inferface.ts new file mode 100644 index 0000000000..d0cf1d77d8 --- /dev/null +++ b/src/config/theme.inferface.ts @@ -0,0 +1,5 @@ +import { Config } from './config.interface'; + +export interface Theme extends Config { + name: string; +} diff --git a/src/styles/_bootstrap_variables.scss b/src/styles/_bootstrap_variables.scss index 7be76ff5d3..5258365cfd 100644 --- a/src/styles/_bootstrap_variables.scss +++ b/src/styles/_bootstrap_variables.scss @@ -1,3 +1,5 @@ +@import '_themed_bootstrap_variables.scss'; + /** Help Variables **/ $fa-fixed-width: 1.25rem; $icon-padding: 1rem; diff --git a/src/styles/_custom_variables.scss b/src/styles/_custom_variables.scss index be03d719c5..8ca2067a2e 100644 --- a/src/styles/_custom_variables.scss +++ b/src/styles/_custom_variables.scss @@ -1,3 +1,5 @@ +@import '_themed_custom_variables.scss'; + $content-spacing: $spacer * 1.5; $button-height: $input-btn-padding-y * 2 + $input-btn-line-height + calculateRem($input-btn-border-width*2); @@ -20,9 +22,9 @@ $sidebar-z-index: 20; $header-logo-height: 80px; $header-logo-height-xs: 50px; -$admin-sidebar-bg: $dark; -$admin-sidebar-active-bg: darken($dark, 3%); -$admin-sidebar-header-bg: darken($dark, 7%); +$admin-sidebar-bg: darken(#2B4E72, 17%); +$admin-sidebar-active-bg: darken($admin-sidebar-bg, 3%); +$admin-sidebar-header-bg: darken($admin-sidebar-bg, 7%); $dark-scrollbar-background: $admin-sidebar-active-bg; $dark-scrollbar-foreground: #47495d; @@ -32,3 +34,5 @@ $submission-sections-margin-bottom: .5rem !default; $edit-item-button-min-width: 100px; $edit-item-metadata-field-width: 190px; $edit-item-language-field-width: 43px; + +$thumbnail-max-width: 175px; diff --git a/src/styles/_exposed_variables.scss b/src/styles/_exposed_variables.scss index 5f0f2d2654..1ab67e709d 100644 --- a/src/styles/_exposed_variables.scss +++ b/src/styles/_exposed_variables.scss @@ -9,4 +9,4 @@ sidebarItemsWidth: $sidebar-items-width; collapsedSidebarWidth: $collapsed-sidebar-width; totalSidebarWidth: $total-sidebar-width; -} \ No newline at end of file +} diff --git a/src/styles/_mixins.scss b/src/styles/_mixins.scss index 40bb9b8f3e..e72af304cd 100644 --- a/src/styles/_mixins.scss +++ b/src/styles/_mixins.scss @@ -1,6 +1,5 @@ @import '../../node_modules/bootstrap/scss/functions.scss'; @import '../../node_modules/bootstrap/scss/mixins.scss'; -@import 'variables.scss'; @mixin word-wrap() { overflow-wrap: break-word; @@ -39,5 +38,4 @@ &::-webkit-resizer { background-color: $dark-scrollbar-background; } - } diff --git a/src/styles/_variables.scss b/src/styles/_variables.scss index 33a3f0b1fa..2632dbfd09 100644 --- a/src/styles/_variables.scss +++ b/src/styles/_variables.scss @@ -1,5 +1,7 @@ @import '_functions.scss'; @import '../../node_modules/bootstrap/scss/functions.scss'; -@import 'bootstrap_variables.scss'; + +@import '_bootstrap_variables.scss'; @import '../../node_modules/bootstrap/scss/variables.scss'; -@import 'custom_variables.scss'; \ No newline at end of file + +@import '_custom_variables.scss'; diff --git a/themes/default/styles/_themed_bootstrap_variables.scss b/themes/default/styles/_themed_bootstrap_variables.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/themes/default/styles/_themed_custom_variables.scss b/themes/default/styles/_themed_custom_variables.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/themes/mantis/app/+home-page/home-news/home-news.component.html b/themes/mantis/app/+home-page/home-news/home-news.component.html new file mode 100644 index 0000000000..4da3ae12f7 --- /dev/null +++ b/themes/mantis/app/+home-page/home-news/home-news.component.html @@ -0,0 +1,21 @@ +
+
+
+

DSpace 7

+

DSpace is the world leading open source repository platform that enables + organisations to:

+
+
+
    +
  • easily ingest documents, audio, video, datasets and their corresponding Dublin Core + metadata +
  • +
  • open up this content to local and global audiences, thanks to the OAI-PMH interface and + Google Scholar optimizations +
  • +
  • issue permanent urls and trustworthy identifiers, including optional integrations with + handle.net and DataCite DOI +
  • +
+

Join an international community of leading institutions using DSpace.

+
diff --git a/themes/mantis/app/+home-page/home-news/home-news.component.scss b/themes/mantis/app/+home-page/home-news/home-news.component.scss new file mode 100644 index 0000000000..c693e9a493 --- /dev/null +++ b/themes/mantis/app/+home-page/home-news/home-news.component.scss @@ -0,0 +1,15 @@ +@import 'src/app/+home-page/home-news/home-news.component.scss'; +$home-news-link-color: $green !default; +$home-news-link-color: darken($home-news-link-color, 15%) !default; + +.jumbotron { + background-color: transparent; +} + +a { + color: $home-news-link-color; + + @include hover { + color: $home-news-link-color; + } +} diff --git a/themes/mantis/app/+home-page/home-page.component.html b/themes/mantis/app/+home-page/home-page.component.html new file mode 100644 index 0000000000..43edbee9ca --- /dev/null +++ b/themes/mantis/app/+home-page/home-page.component.html @@ -0,0 +1,10 @@ +
+
+ + +
+ Photo by @inspiredimages +
+
+ +
diff --git a/themes/mantis/app/+home-page/home-page.component.scss b/themes/mantis/app/+home-page/home-page.component.scss new file mode 100644 index 0000000000..64bd786cd5 --- /dev/null +++ b/themes/mantis/app/+home-page/home-page.component.scss @@ -0,0 +1,52 @@ +@import 'src/app/+home-page/home-page.component.scss'; + +div.background-image { + color: white; + background-color: $info; + position: relative; + background-position-y: -200px; + background-image: url('/assets/images/banner.jpg'); + background-size: cover; + @media screen and (max-width: map-get($grid-breakpoints, lg)) { + background-position-y: 0; + } + + .container { + position: relative; + text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6); + + &:before, &:after { + content: ''; + display: block; + width: $banner-background-gradient-width; + height: 100%; + top: 0; + position: absolute; + } + + &:before { + background: linear-gradient(to left, $banner-text-background, transparent); + left: -$banner-background-gradient-width; + + } + + &:after { + background: linear-gradient(to right, $banner-text-background, transparent); + right: -$banner-background-gradient-width; + } + + background-color: $banner-text-background; + } + + + small.credits { + a { + color: inherit; + } + + opacity: 0.3; + position: absolute; + right: $spacer; + bottom: 0; + } +} diff --git a/themes/mantis/app/+item-page/simple/item-page.component.html b/themes/mantis/app/+item-page/simple/item-page.component.html new file mode 100644 index 0000000000..472df7c78e --- /dev/null +++ b/themes/mantis/app/+item-page/simple/item-page.component.html @@ -0,0 +1,9 @@ +
+
+
+ +
+
+ + +
diff --git a/themes/mantis/app/+item-page/simple/item-types/journal-issue/journal-issue.component.html b/themes/mantis/app/+item-page/simple/item-types/journal-issue/journal-issue.component.html new file mode 100644 index 0000000000..a25a474eb0 --- /dev/null +++ b/themes/mantis/app/+item-page/simple/item-types/journal-issue/journal-issue.component.html @@ -0,0 +1,73 @@ +
+
+
+ + +
+

+ {{'journalissue.page.titleprefix' | translate}} + +

+
+
+ + + + + + +
+
+ + + + + + +
+
+
+
+
+
+
+
+
+
+ + +
+
+ + +
+
+
+
diff --git a/themes/mantis/app/+item-page/simple/item-types/journal-issue/journal-issue.component.scss b/themes/mantis/app/+item-page/simple/item-types/journal-issue/journal-issue.component.scss new file mode 100644 index 0000000000..7ce24acc15 --- /dev/null +++ b/themes/mantis/app/+item-page/simple/item-types/journal-issue/journal-issue.component.scss @@ -0,0 +1,30 @@ +@import 'src/app/+item-page/simple/item-types/journal-issue/journal-issue.component.scss'; + +:host { + > * { + display: block; + padding-top: $content-spacing; + padding-bottom: $content-spacing; + } + + .top-item-page { + background-color: $gray-100; + margin-top: -$content-spacing; + } + + .relationships-item-page { + padding-bottom: $content-spacing - $spacer; + } + + ds-metadata-field-wrapper { + @media screen and (max-width: map-get($grid-breakpoints, md)) { + flex: 1; + padding-right: $spacer/2; + } + + ds-thumbnail { + display: block; + max-width: $thumbnail-max-width; + } + } +} diff --git a/themes/mantis/app/+item-page/simple/item-types/journal-volume/journal-volume.component.html b/themes/mantis/app/+item-page/simple/item-types/journal-volume/journal-volume.component.html new file mode 100644 index 0000000000..c20e9a775a --- /dev/null +++ b/themes/mantis/app/+item-page/simple/item-types/journal-volume/journal-volume.component.html @@ -0,0 +1,62 @@ +
+
+
+ + +
+

+ {{'journalvolume.page.titleprefix' | translate}} + +

+
+
+ + + + + +
+
+ + +
+
+
+
+
+
+
+
+
+
+ + +
+
+ + +
+
+
+
diff --git a/themes/mantis/app/+item-page/simple/item-types/journal-volume/journal-volume.component.scss b/themes/mantis/app/+item-page/simple/item-types/journal-volume/journal-volume.component.scss new file mode 100644 index 0000000000..ab1bc700b1 --- /dev/null +++ b/themes/mantis/app/+item-page/simple/item-types/journal-volume/journal-volume.component.scss @@ -0,0 +1,30 @@ +@import 'src/app/+item-page/simple/item-types/journal-volume/journal-volume.component.scss'; + +:host { + > * { + display: block; + padding-top: $content-spacing; + padding-bottom: $content-spacing; + } + + .top-item-page { + background-color: $gray-100; + margin-top: -$content-spacing; + } + + .relationships-item-page { + padding-bottom: $content-spacing - $spacer; + } + + ds-metadata-field-wrapper { + @media screen and (max-width: map-get($grid-breakpoints, md)) { + flex: 1; + padding-right: $spacer/2; + } + + ds-thumbnail { + display: block; + max-width: $thumbnail-max-width; + } + } +} diff --git a/themes/mantis/app/+item-page/simple/item-types/journal/journal.component.html b/themes/mantis/app/+item-page/simple/item-types/journal/journal.component.html new file mode 100644 index 0000000000..ef827af590 --- /dev/null +++ b/themes/mantis/app/+item-page/simple/item-types/journal/journal.component.html @@ -0,0 +1,67 @@ +
+
+
+ +
+

+ {{'journal.page.titleprefix' | translate}} + +

+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+

{{"item.page.journal.search.title" | translate}}

+
+ + +
diff --git a/themes/mantis/app/+item-page/simple/item-types/journal/journal.component.scss b/themes/mantis/app/+item-page/simple/item-types/journal/journal.component.scss new file mode 100644 index 0000000000..6d97cbf5c3 --- /dev/null +++ b/themes/mantis/app/+item-page/simple/item-types/journal/journal.component.scss @@ -0,0 +1,38 @@ +@import 'src/app/+item-page/simple/item-types/journal/journal.component.scss'; + +:host { + > * { + display: block; + padding-top: $content-spacing; + padding-bottom: $content-spacing; + } + + .top-item-page { + background-color: $gray-100; + margin-top: -$content-spacing; + } + + .relationships-item-page { + padding-bottom: $content-spacing - $spacer; + } + + ds-metadata-field-wrapper { + @media screen and (max-width: map-get($grid-breakpoints, md)) { + flex: 1; + padding-right: $spacer/2; + } + + ds-thumbnail { + display: block; + max-width: $thumbnail-max-width; + } + } + + .search-container { + margin-bottom: $spacer; + @media screen and (max-width: map-get($grid-breakpoints, lg)) { + width: 100%; + max-width: none; + } + } +} diff --git a/themes/mantis/app/+item-page/simple/item-types/orgunit/orgunit.component.html b/themes/mantis/app/+item-page/simple/item-types/orgunit/orgunit.component.html new file mode 100644 index 0000000000..6bb925c93f --- /dev/null +++ b/themes/mantis/app/+item-page/simple/item-types/orgunit/orgunit.component.html @@ -0,0 +1,76 @@ +
+
+
+ + +
+

+ {{'orgunit.page.titleprefix' | translate}} + +

+
+
+ + + + + + +
+
+ + + + +
+
+
+
+
+
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
diff --git a/themes/mantis/app/+item-page/simple/item-types/orgunit/orgunit.component.scss b/themes/mantis/app/+item-page/simple/item-types/orgunit/orgunit.component.scss new file mode 100644 index 0000000000..5b2bdb0382 --- /dev/null +++ b/themes/mantis/app/+item-page/simple/item-types/orgunit/orgunit.component.scss @@ -0,0 +1,30 @@ +@import 'src/app/+item-page/simple/item-types/orgunit/orgunit.component.scss'; + +:host { + > * { + display: block; + padding-top: $content-spacing; + padding-bottom: $content-spacing; + } + + .top-item-page { + background-color: $gray-100; + margin-top: -$content-spacing; + } + + .relationships-item-page { + padding-bottom: $content-spacing - $spacer; + } + + ds-metadata-field-wrapper { + @media screen and (max-width: map-get($grid-breakpoints, md)) { + flex: 1; + padding-right: $spacer/2; + } + + ds-thumbnail { + display: block; + max-width: $thumbnail-max-width; + } + } +} diff --git a/themes/mantis/app/+item-page/simple/item-types/person/person.component.html b/themes/mantis/app/+item-page/simple/item-types/person/person.component.html new file mode 100644 index 0000000000..54d7962b97 --- /dev/null +++ b/themes/mantis/app/+item-page/simple/item-types/person/person.component.html @@ -0,0 +1,85 @@ +
+
+
+ + +
+

+ {{'person.page.titleprefix' | translate}} +

+
+
+ + + + + + + + +
+
+ + + + + + +
+
+
+
+
+
+
+
+
+
+ + +
+
+ + +
+
+
+
+
+
+

{{"item.page.person.search.title" | translate}}

+
+ + +
diff --git a/themes/mantis/app/+item-page/simple/item-types/person/person.component.scss b/themes/mantis/app/+item-page/simple/item-types/person/person.component.scss new file mode 100644 index 0000000000..3b454aab0e --- /dev/null +++ b/themes/mantis/app/+item-page/simple/item-types/person/person.component.scss @@ -0,0 +1,38 @@ +@import 'src/app/+item-page/simple/item-types/person/person.component.scss'; + +:host { + > * { + display: block; + padding-top: $content-spacing; + padding-bottom: $content-spacing; + } + + .top-item-page { + background-color: $gray-100; + margin-top: -$content-spacing; + } + + .relationships-item-page { + padding-bottom: $content-spacing - $spacer; + } + + ds-metadata-field-wrapper { + @media screen and (max-width: map-get($grid-breakpoints, md)) { + flex: 1; + padding-right: $spacer/2; + } + + ds-thumbnail { + display: block; + max-width: $thumbnail-max-width; + } + } + + .search-container { + margin-bottom: $spacer; + @media screen and (max-width: map-get($grid-breakpoints, lg)) { + width: 100%; + max-width: none; + } + } +} diff --git a/themes/mantis/app/+item-page/simple/item-types/project/project.component.html b/themes/mantis/app/+item-page/simple/item-types/project/project.component.html new file mode 100644 index 0000000000..aa4a107247 --- /dev/null +++ b/themes/mantis/app/+item-page/simple/item-types/project/project.component.html @@ -0,0 +1,85 @@ +
+
+
+ + +
+

+ {{'project.page.titleprefix' | translate}} + +

+
+
+ + + + + + + + +
+
+ + + + + + +
+
+
+
+
+
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ diff --git a/themes/mantis/app/+item-page/simple/item-types/project/project.component.scss b/themes/mantis/app/+item-page/simple/item-types/project/project.component.scss new file mode 100644 index 0000000000..9c9aa9c629 --- /dev/null +++ b/themes/mantis/app/+item-page/simple/item-types/project/project.component.scss @@ -0,0 +1,30 @@ +@import 'src/app/+item-page/simple/item-types/project/project.component.scss'; + +:host { + > * { + display: block; + padding-top: $content-spacing; + padding-bottom: $content-spacing; + } + + .top-item-page { + background-color: $gray-100; + margin-top: -$content-spacing; + } + + .relationships-item-page { + padding-bottom: $content-spacing - $spacer; + } + + ds-metadata-field-wrapper { + @media screen and (max-width: map-get($grid-breakpoints, md)) { + flex: 1; + padding-right: $spacer/2; + } + + ds-thumbnail { + display: block; + max-width: $thumbnail-max-width; + } + } +} diff --git a/themes/mantis/app/+item-page/simple/item-types/publication/publication.component.html b/themes/mantis/app/+item-page/simple/item-types/publication/publication.component.html new file mode 100644 index 0000000000..6b6f484183 --- /dev/null +++ b/themes/mantis/app/+item-page/simple/item-types/publication/publication.component.html @@ -0,0 +1,83 @@ +
+
+
+ + +
+ +
+
+ + + + + + + + + + + +
+
+ + + + + + + +
+
+
+
+
+
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
diff --git a/themes/mantis/app/+item-page/simple/item-types/publication/publication.component.scss b/themes/mantis/app/+item-page/simple/item-types/publication/publication.component.scss new file mode 100644 index 0000000000..f65d9a00d5 --- /dev/null +++ b/themes/mantis/app/+item-page/simple/item-types/publication/publication.component.scss @@ -0,0 +1,30 @@ +@import 'src/app/+item-page/simple/item-types/publication/publication.component.scss'; + +:host { + > * { + display: block; + padding-top: $content-spacing; + padding-bottom: $content-spacing; + } + + .top-item-page { + background-color: $gray-100; + margin-top: -$content-spacing; + } + + .relationships-item-page { + padding-bottom: $content-spacing - $spacer; + } + + ds-metadata-field-wrapper { + @media screen and (max-width: map-get($grid-breakpoints, md)) { + flex: 1; + padding-right: $spacer/2; + } + + ds-thumbnail { + display: block; + max-width: $thumbnail-max-width; + } + } +} diff --git a/themes/mantis/app/+search-page/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.html b/themes/mantis/app/+search-page/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.html new file mode 100644 index 0000000000..86076dfd10 --- /dev/null +++ b/themes/mantis/app/+search-page/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.html @@ -0,0 +1,9 @@ + + + {{filterValue.value}} + + {{filterValue.count}} + + \ No newline at end of file diff --git a/themes/mantis/app/+search-page/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.html b/themes/mantis/app/+search-page/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.html new file mode 100644 index 0000000000..bdb37cb52d --- /dev/null +++ b/themes/mantis/app/+search-page/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.html @@ -0,0 +1,8 @@ + + {{filterValue.value}} + + {{filterValue.count}} + + \ No newline at end of file diff --git a/themes/mantis/app/+search-page/search-filters/search-filter/search-filter.component.html b/themes/mantis/app/+search-page/search-filters/search-filter/search-filter.component.html new file mode 100644 index 0000000000..850447a39e --- /dev/null +++ b/themes/mantis/app/+search-page/search-filters/search-filter/search-filter.component.html @@ -0,0 +1,7 @@ +
+
{{'search.filters.filter.' + filter.name + '.head'| translate}}
+
+ +
+
diff --git a/themes/mantis/app/+search-page/search-filters/search-filter/search-filter.component.scss b/themes/mantis/app/+search-page/search-filters/search-filter/search-filter.component.scss new file mode 100644 index 0000000000..8e9b1d32b1 --- /dev/null +++ b/themes/mantis/app/+search-page/search-filters/search-filter/search-filter.component.scss @@ -0,0 +1,10 @@ +@import 'src/app/+search-page/search-filters/search-filter/search-filter.component.scss'; + +.facet-filter { + background-color: map-get($theme-colors, light); + border-radius: $border-radius; + + h5 { + font-size: 1.1rem + } +} diff --git a/themes/mantis/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.scss b/themes/mantis/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.scss new file mode 100644 index 0000000000..42b8e0205b --- /dev/null +++ b/themes/mantis/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.scss @@ -0,0 +1,5 @@ +@import 'src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.scss'; + +::ng-deep .noUi-connect { + background: $info; +} diff --git a/themes/mantis/app/+search-page/search-filters/search-filters.component.html b/themes/mantis/app/+search-page/search-filters/search-filters.component.html new file mode 100644 index 0000000000..b7bb1bf50f --- /dev/null +++ b/themes/mantis/app/+search-page/search-filters/search-filters.component.html @@ -0,0 +1,7 @@ +

{{"search.filters.head" | translate}}

+
+
+ +
+
+{{"search.filters.reset" | translate}} diff --git a/themes/mantis/app/+search-page/search-settings/search-settings.component.html b/themes/mantis/app/+search-page/search-settings/search-settings.component.html new file mode 100644 index 0000000000..1321ced928 --- /dev/null +++ b/themes/mantis/app/+search-page/search-settings/search-settings.component.html @@ -0,0 +1,24 @@ + +

{{ 'search.sidebar.settings.title' | translate}}

+
+
{{ 'search.sidebar.settings.sort-by' | translate}}
+ +
+ +
+
{{ 'search.sidebar.settings.rpp' | translate}}
+ +
+
\ No newline at end of file diff --git a/themes/mantis/app/+search-page/search-settings/search-settings.component.scss b/themes/mantis/app/+search-page/search-settings/search-settings.component.scss new file mode 100644 index 0000000000..602c8ca4c3 --- /dev/null +++ b/themes/mantis/app/+search-page/search-settings/search-settings.component.scss @@ -0,0 +1,10 @@ +@import 'src/app/+search-page/search-settings/search-settings.component.scss'; + +.setting-option { + background-color: map-get($theme-colors, light); + border-radius: $border-radius; + h5 { + font-size: 1.1rem + } +} + diff --git a/themes/mantis/app/navbar/navbar.component.html b/themes/mantis/app/navbar/navbar.component.html new file mode 100644 index 0000000000..d06eceb222 --- /dev/null +++ b/themes/mantis/app/navbar/navbar.component.html @@ -0,0 +1,16 @@ + diff --git a/themes/mantis/app/navbar/navbar.component.scss b/themes/mantis/app/navbar/navbar.component.scss new file mode 100644 index 0000000000..1417acff59 --- /dev/null +++ b/themes/mantis/app/navbar/navbar.component.scss @@ -0,0 +1,7 @@ +@import 'src/app/navbar/navbar.component.scss'; + +nav.navbar { + border-bottom: 5px $green solid; +} + + diff --git a/themes/mantis/app/shared/search-form/search-form.component.html b/themes/mantis/app/shared/search-form/search-form.component.html new file mode 100644 index 0000000000..ea2f54813e --- /dev/null +++ b/themes/mantis/app/shared/search-form/search-form.component.html @@ -0,0 +1,21 @@ +
+
+ +
+
+
+ + + + +
+
+
diff --git a/themes/mantis/styles/_themed_bootstrap_variables.scss b/themes/mantis/styles/_themed_bootstrap_variables.scss new file mode 100644 index 0000000000..e606502e09 --- /dev/null +++ b/themes/mantis/styles/_themed_bootstrap_variables.scss @@ -0,0 +1,19 @@ +@import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro:200,200i,300,300i,400,400i,600,600i,700,700i,900,900i&subset=cyrillic,cyrillic-ext,greek,greek-ext,latin-ext,vietnamese'); + +$font-family-sans-serif: 'Source Sans Pro', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; +$gray-100: #e8ebf3 !default; // #eee +$gray-800: #444444 !default; // #444 + +$navbar-dark-color: #FFFFFF; + +/* Reassign color vars to semantic color scheme */ +$blue: #43515f !default; +$green: #92C642 !default; +$cyan: #2e80a3 !default; +$yellow: #ec9433 !default; +$red: #CF4444 !default; +$dark: #43515f !default; + +$body-color: $gray-800 !default; + +$yiq-contrasted-threshold: 170 !default; diff --git a/themes/mantis/styles/_themed_custom_variables.scss b/themes/mantis/styles/_themed_custom_variables.scss new file mode 100644 index 0000000000..1be25e953f --- /dev/null +++ b/themes/mantis/styles/_themed_custom_variables.scss @@ -0,0 +1,2 @@ +$banner-text-background: rgba(0, 0, 0, 0.35); +$banner-background-gradient-width: 300px; diff --git a/webpack.config.js b/webpack.config.js index 6312cf3605..78ca2d98dc 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,46 +1,45 @@ const webpackMerge = require('webpack-merge'); -const commonPartial = require('./webpack/webpack.common'); -const clientPartial = require('./webpack/webpack.client'); -const { getServerWebpackPartial } = require('./webpack/webpack.server'); + const prodPartial = require('./webpack/webpack.prod'); -const { - getAotPlugin -} = require('./webpack/webpack.aot'); - -module.exports = function(env, options) { +module.exports = function (env, options) { env = env || {}; - if (env.aot) { - console.log(`Running build for ${env.client ? 'client' : 'server'} with AoT Compilation`) - } + const commonPartial = require('./webpack/webpack.common')(env); + const clientPartial = require('./webpack/webpack.client')(env); + const {getAotPlugin} = require('./webpack/webpack.aot')(env); + const {getServerWebpackPartial} = require('./webpack/webpack.server')(env); - let serverPartial = getServerWebpackPartial(env.aot); + if (env.aot) { + console.log(`Running build for ${env.client ? 'client' : 'server'} with AoT Compilation`) + } - let serverConfig = webpackMerge({}, commonPartial, serverPartial, { - plugins: [ - getAotPlugin('server', !!env.aot) - ] - }); + let serverPartial = getServerWebpackPartial(env.aot); - let clientConfig = webpackMerge({}, commonPartial, clientPartial, { - plugins: [ - getAotPlugin('client', !!env.aot) - ] - }); - if (options.mode === 'production') { - serverConfig = webpackMerge({}, serverConfig, prodPartial); - clientConfig = webpackMerge({}, clientConfig, prodPartial); - } + let serverConfig = webpackMerge({}, commonPartial, serverPartial, { + plugins: [ + getAotPlugin('server', !!env.aot) + ] + }); - const configs = []; + let clientConfig = webpackMerge({}, commonPartial, clientPartial, { + plugins: [ + getAotPlugin('client', !!env.aot) + ] + }); + if (options.mode === 'production') { + serverConfig = webpackMerge({}, serverConfig, prodPartial); + clientConfig = webpackMerge({}, clientConfig, prodPartial); + } - if (!env.aot) { - configs.push(clientConfig, serverConfig); - } else if (env.client) { - configs.push(clientConfig); - } else if (env.server) { - configs.push(serverConfig); - } + const configs = []; - return configs; + if (!env.aot) { + configs.push(clientConfig, serverConfig); + } else if (env.client) { + configs.push(clientConfig); + } else if (env.server) { + configs.push(serverConfig); + } + + return configs; }; diff --git a/webpack/helpers.js b/webpack/helpers.js index fdc005f189..fafbbaff5e 100644 --- a/webpack/helpers.js +++ b/webpack/helpers.js @@ -1,13 +1,109 @@ -const { - join, - resolve -} = require('path'); +const path = require('path'); +const fs = require('fs'); -function root(path) { - return resolve(__dirname, '..', path); + +const projectRoot = (relativePath) => { + return path.resolve(__dirname, '..', relativePath); +}; + +const srcPath = projectRoot('src'); + +const buildRoot = (relativePath, env) => { + if (env.aot) { + return path.resolve(projectRoot('./build'), relativePath); + } else { + return path.resolve(projectRoot('src'), relativePath); + } +}; + +//TODO refactor to share between this and config.ts. +const getThemeName = () => { + let defaultCfg = require(projectRoot('config/environment.default.js')); + let envConfigFile; + let envConfigOverride = {}; + + switch (process.env.NODE_ENV) { + case 'prod': + case 'production': + // webpack.prod.dspace-angular-config.ts defines process.env.NODE_ENV = 'production' + envConfigFile = projectRoot('config/environment.prod.js'); + break; + case 'test': + // webpack.test.dspace-angular-config.ts defines process.env.NODE_ENV = 'test' + envConfigFile = projectRoot('config/environment.test.js'); + break; + default: + // if not using webpack.prod.dspace-angular-config.ts or webpack.test.dspace-angular-config.ts, it must be development + envConfigFile = projectRoot('config/environment.dev.js'); + } + + if (envConfigFile) { + try { + envConfigOverride = require(envConfigFile); + } catch (e) { + } + } + + return Object.assign({}, defaultCfg.theme, envConfigOverride.theme).name; } -module.exports = { - root: root, - join: join +const theme = getThemeName(); + +let themePath; + +if (theme !== null && theme !== undefined) { + themePath = path.normalize(path.join(__dirname, '..', 'themes', theme)); +} +else { + themePath = srcPath; +} + +const globalCSSImports = (env) => { return [ + buildRoot('styles/_variables.scss', env), + buildRoot('styles/_mixins.scss', env), +]}; + +const getThemedPath = (componentPath, ext) => { + const parsedPath = path.parse(componentPath); + const relativePath = path.relative(srcPath, parsedPath.dir); + return path.join(themePath, relativePath, `${parsedPath.name}.${ext}`); +}; + +const themedTest = (origPath, extension) => { + if (/\.component.ts$/.test(origPath)) { // only match components + const themedPath = getThemedPath(origPath, extension); + return fs.existsSync(themedPath); + } else { + return false; + } +}; + +const themedUse = (resource, extension) => { + const origPath = path.parse(resource); + let themedPath = getThemedPath(resource, extension); + + /* Make sure backslashes are escaped twice, because the replace unescapes those again */ + themedPath = themedPath.replace(/\\/g, '\\\\'); + + return [ + { + loader: 'string-replace-loader', + options: { + search: `\.\/${origPath.name}\.${extension}`, + replace: themedPath, + flags: 'g' + } + } + ] +}; + +module.exports = { + projectRoot, + buildRoot, + theme: theme, + themePath, + getThemedPath, + themedTest, + themedUse, + globalCSSImports }; diff --git a/webpack/webpack.aot.js b/webpack/webpack.aot.js index 2c2366a23e..c4b970892f 100644 --- a/webpack/webpack.aot.js +++ b/webpack/webpack.aot.js @@ -1,35 +1,37 @@ const { - root + buildRoot } = require('./helpers'); const { - AngularCompilerPlugin + AngularCompilerPlugin } = require('@ngtools/webpack'); -const tsconfigs = { - client: root('./src/tsconfig.browser.json'), - server: root('./src/tsconfig.server.json') -}; +module.exports = (env) => { + const tsconfigs = { + client: buildRoot('./tsconfig.browser.json', env), + server: buildRoot('./tsconfig.server.json', env) + }; -const aotTsconfigs = { - client: root('./src/tsconfig.browser.json'), - server: root('./src/tsconfig.server.aot.json') -}; + const aotTsconfigs = { + client: buildRoot('./tsconfig.browser.json', env), + server: buildRoot('./tsconfig.server.aot.json', env) + }; -/** - * Generates a AotPlugin for @ngtools/webpack - * - * @param {string} platform Should either be client or server - * @param {boolean} aot Enables/Disables AoT Compilation - * @returns {AotPlugin} Configuration of AotPlugin - */ -function getAotPlugin(platform, aot) { - return new AngularCompilerPlugin({ - tsConfigPath: aot ? aotTsconfigs[platform] : tsconfigs[platform], - skipCodeGeneration: !aot - }); -} + /** + * Generates a AotPlugin for @ngtools/webpack + * + * @param {string} platform Should either be client or server + * @param {boolean} aot Enables/Disables AoT Compilation + * @returns {AotPlugin} Configuration of AotPlugin + */ + function getAotPlugin(platform, aot) { + return new AngularCompilerPlugin({ + tsConfigPath: aot ? aotTsconfigs[platform] : tsconfigs[platform], + skipCodeGeneration: !aot + }); + } -module.exports = { - getAotPlugin: getAotPlugin + return { + getAotPlugin: getAotPlugin + } }; diff --git a/webpack/webpack.client.js b/webpack/webpack.client.js index 20dcbddb20..ce49f60ed0 100644 --- a/webpack/webpack.client.js +++ b/webpack/webpack.client.js @@ -2,23 +2,26 @@ const HtmlWebpackPlugin = require('html-webpack-plugin'); const ScriptExtPlugin = require('script-ext-html-webpack-plugin'); const { - root + projectRoot, + buildRoot } = require('./helpers'); -module.exports = { - entry: root('./src/main.browser.ts'), - output: { - filename: 'client.js' - }, - target: 'web', - plugins: [ - new HtmlWebpackPlugin({ - template: root('./src/index.html'), - output: root('dist'), - inject: 'head' - }), - new ScriptExtPlugin({ - defaultAttribute: 'defer' - }) - ] -}; +module.exports = (env) => { + return { + entry: buildRoot('./main.browser.ts', env), + output: { + filename: 'client.js' + }, + target: 'web', + plugins: [ + new HtmlWebpackPlugin({ + template: buildRoot('./index.html', env), + output: projectRoot('dist'), + inject: 'head' + }), + new ScriptExtPlugin({ + defaultAttribute: 'defer' + }) + ] + }; +} diff --git a/webpack/webpack.common.js b/webpack/webpack.common.js index 7fb4656a15..028815d958 100644 --- a/webpack/webpack.common.js +++ b/webpack/webpack.common.js @@ -1,110 +1,173 @@ const CopyWebpackPlugin = require('copy-webpack-plugin'); const path = require('path'); +const fs = require('fs'); const { - root, - join + projectRoot, + buildRoot, + globalCSSImports, + theme, + themePath, + themedTest, + themedUse } = require('./helpers'); -module.exports = { +module.exports = (env) => { + let copyWebpackOptions = [{ + from: path.join(__dirname, '..', 'node_modules', '@fortawesome', 'fontawesome-free', 'webfonts'), + to: path.join('assets', 'fonts') + }, { + from: path.join(__dirname, '..', 'resources', 'images'), + to: path.join('assets', 'images') + }, { + from: path.join(__dirname, '..', 'resources', 'i18n'), + to: path.join('assets', 'i18n') + } + ]; + + const themeImages = path.join(themePath, 'resources', 'images'); + if(theme && fs.existsSync(themeImages)) { + copyWebpackOptions.push({ + from: themeImages, + to: path.join('assets', 'images') , + force: true, + }); + } + + return { mode: 'development', devtool: 'source-map', - resolve: { - extensions: ['.ts', '.js', '.json'] - }, - output: { - path: root('dist') - }, - watchOptions: { - aggregateTimeout: 50, - }, - node: { - fs: "empty", - module: "empty" - }, - module: { - rules: [{ - test: /\.ts$/, - loader: '@ngtools/webpack' + resolve: { + extensions: ['.ts', '.js', '.json'] }, - { - test: /\.css$/, - use: [{ - loader: 'to-string-loader', - options: { - sourceMap: true - } + output: { + path: projectRoot('dist') + }, + watchOptions: { + aggregateTimeout: 50, + }, + node: { + fs: "empty", + module: "empty" + }, + module: { + rules: [ + { + test: (filePath) => themedTest(filePath, 'scss'), + use: (info) => themedUse(info.resource, 'scss') }, - { - loader: 'css-loader', - options: { - sourceMap: true, - modules: true - } - }, - { - loader: 'postcss-loader', - options: { - sourceMap: true - } - } - ] - }, - { - test: /\.scss$/, - exclude: [/node_modules/, - path.resolve(__dirname, '..', 'src/styles/_exposed_variables.scss') - ], - use: [{ - loader: 'to-string-loader', - options: { - sourceMap: true - } - }, { - loader: 'raw-loader', - options: { - sourceMap: true - } + { + test: (filePath) => themedTest(filePath, 'html'), + use: (info) => themedUse(info.resource, 'html') }, - { - loader: 'resolve-url-loader', - options: { - sourceMap: true + { + test: /\.ts$/, + loader: '@ngtools/webpack' + }, + { + test: /\.css$/, + use: [ + { + loader: 'to-string-loader', + options: { + sourceMap: true + } + }, + { + loader: 'css-loader', + options: { + sourceMap: true, + modules: true + } + }, + { + loader: 'postcss-loader', + options: { + sourceMap: true + } } - }, - { - loader: 'sass-loader', - options: { - sourceMap: true + ] + }, + { + test: /\.scss$/, + exclude: [ + /node_modules/, + buildRoot('styles/_exposed_variables.scss', env), + buildRoot('styles/_variables.scss', env) + ], + use: [ + { + loader: 'raw-loader', + options: { + sourceMap: true + } + }, + { + loader: 'postcss-loader', + options: { + sourceMap: true + } + }, + { + loader: 'resolve-url-loader', + options: { + sourceMap: true + } + }, + { + loader: 'sass-loader', + options: { + sourceMap: true, + includePaths: [projectRoot('./'), path.join(themePath, 'styles')] + } + }, + { + loader: 'sass-resources-loader', + options: { + resources: globalCSSImports(env) + }, } - } - ] - }, - { - test: /_exposed_variables.scss$/, - exclude: /node_modules/, - use: [{ - loader: "css-loader" // translates CSS into CommonJS - }, { - loader: "sass-loader" // compiles Sass to CSS - }] - }, - { - test: /\.html$/, - loader: 'raw-loader' - } + ] + }, + { + test: /(_exposed)?_variables.scss$/, + exclude: [/node_modules/], + use: [ + { + loader: 'css-loader', + options: { + sourceMap: true, + modules: true + } + }, + { + loader: 'postcss-loader', + options: { + sourceMap: true + } + }, + { + loader: 'resolve-url-loader', + options: { + sourceMap: true + } + }, + { + loader: 'sass-loader', + options: { + sourceMap: true, + includePaths: [projectRoot('./'), path.join(themePath, 'styles')] + } + } + ] + }, + { + test: /\.html$/, + loader: 'raw-loader' + } + ] + }, + plugins: [ + new CopyWebpackPlugin(copyWebpackOptions) ] - }, - plugins: [ - new CopyWebpackPlugin([{ - from: join(__dirname, '..', 'node_modules', '@fortawesome', 'fontawesome-free', 'webfonts'), - to: join('assets', 'fonts') - }, { - from: join(__dirname, '..', 'resources', 'images'), - to: join('assets', 'images') - }, { - from: join(__dirname, '..', 'resources', 'i18n'), - to: join('assets', 'i18n') - }]) - ] - + } }; diff --git a/webpack/webpack.prod.js b/webpack/webpack.prod.js index 35a683bb96..df0d6274d9 100644 --- a/webpack/webpack.prod.js +++ b/webpack/webpack.prod.js @@ -6,70 +6,70 @@ const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); const cssnano = require("cssnano"); const { - root + projectRoot } = require('./helpers'); module.exports = { - mode: 'production', - recordsOutputPath: root('webpack.records.json'), - plugins: [ - new webpack.EnvironmentPlugin({ - 'process.env': { - 'NODE_ENV': JSON.stringify('production'), - 'AOT': true - } - }), + mode: 'production', + recordsOutputPath: projectRoot('webpack.records.json'), + plugins: [ + new webpack.EnvironmentPlugin({ + 'process.env': { + 'NODE_ENV': JSON.stringify('production'), + 'AOT': true + } + }), - new BundleAnalyzerPlugin({ - analyzerMode: 'disabled', // change it to `server` to view bundle stats - reportFilename: 'report.html', - generateStatsFile: true, - statsFilename: 'stats.json', - }), + new BundleAnalyzerPlugin({ + analyzerMode: 'disabled', // change it to `server` to view bundle stats + reportFilename: 'report.html', + generateStatsFile: true, + statsFilename: 'stats.json', + }), - new CompressionPlugin({ - asset: "[path].gz[query]", - algorithm: "gzip", - test: /\.js$|\.css$|\.html$/, - threshold: 10240, - minRatio: 0.8 - }) + new CompressionPlugin({ + asset: "[path].gz[query]", + algorithm: "gzip", + test: /\.js$|\.css$|\.html$/, + threshold: 10240, + minRatio: 0.8 + }) - ], - optimization: { - minimizer: [ - new UglifyJsPlugin({ - uglifyOptions: { - beautify: false, - mangle: false, - output: { - comments: false - }, - compress: { - warnings: false, - conditionals: false, - unused: true, - comparisons: true, - sequences: true, - dead_code: true, - evaluate: true, - if_return: true, - join_vars: true, - negate_iife: true - }, - sourceMap: true - } - }), - new OptimizeCSSAssetsPlugin({ - cssProcessor: cssnano, - cssProcessorOptions: { - discardComments: { - removeAll: true, - } - }, - safe: true - }) - ] - }, + ], + optimization: { + minimizer: [ + new UglifyJsPlugin({ + uglifyOptions: { + beautify: false, + mangle: false, + output: { + comments: false + }, + compress: { + warnings: false, + conditionals: false, + unused: true, + comparisons: true, + sequences: true, + dead_code: true, + evaluate: true, + if_return: true, + join_vars: true, + negate_iife: true + }, + sourceMap: true + } + }), + new OptimizeCSSAssetsPlugin({ + cssProcessor: cssnano, + cssProcessorOptions: { + discardComments: { + removeAll: true, + } + }, + safe: true + }) + ] + }, }; diff --git a/webpack/webpack.server.js b/webpack/webpack.server.js index ce0c52602a..5e80a286a0 100644 --- a/webpack/webpack.server.js +++ b/webpack/webpack.server.js @@ -1,28 +1,30 @@ var nodeExternals = require('webpack-node-externals'); const { - root + buildRoot } = require('./helpers'); -module.exports = { - getServerWebpackPartial: function (aot) { - const entry = aot ? root('./src/main.server.aot.ts') : root('./src/main.server.ts'); - return { - entry: entry, - output: { - filename: 'server.js' - }, - target: 'node', - externals: [nodeExternals({ - whitelist: [ - /@angular/, - /@ng/, - /angular2-text-mask/, - /ng2-file-upload/, - /angular-sortablejs/, - /sortablejs/, - /ngx/] - })], +module.exports = (env) => { + return { + getServerWebpackPartial: function (aot) { + const entry = aot ? buildRoot('./main.server.aot.ts', env) : buildRoot('./main.server.ts', env); + return { + entry: entry, + output: { + filename: 'server.js' + }, + target: 'node', + externals: [nodeExternals({ + whitelist: [ + /@angular/, + /@ng/, + /angular2-text-mask/, + /ng2-file-upload/, + /angular-sortablejs/, + /sortablejs/, + /ngx/] + })], + } } } }; diff --git a/webpack/webpack.test.js b/webpack/webpack.test.js index 8c6760e377..83e6e44e79 100644 --- a/webpack/webpack.test.js +++ b/webpack/webpack.test.js @@ -1,6 +1,12 @@ const { - root + projectRoot, + buildRoot, + themedTest, + themedUse, + themePath, + globalCSSImports } = require('./helpers'); +const path = require('path'); /** * Webpack Plugins @@ -23,250 +29,288 @@ const ENV = process.env.ENV = process.env.NODE_ENV = 'test'; * * See: http://webpack.github.io/docs/configuration.html#cli */ -module.exports = function (options) { - return { - mode: 'development', - /** - * Source map for Karma from the help of karma-sourcemap-loader & karma-webpack - * - * Do not change, leave as is or it wont work. - * See: https://github.com/webpack/karma-webpack#source-maps - */ - devtool: 'source-map', - - /** - * Options affecting the resolving of modules. - * - * See: http://webpack.github.io/docs/configuration.html#resolve - */ - resolve: { - - /** - * An array of extensions that should be used to resolve modules. - * - * See: http://webpack.github.io/docs/configuration.html#resolve-extensions - */ - extensions: ['.ts', '.js', '.json'], - - /** - * Make sure root is src - */ - modules: [root('src'), 'node_modules'] - - }, - - /** - * Options affecting the normal modules. - * - * See: http://webpack.github.io/docs/configuration.html#module - * - * 'use:' revered back to 'loader:' as a temp. workaround for #1188 - * See: https://github.com/AngularClass/angular2-webpack-starter/issues/1188#issuecomment-262872034 - */ - module: { - - rules: [ +module.exports = function (env) { + return { + mode: 'development', + /** + * Source map for Karma from the help of karma-sourcemap-loader & karma-webpack + * + * Do not change, leave as is or it wont work. + * See: https://github.com/webpack/karma-webpack#source-maps + */ + devtool: 'source-map', /** - * Source map loader support for *.js files - * Extracts SourceMaps for source files that as added as sourceMappingURL comment. + * Options affecting the resolving of modules. * - * See: https://github.com/webpack/source-map-loader + * See: http://webpack.github.io/docs/configuration.html#resolve */ - { - enforce: 'pre', - test: /\.js$/, - loader: 'source-map-loader', - exclude: [/node_modules/], + resolve: { + + /** + * An array of extensions that should be used to resolve modules. + * + * See: http://webpack.github.io/docs/configuration.html#resolve-extensions + */ + extensions: ['.ts', '.js', '.json'], + + /** + * Make sure root is src + */ + modules: [projectRoot('src'), 'node_modules'] }, /** - * Typescript loader support for .ts and Angular 2 async routes via .async.ts + * Options affecting the normal modules. * - * See: https://github.com/TypeStrong/ts-loader + * See: http://webpack.github.io/docs/configuration.html#module + * + * 'use:' revered back to 'loader:' as a temp. workaround for #1188 + * See: https://github.com/AngularClass/angular2-webpack-starter/issues/1188#issuecomment-262872034 */ - { - test: /\.tsx?$/, - loaders: [{ - loader: 'ts-loader', - options: { - configFile: root('src/tsconfig.test.json'), - transpileOnly: true - } - }, - 'angular2-template-loader' - ], - exclude: [/\.e2e\.ts$/] + module: { + + rules: [ + + /** + * Source map loader support for *.js files + * Extracts SourceMaps for source files that as added as sourceMappingURL comment. + * + * See: https://github.com/webpack/source-map-loader + */ + { + test: (filePath) => themedTest(filePath, 'scss'), + use: (info) => themedUse(info.resource, 'scss') + }, + { + test: (filePath) => themedTest(filePath, 'html'), + use: (info) => themedUse(info.resource, 'html') + }, + /** + * Typescript loader support for .ts and Angular 2 async routes via .async.ts + * + * See: https://github.com/TypeStrong/ts-loader + */ + { + test: /\.tsx?$/, + loaders: [{ + loader: 'ts-loader', + options: { + configFile: projectRoot('src/tsconfig.test.json'), + transpileOnly: true + } + }, + 'angular2-template-loader' + ], + exclude: [/\.e2e\.ts$/] + }, + + /** + * CSS loader support for *.css files + * Returns file content as string + * + * See: https://github.com/webpack/css-loader + */ + { + test: /\.css$/, + use: [{ + loader: 'to-string-loader', + options: { + sourceMap: true + } + }, + { + loader: 'css-loader', + options: { + sourceMap: true + } + }, + { + loader: 'postcss-loader', + options: { + sourceMap: true + } + } + ], + }, + + /** + * SASS loader support for *.css files + * Returns file content as string + * + */ + { + test: /\.scss$/, + exclude: [ + /node_modules/, + buildRoot('styles/_exposed_variables.scss', env), + buildRoot('styles/_variables.scss', env) + ], + use: [ + { + loader: 'raw-loader', + options: { + sourceMap: true + } + }, + { + loader: 'postcss-loader', + options: { + sourceMap: true + } + }, + { + loader: 'resolve-url-loader', + options: { + sourceMap: true + } + }, + { + loader: 'sass-loader', + options: { + sourceMap: true, + includePaths: [projectRoot('./'), path.join(themePath, 'styles')] + } + }, + { + loader: 'sass-resources-loader', + options: { + resources: globalCSSImports(env) + }, + } + ] + }, + { + test: /(_exposed)?_variables.scss$/, + exclude: [/node_modules/], + use: [ + { + loader: 'css-loader', + options: { + sourceMap: true, + modules: true + } + }, + { + loader: 'postcss-loader', + options: { + sourceMap: true + } + }, + { + loader: 'resolve-url-loader', + options: { + sourceMap: true + } + }, + { + loader: 'sass-loader', + options: { + sourceMap: true, + includePaths: [projectRoot('./'), path.join(themePath, 'styles')] + } + } + ] + }, + + /** + * Raw loader support for *.html + * Returns file content as string + * + * See: https://github.com/webpack/raw-loader + */ + { + test: /\.html$/, + loader: 'raw-loader', + exclude: [projectRoot('src/index.html')] + }, + + /** + * Instruments JS files with Istanbul for subsequent code coverage reporting. + * Instrument only testing sources. + * + * See: https://github.com/deepsweet/istanbul-instrumenter-loader + */ + { + enforce: 'post', + test: /\.(js|ts)$/, + loader: 'istanbul-instrumenter-loader', + query: { + esModules: true + }, + include: projectRoot('src'), + exclude: [ + /\.(e2e|spec)\.ts$/, + /node_modules/ + ] + } + + ] }, /** - * CSS loader support for *.css files - * Returns file content as string + * Add additional plugins to the compiler. * - * See: https://github.com/webpack/css-loader + * See: http://webpack.github.io/docs/configuration.html#plugins */ - { - test: /\.css$/, - use: [{ - loader: 'to-string-loader', - options: { - sourceMap: true - } - }, - { - loader: 'css-loader', - options: { - sourceMap: true - } - }, - { - loader: 'postcss-loader', - options: { - sourceMap: true - } - } - ], - exclude: [root('src/index.html')] + plugins: [ + + new ContextReplacementPlugin( + /angular(\\|\/)core(\\|\/)@angular/, + projectRoot('./src'), {} + ), + // Workaround for https://github.com/angular/angular/issues/20357 + new ContextReplacementPlugin( + /\@angular(\\|\/)core(\\|\/)esm5/, + projectRoot('./src'), {} + ), + + /** + * Plugin: DefinePlugin + * Description: Define free variables. + * Useful for having development builds with debug logging or adding global constants. + * + * Environment helpers + * + * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin + */ + // NOTE: when adding more properties make sure you include them in custom-typings.d.ts + new DefinePlugin({ + 'ENV': JSON.stringify(ENV), + 'HMR': false, + 'process.env': { + 'ENV': JSON.stringify(ENV), + 'NODE_ENV': JSON.stringify(ENV), + 'HMR': false, + } + }), + new ForkTsCheckerWebpackPlugin() + ], + + /** + * Disable performance hints + * + * See: https://github.com/a-tarasyuk/rr-boilerplate/blob/master/webpack/dev.config.babel.js#L41 + */ + performance: { + hints: false }, /** - * SASS loader support for *.css files - * Returns file content as string + * Include polyfills or mocks for various node stuff + * Description: Node configuration * + * See: https://webpack.github.io/docs/configuration.html#node */ - { - test: /\.scss$/, - use: [{ - loader: 'to-string-loader', - options: { - sourceMap: true - } - }, { - loader: 'raw-loader', - options: { - sourceMap: true - } - }, - { - loader: 'postcss-loader', - options: { - sourceMap: true - } - }, - { - loader: 'resolve-url-loader', - options: { - sourceMap: true - } - }, - { - loader: 'sass-loader', - options: { - sourceMap: true - } - } - ], - exclude: [root('src/index.html')] - }, - - /** - * Raw loader support for *.html - * Returns file content as string - * - * See: https://github.com/webpack/raw-loader - */ - { - test: /\.html$/, - loader: 'raw-loader', - exclude: [root('src/index.html')] - }, - - /** - * Instruments JS files with Istanbul for subsequent code coverage reporting. - * Instrument only testing sources. - * - * See: https://github.com/deepsweet/istanbul-instrumenter-loader - */ - { - enforce: 'post', - test: /\.(js|ts)$/, - loader: 'istanbul-instrumenter-loader', - query: { - esModules: true - }, - include: root('src'), - exclude: [ - /\.(e2e|spec)\.ts$/, - /node_modules/ - ] + node: { + global: true, + process: false, + crypto: 'empty', + module: false, + clearImmediate: false, + setImmediate: false } - ] - }, - - /** - * Add additional plugins to the compiler. - * - * See: http://webpack.github.io/docs/configuration.html#plugins - */ - plugins: [ - - new ContextReplacementPlugin( - /angular(\\|\/)core(\\|\/)@angular/, - root('./src'), {} - ), - // Workaround for https://github.com/angular/angular/issues/20357 - new ContextReplacementPlugin( - /\@angular(\\|\/)core(\\|\/)esm5/, - root('./src'), {} - ), - - /** - * Plugin: DefinePlugin - * Description: Define free variables. - * Useful for having development builds with debug logging or adding global constants. - * - * Environment helpers - * - * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin - */ - // NOTE: when adding more properties make sure you include them in custom-typings.d.ts - new DefinePlugin({ - 'ENV': JSON.stringify(ENV), - 'HMR': false, - 'process.env': { - 'ENV': JSON.stringify(ENV), - 'NODE_ENV': JSON.stringify(ENV), - 'HMR': false, - } - }), - new ForkTsCheckerWebpackPlugin() - ], - - /** - * Disable performance hints - * - * See: https://github.com/a-tarasyuk/rr-boilerplate/blob/master/webpack/dev.config.babel.js#L41 - */ - performance: { - hints: false - }, - - /** - * Include polyfills or mocks for various node stuff - * Description: Node configuration - * - * See: https://webpack.github.io/docs/configuration.html#node - */ - node: { - global: true, - process: false, - crypto: 'empty', - module: false, - clearImmediate: false, - setImmediate: false - } - - }; + }; }; diff --git a/yarn.lock b/yarn.lock index 9a4f96e805..eb0733e695 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1126,6 +1126,12 @@ async@^2.0.0, async@^2.5.0: dependencies: lodash "^4.17.10" +async@^2.1.4: + version "2.6.2" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" + dependencies: + lodash "^4.17.11" + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -1352,6 +1358,10 @@ big.js@^3.1.3: resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + binary-extensions@^1.0.0: version "1.11.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" @@ -2426,6 +2436,18 @@ copy-webpack-plugin@^4.4.1: p-limit "^1.0.0" serialize-javascript "^1.4.0" +copyfiles@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/copyfiles/-/copyfiles-2.1.0.tgz#0e2a4188162d6b2f3c5adfe34e9c0bd564d23164" + integrity sha512-cAeDE0vL/koE9WSEGxqPpSyvU638Kgfu6wfrnj7kqp9FWa1CWsU54Coo6sdYZP4GstWa39tL/wIVJWfXcujgNA== + dependencies: + glob "^7.0.5" + minimatch "^3.0.3" + mkdirp "^0.5.1" + noms "0.0.0" + through2 "^2.0.1" + yargs "^11.0.0" + core-js@^2.2.0, core-js@^2.4.0, core-js@^2.5.7: version "2.5.7" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" @@ -2860,6 +2882,12 @@ dateformat@^1.0.11, dateformat@^1.0.6: get-stdin "^4.0.1" meow "^3.3.0" +debug-loader@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/debug-loader/-/debug-loader-0.0.1.tgz#44dc37e09e3c39e6af334681960f70a534a9d056" + dependencies: + loader-utils "^0.2.12" + debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.6, debug@^2.6.8: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -5617,6 +5645,12 @@ json5@^0.5.0: resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + dependencies: + minimist "^1.2.0" + jsonfile@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" @@ -5922,7 +5956,7 @@ loader-runner@^2.3.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2" integrity sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI= -loader-utils@^0.2.15, loader-utils@^0.2.16: +loader-utils@^0.2.12, loader-utils@^0.2.15, loader-utils@^0.2.16: version "0.2.17" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" integrity sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g= @@ -5941,6 +5975,14 @@ loader-utils@^1.0.0, loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1 emojis-list "^2.0.0" json5 "^0.5.0" +loader-utils@^1.0.4: + version "1.2.3" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" + dependencies: + big.js "^5.2.2" + emojis-list "^2.0.0" + json5 "^1.0.1" + locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -6185,6 +6227,10 @@ lodash@4.17.10, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.13.1, lodash@^4.17.0, lo resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" integrity sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg== +lodash@^4.17.11: + version "4.17.11" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" + log-driver@^1.2.5: version "1.2.7" resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" @@ -6909,6 +6955,14 @@ nodemon@^1.15.0: undefsafe "^2.0.2" update-notifier "^2.3.0" +noms@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/noms/-/noms-0.0.0.tgz#da8ebd9f3af9d6760919b27d9cdc8092a7332859" + integrity sha1-2o69nzr51nYJGbJ9nNyAkqczKFk= + dependencies: + inherits "^2.0.1" + readable-stream "~1.0.31" + "nopt@2 || 3", nopt@3.x: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" @@ -8703,7 +8757,7 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6: +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== @@ -8716,7 +8770,7 @@ read-pkg@^3.0.0: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@1.0: +readable-stream@1.0, readable-stream@~1.0.31: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= @@ -9285,6 +9339,15 @@ sass-loader@7.1.0: pify "^3.0.0" semver "^5.5.0" +sass-resources-loader@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/sass-resources-loader/-/sass-resources-loader-2.0.0.tgz#88569c542fbf1f18f33a6578b77cc5b36c56911d" + dependencies: + async "^2.1.4" + chalk "^1.1.3" + glob "^7.1.1" + loader-utils "^1.0.4" + saucelabs@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/saucelabs/-/saucelabs-1.5.0.tgz#9405a73c360d449b232839919a86c396d379fd9d" @@ -9983,7 +10046,7 @@ streamroller@0.7.0: mkdirp "^0.5.1" readable-stream "^2.3.0" -string-replace-loader@2.1.1: +string-replace-loader@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-replace-loader/-/string-replace-loader-2.1.1.tgz#b72e7b57b6ef04efe615aff0ad989b5c14ca63d1" integrity sha512-0Nvw1LDclF45AFNuYPcD2Jvkv0mwb/dQSnJZMvhqGrT+zzmrpG3OJFD600qfQfNUd5aqfp7fCm2mQMfF7zLbyQ== @@ -10231,6 +10294,14 @@ through2@^2.0.0: readable-stream "^2.1.5" xtend "~4.0.1" +through2@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + through@2, through@X.X.X, through@^2.3.6, through@~2.3, through@~2.3.1: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -11082,6 +11153,12 @@ webpack-dev-server@^3.1.5: webpack-log "^2.0.0" yargs "12.0.1" +webpack-import-glob-loader@^1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/webpack-import-glob-loader/-/webpack-import-glob-loader-1.6.3.tgz#1b1de573f49c2c2afdb814dc13b44b2111b2ea7b" + dependencies: + glob "^5.0.15" + webpack-log@^1.0.1: version "1.2.0" resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-1.2.0.tgz#a4b34cda6b22b518dbb0ab32e567962d5c72a43d" @@ -11332,6 +11409,13 @@ yargs-parser@^5.0.0: dependencies: camelcase "^3.0.0" +yargs-parser@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" + integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc= + dependencies: + camelcase "^4.1.0" + yargs@12.0.1, yargs@^12.0.1: version "12.0.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.1.tgz#6432e56123bb4e7c3562115401e98374060261c2" @@ -11350,6 +11434,24 @@ yargs@12.0.1, yargs@^12.0.1: y18n "^3.2.1 || ^4.0.0" yargs-parser "^10.1.0" +yargs@^11.0.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" + integrity sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A== + dependencies: + cliui "^4.0.0" + decamelize "^1.1.1" + find-up "^2.1.0" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^9.0.2" + yargs@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8"