mirror of
https://github.com/opf/openproject.git
synced 2026-06-14 03:30:14 +00:00
Remove enterprise angular code
This commit is contained in:
@@ -178,11 +178,6 @@ import {
|
||||
import {
|
||||
WorkPackageOverviewGraphComponent,
|
||||
} from 'core-app/shared/components/work-package-graphs/overview/wp-overview-graph.component';
|
||||
import {
|
||||
EEActiveSavedTrialComponent,
|
||||
} from 'core-app/features/enterprise/enterprise-active-trial/ee-active-saved-trial.component';
|
||||
import { FreeTrialButtonComponent } from 'core-app/features/enterprise/free-trial-button/free-trial-button.component';
|
||||
import { EnterpriseBaseComponent } from 'core-app/features/enterprise/enterprise-base.component';
|
||||
import { NoResultsComponent } from 'core-app/shared/components/no-results/no-results.component';
|
||||
import {
|
||||
OpNonWorkingDaysListComponent,
|
||||
@@ -440,9 +435,6 @@ export class OpenProjectModule implements DoBootstrap {
|
||||
registerCustomElement('opce-time-entry-trigger-actions', TriggerActionsEntryComponent, { injector });
|
||||
registerCustomElement('opce-wp-overview-graph', WorkPackageOverviewGraphComponent, { injector });
|
||||
registerCustomElement('opce-header-project-select', OpHeaderProjectSelectComponent, { injector });
|
||||
registerCustomElement('opce-enterprise-active-saved-trial', EEActiveSavedTrialComponent, { injector });
|
||||
registerCustomElement('opce-free-trial-button', FreeTrialButtonComponent, { injector });
|
||||
registerCustomElement('opce-enterprise-base', EnterpriseBaseComponent, { injector });
|
||||
registerCustomElement('opce-no-results', NoResultsComponent, { injector });
|
||||
registerCustomElement('opce-non-working-days-list', OpNonWorkingDaysListComponent, { injector });
|
||||
registerCustomElement('opce-main-menu-toggle', MainMenuToggleComponent, { injector });
|
||||
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
//-- copyright
|
||||
// OpenProject is an open source project management software.
|
||||
// Copyright (C) the OpenProject GmbH
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { ChangeDetectionStrategy, Component, ElementRef } from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { EEActiveTrialBase } from 'core-app/features/enterprise/enterprise-active-trial/ee-active-trial.base';
|
||||
|
||||
@Component({
|
||||
selector: 'opce-enterprise-active-saved-trial',
|
||||
templateUrl: './ee-active-trial.component.html',
|
||||
styleUrls: ['./ee-active-trial.component.sass'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class EEActiveSavedTrialComponent extends EEActiveTrialBase {
|
||||
public subscriber = this.elementRef.nativeElement.dataset.subscriber;
|
||||
|
||||
public email = this.elementRef.nativeElement.dataset.email;
|
||||
|
||||
public company = this.elementRef.nativeElement.dataset.company;
|
||||
|
||||
public domain = this.elementRef.nativeElement.dataset.domain;
|
||||
|
||||
public userCount = this.elementRef.nativeElement.dataset.userCount;
|
||||
|
||||
public startsAt = this.elementRef.nativeElement.dataset.startsAt;
|
||||
|
||||
public expiresAt = this.elementRef.nativeElement.dataset.expiresAt;
|
||||
|
||||
public isExpired:boolean = this.elementRef.nativeElement.dataset.isExpired === 'true';
|
||||
|
||||
public reprieveDaysLeft = this.elementRef.nativeElement.dataset.reprieveDaysLeft;
|
||||
|
||||
public plan:string = this.elementRef.nativeElement.dataset.plan;
|
||||
|
||||
public additionalFeatures:string = this.elementRef.nativeElement.dataset.additionalFeatures;
|
||||
|
||||
constructor(
|
||||
readonly elementRef:ElementRef,
|
||||
readonly I18n:I18nService,
|
||||
) {
|
||||
super(I18n);
|
||||
}
|
||||
|
||||
public get expiredWarningText():string {
|
||||
let warning = this.text.text_expired;
|
||||
|
||||
if (this.reprieveDaysLeft && this.reprieveDaysLeft > 0) {
|
||||
warning = `${warning}: ${this.text.text_reprieve_days_left(this.reprieveDaysLeft)}`;
|
||||
}
|
||||
|
||||
return warning;
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
//-- copyright
|
||||
// OpenProject is an open source project management software.
|
||||
// Copyright (C) the OpenProject GmbH
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { UntilDestroyedMixin } from 'core-app/shared/helpers/angular/until-destroyed.mixin';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
|
||||
export class EEActiveTrialBase extends UntilDestroyedMixin {
|
||||
public text = {
|
||||
label_email: this.I18n.t('js.label_email'),
|
||||
label_expires_at: this.I18n.t('js.admin.enterprise.trial.form.label_expires_at'),
|
||||
label_maximum_users: this.I18n.t('js.admin.enterprise.trial.form.label_maximum_users'),
|
||||
label_company: this.I18n.t('js.admin.enterprise.trial.form.label_company'),
|
||||
label_domain: this.I18n.t('js.admin.enterprise.trial.form.label_domain'),
|
||||
label_starts_at: this.I18n.t('js.admin.enterprise.trial.form.label_starts_at'),
|
||||
label_subscriber: this.I18n.t('js.admin.enterprise.trial.form.label_subscriber'),
|
||||
label_plan: this.I18n.t('js.admin.enterprise.trial.form.label_plan'),
|
||||
label_additional_features: this.I18n.t('js.admin.enterprise.trial.form.label_additional_features'),
|
||||
text_expired: this.I18n.t('js.admin.enterprise.text_expired'),
|
||||
text_reprieve_days_left: (days:number) => this.I18n.t('js.admin.enterprise.text_reprieve_days_left', { days }),
|
||||
};
|
||||
|
||||
constructor(readonly I18n:I18nService) {
|
||||
super();
|
||||
}
|
||||
}
|
||||
-85
@@ -1,85 +0,0 @@
|
||||
<div data-test-selector="op-enterprise--active-token" class="op-enterprise--active-token">
|
||||
<div class="attributes-group">
|
||||
<div class="attributes-group--attributes">
|
||||
<div class="attributes-key-value">
|
||||
<div class="attributes-key-value--key" [textContent]="text.label_subscriber"></div>
|
||||
<div class="attributes-key-value--value-container">
|
||||
<div class="attributes-key-value--value -text">
|
||||
<span [textContent]="subscriber"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="attributes-key-value">
|
||||
<div class="attributes-key-value--key" [textContent]="text.label_email"></div>
|
||||
<div
|
||||
class="attributes-key-value--value-container"
|
||||
data-test-selector="ee-active-trial-email"
|
||||
>
|
||||
<div class="attributes-key-value--value -text">
|
||||
<span [textContent]="email"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="attributes-key-value" *ngIf="company">
|
||||
<div class="attributes-key-value--key" [textContent]="text.label_company"></div>
|
||||
<div class="attributes-key-value--value-container">
|
||||
<div class="attributes-key-value--value -text">
|
||||
<span [textContent]="company"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="attributes-key-value" *ngIf="domain">
|
||||
<div class="attributes-key-value--key" [textContent]="text.label_domain"></div>
|
||||
<div
|
||||
class="attributes-key-value--value-container"
|
||||
data-test-selector="ee-active-trial-domain"
|
||||
>
|
||||
<div class="attributes-key-value--value -text">
|
||||
<span [textContent]="domain"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="attributes-key-value" *ngIf="userCount">
|
||||
<div class="attributes-key-value--key" [textContent]="text.label_maximum_users"></div>
|
||||
<div class="attributes-key-value--value-container">
|
||||
<div class="attributes-key-value--value -text">
|
||||
<span [textContent]="userCount"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="attributes-key-value" *ngIf="startsAt">
|
||||
<div class="attributes-key-value--key" [textContent]="text.label_starts_at"></div>
|
||||
<div class="attributes-key-value--value-container">
|
||||
<div class="attributes-key-value--value -text">
|
||||
<span [textContent]="startsAt"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="attributes-key-value" *ngIf="expiresAt">
|
||||
<div class="attributes-key-value--key" [textContent]="text.label_expires_at"></div>
|
||||
<div class="attributes-key-value--value-container">
|
||||
<div class="attributes-key-value--value -text">
|
||||
<span [textContent]="expiresAt"></span>
|
||||
<span *ngIf="isExpired" [textContent]="expiredWarningText" class="expired-warning"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="attributes-key-value" *ngIf="plan">
|
||||
<div class="attributes-key-value--key" [textContent]="text.label_plan"></div>
|
||||
<div class="attributes-key-value--value-container">
|
||||
<div class="attributes-key-value--value -text">
|
||||
<span [textContent]="plan"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="attributes-key-value" *ngIf="additionalFeatures">
|
||||
<div class="attributes-key-value--key" [textContent]="text.label_additional_features"></div>
|
||||
<div class="attributes-key-value--value-container">
|
||||
<div class="attributes-key-value--value -text">
|
||||
<span [textContent]="additionalFeatures"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
.op-enterprise--active-token
|
||||
.attributes-group
|
||||
margin-bottom: 1.25rem
|
||||
|
||||
.expired-warning
|
||||
margin-left: 0.4rem
|
||||
color: red
|
||||
font-weight: var(--base-text-weight-bold)
|
||||
-92
@@ -1,92 +0,0 @@
|
||||
//-- copyright
|
||||
// OpenProject is an open source project management software.
|
||||
// Copyright (C) the OpenProject GmbH
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnInit } from '@angular/core';
|
||||
import { distinctUntilChanged } from 'rxjs/operators';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { EnterpriseTrialService } from 'core-app/features/enterprise/enterprise-trial.service';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { EEActiveTrialBase } from 'core-app/features/enterprise/enterprise-active-trial/ee-active-trial.base';
|
||||
import { IEnterpriseData } from 'core-app/features/enterprise/enterprise-trial.model';
|
||||
|
||||
@Component({
|
||||
selector: 'enterprise-active-trial',
|
||||
templateUrl: './ee-active-trial.component.html',
|
||||
styleUrls: ['./ee-active-trial.component.sass'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class EEActiveTrialComponent extends EEActiveTrialBase implements OnInit {
|
||||
public subscriber:string;
|
||||
|
||||
public email:string;
|
||||
|
||||
public company:string;
|
||||
|
||||
public domain:string;
|
||||
|
||||
public userCount:string;
|
||||
|
||||
public startsAt:string;
|
||||
|
||||
public expiresAt:string;
|
||||
|
||||
public plan:string;
|
||||
|
||||
public additionalFeatures:string;
|
||||
|
||||
constructor(
|
||||
readonly elementRef:ElementRef,
|
||||
readonly cdRef:ChangeDetectorRef,
|
||||
readonly I18n:I18nService,
|
||||
readonly http:HttpClient,
|
||||
public eeTrialService:EnterpriseTrialService,
|
||||
) {
|
||||
super(I18n);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if (!this.subscriber) {
|
||||
void this.eeTrialService.userData$
|
||||
.pipe(
|
||||
distinctUntilChanged(),
|
||||
this.untilDestroyed(),
|
||||
)
|
||||
.subscribe((data:IEnterpriseData) => {
|
||||
this.formatUserData(data);
|
||||
this.cdRef.detectChanges();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private formatUserData(userForm:IEnterpriseData) {
|
||||
this.subscriber = `${userForm.first_name} ${userForm.last_name}`;
|
||||
this.email = userForm.email;
|
||||
this.company = userForm.company;
|
||||
this.domain = userForm.domain;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<div class="op-enterprise-base">
|
||||
<div *ngIf="noTrialRequested; else alreadyRequested">
|
||||
<p>{{ text.enterprise_edition }}</p>
|
||||
<p class="-bold">{{ text.confidence }}</p>
|
||||
<p>
|
||||
<span class="-bold">{{ text.become_hero }}</span><br>
|
||||
<span>{{ text.you_contribute }}</span>
|
||||
</p>
|
||||
<button class="button -primary" (click)="openTrialModal()">
|
||||
{{ text.button_trial }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<ng-template #alreadyRequested>
|
||||
<enterprise-trial-waiting
|
||||
[trialKey]="trialKey"
|
||||
[trialCreatedAt]="trialCreatedAt"
|
||||
></enterprise-trial-waiting>
|
||||
<p class="op-enterprise-base--confirmation-hint">{{ text.email_not_received }}
|
||||
<a (click)="openTrialModal()">{{ text.try_another_email }}</a>
|
||||
</p>
|
||||
</ng-template>
|
||||
</div>
|
||||
@@ -1,8 +0,0 @@
|
||||
.op-enterprise-base
|
||||
.button
|
||||
float: left
|
||||
|
||||
&--confirmation-hint
|
||||
font-size: 0.9em
|
||||
font-style: italic
|
||||
margin-bottom: 2rem
|
||||
@@ -1,89 +0,0 @@
|
||||
//-- copyright
|
||||
// OpenProject is an open source project management software.
|
||||
// Copyright (C) the OpenProject GmbH
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { ChangeDetectionStrategy, Component, ElementRef, Injector, Input, OnInit } from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { EnterpriseTrialModalComponent } from 'core-app/features/enterprise/enterprise-modal/enterprise-trial.modal';
|
||||
import { OpModalService } from 'core-app/shared/components/modal/modal.service';
|
||||
import { EnterpriseTrialService } from 'core-app/features/enterprise/enterprise-trial.service';
|
||||
import { populateInputsFromDataset } from 'core-app/shared/components/dataset-inputs';
|
||||
|
||||
@Component({
|
||||
// eslint-disable-next-line @angular-eslint/component-selector
|
||||
selector: 'enterprise-base',
|
||||
templateUrl: './enterprise-base.component.html',
|
||||
styleUrls: ['./enterprise-base.component.sass'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class EnterpriseBaseComponent implements OnInit {
|
||||
@Input() public trialKey:string|undefined;
|
||||
|
||||
@Input() public trialCreatedAt:string|undefined;
|
||||
|
||||
@Input() public augurUrl:string;
|
||||
|
||||
@Input() public tokenVersion:string;
|
||||
|
||||
public text = {
|
||||
button_trial: this.I18n.t('js.admin.enterprise.upsell.button_start_trial'),
|
||||
button_book: this.I18n.t('js.admin.enterprise.upsell.button_book_now'),
|
||||
link_quote: this.I18n.t('js.admin.enterprise.upsell.link_quote'),
|
||||
become_hero: this.I18n.t('js.admin.enterprise.upsell.become_hero'),
|
||||
you_contribute: this.I18n.t('js.admin.enterprise.upsell.you_contribute'),
|
||||
email_not_received: this.I18n.t('js.admin.enterprise.trial.email_not_received'),
|
||||
enterprise_edition: this.I18n.t('js.admin.enterprise.upsell.text'),
|
||||
confidence: this.I18n.t('js.admin.enterprise.upsell.confidence'),
|
||||
try_another_email: this.I18n.t('js.admin.enterprise.trial.try_another_email'),
|
||||
};
|
||||
|
||||
constructor(
|
||||
readonly elementRef:ElementRef<HTMLElement>,
|
||||
protected I18n:I18nService,
|
||||
protected opModalService:OpModalService,
|
||||
readonly injector:Injector,
|
||||
public eeTrialService:EnterpriseTrialService,
|
||||
) {
|
||||
populateInputsFromDataset(this);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.eeTrialService.baseUrlAugur = this.augurUrl;
|
||||
this.eeTrialService.tokenVersion = this.tokenVersion;
|
||||
this.eeTrialService.setTrialKey(this.trialKey);
|
||||
}
|
||||
|
||||
public openTrialModal() {
|
||||
// cancel request and open first modal window
|
||||
this.eeTrialService.store.update({ cancelled: true, modalOpen: true });
|
||||
this.opModalService.show(EnterpriseTrialModalComponent, this.injector);
|
||||
}
|
||||
|
||||
public get noTrialRequested() {
|
||||
return !this.trialKey;
|
||||
}
|
||||
}
|
||||
-100
@@ -1,100 +0,0 @@
|
||||
<form id="enterprise-trial-form" class="form" [formGroup]="trialForm">
|
||||
<div class="form--field -wide-label -required">
|
||||
<label class="form--label" for="trial-company-name">{{ text.label_company }}</label>
|
||||
<div class="form--field-container">
|
||||
<div class="form--text-field-container">
|
||||
<input type="text"
|
||||
id="trial-company-name"
|
||||
class="form--text-field"
|
||||
formControlName="company">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form--field -wide-label -required">
|
||||
<label class="form--label" for="trial-first-name">{{ text.label_first_name }}</label>
|
||||
<div class="form--field-container">
|
||||
<div class="form--text-field-container">
|
||||
<input type="text"
|
||||
id="trial-first-name"
|
||||
class="form--text-field"
|
||||
formControlName="first_name">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form--field -wide-label -required">
|
||||
<label class="form--label" for="trial-last-name">{{ text.label_last_name }}</label>
|
||||
<div class="form--field-container">
|
||||
<div class="form--text-field-container">
|
||||
<input type="text"
|
||||
id="trial-last-name"
|
||||
class="form--text-field"
|
||||
formControlName="last_name">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
*ngIf="{ emailError: (eeTrialService.emailError$ | async) } as field"
|
||||
class="form--field -wide-label -required">
|
||||
<label class="form--label" for="trial-email">{{ text.label_email }}</label>
|
||||
<div class="form--field-container">
|
||||
<div class="form--text-field-container"
|
||||
[ngClass]="{ '-required-highlighting' : field.emailError }">
|
||||
<input type="email"
|
||||
class="form--text-field"
|
||||
id="trial-email"
|
||||
formControlName="email" (blur)="checkMailField()">
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
*ngIf="field.emailError"
|
||||
[textContent]="field.emailError"
|
||||
class="form--field-instructions op-ee-trial-email-error"
|
||||
></div>
|
||||
</div>
|
||||
<div
|
||||
*ngIf="{ domainError: (eeTrialService.domainTaken$ | async) } as field"
|
||||
class="form--field -wide-label -required">
|
||||
<label class="form--label" for="trial-domain-name">{{ text.label_domain }}</label>
|
||||
<div class="form--field-container">
|
||||
<div class="form--text-field-container"
|
||||
[ngClass]="{ '-required-highlighting' : field.domainError }">
|
||||
<input type="text"
|
||||
id="trial-domain-name"
|
||||
class="form--text-field"
|
||||
formControlName="domain"
|
||||
disabled>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form--field-instructions">
|
||||
<p *ngIf="requestHost !== configuredHost" [textContent]="text.domain_mismatch"></p>
|
||||
<p *ngIf="field.domainError" [textContent]="field.domainError"></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form--field -required">
|
||||
<div class="form--field-container">
|
||||
<label class="form--label-with-check-box -no-ellipsis" for="trial-general-consent">
|
||||
<div class="form--check-box-container">
|
||||
<input type="checkbox"
|
||||
id="trial-general-consent"
|
||||
class="form--check-box"
|
||||
formControlName="general_consent"
|
||||
required>
|
||||
</div>
|
||||
<span [innerHTML]="text.general_consent"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form--field">
|
||||
<div class="form--field-container">
|
||||
<label class="form--label-with-check-box -no-ellipsis" for="trial-newsletter-consent">
|
||||
<div class="form--check-box-container">
|
||||
<input type="checkbox"
|
||||
id="trial-newsletter-consent"
|
||||
class="form--check-box"
|
||||
formControlName="newsletter_consent">
|
||||
</div>
|
||||
<span [innerHtml]="text.receive_newsletter"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
.op-ee-trial-email-error
|
||||
width: min-content
|
||||
-117
@@ -1,117 +0,0 @@
|
||||
//-- copyright
|
||||
// OpenProject is an open source project management software.
|
||||
// Copyright (C) the OpenProject GmbH
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
ElementRef,
|
||||
} from '@angular/core';
|
||||
import {
|
||||
UntypedFormBuilder,
|
||||
Validators,
|
||||
} from '@angular/forms';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { EnterpriseTrialService } from 'core-app/features/enterprise/enterprise-trial.service';
|
||||
import { CurrentUserService } from 'core-app/core/current-user/current-user.service';
|
||||
import { localizeLink } from 'core-app/shared/helpers/i18n/localized-link';
|
||||
import { ConfigurationService } from 'core-app/core/config/configuration.service';
|
||||
import { IEnterpriseData } from 'core-app/features/enterprise/enterprise-trial.model';
|
||||
|
||||
const newsletterURL = 'https://www.openproject.org/newsletter/';
|
||||
|
||||
@Component({
|
||||
selector: 'enterprise-trial-form',
|
||||
templateUrl: './ee-trial-form.component.html',
|
||||
styleUrls: ['./ee-trial-form.component.sass'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class EETrialFormComponent {
|
||||
// Retain used values
|
||||
userData:Partial<IEnterpriseData> = this.eeTrialService.current.data || {};
|
||||
|
||||
// The current request host
|
||||
requestHost = window.location.host;
|
||||
|
||||
// The configured host name
|
||||
configuredHost = this.configurationService.hostName;
|
||||
|
||||
trialForm = this.formBuilder.group({
|
||||
company: [this.userData.company, Validators.required],
|
||||
first_name: [this.userData.first_name, Validators.required],
|
||||
last_name: [this.userData.last_name, Validators.required],
|
||||
email: ['', [Validators.required, Validators.email]],
|
||||
domain: [this.userData.domain || this.configuredHost, Validators.required],
|
||||
general_consent: [null, Validators.required],
|
||||
newsletter_consent: null,
|
||||
language: this.currentUserService.language,
|
||||
});
|
||||
|
||||
public text = {
|
||||
general_consent: this.I18n.t('js.admin.enterprise.trial.form.general_consent', {
|
||||
link_terms: localizeLink({
|
||||
en: 'https://www.openproject.org/terms-of-service/',
|
||||
de: 'https://www.openproject.org/de/nutzungsbedingungen/',
|
||||
}),
|
||||
link_privacy: localizeLink({
|
||||
en: 'https://www.openproject.org/data-privacy-and-security/',
|
||||
de: 'https://www.openproject.org/de/datenschutz/',
|
||||
}),
|
||||
}),
|
||||
label_test_ee: this.I18n.t('js.admin.enterprise.trial.form.test_ee'),
|
||||
label_company: this.I18n.t('js.admin.enterprise.trial.form.label_company'),
|
||||
label_first_name: this.I18n.t('js.admin.enterprise.trial.form.label_first_name'),
|
||||
label_last_name: this.I18n.t('js.admin.enterprise.trial.form.label_last_name'),
|
||||
label_email: this.I18n.t('js.label_email'),
|
||||
label_domain: this.I18n.t('js.admin.enterprise.trial.form.label_domain'),
|
||||
domain_mismatch: this.I18n.t('js.admin.enterprise.trial.form.domain_mismatch'),
|
||||
privacy_policy: this.I18n.t('js.admin.enterprise.trial.form.privacy_policy'),
|
||||
receive_newsletter: this.I18n.t('js.admin.enterprise.trial.form.receive_newsletter', { link: newsletterURL }),
|
||||
terms_of_service: this.I18n.t('js.admin.enterprise.trial.form.terms_of_service'),
|
||||
};
|
||||
|
||||
constructor(
|
||||
readonly elementRef:ElementRef,
|
||||
readonly I18n:I18nService,
|
||||
readonly formBuilder:UntypedFormBuilder,
|
||||
readonly currentUserService:CurrentUserService,
|
||||
readonly configurationService:ConfigurationService,
|
||||
readonly eeTrialService:EnterpriseTrialService,
|
||||
) {
|
||||
}
|
||||
|
||||
// checks if mail is valid after input field was edited by the user
|
||||
// displays message for user
|
||||
public checkMailField():void {
|
||||
const data = this.trialForm.value as IEnterpriseData;
|
||||
if (data.email !== '' && this.trialForm.controls.email.errors) {
|
||||
this.eeTrialService.store.update({ emailInvalid: true });
|
||||
} else {
|
||||
this.eeTrialService.store.update({ emailInvalid: false, error: undefined });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
<div class="spot-modal op-enterprise-modal">
|
||||
<div id="spotModalTitle" class="spot-modal--header" [textContent]="headerText$ | async"></div>
|
||||
|
||||
<div class="spot-divider"></div>
|
||||
|
||||
<div [ngSwitch]="showState$ | async" class="spot-modal--body spot-container">
|
||||
<!-- first modal window -->
|
||||
<div *ngSwitchCase="'trial-form'">
|
||||
<enterprise-trial-form></enterprise-trial-form>
|
||||
</div>
|
||||
<!-- second modal window -->
|
||||
<div *ngSwitchCase="'trial-waiting'">
|
||||
<enterprise-trial-waiting></enterprise-trial-waiting>
|
||||
</div>
|
||||
<!-- third modal window -->
|
||||
<div *ngSwitchCase="'overview'">
|
||||
<div class="onboarding--video-block">
|
||||
<div class="onboarding--video-text">
|
||||
<span>{{ text.quick_overview }}</span>
|
||||
</div>
|
||||
<div class="onboarding--video iframe-target-wrapper">
|
||||
<iframe frameborder="0"
|
||||
height="400"
|
||||
width="100%"
|
||||
[src]="trustedEEVideoURL"
|
||||
allowfullscreen>
|
||||
</iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="spot-action-bar"
|
||||
*ngIf="{ status: eeTrialService.status$ | async, cancelled: eeTrialService.cancelled$ | async, confirmed: eeTrialService.confirmed$ | async } as context"
|
||||
>
|
||||
<div class="spot-action-bar--right">
|
||||
<div *ngIf="!context.status || context.cancelled; else mailSubmitted"
|
||||
class="spot-action-bar--right">
|
||||
<button
|
||||
class="button button_no-margin spot-action-bar--action spot-modal--cancel-button"
|
||||
data-test-selector="confirmation-modal--cancel"
|
||||
(click)="closeModal($event)"
|
||||
[textContent]="text.button_cancel"
|
||||
[attr.title]="text.button_cancel"
|
||||
></button>
|
||||
<button
|
||||
class="button button_no-margin -primary spot-action-bar--action"
|
||||
data-test-selector="confirmation-modal--confirmed"
|
||||
(click)="onSubmit()"
|
||||
[disabled]="!trialForm || trialForm.invalid"
|
||||
[textContent]="text.button_submit"
|
||||
[attr.title]="text.button_submit"
|
||||
[hidden]="context.status === 'mailSubmitted' && !context.cancelled"
|
||||
></button>
|
||||
</div>
|
||||
<ng-template #mailSubmitted>
|
||||
<div class="spot-action-bar--right">
|
||||
<button
|
||||
class="button button_no-margin -primary spot-action-bar--action"
|
||||
data-test-selector="confirmation-modal--confirmed"
|
||||
(click)="startEnterpriseTrial()"
|
||||
[textContent]="text.button_continue"
|
||||
[attr.title]="text.button_continue"
|
||||
[disabled]="!context.confirmed"
|
||||
[hidden]="context.status === 'startTrial'"
|
||||
></button>
|
||||
<button
|
||||
*ngIf="context.status === 'startTrial'"
|
||||
class="button button_no-margin -primary spot-action-bar--action"
|
||||
data-test-selector="confirmation-modal--confirmed"
|
||||
(click)="closeModal($event)"
|
||||
[textContent]="text.button_continue"
|
||||
[attr.title]="text.button_continue"
|
||||
></button>
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,3 +0,0 @@
|
||||
.op-enterprise-modal
|
||||
.onboarding--video-text
|
||||
margin-bottom: 1.25rem
|
||||
@@ -1,156 +0,0 @@
|
||||
//-- copyright
|
||||
// OpenProject is an open source project management software.
|
||||
// Copyright (C) the OpenProject GmbH
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import {
|
||||
AfterViewInit,
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
ElementRef,
|
||||
Inject,
|
||||
Input,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
|
||||
import { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||
import { OpModalComponent } from 'core-app/shared/components/modal/modal.component';
|
||||
import { OpModalLocalsToken } from 'core-app/shared/components/modal/modal.service';
|
||||
import { OpModalLocalsMap } from 'core-app/shared/components/modal/modal.types';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { EETrialFormComponent } from 'core-app/features/enterprise/enterprise-modal/enterprise-trial-form/ee-trial-form.component';
|
||||
import { EnterpriseTrialService } from 'core-app/features/enterprise/enterprise-trial.service';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
export const eeOnboardingVideoURL = 'https://www.youtube.com/embed/zLMSydhFSkw?autoplay=1';
|
||||
|
||||
@Component({
|
||||
selector: 'enterprise-trial-modal',
|
||||
templateUrl: './enterprise-trial.modal.html',
|
||||
styleUrls: ['./enterprise-trial.modal.sass'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class EnterpriseTrialModalComponent extends OpModalComponent implements AfterViewInit {
|
||||
@ViewChild(EETrialFormComponent, { static: false }) formComponent:EETrialFormComponent;
|
||||
|
||||
@Input() public opReferrer:string;
|
||||
|
||||
public trialForm:UntypedFormGroup;
|
||||
|
||||
public trustedEEVideoURL:SafeResourceUrl;
|
||||
|
||||
public text = {
|
||||
button_submit: this.I18n.t('js.modals.button_submit'),
|
||||
button_cancel: this.I18n.t('js.modals.button_cancel'),
|
||||
button_continue: this.I18n.t('js.button_continue'),
|
||||
close_popup: this.I18n.t('js.close_popup_title'),
|
||||
heading_confirmation: this.I18n.t('js.admin.enterprise.trial.confirmation'),
|
||||
heading_next_steps: this.I18n.t('js.admin.enterprise.trial.next_steps'),
|
||||
heading_test_ee: this.I18n.t('js.admin.enterprise.trial.test_ee'),
|
||||
quick_overview: this.I18n.t('js.admin.enterprise.trial.quick_overview'),
|
||||
};
|
||||
|
||||
headerText$:Observable<string> = this
|
||||
.eeTrialService
|
||||
.observe$
|
||||
.pipe(
|
||||
map(({ status }) => {
|
||||
if (status === 'mailSubmitted') {
|
||||
return this.text.heading_confirmation;
|
||||
}
|
||||
|
||||
if (status === 'startTrial') {
|
||||
return this.text.heading_next_steps;
|
||||
}
|
||||
|
||||
return this.text.heading_test_ee;
|
||||
}),
|
||||
);
|
||||
|
||||
showState$ = this
|
||||
.eeTrialService
|
||||
.observe$
|
||||
.pipe(
|
||||
map(({ status, cancelled }) => {
|
||||
if (!status || cancelled) {
|
||||
return 'trial-form';
|
||||
}
|
||||
if (status === 'mailSubmitted' && !cancelled) {
|
||||
return 'trial-waiting';
|
||||
}
|
||||
|
||||
return 'overview';
|
||||
}),
|
||||
);
|
||||
|
||||
constructor(readonly elementRef:ElementRef,
|
||||
@Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,
|
||||
readonly cdRef:ChangeDetectorRef,
|
||||
readonly I18n:I18nService,
|
||||
readonly domSanitizer:DomSanitizer,
|
||||
public eeTrialService:EnterpriseTrialService) {
|
||||
super(locals, cdRef, elementRef);
|
||||
this.trustedEEVideoURL = this.trustedURL(eeOnboardingVideoURL);
|
||||
}
|
||||
|
||||
ngAfterViewInit():void {
|
||||
this.trialForm = this.formComponent.trialForm;
|
||||
}
|
||||
|
||||
// checks if form is valid and submits it
|
||||
public onSubmit():void {
|
||||
if (this.trialForm.valid) {
|
||||
this.trialForm.addControl('_type', new UntypedFormControl('enterprise-trial'));
|
||||
void this.eeTrialService.sendForm(this.trialForm);
|
||||
}
|
||||
}
|
||||
|
||||
public startEnterpriseTrial():void {
|
||||
// open onboarding modal screen
|
||||
this.eeTrialService.setStartTrialStatus();
|
||||
}
|
||||
|
||||
public closeModal(event:Event):void {
|
||||
this.closeMe(event);
|
||||
|
||||
const { status, confirmed } = this.eeTrialService.current;
|
||||
// refresh page to show enterprise trial
|
||||
if (status === 'startTrial' || confirmed) {
|
||||
window.location.reload();
|
||||
} else if (status === 'mailSubmitted') {
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
this.eeTrialService.store.update({ modalOpen: false });
|
||||
}
|
||||
|
||||
public trustedURL(url:string):SafeResourceUrl {
|
||||
return this.domSanitizer.bypassSecurityTrustResourceUrl(url);
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
<div
|
||||
class="op-ee-trial-waiting"
|
||||
*ngIf="{ confirmed: (eeTrialService.confirmed$ | async), cancelled: (eeTrialService.cancelled$ | async) } as context"
|
||||
>
|
||||
<enterprise-active-trial></enterprise-active-trial>
|
||||
|
||||
<p>{{ text.confirmation_info(created, email) }}</p>
|
||||
<p>
|
||||
<span>{{ text.status_label }} </span>
|
||||
<span *ngIf="!context.confirmed; else confirmedStatus" class="op-ee-trial-waiting-status--waiting"
|
||||
data-test-selector="op-ee-trial-waiting-status--waiting">
|
||||
{{ text.status_waiting }}
|
||||
|
||||
<!-- <a id="op-ee-trial-waiting-resend-link"
|
||||
data-test-selector='op-ee-trial-waiting-resend-link' (click)="resendMail()">{{ text.resend }}</a> -->
|
||||
<button
|
||||
*ngIf="resendLink$ | async"
|
||||
class="spot-link op-ee-trial-waiting-resend-link"
|
||||
data-test-selector='op-ee-trial-waiting-resend-link'
|
||||
(click)="resendMail()">
|
||||
{{ text.resend }}</button>
|
||||
</span>
|
||||
<span *ngIf="context.cancelled">{{ text.session_timeout }}</span>
|
||||
|
||||
<ng-template #confirmedStatus>
|
||||
<span
|
||||
class="op-ee-trial-waiting-status--confirmed icon-yes"
|
||||
data-test-selector="op-ee-trial-waiting-status--confirmed"> {{ text.status_confirmed }}
|
||||
</span>
|
||||
</ng-template>
|
||||
</p>
|
||||
</div>
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
.op-ee-trial-waiting
|
||||
|
||||
&-status--confirmed
|
||||
color: var(--button--primary-background-color)
|
||||
&-status--waiting
|
||||
color: orange
|
||||
-130
@@ -1,130 +0,0 @@
|
||||
//-- copyright
|
||||
// OpenProject is an open source project management software.
|
||||
// Copyright (C) the OpenProject GmbH
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import {
|
||||
Component,
|
||||
ElementRef, Input,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { EnterpriseTrialService } from 'core-app/features/enterprise/enterprise-trial.service';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { ToastService } from 'core-app/shared/components/toaster/toast.service';
|
||||
import { distinctUntilChanged } from 'rxjs/operators';
|
||||
import { TimezoneService } from 'core-app/core/datetime/timezone.service';
|
||||
import { EXTERNAL_REQUEST_HEADER } from 'core-app/features/hal/http/openproject-header-interceptor';
|
||||
import { IEnterpriseData } from 'core-app/features/enterprise/enterprise-trial.model';
|
||||
|
||||
@Component({
|
||||
selector: 'enterprise-trial-waiting',
|
||||
templateUrl: './ee-trial-waiting.component.html',
|
||||
styleUrls: ['./ee-trial-waiting.component.sass'],
|
||||
})
|
||||
export class EETrialWaitingComponent implements OnInit {
|
||||
@Input() public trialKey:string|undefined;
|
||||
|
||||
@Input() public trialCreatedAt:string|undefined;
|
||||
|
||||
created = this.timezoneService.formattedDate(new Date().toString());
|
||||
|
||||
resendLink$ = this.eeTrialService.resendLink$;
|
||||
|
||||
email = '';
|
||||
|
||||
public text = {
|
||||
confirmation_info: (date:string, email:string) => this.I18n.t('js.admin.enterprise.trial.confirmation_info', {
|
||||
date,
|
||||
email,
|
||||
}),
|
||||
resend: this.I18n.t('js.admin.enterprise.trial.resend_link'),
|
||||
resend_success: this.I18n.t('js.admin.enterprise.trial.resend_success'),
|
||||
resend_warning: this.I18n.t('js.admin.enterprise.trial.resend_warning'),
|
||||
session_timeout: this.I18n.t('js.admin.enterprise.trial.session_timeout'),
|
||||
status_confirmed: this.I18n.t('js.admin.enterprise.trial.status_confirmed'),
|
||||
status_label: this.I18n.t('js.admin.enterprise.trial.status_label'),
|
||||
status_waiting: this.I18n.t('js.admin.enterprise.trial.status_waiting'),
|
||||
};
|
||||
|
||||
constructor(
|
||||
readonly elementRef:ElementRef,
|
||||
readonly I18n:I18nService,
|
||||
protected http:HttpClient,
|
||||
protected toastService:ToastService,
|
||||
public eeTrialService:EnterpriseTrialService,
|
||||
readonly timezoneService:TimezoneService) {
|
||||
}
|
||||
|
||||
ngOnInit():void {
|
||||
if (this.trialCreatedAt) {
|
||||
this.created = this.timezoneService.formattedDate(this.trialCreatedAt);
|
||||
}
|
||||
|
||||
this.eeTrialService
|
||||
.userData$
|
||||
.pipe(
|
||||
distinctUntilChanged(),
|
||||
)
|
||||
.subscribe((data:IEnterpriseData) => {
|
||||
this.email = data.email;
|
||||
});
|
||||
}
|
||||
|
||||
// resend mail if resend link has been clicked
|
||||
public resendMail():void {
|
||||
const { resendLink } = this.eeTrialService.store.getValue();
|
||||
|
||||
if (!resendLink) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.eeTrialService.store.update({ cancelled: false });
|
||||
this.http.post(
|
||||
resendLink,
|
||||
{},
|
||||
{
|
||||
headers: {
|
||||
[EXTERNAL_REQUEST_HEADER]: 'true',
|
||||
},
|
||||
},
|
||||
)
|
||||
.toPromise()
|
||||
.then(() => {
|
||||
this.toastService.addSuccess(this.text.resend_success);
|
||||
this.eeTrialService.retryConfirmation();
|
||||
})
|
||||
.catch(() => {
|
||||
const { trialLink } = this.eeTrialService.store.getValue();
|
||||
if (trialLink) {
|
||||
// Check whether the mail has been confirmed by now
|
||||
this.eeTrialService.getToken();
|
||||
} else {
|
||||
this.toastService.addError(this.text.resend_warning);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import {
|
||||
IHalOptionalTitledLink,
|
||||
IHalResourceLinks,
|
||||
} from 'core-app/core/state/hal-resource';
|
||||
|
||||
export interface IEnterpriseData {
|
||||
id?:string;
|
||||
company:string;
|
||||
first_name:string;
|
||||
last_name:string;
|
||||
email:string;
|
||||
domain:string;
|
||||
general_consent?:boolean;
|
||||
newsletter_consent?:boolean;
|
||||
}
|
||||
|
||||
export interface IEnterpriseTrial {
|
||||
trialLink?:string;
|
||||
resendLink?:string;
|
||||
modalOpen:boolean;
|
||||
confirmed:boolean;
|
||||
cancelled:boolean;
|
||||
status?:'mailSubmitted'|'startTrial';
|
||||
error?:HttpErrorResponse;
|
||||
emailInvalid:boolean;
|
||||
|
||||
data?:IEnterpriseData;
|
||||
}
|
||||
|
||||
export interface EnterpriseTrialHalResource {
|
||||
_links:IHalResourceLinks;
|
||||
}
|
||||
|
||||
export interface EnterpriseTrialErrorHalResource {
|
||||
identifier:string;
|
||||
message?:string;
|
||||
description?:string;
|
||||
_links:{
|
||||
self:IHalOptionalTitledLink;
|
||||
resend:IHalOptionalTitledLink;
|
||||
};
|
||||
}
|
||||
@@ -1,320 +0,0 @@
|
||||
//-- copyright
|
||||
// OpenProject is an open source project management software.
|
||||
// Copyright (C) the OpenProject GmbH
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { UntypedFormGroup } from '@angular/forms';
|
||||
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
|
||||
import { Query } from '@datorama/akita';
|
||||
import { filter, map, shareReplay } from 'rxjs/operators';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { PathHelperService } from 'core-app/core/path-helper/path-helper.service';
|
||||
import { ToastService } from 'core-app/shared/components/toaster/toast.service';
|
||||
import { EXTERNAL_REQUEST_HEADER } from 'core-app/features/hal/http/openproject-header-interceptor';
|
||||
import { EnterpriseTrialStore } from 'core-app/features/enterprise/enterprise-trial.store';
|
||||
import {
|
||||
EnterpriseTrialErrorHalResource,
|
||||
EnterpriseTrialHalResource,
|
||||
IEnterpriseData,
|
||||
IEnterpriseTrial,
|
||||
} from 'core-app/features/enterprise/enterprise-trial.model';
|
||||
import isDefinedEntity from 'core-app/core/state/is-defined-entity';
|
||||
|
||||
@Injectable()
|
||||
export class EnterpriseTrialService {
|
||||
readonly store = new EnterpriseTrialStore();
|
||||
|
||||
private query = new Query(this.store);
|
||||
|
||||
resendLink$ = this.query.select('resendLink');
|
||||
|
||||
confirmed$ = this.query.select('confirmed');
|
||||
|
||||
cancelled$ = this.query.select('cancelled');
|
||||
|
||||
status$ = this.query.select('status');
|
||||
|
||||
observe$ = this.query.select();
|
||||
|
||||
userData$ = this.query
|
||||
.select('data')
|
||||
.pipe(filter(isDefinedEntity));
|
||||
|
||||
emailError$ = this
|
||||
.query
|
||||
.select()
|
||||
.pipe(
|
||||
map(({ error, emailInvalid }) => {
|
||||
if (emailInvalid) {
|
||||
return this.text.invalid_email;
|
||||
}
|
||||
|
||||
const errorResponse = error?.error as { identifier?:string };
|
||||
if (error && errorResponse.identifier === 'user_already_created_trial') {
|
||||
return this.text.taken_email;
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
shareReplay(1),
|
||||
);
|
||||
|
||||
domainTaken$ = this
|
||||
.query
|
||||
.select()
|
||||
.pipe(
|
||||
map(({ error }) => {
|
||||
const errorResponse = error?.error as { identifier?:string };
|
||||
if (error && errorResponse.identifier === 'domain_taken') {
|
||||
return this.text.taken_domain;
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
shareReplay(1),
|
||||
);
|
||||
|
||||
public baseUrlAugur:string;
|
||||
|
||||
public tokenVersion:string;
|
||||
|
||||
public trialKey:string|undefined;
|
||||
|
||||
public text = {
|
||||
invalid_email: this.I18n.t('js.admin.enterprise.trial.form.invalid_email'),
|
||||
taken_email: this.I18n.t('js.admin.enterprise.trial.form.taken_email'),
|
||||
taken_domain: this.I18n.t('js.admin.enterprise.trial.form.taken_domain'),
|
||||
};
|
||||
|
||||
constructor(
|
||||
readonly I18n:I18nService,
|
||||
protected http:HttpClient,
|
||||
readonly pathHelper:PathHelperService,
|
||||
protected toastService:ToastService,
|
||||
) {
|
||||
}
|
||||
|
||||
public setTrialKey(trialKey:string|undefined):void {
|
||||
this.trialKey = trialKey;
|
||||
|
||||
if (this.trialKey) {
|
||||
const trialLink = `${this.baseUrlAugur}/public/v1/trials/${this.trialKey}`;
|
||||
this.store.update({ trialLink });
|
||||
this.getUserDataFromAugur(trialLink);
|
||||
this.setMailSubmittedStatus();
|
||||
}
|
||||
}
|
||||
|
||||
// send POST request with form object
|
||||
// receive an enterprise trial link to access a token
|
||||
public sendForm(form:UntypedFormGroup):Promise<unknown> {
|
||||
const request:unknown = { ...form.value, token_version: this.tokenVersion };
|
||||
return this.http
|
||||
.post(
|
||||
`${this.baseUrlAugur}/public/v1/trials`,
|
||||
request,
|
||||
{
|
||||
headers: {
|
||||
[EXTERNAL_REQUEST_HEADER]: 'true',
|
||||
},
|
||||
},
|
||||
)
|
||||
.toPromise()
|
||||
.then((enterpriseTrial:EnterpriseTrialHalResource) => {
|
||||
const trialLink = enterpriseTrial._links.self.href;
|
||||
const data = form.value as IEnterpriseData;
|
||||
|
||||
this.store.update({
|
||||
trialLink,
|
||||
data,
|
||||
cancelled: false,
|
||||
});
|
||||
|
||||
void this.saveTrialKey(trialLink);
|
||||
this.retryConfirmation();
|
||||
})
|
||||
.catch((error:HttpErrorResponse) => {
|
||||
// mail is invalid or user already created a trial
|
||||
if (error.status === 422 || error.status === 400) {
|
||||
this.store.update({ error });
|
||||
} else {
|
||||
const description = (error.error as { description?:string }).description;
|
||||
this.toastService.addWarning(description || I18n.t('js.error.internal'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// use the trial key saved in the db
|
||||
// to get the user data from Augur
|
||||
public getUserDataFromAugur(trialLink:string) {
|
||||
this
|
||||
.http
|
||||
.get(
|
||||
`${trialLink}/details`,
|
||||
{
|
||||
headers: {
|
||||
[EXTERNAL_REQUEST_HEADER]: 'true',
|
||||
},
|
||||
},
|
||||
)
|
||||
.toPromise()
|
||||
.then((data:IEnterpriseData) => {
|
||||
this.store.update({ data });
|
||||
this.retryConfirmation();
|
||||
})
|
||||
.catch(() => {
|
||||
// Check whether the mail has been confirmed by now
|
||||
this.getToken();
|
||||
});
|
||||
}
|
||||
|
||||
// get a token from the trial link if user confirmed mail
|
||||
public getToken():void {
|
||||
// 2) GET /public/v1/trials/:id
|
||||
this.http.get(
|
||||
this.store.getValue().trialLink as string,
|
||||
{
|
||||
headers: {
|
||||
[EXTERNAL_REQUEST_HEADER]: 'true',
|
||||
},
|
||||
},
|
||||
)
|
||||
.toPromise()
|
||||
.then(async (res:{ token_retrieved?:boolean, token:string }) => {
|
||||
// show confirmed status and enable continue btn
|
||||
this.store.update({ confirmed: true });
|
||||
|
||||
// returns token if mail was confirmed
|
||||
// -> if token is new (token_retrieved: false) save token in backend
|
||||
if (!res.token_retrieved) {
|
||||
await this.saveToken(res.token);
|
||||
}
|
||||
})
|
||||
.catch((error:HttpErrorResponse) => {
|
||||
const errorResponse = error.error as EnterpriseTrialErrorHalResource;
|
||||
// returns error 422 while waiting of confirmation
|
||||
if (error.status === 422 && errorResponse.identifier === 'waiting_for_email_verification') {
|
||||
// get resend button link
|
||||
const resendLink = errorResponse._links.resend.href;
|
||||
this.store.update({ resendLink });
|
||||
|
||||
const { status, cancelled } = this.store.getValue();
|
||||
|
||||
// save a key for the requested trial
|
||||
if (!status || cancelled) { // only do it once
|
||||
void this.saveTrialKey(resendLink);
|
||||
}
|
||||
// open next modal window -> status waiting
|
||||
this.setMailSubmittedStatus();
|
||||
this.store.update({ confirmed: false });
|
||||
} else if (errorResponse?.message) {
|
||||
this.toastService.addError(errorResponse.message);
|
||||
} else {
|
||||
this.toastService.addError(String(error.error) || I18n.t('js.error.internal'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// save a part of the resend link in db
|
||||
// which allows to remember if a user has already requested a trial token
|
||||
// and to ask for the corresponding user data saved in Augur
|
||||
private saveTrialKey(resendlink:string):Promise<unknown> {
|
||||
// extract token from resend link
|
||||
const trialKey = resendlink.split('/')[6];
|
||||
return this.http.post(
|
||||
`${this.pathHelper.appBasePath}/admin/enterprise_tokens/save_trial_key`,
|
||||
{ trial_key: trialKey },
|
||||
{ withCredentials: true },
|
||||
)
|
||||
.toPromise()
|
||||
.catch((e:HttpErrorResponse) => {
|
||||
const errorResponse = e.error as EnterpriseTrialErrorHalResource;
|
||||
this.toastService.addError(errorResponse.message || e.message || e);
|
||||
});
|
||||
}
|
||||
|
||||
// save received token in controller
|
||||
private saveToken(token:string) {
|
||||
return this.http.post(
|
||||
`${this.pathHelper.appBasePath}/admin/enterprise_tokens`,
|
||||
{ enterprise_token: { encoded_token: token } },
|
||||
{ withCredentials: true },
|
||||
)
|
||||
.toPromise()
|
||||
.then(() => {
|
||||
const { modalOpen } = this.store.getValue();
|
||||
// load page if mail was confirmed and modal window is not open
|
||||
if (!modalOpen) {
|
||||
setTimeout(() => { // display confirmed status before reloading
|
||||
window.location.reload();
|
||||
}, 500);
|
||||
}
|
||||
})
|
||||
.catch((error:HttpErrorResponse) => {
|
||||
// Delete the trial key as the token could not be saved and thus something is wrong with the token.
|
||||
// Without this deletion, we run into an endless loop of an confirmed mail, but no saved token.
|
||||
void this.http
|
||||
.delete(
|
||||
`${this.pathHelper.api.v3.apiV3Base}/admin/enterprise_tokens/delete_trial_key`,
|
||||
{ withCredentials: true },
|
||||
)
|
||||
.toPromise();
|
||||
|
||||
const errorResponse = error.error as EnterpriseTrialErrorHalResource;
|
||||
this.toastService.addError(errorResponse.description || I18n.t('js.error.internal'));
|
||||
});
|
||||
}
|
||||
|
||||
// retry request while waiting for mail confirmation
|
||||
public retryConfirmation(delay = 5000, retries = 60):void {
|
||||
const { cancelled, confirmed } = this.store.getValue();
|
||||
|
||||
if (cancelled || confirmed) {
|
||||
// no need to retry
|
||||
return;
|
||||
}
|
||||
|
||||
if (retries === 0) {
|
||||
this.store.update({ cancelled: true });
|
||||
} else {
|
||||
this.getToken();
|
||||
setTimeout(() => {
|
||||
this.retryConfirmation(delay, retries - 1);
|
||||
}, delay);
|
||||
}
|
||||
}
|
||||
|
||||
public setStartTrialStatus():void {
|
||||
this.store.update({ status: 'startTrial' });
|
||||
}
|
||||
|
||||
public setMailSubmittedStatus():void {
|
||||
this.store.update({ status: 'mailSubmitted' });
|
||||
}
|
||||
|
||||
public get current():IEnterpriseTrial {
|
||||
return this.store.getValue();
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import {
|
||||
Store,
|
||||
StoreConfig,
|
||||
} from '@datorama/akita';
|
||||
import { IEnterpriseTrial } from 'core-app/features/enterprise/enterprise-trial.model';
|
||||
|
||||
export function createInitialState():IEnterpriseTrial {
|
||||
return {
|
||||
modalOpen: false,
|
||||
confirmed: false,
|
||||
cancelled: false,
|
||||
emailInvalid: false,
|
||||
};
|
||||
}
|
||||
|
||||
@StoreConfig({ name: 'enterprise-trial' })
|
||||
export class EnterpriseTrialStore extends Store<IEnterpriseTrial> {
|
||||
constructor() {
|
||||
super(createInitialState());
|
||||
}
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
<div
|
||||
[attr.data-tooltip]="trialRequested ? text.confirmation_info(created, email) : ''"
|
||||
[ngClass]="{'tooltip--right': trialRequested}">
|
||||
<button
|
||||
type="button"
|
||||
[disabled]="trialRequested"
|
||||
class="Button--secondary Button--medium Button"
|
||||
(click)="openTrialModal()"
|
||||
>
|
||||
{{ text.button_trial }}
|
||||
</button>
|
||||
</div>
|
||||
-122
@@ -1,122 +0,0 @@
|
||||
//-- copyright
|
||||
// OpenProject is an open source project management software.
|
||||
// Copyright (C) the OpenProject GmbH
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
ElementRef,
|
||||
Injector,
|
||||
Input,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { EnterpriseTrialModalComponent } from 'core-app/features/enterprise/enterprise-modal/enterprise-trial.modal';
|
||||
import { OpModalService } from 'core-app/shared/components/modal/modal.service';
|
||||
import { EnterpriseTrialService } from 'core-app/features/enterprise/enterprise-trial.service';
|
||||
import { TimezoneService } from 'core-app/core/datetime/timezone.service';
|
||||
import { distinctUntilChanged } from 'rxjs/operators';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { GonService } from 'core-app/core/gon/gon.service';
|
||||
import { IEnterpriseData } from 'core-app/features/enterprise/enterprise-trial.model';
|
||||
import { populateInputsFromDataset } from 'core-app/shared/components/dataset-inputs';
|
||||
|
||||
@Component({
|
||||
selector: 'opce-free-trial-button',
|
||||
templateUrl: './free-trial-button.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class FreeTrialButtonComponent implements OnInit {
|
||||
@Input() public trialKey:string|undefined;
|
||||
|
||||
@Input() public trialCreatedAt:string|undefined;
|
||||
|
||||
@Input() public augurUrl:string;
|
||||
|
||||
@Input() public tokenVersion:string;
|
||||
|
||||
created = this.timezoneService.formattedDate(new Date().toString());
|
||||
|
||||
email = '';
|
||||
|
||||
public text = {
|
||||
button_trial: this.I18n.t('js.admin.enterprise.upsell.button_start_trial'),
|
||||
confirmation_info: (date:string, email:string):string => this.I18n.t('js.admin.enterprise.trial.confirmation_info', {
|
||||
date,
|
||||
email,
|
||||
}),
|
||||
};
|
||||
|
||||
constructor(
|
||||
readonly elementRef:ElementRef<HTMLElement>,
|
||||
protected I18n:I18nService,
|
||||
protected opModalService:OpModalService,
|
||||
readonly injector:Injector,
|
||||
readonly http:HttpClient,
|
||||
readonly cdRef:ChangeDetectorRef,
|
||||
readonly Gon:GonService,
|
||||
public eeTrialService:EnterpriseTrialService,
|
||||
readonly timezoneService:TimezoneService,
|
||||
) {
|
||||
populateInputsFromDataset(this);
|
||||
}
|
||||
|
||||
ngOnInit():void {
|
||||
this.eeTrialService.baseUrlAugur = this.augurUrl;
|
||||
this.eeTrialService.tokenVersion = this.tokenVersion;
|
||||
this.eeTrialService.setTrialKey(this.trialKey);
|
||||
|
||||
this.eeTrialService
|
||||
.userData$
|
||||
.pipe(
|
||||
distinctUntilChanged(),
|
||||
)
|
||||
.subscribe((userForm:IEnterpriseData) => {
|
||||
this.email = userForm.email;
|
||||
this.cdRef.detectChanges();
|
||||
});
|
||||
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
private initialize():void {
|
||||
if (this.trialCreatedAt) {
|
||||
this.created = this.timezoneService.formattedDate(this.trialCreatedAt);
|
||||
}
|
||||
}
|
||||
|
||||
public openTrialModal():void {
|
||||
// cancel request and open first modal window
|
||||
this.eeTrialService.store.update({ cancelled: true, modalOpen: true });
|
||||
this.opModalService.show(EnterpriseTrialModalComponent, this.injector);
|
||||
}
|
||||
|
||||
public get trialRequested():boolean {
|
||||
return !!this.trialKey;
|
||||
}
|
||||
}
|
||||
@@ -29,36 +29,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { OpSharedModule } from 'core-app/shared/shared.module';
|
||||
import { OpenprojectModalModule } from 'core-app/shared/components/modal/modal.module';
|
||||
import { EnterpriseTrialService } from 'core-app/features/enterprise/enterprise-trial.service';
|
||||
import { EnterpriseBaseComponent } from 'core-app/features/enterprise/enterprise-base.component';
|
||||
import { EnterpriseTrialModalComponent } from 'core-app/features/enterprise/enterprise-modal/enterprise-trial.modal';
|
||||
import { EETrialFormComponent } from 'core-app/features/enterprise/enterprise-modal/enterprise-trial-form/ee-trial-form.component';
|
||||
import { EETrialWaitingComponent } from 'core-app/features/enterprise/enterprise-trial-waiting/ee-trial-waiting.component';
|
||||
import { EEActiveTrialComponent } from 'core-app/features/enterprise/enterprise-active-trial/ee-active-trial.component';
|
||||
import { EEActiveSavedTrialComponent } from 'core-app/features/enterprise/enterprise-active-trial/ee-active-saved-trial.component';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { EnterpriseBannerFrameComponent } from 'core-app/features/enterprise/enterprise-banner-frame.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
OpSharedModule,
|
||||
OpenprojectModalModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
],
|
||||
providers: [
|
||||
EnterpriseTrialService,
|
||||
],
|
||||
exports: [
|
||||
EnterpriseBannerFrameComponent,
|
||||
],
|
||||
declarations: [
|
||||
EnterpriseBaseComponent,
|
||||
EnterpriseTrialModalComponent,
|
||||
EETrialFormComponent,
|
||||
EETrialWaitingComponent,
|
||||
EEActiveTrialComponent,
|
||||
EEActiveSavedTrialComponent,
|
||||
EnterpriseBannerFrameComponent,
|
||||
],
|
||||
})
|
||||
|
||||
@@ -57,7 +57,6 @@ import {
|
||||
import { OPContextMenuComponent } from 'core-app/shared/components/op-context-menu/op-context-menu.component';
|
||||
import { OpenprojectPrincipalRenderingModule } from 'core-app/shared/components/principal/principal-rendering.module';
|
||||
import { FocusModule } from 'core-app/shared/directives/focus/focus.module';
|
||||
import { FreeTrialButtonComponent } from 'core-app/features/enterprise/free-trial-button/free-trial-button.component';
|
||||
import { HomescreenNewFeaturesBlockComponent } from 'core-app/features/homescreen/blocks/new-features.component';
|
||||
import { TablePaginationComponent } from 'core-app/shared/components/table-pagination/table-pagination.component';
|
||||
import { StaticQueriesService } from 'core-app/shared/components/op-view-select/op-static-queries.service';
|
||||
@@ -170,9 +169,6 @@ export function bootstrapModule(injector:Injector):void {
|
||||
|
||||
EditableToolbarTitleComponent,
|
||||
|
||||
// Enterprise Edition
|
||||
FreeTrialButtonComponent,
|
||||
|
||||
DynamicModule,
|
||||
|
||||
OpOptionListComponent,
|
||||
@@ -211,9 +207,6 @@ export function bootstrapModule(injector:Injector):void {
|
||||
PersistentToggleComponent,
|
||||
RemoteFieldUpdaterComponent,
|
||||
|
||||
// Enterprise Edition
|
||||
FreeTrialButtonComponent,
|
||||
|
||||
HomescreenNewFeaturesBlockComponent,
|
||||
|
||||
OpOptionListComponent,
|
||||
|
||||
Reference in New Issue
Block a user