diff --git a/.github/workflows/build-and-release.yaml b/.github/workflows/build-and-release.yaml new file mode 100644 index 00000000..ed20303d --- /dev/null +++ b/.github/workflows/build-and-release.yaml @@ -0,0 +1,93 @@ +name: 'Build and Deploy' +on: + push: + branches: + - 'master' + paths-ignore: + - projects/server/** + - terraform/** +jobs: + bump-version: + name: 'Build and Deploy' + runs-on: ubuntu-latest + if: github.repository_owner == 'CarnegieLearningWeb' + steps: + - uses: 'actions/checkout@v2' + with: + fetch-depth: 0 + - uses: actions/setup-node@v1 + with: + node-version: 12.x + - uses: phips28/gh-action-bump-version@v8.0.12 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - run: npm ci + - run: npm run build:prod + - run: zip -r upgrade-client-v${{ steps.package-version.outputs.current-version}}.zip * + working-directory: dist/abtesting + - run: mv dist/abtesting/upgrade-client-v${{ steps.package-version.outputs.current-version}}.zip . + - name: Generate Release Changelog + uses: Bullrich/generate-release-changelog@2.0.1 + id: changelog + env: + REPO: ${{ github.repository }} + - name: Generate Slack Changelog + run: | + echo 'CHANGELOG<> $GITHUB_ENV + git log --color=never --pretty='tformat:%xe2%x80%xa2 `%h` %s (%an)' ${{github.event.before}}..HEAD >> $GITHUB_ENV + echo 'EOF' >> $GITHUB_ENV + - uses: martinbeentjes/npm-get-version-action@v1.1.0 + id: package-version + - name: Create Release + uses: ncipollo/release-action@v1 + with: + artifacts: upgrade-client-v${{ steps.package-version.outputs.current-version}}.zip + tag: v${{ steps.package-version.outputs.current-version}} + name: Upgrade Client ${{ steps.package-version.outputs.current-version}} + body: ${{ steps.changelog.outputs.changelog }} + commit: master + token: ${{ secrets.GITHUB_TOKEN }} + - name: Success Build Message + uses: aibexhq/slack-rich-notify@v2.0.1 + with: + token: ${{ secrets.SLACK_TOKEN }} + channel: ${{ secrets.SLACK_BUILD_CHANNEL }} + message: | + * build was successful* + {{ env.CHANGELOG }} + - name: Failure Build Message + uses: aibexhq/slack-rich-notify@v2.0.1 + if: failure() + with: + token: ${{ secrets.SLACK_TOKEN }} + channel: ${{ secrets.SLACK_BUILD_CHANNEL }} + message: | + ${{ secrets.SLACK_FAILURE_PINGS}} *UpGrade Client ${{ steps.package-version.outputs.current-version }}> build FAILURE* + + {{ env.CHANGELOG }} + - name: Deploy to QA + id: deploy + uses: jakejarvis/s3-sync-action@v0.5.1 + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_S3_BUCKET: ${{ secrets.S3_BUCKET }} + SOURCE_DIR: dist/abtesting + - name: Success Deploy Message + uses: aibexhq/slack-rich-notify@v2.0.1 + with: + token: ${{ secrets.SLACK_TOKEN }} + channel: ${{ secrets.SLACK_DEPLOY_CHANNEL }} + message: | + ** has been deployed to the `dev` environment at https://upgrade.qa-cli.net + {{ env.CHANGELOG }} + - name: Failure Deploy Message + uses: aibexhq/slack-rich-notify@v2.0.1 + if: failure() && steps.deploy.outcome == 'failure' + with: + token: ${{ secrets.SLACK_TOKEN }} + channel: ${{ secrets.SLACK_DEPLOY_CHANNEL }} + message: | + ${{ secrets.SLACK_FAILURE_PINGS}} * deployment FAILURE* + + {{ env.CHANGELOG }} \ No newline at end of file diff --git a/.github/workflows/version.yaml b/.github/workflows/version.yaml deleted file mode 100644 index 23c4e59b..00000000 --- a/.github/workflows/version.yaml +++ /dev/null @@ -1,20 +0,0 @@ -name: 'Bump Version' - -on: - push: - branches: - - 'master' -jobs: - bump-version: - name: 'Bump Version on master' - runs-on: ubuntu-latest - steps: - - name: 'Checkout source code' - uses: 'actions/checkout@v2' - - name: 'GitHub Version Bumper' - uses: 'kaangokdemir/github-version-bumper@master' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_NAME: 'tanmayjain3' - GITHUB_EMAIL: 'tanmayjain53@gmail.com' - VERSION_FILE_NAME: 'package.json' diff --git a/package-lock.json b/package-lock.json index 713206ce..117a7e74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "ab-testing", - "version": "8.3.2", + "version": "1.0.10", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -8768,6 +8768,11 @@ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", "dev": true }, + "papaparse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.3.0.tgz", + "integrity": "sha512-Lb7jN/4bTpiuGPrYy4tkKoUS8sTki8zacB5ke1p5zolhcSE4TlWgrlsxjrDTbG/dFVh07ck7X36hUf/b5V68pg==" + }, "parallel-transform": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", @@ -12942,9 +12947,9 @@ "dev": true }, "upgrade_types": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/upgrade_types/-/upgrade_types-1.0.3.tgz", - "integrity": "sha512-Mkv1TPW2SSOLAuVLUO0iGomKoQnS7m28RQRNh8iFxIQ8PZXqMeK9jCPFi1SNm93q/Efvz7r/StZWNFPFZQCsPQ==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/upgrade_types/-/upgrade_types-1.0.4.tgz", + "integrity": "sha512-Xck0S3wVJslFlmc0N4r7rOJJHDAGRW6UM6UhhLJfyc/f6kmSlio1wAGGZMVvlHjUlgL9XTRZgkUfPNiNutlFIg==" }, "uri-js": { "version": "4.2.2", diff --git a/package.json b/package.json index d20dfc9c..67edba30 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ab-testing", - "version": "1.0.2", + "version": "1.0.10", "license": "MIT", "scripts": { "ng": "ng", @@ -62,9 +62,10 @@ "lodash.groupby": "^4.6.0", "ng-pick-datetime": "^7.0.0", "ngx-skeleton-loader": "^2.2.0", + "papaparse": "^5.3.0", "rxjs": "~6.5.0", "tslib": "^1.9.0", - "upgrade_types": "1.0.3", + "upgrade_types": "^1.0.4", "uuid": "^3.3.3", "zone.js": "~0.9.1" }, diff --git a/projects/abtesting/src/app/core/experiment-users/store/experiment-users.model.ts b/projects/abtesting/src/app/core/experiment-users/store/experiment-users.model.ts index 3a4773f5..73069c8f 100644 --- a/projects/abtesting/src/app/core/experiment-users/store/experiment-users.model.ts +++ b/projects/abtesting/src/app/core/experiment-users/store/experiment-users.model.ts @@ -3,7 +3,7 @@ import { EntityState } from '@ngrx/entity'; export enum EntityTypes { GROUP_ID = 'Group ID', - USER_ID = 'User ID' + PARTICIPANT_ID = 'Participant ID' } export interface ExcludeEntity { diff --git a/projects/abtesting/src/app/core/experiments/experiments.data.service.ts b/projects/abtesting/src/app/core/experiments/experiments.data.service.ts index a45d361a..f3cd4a3a 100644 --- a/projects/abtesting/src/app/core/experiments/experiments.data.service.ts +++ b/projects/abtesting/src/app/core/experiments/experiments.data.service.ts @@ -27,6 +27,11 @@ export class ExperimentDataService { return this.http.post(url, { ...experiment }); } + importExperiment(experiment: Experiment) { + const url = environment.api.importExperiment; + return this.http.post(url, {...experiment}); + } + updateExperiment(experiment: Experiment) { const url = `${environment.api.updateExperiments}/${experiment.id}`; return this.http.put(url, { ...experiment }); diff --git a/projects/abtesting/src/app/core/experiments/experiments.service.ts b/projects/abtesting/src/app/core/experiments/experiments.service.ts index 36f31a57..c7e00d22 100644 --- a/projects/abtesting/src/app/core/experiments/experiments.service.ts +++ b/projects/abtesting/src/app/core/experiments/experiments.service.ts @@ -91,6 +91,12 @@ export class ExperimentService { ); } + importExperiment(experiment: Experiment) { + this.store$.dispatch( + experimentAction.actionUpsertExperiment({ experiment, actionType: UpsertExperimentType.IMPORT_EXPERIMENT }) + ); + } + updateExperiment(experiment: ExperimentVM) { delete experiment.stat; this.store$.dispatch( diff --git a/projects/abtesting/src/app/core/experiments/store/experiments.effects.ts b/projects/abtesting/src/app/core/experiments/store/experiments.effects.ts index 03ee6d3d..51208d99 100644 --- a/projects/abtesting/src/app/core/experiments/store/experiments.effects.ts +++ b/projects/abtesting/src/app/core/experiments/store/experiments.effects.ts @@ -28,6 +28,7 @@ import { } from './experiments.selectors'; import { combineLatest } from 'rxjs'; import { selectCurrentUser } from '../../auth/store/auth.selectors'; +import { MatSnackBar } from '@angular/material'; @Injectable() export class ExperimentEffects { @@ -35,7 +36,8 @@ export class ExperimentEffects { private actions$: Actions, private store$: Store, private experimentDataService: ExperimentDataService, - private router: Router + private router: Router, + private _snackBar: MatSnackBar ) {} getPaginatedExperiment$ = createEffect(() => @@ -129,10 +131,11 @@ export class ExperimentEffects { const experimentMethod = actionType === UpsertExperimentType.CREATE_NEW_EXPERIMENT ? this.experimentDataService.createNewExperiment(experiment) + : actionType === UpsertExperimentType.IMPORT_EXPERIMENT + ? this.experimentDataService.importExperiment(experiment) : this.experimentDataService.updateExperiment(experiment); return experimentMethod.pipe( - switchMap((data: Experiment) => - this.experimentDataService.getAllExperimentsStats([data.id]).pipe( + switchMap((data: Experiment) => this.experimentDataService.getAllExperimentsStats([data.id]).pipe( switchMap((experimentStat: IExperimentEnrollmentStats) => { const stats = { ...experimentStats, [data.id]: experimentStat[0] }; const queryIds = data.queries.map(query => query.id); @@ -145,7 +148,10 @@ export class ExperimentEffects { }) ) ), - catchError(() => [experimentAction.actionUpsertExperimentFailure()]) + catchError((error) => { + this._snackBar.open(error.error.message, null, { duration: 2000 }); + return [experimentAction.actionUpsertExperimentFailure()]; + }) ); }) ) diff --git a/projects/abtesting/src/app/core/experiments/store/experiments.model.ts b/projects/abtesting/src/app/core/experiments/store/experiments.model.ts index 6adb2e4e..f2c4358f 100644 --- a/projects/abtesting/src/app/core/experiments/store/experiments.model.ts +++ b/projects/abtesting/src/app/core/experiments/store/experiments.model.ts @@ -47,7 +47,8 @@ export enum GroupTypes { export enum NewExperimentDialogEvents { CLOSE_DIALOG = 'Close Dialog', SEND_FORM_DATA = 'Send Form Data', - UPDATE_EXPERIMENT = 'Update experiment' + UPDATE_EXPERIMENT = 'Update experiment', + SAVE_DATA = 'Save Data' } export enum NewExperimentPaths { @@ -70,7 +71,8 @@ export enum DateType { export enum UpsertExperimentType { CREATE_NEW_EXPERIMENT = 'Create new experiment', - UPDATE_EXPERIMENT = 'Update experiment' + UPDATE_EXPERIMENT = 'Update experiment', + IMPORT_EXPERIMENT = 'Import experiment' } export enum EndExperimentCondition { diff --git a/projects/abtesting/src/app/features/dashboard/dashboard-root/dashboard-root.component.ts b/projects/abtesting/src/app/features/dashboard/dashboard-root/dashboard-root.component.ts index 65a6c113..4e617f45 100644 --- a/projects/abtesting/src/app/features/dashboard/dashboard-root/dashboard-root.component.ts +++ b/projects/abtesting/src/app/features/dashboard/dashboard-root/dashboard-root.component.ts @@ -27,7 +27,7 @@ export class DashboardRootComponent implements OnInit { iconType: 'toggle_on' }, { - path: ['/users'], + path: ['/participants'], text: 'global.experiment-user.title', iconType: 'supervisor_account' }, diff --git a/projects/abtesting/src/app/features/dashboard/dashboard-routing.module.ts b/projects/abtesting/src/app/features/dashboard/dashboard-routing.module.ts index 4246f49c..7c539e19 100644 --- a/projects/abtesting/src/app/features/dashboard/dashboard-routing.module.ts +++ b/projects/abtesting/src/app/features/dashboard/dashboard-routing.module.ts @@ -20,7 +20,7 @@ const routes: Routes = [ } }, { - path: 'users', + path: 'participants', loadChildren: () => import('./experiment-users/experiment-users.module').then(m => m.ExperimentUsersModule), data: { title: 'app-header.title.users' @@ -59,4 +59,4 @@ const routes: Routes = [ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) -export class DashboardRoutingModule {} +export class DashboardRoutingModule { } diff --git a/projects/abtesting/src/app/features/dashboard/experiment-users/components/experiment-users/experiment-users.component.ts b/projects/abtesting/src/app/features/dashboard/experiment-users/components/experiment-users/experiment-users.component.ts index 6dd3ea86..6c1e7c19 100644 --- a/projects/abtesting/src/app/features/dashboard/experiment-users/components/experiment-users/experiment-users.component.ts +++ b/projects/abtesting/src/app/features/dashboard/experiment-users/components/experiment-users/experiment-users.component.ts @@ -23,7 +23,7 @@ export class ExperimentUsersComponent implements OnInit, OnDestroy { allExcludedEntitiesSub: Subscription; excludeEntitiesForm: FormGroup; - entityTypes = [{ value: EntityTypes.USER_ID }, { value: EntityTypes.GROUP_ID }]; + entityTypes = [{ value: EntityTypes.PARTICIPANT_ID }, { value: EntityTypes.GROUP_ID }]; groupTypes = [ { value: GroupTypes.CLASS }, { value: GroupTypes.DISTRICT }, @@ -88,7 +88,7 @@ export class ExperimentUsersComponent implements OnInit, OnDestroy { this.excludeEntitiesForm.get('id').reset(); this.excludeEntitiesForm.get('customGroupName').reset(); switch (entityType) { - case EntityTypes.USER_ID: + case EntityTypes.PARTICIPANT_ID: this.experimentUserService.excludeUser(id); break; case EntityTypes.GROUP_ID: @@ -120,8 +120,8 @@ export class ExperimentUsersComponent implements OnInit, OnDestroy { // For getting custom placeholder get getIdPlaceholder() { const { entityType, groupType, customGroupName } = this.excludeEntitiesForm.value; - if (entityType === EntityTypes.USER_ID) { - return 'Enter user ID'; + if (entityType === EntityTypes.PARTICIPANT_ID) { + return 'Enter participant ID'; } else { if (groupType === GroupTypes.OTHER) { return 'Enter ' + (customGroupName || '') + ' ID'; diff --git a/projects/abtesting/src/app/features/dashboard/home/components/experiment-design/experiment-design.component.html b/projects/abtesting/src/app/features/dashboard/home/components/experiment-design/experiment-design.component.html index 77070a96..ffde94c3 100644 --- a/projects/abtesting/src/app/features/dashboard/home/components/experiment-design/experiment-design.component.html +++ b/projects/abtesting/src/app/features/dashboard/home/components/experiment-design/experiment-design.component.html @@ -244,6 +244,14 @@ > {{ 'global.cancel.text' | translate }} + +
+ + +
{ + // Code will be executed after closing dialog + }); + } + setChipsVisible(experimentId: string, type: string) { const index = this[type].findIndex( data => data.experimentId === experimentId diff --git a/projects/abtesting/src/app/features/dashboard/home/components/experiment-overview/experiment-overview.component.html b/projects/abtesting/src/app/features/dashboard/home/components/experiment-overview/experiment-overview.component.html index 2d989af5..49b38c39 100644 --- a/projects/abtesting/src/app/features/dashboard/home/components/experiment-overview/experiment-overview.component.html +++ b/projects/abtesting/src/app/features/dashboard/home/components/experiment-overview/experiment-overview.component.html @@ -150,6 +150,14 @@ > {{ 'global.cancel.text' | translate }} + + + +
+ diff --git a/projects/abtesting/src/app/features/dashboard/home/components/modal/import-experiment/import-experiment.component.scss b/projects/abtesting/src/app/features/dashboard/home/components/modal/import-experiment/import-experiment.component.scss new file mode 100644 index 00000000..c592630d --- /dev/null +++ b/projects/abtesting/src/app/features/dashboard/home/components/modal/import-experiment/import-experiment.component.scss @@ -0,0 +1,33 @@ +.import-experiment-container { + .title { + display: block; + padding: 30px 40px 0; + height: 88px; + } + + .import-experiment-body { + margin: 20px 0; + padding: 0 40px; + + .file-input { + &:hover { + cursor: pointer; + } + } + + .error-msg { + display: block; + padding-top: 10px; + } + + .error-msg { + color: var(--red); + } + } + + .button-container { + display: flex; + justify-content: flex-end; + padding: 0 40px 40px; + } +} diff --git a/projects/abtesting/src/app/features/dashboard/home/components/modal/import-experiment/import-experiment.component.spec.ts b/projects/abtesting/src/app/features/dashboard/home/components/modal/import-experiment/import-experiment.component.spec.ts new file mode 100644 index 00000000..8c63c37b --- /dev/null +++ b/projects/abtesting/src/app/features/dashboard/home/components/modal/import-experiment/import-experiment.component.spec.ts @@ -0,0 +1,34 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ImportExperimentComponent } from './import-experiment.component'; +import { TestingModule } from '../../../../../../../testing/testing.module'; +import { ExperimentService } from '../../../../../../core/experiments/experiments.service'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; + +describe('ImportExperimentComponent', () => { + let component: ImportExperimentComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ImportExperimentComponent ], + imports: [TestingModule], + providers: [ + ExperimentService, + { provide: MatDialogRef, useValue: {} }, + { provide: MAT_DIALOG_DATA, useValue: [] }, + ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ImportExperimentComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/abtesting/src/app/features/dashboard/home/components/modal/import-experiment/import-experiment.component.ts b/projects/abtesting/src/app/features/dashboard/home/components/modal/import-experiment/import-experiment.component.ts new file mode 100644 index 00000000..b5f67b06 --- /dev/null +++ b/projects/abtesting/src/app/features/dashboard/home/components/modal/import-experiment/import-experiment.component.ts @@ -0,0 +1,118 @@ +import { Component, Inject } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; +import { Experiment, ExperimentCondition, ExperimentPartition } from '../../../../../../core/experiments/store/experiments.model'; +import { ExperimentService } from '../../../../../../core/experiments/experiments.service'; + +interface ImportExperimentJSON { + schema: Record | Record | Record, + data: Experiment | ExperimentCondition | ExperimentPartition +} + +@Component({ + selector: 'app-import-experiment', + templateUrl: './import-experiment.component.html', + styleUrls: ['./import-experiment.component.scss'] +}) +export class ImportExperimentComponent { + file: any; + experimentInfo: Experiment; + isExperimentJSONValid = true; + + constructor( + private experimentService: ExperimentService, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any + ) {} + + onCancelClick(): void { + this.dialogRef.close(); + } + + importExperiment() { + this.isExperimentJSONValid = this.validateExperimentJSON({ ...this.experimentInfo, queries: [] }); + if (this.isExperimentJSONValid) { + this.experimentService.importExperiment({ ...this.experimentInfo, queries: [] }); + this.onCancelClick(); + } + } + + uploadFile(event) { + const reader = new FileReader(); + reader.addEventListener( + 'load', + function() { + const result = JSON.parse(reader.result as any); + this.experimentInfo = result; + }.bind(this) + ); + reader.readAsText(event.target.files[0]); + } + + private validateExperimentJSON(experiment: Experiment) { + const experimentSchema: Record = { + id: 'string', + name: 'string', + description: 'string', + createdAt: 'string', + updatedAt: 'string', + state: 'enum', + context: 'array', + startOn: 'string', + consistencyRule: 'enum', + assignmentUnit: 'enum', + postExperimentRule: 'enum', + enrollmentCompleteCondition: 'enum', + endOn: 'string', + revertTo: 'string', + tags: 'array', + group: 'string', + conditions: 'interface', + partitions: 'interface', + queries: 'array', + }; + + const conditionSchema: Record = { + id: 'string', + name: 'string', + description: 'string', + conditionCode: 'string', + assignmentWeight: 'number', + twoCharacterId: 'string', + } + + const partitionSchema: Record = { + id: 'string', + expPoint: 'string', + expId: 'string', + description: 'string', + twoCharacterId: 'string', + } + + let missingProperties = this.checkForMissingProperties({ schema: experimentSchema, data: experiment }); + if (missingProperties.length > 0) { + return false; + } else { + experiment.conditions.map(condition => { + missingProperties = [ ...missingProperties, ...this.checkForMissingProperties({ schema: conditionSchema, data: condition })]; + }); + + if (missingProperties.length > 0) { + return false; + } else { + experiment.partitions.map(partition => { + missingProperties = [ ...missingProperties, ...this.checkForMissingProperties({ schema: partitionSchema, data: partition })]; + }); + return missingProperties.length === 0; + } + } + } + + private checkForMissingProperties(experimentJson: ImportExperimentJSON) { + const { schema, data } = experimentJson; + const missingProperties = Object.keys(schema) + .filter(key => data[key] === undefined) + .map(key => key as keyof (Experiment | ExperimentPartition | ExperimentCondition)) + .map(key => new Error(`Document is missing ${key} ${schema[key]}`)); + return missingProperties; + } +} diff --git a/projects/abtesting/src/app/features/dashboard/home/components/modal/import-experiment/import-experiment.theme.scss b/projects/abtesting/src/app/features/dashboard/home/components/modal/import-experiment/import-experiment.theme.scss new file mode 100644 index 00000000..2b6b50a1 --- /dev/null +++ b/projects/abtesting/src/app/features/dashboard/home/components/modal/import-experiment/import-experiment.theme.scss @@ -0,0 +1,11 @@ +@import '~@angular/material/theming'; + +@mixin import-experiment-component-theme($theme) { + $background: map-get($theme, background); + + .import-experiment-container { + .title { + box-shadow: 0 0 8px 0 mat-color($background, shadow-color); + } + } +} diff --git a/projects/abtesting/src/app/features/dashboard/home/components/modal/new-experiment/new-experiment.component.ts b/projects/abtesting/src/app/features/dashboard/home/components/modal/new-experiment/new-experiment.component.ts index 98bf5875..8a1efc07 100644 --- a/projects/abtesting/src/app/features/dashboard/home/components/modal/new-experiment/new-experiment.component.ts +++ b/projects/abtesting/src/app/features/dashboard/home/components/modal/new-experiment/new-experiment.component.ts @@ -57,6 +57,7 @@ export class NewExperimentComponent implements OnInit { } break; case NewExperimentDialogEvents.UPDATE_EXPERIMENT: + case NewExperimentDialogEvents.SAVE_DATA: this.newExperimentData = { ...this.experimentInfo, ...this.newExperimentData, diff --git a/projects/abtesting/src/app/features/dashboard/home/components/modal/post-experiment-rule/post-experiment-rule.component.ts b/projects/abtesting/src/app/features/dashboard/home/components/modal/post-experiment-rule/post-experiment-rule.component.ts index b7c3e71c..f9b26724 100644 --- a/projects/abtesting/src/app/features/dashboard/home/components/modal/post-experiment-rule/post-experiment-rule.component.ts +++ b/projects/abtesting/src/app/features/dashboard/home/components/modal/post-experiment-rule/post-experiment-rule.component.ts @@ -17,7 +17,7 @@ export class PostExperimentRuleComponent implements OnInit { postExperimentRuleForm: FormGroup; postExperimentRules = [ { value: POST_EXPERIMENT_RULE.CONTINUE }, - { value: POST_EXPERIMENT_RULE.REVERT } + { value: POST_EXPERIMENT_RULE.ASSIGN } ]; experimentConditions = [ { value: 'default', id: 'default' } @@ -65,7 +65,7 @@ export class PostExperimentRuleComponent implements OnInit { validatePostExperimentRuleForm(controls: AbstractControl): { [key: string]: any } | null { const postExperimentRule = controls.get('postExperimentRule').value; const revertTo = controls.get('revertTo').value; - if (postExperimentRule === POST_EXPERIMENT_RULE.REVERT && !revertTo) { + if (postExperimentRule === POST_EXPERIMENT_RULE.ASSIGN && !revertTo) { return { conditionSelectionError: true }; } return null; diff --git a/projects/abtesting/src/app/features/dashboard/home/home.module.ts b/projects/abtesting/src/app/features/dashboard/home/home.module.ts index 9bc59256..c31a4bb3 100644 --- a/projects/abtesting/src/app/features/dashboard/home/home.module.ts +++ b/projects/abtesting/src/app/features/dashboard/home/home.module.ts @@ -30,7 +30,7 @@ import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { ExperimentQueryResultComponent } from './components/experiment-query-result/experiment-query-result.component'; import { ExperimentEndCriteriaComponent } from './components/modal/experiment-end-criteria/experiment-end-criteria.component'; import { RepeatedMeasurePipe } from './pipes/repeated-measure.pipe'; - +import { ImportExperimentComponent } from './components/modal/import-experiment/import-experiment.component'; @NgModule({ declarations: [ HomeComponent, @@ -47,6 +47,7 @@ import { RepeatedMeasurePipe } from './pipes/repeated-measure.pipe'; EnrollmentPointPartitionTableComponent, ExperimentPostConditionComponent, DeleteExperimentComponent, + ImportExperimentComponent, TableRowComponent, QueriesModalComponent, CreateQueryComponent, @@ -71,6 +72,7 @@ import { RepeatedMeasurePipe } from './pipes/repeated-measure.pipe'; ExperimentStatusComponent, PostExperimentRuleComponent, DeleteExperimentComponent, + ImportExperimentComponent, QueriesModalComponent, ExperimentEndCriteriaComponent ] diff --git a/projects/abtesting/src/app/features/dashboard/home/pages/view-experiment/view-experiment.component.ts b/projects/abtesting/src/app/features/dashboard/home/pages/view-experiment/view-experiment.component.ts index 778afc00..5ff6e918 100644 --- a/projects/abtesting/src/app/features/dashboard/home/pages/view-experiment/view-experiment.component.ts +++ b/projects/abtesting/src/app/features/dashboard/home/pages/view-experiment/view-experiment.component.ts @@ -84,7 +84,8 @@ export class ViewExperimentComponent implements OnInit, OnDestroy { : NewExperimentComponent; const dialogRef = this.dialog.open(dialogComponent as any, { panelClass: dialogType === DialogType.EDIT_EXPERIMENT ? 'new-experiment-modal' : 'experiment-general-modal', - data: { experiment: clonedeep(this.experiment) } + data: { experiment: clonedeep(this.experiment) }, + disableClose : dialogType === DialogType.EDIT_EXPERIMENT }); dialogRef.afterClosed().subscribe(() => {}); diff --git a/projects/abtesting/src/app/features/dashboard/home/root/home.component.html b/projects/abtesting/src/app/features/dashboard/home/root/home.component.html index 104f3500..045c6ea6 100644 --- a/projects/abtesting/src/app/features/dashboard/home/root/home.component.html +++ b/projects/abtesting/src/app/features/dashboard/home/root/home.component.html @@ -15,6 +15,16 @@

{{ 'global.experiment.title' | translate }}

class="text ft-24-600" [innerHTML]="'home.no-experiment.text' | translate" > +