Merge branch 'dmp-refactoring' of code-repo.d4science.org:MaDgiK-CITE/argos into dmp-refactoring

This commit is contained in:
Efstratios Giannopoulos 2024-05-21 18:10:37 +03:00
commit b4857b403e
30 changed files with 250 additions and 386 deletions

View File

@ -40,6 +40,7 @@ import { OpenDMPCustomTranslationCompiler } from './utilities/translate/opendmp-
import { CoreAnnotationServiceModule } from 'annotation-service/services/core-service.module';
import { CoreNotificationServiceModule } from '@notification-service/services/core-service.module';
import { DepositOauth2DialogModule } from './ui/misc/deposit-oauth2-dialog/deposit-oauth2-dialog.module';
import { AnalyticsService } from './core/services/matomo/analytics-service';
// AoT requires an exported function for factories
export function HttpLoaderFactory(languageHttpService: LanguageHttpService) {
@ -182,7 +183,8 @@ export function InstallationConfigurationFactory(appConfig: ConfigurationService
},
Title,
CookieService,
MatomoService
MatomoService,
AnalyticsService
],
bootstrap: [AppComponent]
})

View File

@ -0,0 +1,67 @@
export class AnalyticsProviders {
private _providers: AnalyticsProvider[];
get providers(): AnalyticsProvider[] {
return this._providers;
}
set providers(providers: AnalyticsProvider[]) {
this._providers = providers;
}
public static parseValue(value: any): AnalyticsProviders {
const analyticsProvidersObj: AnalyticsProviders = new AnalyticsProviders();
analyticsProvidersObj.providers = [];
for (let providerValue of value.providers) {
const providerObj: AnalyticsProvider = AnalyticsProvider.parseValue(providerValue);
analyticsProvidersObj.providers.push(providerObj);
}
return analyticsProvidersObj;
}
}
export class AnalyticsProvider {
private _type: AnalyticsProviderType;
get type(): AnalyticsProviderType {
return this._type;
}
set type(type: AnalyticsProviderType) {
this._type = type;
}
private _enabled: boolean;
get enabled(): boolean {
return this._enabled;
}
set enabled(enabled: boolean) {
this._enabled = enabled;
}
private _options: any;
get options(): any {
return this._options;
}
set options(options: any) {
this._options = options;
}
public static parseValue(value: any): AnalyticsProvider {
const obj: AnalyticsProvider = new AnalyticsProvider();
obj.type = value.type;
obj.enabled = value.enabled;
obj.options = value.options;
return obj;
}
}
export enum AnalyticsProviderType {
Matomo = "matomo"
}

View File

