From d7b394520fab0df4b6a822e2ab4622380befb9d2 Mon Sep 17 00:00:00 2001 From: "k.triantafyllou" Date: Fri, 29 Jul 2022 12:15:54 +0300 Subject: [PATCH] Fix a style bug in notification-user. Add manager authorization in admin login guard(optional). Add resources service for Resource menu item build. Move methodology in library. Fix sub-submenu items with _self target in navigation bar. --- .../users/role-users/role-users.component.ts | 11 +- login/adminLoginGuard.guard.ts | 4 +- monitor/indicators/indicators.component.ts | 40 +- monitor/methodology/methodology.component.ts | 465 ++++++++++++++++++ monitor/methodology/methodology.module.ts | 28 ++ monitor/services/resources.service.ts | 117 +++++ .../notification-user.component.less | 2 +- sharedComponents/navigationBar.component.html | 10 +- utils/theme/theme.component.html | 10 +- 9 files changed, 660 insertions(+), 27 deletions(-) create mode 100644 monitor/methodology/methodology.component.ts create mode 100644 monitor/methodology/methodology.module.ts create mode 100644 monitor/services/resources.service.ts diff --git a/dashboard/users/role-users/role-users.component.ts b/dashboard/users/role-users/role-users.component.ts index 6ce7517b..bf02493e 100644 --- a/dashboard/users/role-users/role-users.component.ts +++ b/dashboard/users/role-users/role-users.component.ts @@ -256,9 +256,14 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges { NotificationHandler.rise('Group has been successfully created'); this.updateLists(); }, error => { - NotificationHandler.rise('An error has occurred. Please try again later', 'danger'); - this.loadActive = false; - this.loadPending = false; + if(error.status === 409) { + NotificationHandler.rise('Group already exists. You can try to invite a ' + this.role + ' instead.', 'warning'); + this.updateLists(); + } else { + NotificationHandler.rise('An error has occurred. Please try again later', 'danger'); + this.loadActive = false; + this.loadPending = false; + } }); } diff --git a/login/adminLoginGuard.guard.ts b/login/adminLoginGuard.guard.ts index 6c01ac49..5c5fb990 100644 --- a/login/adminLoginGuard.guard.ts +++ b/login/adminLoginGuard.guard.ts @@ -28,7 +28,9 @@ export class AdminLoginGuard implements CanActivate, CanActivateChild { } return Session.isPortalAdministrator(user) || (data.monitorCurator && Session.isMonitorCurator(user)) || - (data.communityCurator && Session.isCommunityCurator(user)) + (data.communityCurator && Session.isCommunityCurator(user)) || + (data.monitorManager && Session.isKindOfMonitorManager(user)) || + (data.communityManager && Session.isKindOfCommunityManager(user)) }),tap(isAdmin => { if(!isAdmin) { this.router.navigate(['/user-info'], { diff --git a/monitor/indicators/indicators.component.ts b/monitor/indicators/indicators.component.ts index b5cd56a2..eb9e0fd5 100644 --- a/monitor/indicators/indicators.component.ts +++ b/monitor/indicators/indicators.component.ts @@ -3,8 +3,9 @@ import {Subscriber} from "rxjs"; import {properties} from "../../../../environments/environment"; import {ActivatedRoute, Router} from "@angular/router"; import {HelperService} from "../../utils/helper/helper.service"; -import {StakeholderService} from "../services/stakeholder.service"; -import {ConfigurationService} from "../../utils/configuration/configuration.service"; +import {Meta, Title} from "@angular/platform-browser"; +import {SEOService} from "../../sharedComponents/SEO/SEO.service"; +import {ResourcesService} from "../services/resources.service"; @Component({ selector: 'indicators-page', @@ -12,28 +13,43 @@ import {ConfigurationService} from "../../utils/configuration/configuration.serv }) export class IndicatorsComponent implements OnInit, OnDestroy { private subscriptions: any[] = []; + public types = ResourcesService.types; public properties = properties; public pageContents; constructor(private helper: HelperService, - private configurationService: ConfigurationService, + private resourcesService: ResourcesService, private router: Router, - private stakeholderService: StakeholderService, + private meta: Meta, + private title: Title, + private seoService: SEOService, private route: ActivatedRoute) { } ngOnInit() { this.subscriptions.push(this.route.params.subscribe(params => { - if(params['stakeholder']) { - this.subscriptions.push(this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => { - this.getPageContents(stakeholder.type); - })); - } else if(params['type']){ - this.getPageContents(params['type']); + if(params['type']){ + let type = this.types.find(type => type.value === params['type']); + if(type) { + this.getPageContents(type.value); + const description = "Monitor | Indicators " + type.label; + const title = "Monitor | Indicators " + type.label; + this.metaTags(title, description); + } } })) } + metaTags(title, description) { + const url = properties.domain + properties.baseLink + this.router.url; + this.seoService.createLinkForCanonicalURL(url, false); + this.meta.updateTag({content: url}, "property='og:url'"); + this.meta.updateTag({content: description}, "name='description'"); + this.meta.updateTag({content: description}, "property='og:description'"); + this.meta.updateTag({content: title}, "property='og:title'"); + this.title.setTitle(title); + } + ngOnDestroy() { this.subscriptions.forEach(subscription => { if (subscription instanceof Subscriber) { @@ -43,8 +59,8 @@ export class IndicatorsComponent implements OnInit, OnDestroy { } public getPageContents(type: string) { - this.subscriptions.push(this.configurationService.isPageEnabled('monitor', '/indicators/' + type, 'monitor').subscribe(isEnabled => { - if(isEnabled) { + this.subscriptions.push(this.resourcesService.isPagesEnabled().subscribe(status => { + if(status[0]) { this.subscriptions.push(this.helper.getPageHelpContents(this.properties, 'monitor', '/indicators/' + type, 'monitor').subscribe(contents => { this.pageContents = contents; })); diff --git a/monitor/methodology/methodology.component.ts b/monitor/methodology/methodology.component.ts new file mode 100644 index 00000000..5a84b1a5 --- /dev/null +++ b/monitor/methodology/methodology.component.ts @@ -0,0 +1,465 @@ +import {Component, OnDestroy, OnInit} from "@angular/core"; +import {Subscription} from "rxjs"; +import {Meta, Title} from "@angular/platform-browser"; +import {ActivatedRoute, Router} from "@angular/router"; +import {Stakeholder} from "../entities/stakeholder"; +import {OpenaireEntities} from "../../utils/properties/searchFields"; +import {StakeholderService} from "../services/stakeholder.service"; +import {SEOService} from "../../sharedComponents/SEO/SEO.service"; +import {properties} from "../../../../environments/environment"; + +@Component({ + selector: 'methodology', + template: ` +
+
+

Terminology and
construction.

+
+
+ +
    +
  • +
    +
    +
    {{openaireEntities.RESULTS}}
    +
    +
    There are currently four different types of {{openaireEntities.RESULTS | lowercase}} in the OpenAIRE Research
    Graph:
    +
      +
    • {{openaireEntities.PUBLICATIONS}}
    • +
    • {{openaireEntities.DATASETS}}
    • +
    • {{openaireEntities.SOFTWARE}}
    • +
    • {{openaireEntities.OTHER}}.
    • +
    +
    + OpenAIRE deduplicates (merges) different records of {{openaireEntities.RESULTS | lowercase}} and keeps the
    metadata of all instances. +
    +
    +
    +
    +
    +
    {{openaireEntities.PUBLICATION}}
    +
    + {{openaireEntities.RESULTS}} intended for human reading (published articles, pre-prints, conference
    papers, presentations, technical reports, etc.) +
    +
    +
    +
    +
    {{openaireEntities.DATASET}}
    +
    + +
    Granularity is not defined by OpenAIRE, it reflects the granularity supported by + the sources
    from which the description of the {{openaireEntities.DATASET | lowercase}} has been collected.
    +
    +
    +
    +
    +
    {{openaireEntities.SOFTWARE_SINGULAR}}
    +
    + Source code or software package developed and/or used in a research context +
    +
    +
    +
    +
    {{openaireEntities.OTHER_SINGULAR}}
    +
    + Anything that does not fall in the previous categories (e.g. workflow, methods, protocols) +
    +
    +
    +
  • +
  • +
    + The attributes of entities listed below are either inherited via entries in the harvested metadata records or automatically generated by our inference (text and data mining) algorithms. +
    +
    +
    +
    +
    {{openaireEntities.ORGANIZATION}}
    +
    +

    For {{openaireEntities.RESULTS | lowercase}}, this refers to the affiliated organizations of its authors

    +

    For {{openaireEntities.PROJECTS | lowercase}}: the {{openaireEntities.ORGANIZATIONS | lowercase}} participating in the {{openaireEntities.PROJECT | lowercase}} + (i.e. beneficiaries of the grant)

    +

    The OpenAIRE research graph is in the process of improving the {{openaireEntities.ORGANIZATION | lowercase}} database (disambiguation) with the newly developed OpenOrgs tool.

    +
    +
    +
    +
    +
    Country
    +
    +

    The country of the {{openaireEntities.ORGANIZATION | lowercase}}.

    +

    + Country code mapping: + + https://api.openaire.eu/vocabularies/dnet:countries +

    +
    +
    +
    +
    +
    Funder
    +
    +

    Funders that have joined OpenAIRE, i.e. their {{openaireEntities.PROJECT | lowercase}} data have gone through a validation process.

    +

    You can visit https://explore.openaire.eu/search/find if you would like to explore the {{openaireEntities.RESULTS | lowercase}} and {{openaireEntities.PROJECTS | lowercase}} of all funders in OpenAIRE (the list of funders can be seen under the "Funder" Filter shown on the left side of the page).

    +

    To join: https://www.openaire.eu/funders-how-to-join-guide

    +
    +
    +
    +
    +
    Type
    +
    +

    The sub-type of a {{openaireEntities.RESULT | lowercase}} (e.g., a {{openaireEntities.PUBLICATION | lowercase}} can be a pre-print, conference proceeding, + article, + etc.)

    +

    Resource type mapping: + https://api.openaire.eu/vocabularies/dnet:result_typologies + (click on the code to see the specific types for each result type) +

    +
    +
    +
    +
    +
    Access mode or access rights
    +
    +

    The best available (across all instances) access rights of a {{openaireEntities.RESULT | lowercase}}

    +

    Types: open, restricted, closed, embargo (= closed for a specific period of time, then open)

    +

    Note: definition of restricted + may vary by data source, it may refer to access rights being given to registered users, potentially behind a paywall.

    +
    +
    +
    +
    +
    CC license
    +
    +

    A Creative Commons copyright license (https://creativecommons.org/)

    +
    +
    +
    +
    +
    PID (persistent identifier)
    +
    +

    A long-lasting reference to a resource

    +

    Types: http://api.openaire.eu/vocabularies/dnet:pid_types +

    +
    +
    +
    +
    +
    Context
    +
    + Related {{openaireEntities.COMMUNITY | lowercase}}, initiative or infrastructure. +
    +
    +
    +
    +
    Journal
    +
    + The scientific journal an article is published in. +
    +
    +
    +
    +
    Publisher
    +
    + The publisher of the venue (journal, book, etc.) of a {{openaireEntities.RESULT | lowercase}}. +
    +
    +
    +
    +
    {{openaireEntities.DATASOURCES}}
    +
    +

    The different data sources ingested in the OpenAIRE Research Graph.

    +
    Data Source Types:
    +
      +
    • Repositories
    • +
    • Open Access Publishers & Journals
    • +
    • Aggregators
    • +
    • Entity Registries
    • +
    • Journal Aggregators
    • +
    • CRIS (Current Research Information System)
    • +
    +
    +
    +
    +
    +
    Repositories
    +
    + Information systems where scientists upload the bibliographic metadata and payloads of their + {{openaireEntities.RESULTS | lowercase}} (e.g. PDFs of their scientific articles, CSVs of their data, archive with their + software), due to obligations from their {{openaireEntities.ORGANIZATIONS | lowercase}}, their funders, or due to community practices + (e.g. ArXiv, Europe PMC, Zenodo). +
    +
    +
    +
    +
    Open Access Publishers & Journals
    +
    + Information systems of open access publishers or relative journals, which offer bibliographic + metadata and PDFs of their published articles. +
    +
    +
    +
    +
    Aggregators
    +
    + Information systems that collect descriptive metadata about {{openaireEntities.RESULTS | lowercase}} from multiple sources + in order to enable cross-data source discovery of given {{openaireEntities.RESULTS | lowercase}} (e,g, DataCite, + BASE, DOAJ). +
    +
    +
    +
    +
    Entity Registries
    +
    + Information systems created with the intent of maintaining authoritative registries of given + entities in the scholarly communication, such as OpenDOAR for the institutional repositories, re3data + for the data repositories, CORDA and other funder databases for {{openaireEntities.PROJECTS | lowercase}} and funding information. +
    +
    +
    +
    +
    CRIS (Current Research Information System)
    +
    + Information systems adopted by research and academic {{openaireEntities.ORGANIZATIONS | lowercase}} to keep track of their research + administration records and relative results; examples of CRIS content are articles or {{openaireEntities.DATASETS | lowercase}} funded + by {{openaireEntities.PROJECTS | lowercase}}, their principal investigators, facilities acquired thanks to funding, etc. +
    +
    +
    +
  • +
  • +
    + The attributes of entities under this tab are constructed following the methodology described below. +
    +
    +
    +
    +
    Attribute
    +
    Definition
    +
    Construction
    +
    +
    +
    + Journal Business Models +
    +
    +
    +
    Fully Open Access (OA)
    +
    +

    A journal that publishes only in open access.

    +
    +
    +

    We construct the list of fully OA journals using Unpaywall data.

    +

    In brief, a journal is fully OA if

    +
      +
    1. It is in the Directory of Open Access Journals (DOAJ)
    2. +
    3. It has a known (curated list) fully OA Publisher.
    4. +
    5. It only publishes OA articles.
    6. +
    +

    More information

    +
    +
    +
    +
    +
    Subscription
    +
    +

    A journal that charges for access to its articles.

    +
    +
    +

    Journals without any open access articles.

    +
    +
    +
    +
    +
    Hybrid
    +
    +

    A subscription journal where some of its articles are open access.

    +
    +
    +

    Journals with open access articles that are not fully OA journals are hybrid.

    +
    +
    +
    +
    +
    Transformative
    +
    +

    "A Transformative Journal is a subscription/hybrid journal that is actively committed to transitioning to a fully Open Access journal.

    +

    In addition, a Transformative Journal must:

    +
      +
    • gradually increase the share of Open Access content; and
    • +
    • offset subscription income from payments for publishing services (to avoid double payments)."
    • +
    +

    Source:

    +

    https://www.coalition-s.org/transformative-journals-faq/

    +
    +
    +

    Transformative Journals are identified by ISSN matching with the publicly available Transformative Journals data (https://journalcheckertool.org/transformative-journals/)

    +
    +
    +
    +
    + Journal APC Business Models +
    +
    +
    +
    Diamond OA
    +
    +

    A fully OA journal that does not charge article processing charges (APCs).

    +
    +
    +

    APC information is obtained from DOAJ using DOAJ’s exportable version of the journal metadata (https://doaj.org/docs/public-data-dump/). We used it to determine whether a particular fully OA journal charges APCs.

    +
    +
    +
    +
    + Routes to Open Access (OA) +
    +
    +
    +
    Green OA
    +
    +

    An open access scientific publication deposited in a repository

    +
    +
    +

    As in definition

    +
    +
    +
    +
    +
    Gold OA
    +
    +

    A scientific publication published in a fully OA journal.

    +
    +
    +

    Fully OA journals are defined above.

    +
    +
    +
    +
    +
    Hybrid OA
    +
    +

    An open access scientific publication published in a hybrid journal with an open license.

    +
    +
    +

    Hybrid journals are defined above.

    +

    At this point we consider only CC licenses “open”, we are currently working on cleaning non-CC licenses as well to identify other open ones.

    +

    In principle, this means that we may be underestimating the number of hybrid OA articles and overestimating the number of bronze.

    +
    +
    +
    +
    +
    Bronze OA
    +
    +

    An open access scientific publication published in a hybrid journal without an open license.

    +
    +
    + +
    +
    +
    +
    + Miscellaneous +
    +
    +
    +
    Downloads
    +
    +

    The number of downloads of a publication’s full text in a specific time frame, from a given set of data sources.

    +
    +
    +

    Data for downloads is taken from OpenAIRE’s Usage Counts service that harvests it from a set of repositories. The time range of available downloads varies for each repository.

    +

    + More information +

    +
    +
    +
    +
    +
  • +
+
+ + More information for + OpenAIRE Research Graph + . +
+
+
+

+ Inclusion, transparency,
quality, state of the art
technology. +

+
+

Our methodological approach is based on the following operational quality criteria:

+
    +
  • Openness and transparency: Methodological assumptions are openly and clearly presented.
  • +
  • Coverage and accuracy: As detailed in graph.openaire.eu + multiple data sources are ingested in the OpenAIRE research graph for coverage to the fullest extent possible, in order to provide meaningful indicators.
  • +
  • Clarity and replicability: We describe our construction methodology in detail, so that + it can be verified and used by the scholarly communication community to create ongoing updates to our proposed statistics and indicators.
  • +
  • Readiness and timeliness: The methodology is built around well-established open databases + and already tested knowledge extraction technologies - natural language processing (NLP)/machine-learning (ML) - using operational + workflows in OpenAIRE to warrant timely results.
  • +
  • Trust and robustness: Our methodology also strives to be reliable, robust, and aligned + to other assessment methods so that it can be operationalized, used and reused, in conjunction with other assessment methods.
  • +
+
The text above is modified from this report (DOI: 10.2777/268348).
+
+
+

Step-by-step

+ +
+
+
+ ` +}) +export class MethodologyComponent implements OnInit, OnDestroy { + public stakeholder: Stakeholder; + public tab: 'entities' | 'attributes' = 'entities'; + private subscriptions: any[] = []; + public openaireEntities = OpenaireEntities; + + constructor(private stakeholderService: StakeholderService, + private seoService: SEOService, + private _meta: Meta, + private _router: Router, + private route: ActivatedRoute, + private _title: Title) { + } + + ngOnInit() { + this.subscriptions.push(this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => { + this.stakeholder = stakeholder; + if (this.stakeholder) { + /* Metadata */ + const url = properties.domain + properties.baseLink + this._router.url; + this.seoService.createLinkForCanonicalURL(url, false); + this._meta.updateTag({content: url}, "property='og:url'"); + const description = "Methodology | " + this.stakeholder.name; + const title = "Methodology | " + this.stakeholder.name; + this._meta.updateTag({content: description}, "name='description'"); + this._meta.updateTag({content: description}, "property='og:description'"); + this._meta.updateTag({content: title}, "property='og:title'"); + this._title.setTitle(title); + } + })); + } + + ngOnDestroy() { + this.subscriptions.forEach(subscription => { + if (subscription instanceof Subscription) { + subscription.unsubscribe(); + } + }); + } +} diff --git a/monitor/methodology/methodology.module.ts b/monitor/methodology/methodology.module.ts new file mode 100644 index 00000000..f47f116d --- /dev/null +++ b/monitor/methodology/methodology.module.ts @@ -0,0 +1,28 @@ +import {NgModule} from "@angular/core"; +import {CommonModule} from "@angular/common"; +import {MethodologyComponent} from "./methodology.component"; +import {RouterModule} from "@angular/router"; +import {PreviousRouteRecorder} from "../../utils/piwik/previousRouteRecorder.guard"; +import {PageContentModule} from "../../dashboard/sharedComponents/page-content/page-content.module"; +import {HowModule} from "../../monitor/how/how.module"; +import {TabsModule} from "../../utils/tabs/tabs.module"; +import {IconsModule} from "../../utils/icons/icons.module"; +import {IconsService} from "../../utils/icons/icons.service"; +import {graph} from "../../utils/icons/icons"; + +@NgModule({ + declarations: [MethodologyComponent], + imports: [CommonModule, RouterModule.forChild([ + { + path: '', + component: MethodologyComponent, + canDeactivate: [PreviousRouteRecorder] + }, + ]), PageContentModule, HowModule, TabsModule, IconsModule], + exports: [MethodologyComponent] +}) +export class MethodologyModule { + constructor(private iconsService: IconsService) { + this.iconsService.registerIcons([graph]); + } +} diff --git a/monitor/services/resources.service.ts b/monitor/services/resources.service.ts new file mode 100644 index 00000000..d51b9997 --- /dev/null +++ b/monitor/services/resources.service.ts @@ -0,0 +1,117 @@ +import {Injectable} from "@angular/core"; +import {MenuItem, RootMenuItem} from "../../sharedComponents/menu"; +import {Option} from "../../sharedComponents/input/input.component"; +import {StakeholderEntities} from "../entities/stakeholder"; +import {from, Subscription} from "rxjs"; +import {HttpClient} from "@angular/common/http"; +import {properties} from "../../../../environments/environment"; +import {Page} from "../../utils/entities/adminTool/page"; +import {map} from "rxjs/operators"; + +@Injectable({ + providedIn: 'root' +}) +export class ResourcesService { + + private subscription: Subscription; + private routes = ResourcesService.types.map(type => '/indicators/' + type.value); + + public static readonly types: Option[] = [ + {value: 'funder', label: StakeholderEntities.FUNDERS}, + {value: 'ri', label: StakeholderEntities.RIS}, + {value: 'project', label: StakeholderEntities.PROJECTS}, + {value: 'organization', label: StakeholderEntities.ORGANIZATIONS} + ]; + + constructor(private http: HttpClient) { + } + + private async getResourcesItemsAsync(prefix = '', portal: string = null): Promise { + let items = []; + let methodology = ResourcesService.setLink(new MenuItem("methodology", "Methodology", "", "", false, [], + null, {}, null, null, null, null, '_self'), + prefix + "/methodology", portal); + methodology.items = [ResourcesService.setLink(new MenuItem("methodology", "Terminology and construction", + "", "", false, [], null, {}, null, null, null, null, '_self'), + prefix + "/methodology", portal), + ResourcesService.setLink(new MenuItem("methodology", "See how it works", + "", "", false, [], null, {}, null, "how", null, null, '_self'), + prefix + "/methodology", portal)]; + items.push(methodology); + let indicators = new MenuItem("indicators-page", "Indicators", + "", "", false, [], null, {}, null, null, null, null, '_self'); + let promise = new Promise(resolve => { + this.isPagesEnabled().subscribe(status => { + ResourcesService.types.forEach((type, index) => { + if(status[index]) { + indicators.items.push(ResourcesService.setLink( + new MenuItem("indicators-" + type.value, type.label, + "", "", false, [], null, {}, null, null, null, null, '_self'), + prefix + "/indicators/" + type.value, portal) + ); + } + }); + resolve(); + }, error => { + console.error(error); + resolve(); + }); + }) + await promise; + if(indicators.items.length > 0) { + indicators.url = indicators.items[0].url; + indicators.route = indicators.items[0].route; + items.push(indicators); + } + return items; + } + + /** + * @deprecated + * */ + setResourcesDeprecated(items: RootMenuItem[], prefix = '', portal: string = null) { + if(this.subscription) { + this.subscription.unsubscribe(); + } + let resources = new MenuItem('resources', 'Resources', "", "", false, [], null, {}); + let index = items.push({rootItem: resources, items: []}) - 1; + this.subscription = from(this.getResourcesItemsAsync(prefix, portal)).subscribe(resourcesItems => { + items[index].items = resourcesItems; + }); + } + + setResources(items: MenuItem[], prefix = '', portal: string = null) { + if(this.subscription) { + this.subscription.unsubscribe(); + } + let resources = new MenuItem('resources', 'Resources', "", "", false, [], null, {}); + let index = items.push(resources) - 1; + this.subscription = from(this.getResourcesItemsAsync(prefix, portal)).subscribe(resourcesItems => { + items[index].items = resourcesItems; + }); + } + + public isPagesEnabled() { + let url = properties.adminToolsAPIURL + "/monitor/monitor/pages"; + return this.http.get((properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url) + .pipe(map(pages => { + let result = this.routes.map(() => false); + pages.forEach(page => { + let index = this.routes.findIndex(route => route === page.route && page.isEnabled); + if(index !== -1) { + result[index] = true; + } + }); + return result; + })); + } + + private static setLink(item: MenuItem, route: string, portal: string = null) { + if(portal) { + item.url = portal + route + (item.fragment?'#' + item.fragment:''); + } else { + item.route = route; + } + return item; + } +} diff --git a/notifications/notification-user/notification-user.component.less b/notifications/notification-user/notification-user.component.less index 1a0bf5a4..8f68ec58 100644 --- a/notifications/notification-user/notification-user.component.less +++ b/notifications/notification-user/notification-user.component.less @@ -15,7 +15,7 @@ svg { &.outlined { circle { - ill: white; + fill: white; stroke: currentColor; } diff --git a/sharedComponents/navigationBar.component.html b/sharedComponents/navigationBar.component.html index 875e8a40..50a216fe 100644 --- a/sharedComponents/navigationBar.component.html +++ b/sharedComponents/navigationBar.component.html @@ -64,13 +64,13 @@ target="{{submenu.target}}">{{submenu.title}}
    -
  • +
  • {{subsubmenu.title}} {{subsubmenu.title}} + href="{{subsubmenu.url}}" (click)="closeCanvas(canvas)" [class.custom-external]="subsubmenu.target != '_self'" + target="{{subsubmenu.target}}">{{subsubmenu.title}}
@@ -160,12 +160,12 @@ target="{{submenu.target}}">{{submenu.title}} diff --git a/utils/theme/theme.component.html b/utils/theme/theme.component.html index 168f72fb..deb6c2c4 100644 --- a/utils/theme/theme.component.html +++ b/utils/theme/theme.component.html @@ -532,12 +532,12 @@
- + +