@ -10,6 +10,7 @@ import { HttpClient } from '@angular/common/http';
import { KeycloakConfiguration } from '@app/core/model/configuration-models/keycloak-configuration.model';
import { Guid } from '@common/types/guid';
import { AuthProviders } from '@app/core/model/configuration-models/auth-providers.model';
import { AnalyticsProviders } from '@app/core/model/configuration-models/analytics-providers.model';
@Injectable({
providedIn: 'root',
@ -153,6 +154,11 @@ export class ConfigurationService extends BaseComponent {
get authProviders(): AuthProviders {
return this._authProviders;
}
private _analyticsProviders: AnalyticsProviders;
get analyticsProviders(): AnalyticsProviders {
return this._analyticsProviders;
}
private _researcherId: any;
get researcherId(): boolean {
@ -239,6 +245,7 @@ export class ConfigurationService extends BaseComponent {
this._newReleaseNotificationLink = config.newReleaseNotification?.link;
this._newReleaseNotificationVersionCode = config.newReleaseNotification?.versionCode;
this._authProviders = AuthProviders.parseValue(config.authProviders);
this._analyticsProviders = AnalyticsProviders.parseValue(config.analytics);
this._researcherId = config.referenceTypes.researcherId;
this._grantId = config.referenceTypes.grantId;
this._organizationId = config.referenceTypes.organizationId;

View File

@ -0,0 +1,31 @@
import { Injectable } from "@angular/core";
import { ConfigurationService } from "../configuration/configuration.service";
import { MatomoService } from "./matomo-service";
import { AnalyticsProviderType, AnalyticsProviders } from "@app/core/model/configuration-models/analytics-providers.model";
@Injectable()
export class AnalyticsService {
public static Dashboard: string = 'Home Dashboard';
constructor(
private configurationService: ConfigurationService,
private matomoService: MatomoService
) { }
trackPageView(customTitle?: string): void {
const analytics: AnalyticsProviders = this.configurationService.analyticsProviders;
for (let provider of analytics.providers) {
switch(provider.type) {
case(AnalyticsProviderType.Matomo):
this.matomoService.trackPageViewCopy(provider, customTitle);
}
}
}
trackSiteSearch(keyword: string, category?: string, resultsCount?: number): void {
}
trackDownload(category: "dmps" | "datasets" | "descriptions", type: string, id: string): void {
}
}

View File

@ -2,6 +2,7 @@ import { Injectable } from '@angular/core';
import { MatomoInitializerService, MatomoTracker } from 'ngx-matomo-client';
import { AuthService } from '../auth/auth.service';
import { ConfigurationService } from '../configuration/configuration.service';
import { AnalyticsProvider } from '@app/core/model/configuration-models/analytics-providers.model';
@Injectable()
export class MatomoService {
@ -28,6 +29,14 @@ export class MatomoService {
this.matomoTracker.trackPageView(customTitle);
}
}
trackPageViewCopy(provider: AnalyticsProvider, customTitle?: string): void {
if (provider.enabled) {
var principalid = this.authService.userId();
if (principalid != null) { this.matomoTracker.setUserId(principalid.toString()); }
this.matomoTracker.trackPageView(customTitle);
}
}
trackSiteSearch(keyword: string, category?: string, resultsCount?: number): void {
if (this.configurationService.matomoEnabled) {

View File

@ -254,7 +254,7 @@
<div class="col">
<div class="row">
<div class="col-12 col-lg-6 col-xl-3">
<div class="col-12 col-lg-6 col-xl">
<mat-form-field class="w-100 mt-3">
<mat-label>{{'DMP-BLUEPRINT-EDITOR.FIELDS.DESCRIPTION-TEMPLATE' | translate}}</mat-label>
<app-single-auto-complete [formControl]="descriptionTemplate.get('descriptionTemplateGroupId')" [configuration]="descriptionTempalteGroupSingleAutocompleteConfiguration" (optionActionClicked)="onPreviewDescriptionTemplate($event, sectionIndex, descriptionTemplateIndex)"></app-single-auto-complete>
@ -262,7 +262,7 @@
<mat-error *ngIf="descriptionTemplate.get('descriptionTemplateGroupId').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-12 col-lg-6 col-xl-3">
<div class="col-12 col-lg-6 col-xl-2">
<mat-form-field class="w-100 mt-3">
<mat-label>{{'DMP-BLUEPRINT-EDITOR.FIELDS.DESCRIPTION-TEMPLATE-LABEL' | translate}}</mat-label>
<input matInput type="text" name="label" [formControl]="descriptionTemplate.get('label')">
@ -270,7 +270,7 @@
<mat-error *ngIf="descriptionTemplate.get('label').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-12 col-lg-6 col-xl-3">
<div class="col-12 col-lg-6 col-xl-2">
<mat-form-field class="w-100 mt-3">
<mat-label>{{'DMP-BLUEPRINT-EDITOR.FIELDS.DESCRIPTION-TEMPLATE-MIN-MULTIPLICITY' | translate}}</mat-label>
<input matInput type="number" min="0" [max]="descriptionTemplate.get('maxMultiplicity').value" name="minMultiplicity" [formControl]="descriptionTemplate.get('minMultiplicity')">
@ -278,7 +278,7 @@
<mat-error *ngIf="descriptionTemplate.get('minMultiplicity').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-12 col-lg-6 col-xl-3">
<div class="col-12 col-lg-6 col-xl-2">
<mat-form-field class="w-100 mt-3">
<mat-label>{{'DMP-BLUEPRINT-EDITOR.FIELDS.DESCRIPTION-TEMPLATE-MAX-MULTIPLICITY' | translate}}</mat-label>
<input matInput type="number" [min]="descriptionTemplate.get('minMultiplicity').value" name="maxMultiplicity" [formControl]="descriptionTemplate.get('maxMultiplicity')">

View File

@ -96,7 +96,6 @@
.personal-usage {
text-align: left;
font-weight: 300;
font-family: "Roboto", sans-serif;
font-size: 1.25rem;
letter-spacing: 0px;
color: #212121;
@ -127,7 +126,6 @@
text-align: left;
text-decoration: underline;
font-weight: 300;
font-family: "Roboto", sans-serif;
font-size: 1rem;
letter-spacing: 0px;
color: var(--primary-color-2);
@ -137,7 +135,6 @@
.link-disabled {
text-align: left;
font-weight: 300;
font-family: "Roboto", sans-serif;
font-size: 1rem;
letter-spacing: 0px;
color: #212121;
@ -147,7 +144,6 @@
.latest-activity-title {
text-align: left;
font-weight: 300;
font-family: "Roboto", sans-serif;
font-size: 1.25rem;
letter-spacing: 0px;
color: #212121;
@ -186,16 +182,6 @@ input[type="text"] {
padding-left: 15px;
}
.edited-date {
text-align: left;
font-weight: 300;
font-family: "Roboto", sans-serif;
line-height: 2.4;
letter-spacing: 0px;
color: #212121;
opacity: 0.6;
}
.dmp-label {
background: var(--primary-color) 0% 0% no-repeat padding-box;
border-radius: 4px 0px;
@ -220,43 +206,6 @@ input[type="text"] {
font-weight: 400;
}
.dmp-title,
.dataset-title {
text-align: left;
font-weight: 600;
font-family: "Roboto", sans-serif;
font-size: 1rem;
// opacity: 0.81;
padding-top: 0.75rem;
padding-bottom: 0.55rem;
color: #212121;
}
.dataset-subtitle,
.dmp-subtitle {
display: flex;
flex-direction: row;
text-align: left;
font-weight: 400;
font-family: "Roboto", sans-serif;
font-size: 0.875rem;
opacity: 1;
align-items: center;
color: #848484;
}
.dmp-title-draft,
.dataset-title-draft {
text-align: left;
font-weight: 600;
font-family: "Roboto", sans-serif;
font-size: 1rem;
// opacity: 0.81;
padding-top: 0.75rem;
padding-bottom: 0.55rem;
color: #f16868;
}
.icon-align {
display: inline-flex;
vertical-align: middle;

View File

@ -18,6 +18,7 @@ import { CookieService } from 'ngx-cookie-service';
import { takeUntil } from 'rxjs/operators';
import { StartNewDescriptionDialogComponent } from '../description/start-new-description-dialog/start-new-description-dialog.component';
import { StartNewDmpDialogComponent } from '../dmp/new/start-new-dmp-dialogue/start-new-dmp-dialog.component';
import { AnalyticsService } from '@app/core/services/matomo/analytics-service';
@Component({
@ -43,6 +44,7 @@ export class DashboardComponent extends BaseComponent implements OnInit {
private language: TranslateService,
private guidedTourService: GuidedTourService,
private matomoService: MatomoService,
private analyticsService: AnalyticsService,
public referenceTypeService: ReferenceTypeService,
private fb: UntypedFormBuilder,
private cookieService: CookieService,
@ -62,7 +64,8 @@ export class DashboardComponent extends BaseComponent implements OnInit {
}
});
this.matomoService.trackPageView('Home Dashboard');
this.analyticsService.trackPageView(AnalyticsService.Dashboard);
// this.matomoService.trackPageView('Home Dashboard');
if (!this.isAuthenticated()) {
this.dashboardService.getPublicDashboardStatistics()

View File

@ -1,14 +1,3 @@
.latest-activity-title {
text-align: left;
font-weight: 300;
font-family: "Roboto", sans-serif;
font-size: 1.25rem;
letter-spacing: 0px;
color: #212121;
opacity: 0.6;
padding-bottom: 1.2rem;
}
.dmp-card,
.dataset-card {
min-width: 712px;
@ -39,7 +28,6 @@ input[type="text"] {
.edited-date {
text-align: left;
font-weight: 300;
font-family: "Roboto", sans-serif;
line-height: 2.4;
letter-spacing: 0px;
color: #212121;
@ -69,43 +57,6 @@ input[type="text"] {
font-weight: 400;
}
.dmp-title,
.dataset-title {
text-align: left;
font-weight: 600;
font-family: "Roboto", sans-serif;
font-size: 1rem;
/* opacity: 0.81; */
padding-top: 0.75rem;
padding-bottom: 0.55rem;
color: #212121;
}
.dataset-subtitle,
.dmp-subtitle {
display: flex;
flex-direction: row;
text-align: left;
font-weight: 400;
font-family: "Roboto", sans-serif;
font-size: 0.875rem;
opacity: 1;
align-items: center;
color: #848484;
}
.dmp-title-draft,
.dataset-title-draft {
text-align: left;
font-weight: 600;
font-family: "Roboto", sans-serif;
font-size: 1rem;
/* opacity: 0.81; */
padding-top: 0.75rem;
padding-bottom: 0.55rem;
color: #f16868;
}
.icon-align {
display: inline-flex;
vertical-align: middle;

View File

@ -1,26 +1,3 @@
.latest-activity-title {
text-align: left;
font-weight: 300;
font-family: "Roboto", sans-serif;
font-size: 1.25rem;
letter-spacing: 0px;
color: #212121;
opacity: 0.6;
padding-bottom: 1.2rem;
}
.dmp-card,
.dataset-card {
min-width: 712px;
/* min-height: 308px; */
background: #ffffff 0% 0% no-repeat padding-box;
box-shadow: 0px 3px 6px #0000001a;
border-radius: 4px;
opacity: 1;
margin-top: 2.43rem;
margin-bottom: 1rem;
}
.remove-border-bottom ::ng-deep .mat-tab-header {
border-bottom: none;
}
@ -36,16 +13,6 @@ input[type="text"] {
padding-left: 15px;
}
.edited-date {
text-align: left;
font-weight: 300;
font-family: "Roboto", sans-serif;
line-height: 2.4;
letter-spacing: 0px;
color: #212121;
opacity: 0.6;
}
.dmp-label {
background: var(--primary-color) 0% 0% no-repeat padding-box;
border-radius: 4px 0px;
@ -69,43 +36,6 @@ input[type="text"] {
font-weight: 400;
}
.dmp-title,
.dataset-title {
text-align: left;
font-weight: 600;
font-family: "Roboto", sans-serif;
font-size: 1rem;
/* opacity: 0.81; */
padding-top: 0.75rem;
padding-bottom: 0.55rem;
color: #212121;
}
.dataset-subtitle,
.dmp-subtitle {
display: flex;
flex-direction: row;
text-align: left;
font-weight: 400;
font-family: "Roboto", sans-serif;
font-size: 0.875rem;
opacity: 1;
align-items: center;
color: #848484;
}
.dmp-title-draft,
.dataset-title-draft {
text-align: left;
font-weight: 600;
font-family: "Roboto", sans-serif;
font-size: 1rem;
/* opacity: 0.81; */
padding-top: 0.75rem;
padding-bottom: 0.55rem;
color: #f16868;
}
.icon-align {
display: inline-flex;
vertical-align: middle;

View File

@ -1,26 +1,3 @@
.latest-activity-title {
text-align: left;
font-weight: 300;
font-family: "Roboto", sans-serif;
font-size: 1.25rem;
letter-spacing: 0px;
color: #212121;
opacity: 0.6;
padding-bottom: 1.2rem;
}
.dmp-card,
.description-card {
min-width: 712px;
/* min-height: 308px; */
background: #ffffff 0% 0% no-repeat padding-box;
box-shadow: 0px 3px 6px #0000001a;
border-radius: 4px;
opacity: 1;
margin-top: 2.43rem;
margin-bottom: 1rem;
}
.remove-border-bottom ::ng-deep .mat-tab-header {
border-bottom: none;
}
@ -36,16 +13,6 @@ input[type="text"] {
padding-left: 15px;
}
.edited-date {
text-align: left;
font-weight: 300;
font-family: "Roboto", sans-serif;
line-height: 2.4;
letter-spacing: 0px;
color: #212121;
opacity: 0.6;
}
.dmp-label {
background: var(--primary-color) 0% 0% no-repeat padding-box;
border-radius: 4px 0px;
@ -69,43 +36,6 @@ input[type="text"] {
font-weight: 400;
}
.dmp-title,
.description-title {
text-align: left;
font-weight: 600;
font-family: "Roboto", sans-serif;
font-size: 1rem;
// opacity: 0.81;
padding-top: 0.75rem;
padding-bottom: 0.55rem;
color: #212121;
}
.description-subtitle,
.dmp-subtitle {
display: flex;
flex-direction: row;
text-align: left;
font-weight: 400;
font-family: "Roboto", sans-serif;
font-size: 0.875rem;
opacity: 1;
align-items: center;
color: #848484;
}
.dmp-title-draft,
.description-title-draft {
text-align: left;
font-weight: 600;
font-family: "Roboto", sans-serif;
font-size: 1rem;
// opacity: 0.81;
padding-top: 0.75rem;
padding-bottom: 0.55rem;
color: #f16868;
}
.icon-align {
display: inline-flex;
vertical-align: middle;

View File

@ -1,14 +1,3 @@
.latest-activity-title {
text-align: left;
font-weight: 300;
font-family: "Roboto", sans-serif;
font-size: 1.25rem;
letter-spacing: 0px;
color: #212121;
opacity: 0.6;
padding-bottom: 1.2rem;
}
.dmp-card, .dataset-card {
min-width: 712px;
/* min-height: 308px; */
@ -35,16 +24,6 @@ input[type="text"] {
padding-left: 15px;
}
.edited-date {
text-align: left;
font-weight: 300;
font-family: "Roboto", sans-serif;
line-height: 2.4;
letter-spacing: 0px;
color: #212121;
opacity: 0.6;
}
.dmp-label {
background: var(--primary-color) 0% 0% no-repeat padding-box;
border-radius: 4px 0px;
@ -67,41 +46,6 @@ input[type="text"] {
color: #212121;
}
.dmp-title, .dataset-title {
text-align: left;
font-weight: 600;
font-family: "Roboto", sans-serif;
font-size: 1rem;
/* opacity: 0.81; */
padding-top: 0.75rem;
padding-bottom: 0.55rem;
color: #212121;
}
.dataset-subtitle, .dmp-subtitle {
display: flex;
flex-direction: row;
text-align: left;
font-weight: 400;
font-family: "Roboto", sans-serif;
font-size: 0.875rem;
opacity: 1;
align-items: center;
color: #848484;
}
.dmp-title-draft,
.dataset-title-draft {
text-align: left;
font-weight: 600;
font-family: "Roboto", sans-serif;
font-size: 1rem;
/* opacity: 0.81; */
padding-top: 0.75rem;
padding-bottom: 0.55rem;
color: #f16868;
}
.icon-align {
display: inline-flex;
vertical-align: middle;

View File

@ -4,19 +4,24 @@
<div class="col-auto ml-auto close-btn" (click)="close()"><mat-icon class="close-icon">close</mat-icon></div>
</div>
<div mat-dialog-content class="confirmation-message">
<mat-form-field class="col-12">
<app-single-auto-complete [formControl]="data.formGroup.get('dmpId')" placeholder="{{'DESCRIPTION-COPY-DIALOG.SELECT-DMP' | translate}}" [configuration]="dmpAutoCompleteConfiguration">
</app-single-auto-complete>
</mat-form-field>
<div *ngIf="this.sections.length > 1">
<mat-form-field>
<mat-label>{{'DESCRIPTION-COPY-DIALOG.DMP-SECTION' | translate}}</mat-label>
<mat-select [formControl]="data.formGroup.get('sectionId')">
<mat-option *ngFor="let section of sections" [value]="section.id">{{section.label}}</mat-option>
</mat-select>
</mat-form-field>
<div class="row mt-3">
<div class="col-12">
<mat-form-field class="w-100">
<app-single-auto-complete [formControl]="data.formGroup.get('dmpId')" placeholder="{{'DESCRIPTION-COPY-DIALOG.SELECT-DMP' | translate}}" [configuration]="dmpAutoCompleteConfiguration">
</app-single-auto-complete>
</mat-form-field>
</div>
</div>
<div *ngIf="this.sections.length > 1" class="row">
<div class="col-12">
<mat-form-field class="w-100">
<mat-label>{{'DESCRIPTION-COPY-DIALOG.DMP-SECTION' | translate}}</mat-label>
<mat-select [formControl]="data.formGroup.get('sectionId')">
<mat-option *ngFor="let section of sections" [value]="section.id">{{section.label}}</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
<!-- <mat-error *ngIf="data.formControl.hasError('incorrect')">{{getErrorMessage()}}</mat-error> -->
</div>
<div mat-dialog-actions class="row">
<div class="col-auto ml-auto"><button mat-button class="cancel-btn" type="button" (click)="cancel()">{{ data.cancelButton }}</button></div>

View File

@ -250,7 +250,6 @@
.dmp-title {
text-align: left;
font-weight: 700;
font-family: "Roboto", sans-serif;
font-size: 1rem;
color: #212121;
overflow: hidden;

View File

@ -17,10 +17,10 @@
<div *ngSwitchCase="descriptionTemplateFieldTypeEnum.REFERENCE_TYPES" class="col-12">
<ng-container *ngIf="field.data.multipleSelect">
<app-reference-field-component [form]="propertiesFormGroup?.get(field.id).get('references')" [label]="(field.data.label | translate) + (isRequired ? ' *': '')" [placeholder]="(field.data.label | translate) + (isRequired ? ' *': '')" [referenceType]="field.data.referenceType" [multiple]="true" [required]="isRequired" hint=""></app-reference-field-component>
<app-reference-field-component [form]="propertiesFormGroup?.get(field.id).get('references')" [label]="(field.data.label | translate) + (isRequired ? ' *': '')" [placeholder]="(field.data.label | translate) + (isRequired ? ' *': '')" [referenceType]="field.data.referenceType" [multiple]="true" [required]="isRequired" hint="{{ 'TYPES.DATASET-PROFILE-COMBO-BOX-TYPE.EXTERNAL-SOURCE-HINT' | translate }}"></app-reference-field-component>
</ng-container>
<ng-container *ngIf="!(field.data.multipleSelect)">
<app-reference-field-component [form]="propertiesFormGroup?.get(field.id).get('reference')" [label]="(field.data.label | translate) + (isRequired ? ' *': '')" [placeholder]="(field.data.label | translate) + (isRequired ? ' *': '')" [referenceType]="field.data.referenceType" [multiple]="false" [required]="isRequired" hint=""></app-reference-field-component>
<app-reference-field-component [form]="propertiesFormGroup?.get(field.id).get('reference')" [label]="(field.data.label | translate) + (isRequired ? ' *': '')" [placeholder]="(field.data.label | translate) + (isRequired ? ' *': '')" [referenceType]="field.data.referenceType" [multiple]="false" [required]="isRequired" hint="{{ 'TYPES.DATASET-PROFILE-COMBO-BOX-TYPE.EXTERNAL-SOURCE-HINT' | translate }}"></app-reference-field-component>
</ng-container>
</div>
<div *ngSwitchCase="descriptionTemplateFieldTypeEnum.SELECT" class="col-12">
@ -53,6 +53,7 @@
</app-multiple-auto-complete>
<mat-error *ngIf="propertiesFormGroup?.get(field.id).get('textListValue').hasError('backendError')">{{propertiesFormGroup?.get(field.id).get('textListValue').getError('backendError').message}}</mat-error>
<mat-error *ngIf="propertiesFormGroup?.get(field.id).get('textListValue').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
<mat-hint>{{ "TYPES.DATASET-PROFILE-COMBO-BOX-TYPE.EXTERNAL-SOURCE-HINT" | translate }}</mat-hint>
</mat-form-field>
</ng-container>
<ng-container *ngIf="!(field.data.multipleSelect)">
@ -62,6 +63,7 @@
</app-single-auto-complete>
<mat-error *ngIf="propertiesFormGroup?.get(field.id).get('textValue').hasError('backendError')">{{propertiesFormGroup?.get(field.id).get('textValue').getError('backendError').message}}</mat-error>
<mat-error *ngIf="propertiesFormGroup?.get(field.id).get('textValue').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
<mat-hint>{{ "TYPES.DATASET-PROFILE-COMBO-BOX-TYPE.EXTERNAL-SOURCE-HINT" | translate }}</mat-hint>
</mat-form-field>
</ng-container>
</div>
@ -75,6 +77,7 @@
</app-multiple-auto-complete>
<mat-error *ngIf="propertiesFormGroup?.get(field.id).get('textListValue').hasError('backendError')">{{propertiesFormGroup?.get(field.id).get('textListValue').getError('backendError').message}}</mat-error>
<mat-error *ngIf="propertiesFormGroup?.get(field.id).get('textListValue').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
<mat-hint>{{ "TYPES.DATASET-PROFILE-COMBO-BOX-TYPE.EXTERNAL-SOURCE-HINT" | translate }}</mat-hint>
</mat-form-field>
</ng-container>
<ng-container *ngIf="!(field.data.multipleSelect)">
@ -84,6 +87,7 @@
</app-single-auto-complete>
<mat-error *ngIf="propertiesFormGroup?.get(field.id).get('textValue').hasError('backendError')">{{propertiesFormGroup?.get(field.id).get('textValue').getError('backendError').message}}</mat-error>
<mat-error *ngIf="propertiesFormGroup?.get(field.id).get('textValue').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
<mat-hint>{{ "TYPES.DATASET-PROFILE-COMBO-BOX-TYPE.EXTERNAL-SOURCE-HINT" | translate }}</mat-hint>
</mat-form-field>
</ng-container>
</div>

View File

@ -100,14 +100,12 @@ input[type="text"] {
opacity: 1;
width: 347px;
height: 56px;
font-family: Arial, FontAwesome;
padding-left: 15px;
}
.edited-date {
text-align: left;
font-weight: 300;
font-family: "Roboto", sans-serif;
line-height: 2.4;
letter-spacing: 0px;
color: #212121;
@ -141,7 +139,6 @@ input[type="text"] {
.description-title {
text-align: left;
font-weight: 600;
font-family: "Roboto", sans-serif;
font-size: 1rem;
// opacity: 0.81;
padding-top: 0.75rem;
@ -149,24 +146,20 @@ input[type="text"] {
color: #212121;
}
.description-subtitle,
.dmp-subtitle {
.description-subtitle {
display: flex;
flex-direction: row;
text-align: left;
font-weight: 400;
font-family: "Roboto", sans-serif;
font-size: 0.875rem;
opacity: 1;
align-items: center;
color: #848484;
}
.dmp-title-draft,
.description-title-draft {
text-align: left;
font-weight: 600;
font-family: "Roboto", sans-serif;
font-size: 1rem;
// opacity: 0.81;
padding-top: 0.75rem;

View File

@ -183,10 +183,10 @@
<p class="header">{{ 'DESCRIPTION-OVERVIEW.DESCRIPTION-AUTHORS' | translate }}</p>
</div>
<div class="col-12">
<div *ngFor="let dmpUser of description.dmp?.dmpUsers" class="row authors">
<div *ngFor="let dmpUser of description.dmp?.dmpUsers" class="row authors pt-1" [ngClass]="{'author-focused': authorFocus && authorFocus == dmpUser.user?.id}" (mouseover)="focusOnAuthor(dmpUser.user?.id)" (mouseout)="resetAuthorFocus()">
<div class="col-auto d-flex flex-row pr-0">
<button class="account_btn mr-3 pl-0">
<mat-icon class="account-icon">account_circle</mat-icon>
<mat-icon class="account-icon" [ngClass]="{'author-icon-focused': authorFocus && authorFocus == dmpUser.user?.id}">account_circle</mat-icon>
</button>
</div>
<div class="col pl-0" style="min-width: 0;">
@ -197,13 +197,10 @@
<span *ngIf="dmpUser.sectionId">{{ getSectionNameById(dmpUser.sectionId) }}</span>
</p>
</div>
<div class="col-auto" *ngIf="canInviteDmpUsers && description.dmp?.status === dmpStatusEnum.Draft && dmpUser.role != dmpUserRoleEnum.Owner" >
<!-- <button (click)="removeUserFromDmp(dmpUser)" class="remove-btn">{{ 'DESCRIPTION-OVERVIEW.ACTIONS.REMOVE-AUTHOR' | translate}}</button> -->
<div class="col-auto" *ngIf="canInviteDmpUsers && description.dmp?.status === dmpStatusEnum.Draft && dmpUser.role != dmpUserRoleEnum.Owner">
<button (click)="removeUserFromDmp(dmpUser)" mat-mini-fab matTooltip="{{ 'DESCRIPTION-OVERVIEW.ACTIONS.REMOVE-AUTHOR' | translate}}" matTooltipPosition="above">
<mat-icon class="mat-mini-fab-icon">delete</mat-icon>
</button>
</div>
</div>
</div>

View File

@ -116,7 +116,7 @@
}
.account_btn {
background: white;
background: transparent;
color: #d5d5d5;
border: none;
height: 2.9em;
@ -300,3 +300,12 @@
display: flex;
justify-content: center;
}
.author-focused {
background-color: #e0e0e0;
border-radius: 3px;
}
.author-icon-focused {
color: #a8a8a8 !important;
}

View File

@ -71,6 +71,8 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
canReview = false;
canInviteDmpUsers = false;
authorFocus: Guid;
constructor(
private route: ActivatedRoute,
private router: Router,
@ -214,6 +216,14 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
} else return false;
}
focusOnAuthor(userId: Guid): void {
this.authorFocus = userId;
console.log(this.authorFocus);
}
resetAuthorFocus(): void {
this.authorFocus = null;
}
openShareDialog() {
const dialogRef = this.dialog.open(DmpInvitationDialogComponent, {

View File

@ -141,7 +141,6 @@ input[type="text"] {
.edited-date {
text-align: left;
font-weight: 300;
font-family: "Roboto", sans-serif;
line-height: 2.4;
letter-spacing: 0px;
color: #212121;
@ -174,7 +173,6 @@ input[type="text"] {
.dataset-title {
text-align: left;
font-weight: 600;
font-family: "Roboto", sans-serif;
font-size: 1rem;
// opacity: 0.81;
padding-top: 0.75rem;
@ -188,7 +186,6 @@ input[type="text"] {
flex-direction: row;
text-align: left;
font-weight: 400;
font-family: "Roboto", sans-serif;
font-size: 0.875rem;
opacity: 1;
align-items: center;
@ -199,7 +196,6 @@ input[type="text"] {
.dataset-title-draft {
text-align: left;
font-weight: 600;
font-family: "Roboto", sans-serif;
font-size: 1rem;
// opacity: 0.81;
padding-top: 0.75rem;

View File

@ -240,43 +240,40 @@
<div class="row">
<div class="col-12">
<div class="frame mb-3 pt-4 pl-3 pr-3 pb-3">
<div class="row">
<div class="col-12">
<p class="header">{{ 'DMP-OVERVIEW.DMP-AUTHORS' | translate }}</p>
</div>
<div class="col-12">
<div *ngFor="let dmpUser of dmp.dmpUsers" class="row authors">
<div class="col-auto d-flex flex-row pr-0">
<button class="account_btn mr-3 pl-0">
<mat-icon class="account-icon">account_circle</mat-icon>
</button>
</div>
<div class="col pl-0" style="min-width: 0;">
<!-- <div class="mytext">{{ dmpUser.user?.name }}</div> -->
<p class="authors-label">{{ dmpUser.user?.name }}
<span *ngIf="isUserAuthor(dmpUser.user?.id)">
({{ 'DMP-OVERVIEW.YOU' | translate }})</span>
</p>
<p class="authors-role">
<span>{{ enumUtils.toDmpUserRoleString(dmpUser.role) }} - </span>
<span *ngIf="!dmpUser.sectionId">{{ 'DMP-OVERVIEW.ROLES.ALL-SECTIONS' | translate}}</span>
<span *ngIf="dmpUser.sectionId">{{ getSectionNameById(dmpUser.sectionId) }}</span>
</p>
</div>
<div *ngIf="canAssignDmpUsers(dmp) && dmp.status === dmpStatusEnum.Draft && dmpUser.role != dmpUserRoleEnum.Owner" class="col-auto">
<button (click)="removeUserFromDmp(dmpUser)" mat-mini-fab matTooltip="{{ 'DMP-OVERVIEW.ACTIONS.REMOVE-AUTHOR' | translate}}" matTooltipPosition="above">
<mat-icon class="mat-mini-fab-icon">delete</mat-icon>
</button>
</div>
<div class="col-12">
<p class="header">{{ 'DMP-OVERVIEW.DMP-AUTHORS' | translate }}</p>
</div>
<div class="col-12">
<div *ngFor="let dmpUser of dmp.dmpUsers" class="row authors pt-1" [ngClass]="{'author-focused': authorFocus && authorFocus == dmpUser.user?.id}" (mouseover)="focusOnAuthor(dmpUser.user?.id)" (mouseout)="resetAuthorFocus()">
<div class="col-auto d-flex flex-row pr-0">
<button class="account_btn mr-3 pl-0">
<mat-icon class="account-icon" [ngClass]="{'author-icon-focused': authorFocus && authorFocus == dmpUser.user?.id}">account_circle</mat-icon>
</button>
</div>
<div class="col pl-0" style="min-width: 0;">
<!-- <div class="mytext">{{ dmpUser.user?.name }}</div> -->
<p class="authors-label">{{ dmpUser.user?.name }}
<span *ngIf="isUserAuthor(dmpUser.user?.id)">
({{ 'DMP-OVERVIEW.YOU' | translate }})</span>
</p>
<p class="authors-role">
<span>{{ enumUtils.toDmpUserRoleString(dmpUser.role) }} - </span>
<span *ngIf="!dmpUser.sectionId">{{ 'DMP-OVERVIEW.ROLES.ALL-SECTIONS' | translate}}</span>
<span *ngIf="dmpUser.sectionId">{{ getSectionNameById(dmpUser.sectionId) }}</span>
</p>
</div>
<div *ngIf="canAssignDmpUsers(dmp) && dmp.status === dmpStatusEnum.Draft && dmpUser.role != dmpUserRoleEnum.Owner" class="col-auto">
<button (click)="removeUserFromDmp(dmpUser)" mat-mini-fab matTooltip="{{ 'DMP-OVERVIEW.ACTIONS.REMOVE-AUTHOR' | translate}}" matTooltipPosition="above">
<mat-icon class="mat-mini-fab-icon">delete</mat-icon>
</button>
</div>
</div>
<!-- <div *ngIf="canInviteDmpUsers()" class="col-12 d-flex align-items-center justify-content-center"> -->
<div *ngIf="canInviteDmpUsers()" class="col-12 d-flex align-items-center justify-content-center">
<button mat-raised-button class="invite-btn" (click)="openShareDialog(dmp.id,dmp.label)">
<mat-icon>group_add</mat-icon>
{{'DMP-OVERVIEW.ACTIONS.INVITE-SHORT' | translate}}
</button>
</div>
</div>
<div *ngIf="canInviteDmpUsers()" class="col-12 d-flex align-items-center justify-content-center mt-2">
<button mat-raised-button class="invite-btn" (click)="openShareDialog(dmp.id,dmp.label)">
<mat-icon>group_add</mat-icon>
{{'DMP-OVERVIEW.ACTIONS.INVITE-SHORT' | translate}}
</button>
</div>
</div>
</div>

View File

@ -114,7 +114,7 @@
}
.account_btn {
background: white;
background: transparent;
color: #d5d5d5;
border: none;
height: 2.9em;
@ -264,7 +264,6 @@
display: flex;
flex-direction: row;
justify-content: space-between;
width: 100%;
}
.authors-label {
@ -348,3 +347,12 @@
justify-content: space-between;
border: none;
}
.author-focused {
background-color: #e0e0e0;
border-radius: 3px;
}
.author-icon-focused {
color: #a8a8a8 !important;
}

View File

@ -82,6 +82,8 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
dmpStatusEnum = DmpStatus;
dmpUserRoleEnum = DmpUserRole;
authorFocus: Guid;
constructor(
private route: ActivatedRoute,
private router: Router,
@ -216,6 +218,15 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
} else return false;
}
focusOnAuthor(userId: Guid): void {
this.authorFocus = userId;
console.log(this.authorFocus);
}
resetAuthorFocus(): void {
this.authorFocus = null;
}
canEditDmp(): boolean{
return (this.isDraftDmp()) && (this.dmp.authorizationFlags?.some(x => x === AppPermission.EditDmp) || this.authentication.hasPermission(AppPermission.EditDmp)) && this.isPublicView == false && this.dmp.belongsToCurrentTenant != false;
}

View File

@ -4,7 +4,11 @@
</app-multiple-auto-complete>
<mat-error *ngIf="form.hasError('backendError')">{{form.getError('backendError').message}}</mat-error>
<mat-error *ngIf="form.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
<mat-hint *ngIf="hint">{{hint}}</mat-hint>
<mat-hint *ngIf="hint" align="start">{{hint}}</mat-hint>
<mat-hint *ngIf="hint" align="end">
<span *ngIf="!form.disabled" class="not-found">{{'REFERENCE-FIELD.COULD-NOT-FIND-MESSAGE' | translate}} </span>
<span *ngIf="!form.disabled" class="insert-manually" (click)="addReference($event)">{{'REFERENCE-FIELD.ACTIONS.INSERT-MANUALLY' | translate}}</span>
</mat-hint>
</mat-form-field>
<mat-form-field class="w-100" *ngIf="singleAutoCompleteSearchConfiguration">
<mat-label>{{label?.length > 0 ? label : referenceType?.name}}</mat-label>
@ -12,9 +16,11 @@
</app-single-auto-complete>
<mat-error *ngIf="form.hasError('backendError')">{{form.getError('backendError').message}}</mat-error>
<mat-error *ngIf="form.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
<mat-hint *ngIf="hint">{{hint}}</mat-hint>
<mat-hint *ngIf="hint" align="start">{{hint}}</mat-hint>
<mat-hint *ngIf="hint" align="end">
<span *ngIf="!form.disabled" class="not-found">{{'REFERENCE-FIELD.COULD-NOT-FIND-MESSAGE' | translate}} </span>
<span *ngIf="!form.disabled" class="insert-manually" (click)="addReference($event)">{{'REFERENCE-FIELD.ACTIONS.INSERT-MANUALLY' | translate}}</span>
</mat-hint>
</mat-form-field>
<div class="mb-4">
<span *ngIf="!form.disabled" class="not-found">{{'REFERENCE-FIELD.COULD-NOT-FIND-MESSAGE' | translate}}</span>
<span *ngIf="!form.disabled" class="insert-manually" (click)="addReference($event)">{{'REFERENCE-FIELD.ACTIONS.INSERT-MANUALLY' | translate}}</span>
</div>

View File

@ -2,14 +2,14 @@
text-decoration: underline;
color: var(--primary-color-3);
cursor: pointer;
font-size: 1rem;
// font-size: 1rem;
font-weight: 400;
}
.not-found {
// cursor: pointer;
color: #333;
font-size: 1rem;
// font-size: 1rem;
font-weight: 400;
padding: 0rem 0.5rem 0rem 0rem;
}

View File

@ -13,7 +13,6 @@
cursor: pointer;
display: inline-flex;
font-size: small;
font-family: 'Roboto';
}
.sidebar-footer .option:hover {

View File

@ -41,7 +41,6 @@
color: #000000;
opacity: 1;
font-size: 0.93rem;
font-family: 'Roboto',sans-serif;
}
.nav-subrow {
@ -54,7 +53,6 @@
color: #000000;
opacity: 1;
font-size: 0.93rem;
font-family: 'Roboto',sans-serif;
}
.nav-row:hover {

View File

@ -42,6 +42,18 @@
"url": "https://beta.analytics.openaire.eu/",
"siteId": 361
},
"analytics": {
"providers": [
{
"enabled": true,
"type": "matomo",
"options": {
"url": "https://beta.analytics.openaire.eu/",
"siteId": 361
}
}
]
},
"lockInterval": 60000,
"guideAssets": "assets/images/guide",
"allowOrganizationCreator": true,

View File

@ -408,9 +408,6 @@ input[type=email], select {
p {
text-align: left;
font-family: 'Roboto', sans-serif;
/* font-weight: 300;
font-size: 1.25rem; */
letter-spacing: 0px;
color: #212121;
}

View File

@ -72,7 +72,7 @@ $mat-typography: mat.define-typography-config($font-family: 'Roboto, sans-serif;
// $subheading-1: mat.define-typography-level($font-size: 20px, $font-weight: 500, $font-family: 'Roboto, sans-serif;'),
$body-2: mat.define-typography-level($font-size: 16px, $font-weight: 400, $font-family: 'Roboto, sans-serif;'),
$body-1: mat.define-typography-level($font-size: 18px, $font-weight: 400, $font-family: 'Roboto, sans-serif;'),
$caption: mat.define-typography-level($font-size: 16px, $font-weight: Medium, $font-family: 'Roboto, sans-serif;'),
// $caption: mat.define-typography-level($font-size: 16px, $font-weight: Medium, $font-family: 'Roboto, sans-serif;'),
$button: mat.define-typography-level($font-size: 16px, $font-weight: 500, $font-family: 'Roboto, sans-serif;'),
// Line-height must be unit-less fraction of the font-size.
// $input: mat.define-typography-level($font-size: inherit, $line-height: 1.125, $font-weight: 500, $font-family: 'Roboto, sans-serif;'),