Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@
* limitations under the License.
*/

import { Component } from '@angular/core';
import { Component, effect, input } from '@angular/core';
import { MatSlideToggleChange } from '@angular/material/slide-toggle';
import { Subscription } from 'rxjs';

import { Survey, SurveyDataVisibility } from 'app/models/survey.model';
import { AuthService } from 'app/services/auth/auth.service';
Expand All @@ -28,7 +27,7 @@ import { DraftSurveyService } from 'app/services/draft-survey/draft-survey.servi
standalone: false,
})
export class DataVisibilityControlComponent {
private subscription = new Subscription();
survey = input<Survey>();

selectedDataVisibility!: SurveyDataVisibility;

Expand All @@ -38,16 +37,14 @@ export class DataVisibilityControlComponent {
readonly authService: AuthService,
readonly draftSurveyService: DraftSurveyService
) {
this.subscription.add(
this.draftSurveyService
.getSurvey$()
.subscribe(survey => this.onSurveyLoaded(survey))
);
}

private async onSurveyLoaded(survey: Survey): Promise<void> {
this.selectedDataVisibility =
survey.dataVisibility || SurveyDataVisibility.CONTRIBUTOR_AND_ORGANIZERS;
effect(() => {
const survey = this.survey();
if (survey) {
this.selectedDataVisibility =
survey.dataVisibility ||
SurveyDataVisibility.CONTRIBUTOR_AND_ORGANIZERS;
}
});
}

changeDataVisibility(event: MatSlideToggleChange) {
Expand All @@ -59,8 +56,4 @@ export class DataVisibilityControlComponent {

this.draftSurveyService.updateDataVisibility(dataVisibility);
}

ngOnDestroy() {
this.subscription.unsubscribe();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@

import '@angular/localize/init';

import { Component } from '@angular/core';
import { Component, effect, input } from '@angular/core';
import { Map } from 'immutable';
import { Subscription } from 'rxjs';

import { Survey, SurveyGeneralAccess } from 'app/models/survey.model';
import { AuthService } from 'app/services/auth/auth.service';
Expand Down Expand Up @@ -53,7 +52,7 @@ const generalAccessLabels = Map<
standalone: false,
})
export class GeneralAccessControlComponent {
private subscription = new Subscription();
survey = input<Survey>();

selectedGeneralAccess!: SurveyGeneralAccess;

Expand All @@ -65,31 +64,24 @@ export class GeneralAccessControlComponent {
readonly authService: AuthService,
readonly draftSurveyService: DraftSurveyService
) {
this.subscription.add(
this.draftSurveyService
.getSurvey$()
.subscribe(survey => this.onSurveyLoaded(survey))
);
effect(() => {
const survey = this.survey();
if (survey) {
// Default to RESTRICTED for general access if not explicitly set.
// This is present for backward-compatibility with older surveys.
this.selectedGeneralAccess =
survey.generalAccess || SurveyGeneralAccess.RESTRICTED;
}
});
}

get generalAccessKeys(): SurveyGeneralAccess[] {
return Array.from(this.generalAccessLabels.keys());
}

private async onSurveyLoaded(survey: Survey): Promise<void> {
// Default to RESTRICTED for general access if not explicitly set.
// This is present for backward-compatibility with older surveys.
this.selectedGeneralAccess =
survey.generalAccess || SurveyGeneralAccess.RESTRICTED;
}

changeGeneralAccess(generalAccess: SurveyGeneralAccess) {
this.selectedGeneralAccess = generalAccess;

this.draftSurveyService.updateGeneralAccess(generalAccess);
}

ngOnDestroy() {
this.subscription.unsubscribe();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatListModule } from '@angular/material/list';
import { MatSelectModule } from '@angular/material/select';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { Map } from 'immutable';
import { of } from 'rxjs';

import { DataSharingType, Survey } from 'app/models/survey.model';
import { DraftSurveyService } from 'app/services/draft-survey/draft-survey.service';

import { ShareDialogComponent } from './share-dialog.component';
Expand All @@ -52,9 +52,20 @@ describe('ShareDialogComponent', () => {
{ provide: MatDialogRef, useValue: {} },
{
provide: DraftSurveyService,
useValue: { updateAcl: () => null },
},
{
provide: MAT_DIALOG_DATA,
useValue: {
getSurvey$: () => of({ acl: Map(), getAclEntriesSorted: () => [] }),
updateAcl: () => null,
survey: new Survey(
'id',
'title',
'description',
Map(),
Map(),
'owner@example.com',
{ type: DataSharingType.PRIVATE }
),
},
},
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import { Component } from '@angular/core';
import { Component, Inject } from '@angular/core';
import {
AbstractControl,
FormControl,
Expand All @@ -23,10 +23,9 @@ import {
ValidatorFn,
Validators,
} from '@angular/forms';
import { MatDialogRef } from '@angular/material/dialog';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { MatSelectChange } from '@angular/material/select';
import { Map } from 'immutable';
import { Subscription } from 'rxjs';

import { AclEntry } from 'app/models/acl-entry.model';
import { Role } from 'app/models/role.model';
Expand Down Expand Up @@ -65,17 +64,12 @@ export class ShareDialogComponent {
/** The active survey. */
private survey?: Survey;

private subscription = new Subscription();

constructor(
private dialogRef: MatDialogRef<ShareDialogComponent>,
private draftSurveyService: DraftSurveyService
private draftSurveyService: DraftSurveyService,
@Inject(MAT_DIALOG_DATA) data: { survey: Survey }
) {
this.subscription.add(
this.draftSurveyService
.getSurvey$()
.subscribe(survey => this.onSurveyLoaded(survey))
);
this.onSurveyLoaded(data.survey);
}

/**
Expand Down Expand Up @@ -128,13 +122,6 @@ export class ShareDialogComponent {
this.dialogRef.close();
}

/**
* Clean up Rx subscription when cleaning up the component.
*/
ngOnDestroy(): void {
this.subscription.unsubscribe();
}

/**
* Update ACL and surveyId when survey is loaded.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatListModule } from '@angular/material/list';
import { MatSelectChange, MatSelectModule } from '@angular/material/select';
import { Map } from 'immutable';
import { Subject } from 'rxjs';

import { Role } from 'app/models/role.model';
import { DataSharingType, Survey } from 'app/models/survey.model';
Expand All @@ -34,23 +33,19 @@ describe('ShareListComponent', () => {

let draftSurveyServiceSpy: jasmine.SpyObj<DraftSurveyService>;
let authServiceSpy: jasmine.SpyObj<AuthService>;
let activeSurvey$: Subject<Survey>;

const user = new User('user1', 'user1@gmail.com', true);

beforeEach(async () => {
draftSurveyServiceSpy = jasmine.createSpyObj<DraftSurveyService>(
'DraftSurveyService',
['getSurvey$', 'updateAcl']
['updateAcl']
);

authServiceSpy = jasmine.createSpyObj<AuthService>('AuthService', [
'getUser',
]);

activeSurvey$ = new Subject<Survey>();

draftSurveyServiceSpy.getSurvey$.and.returnValue(activeSurvey$);
authServiceSpy.getUser.and.callFake(email => {
if (email === 'owner-email') {
return Promise.resolve(new User('owner', 'owner@gmail.com', true));
Expand Down Expand Up @@ -79,7 +74,8 @@ describe('ShareListComponent', () => {
});

it('updates itself when acl changes', async () => {
activeSurvey$.next(
fixture.componentRef.setInput(
'survey',
new Survey(
'id',
'title',
Expand All @@ -90,6 +86,7 @@ describe('ShareListComponent', () => {
{ type: DataSharingType.PRIVATE }
)
);
fixture.detectChanges();
await fixture.whenStable();
fixture.detectChanges();

Expand Down
25 changes: 9 additions & 16 deletions web/src/app/components/shared/share-list/share-list.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@
* limitations under the License.
*/

import { Component } from '@angular/core';
import { Component, effect, input } from '@angular/core';
import { MatSelectChange } from '@angular/material/select';
import { Map } from 'immutable';
import { Subscription } from 'rxjs';

import { AclEntry } from 'app/models/acl-entry.model';
import { Role } from 'app/models/role.model';
Expand All @@ -32,12 +31,11 @@ import { DraftSurveyService } from 'app/services/draft-survey/draft-survey.servi
standalone: false,
})
export class ShareListComponent {
survey = input<Survey>();

acl: Array<AclEntry> = [];
survey?: Survey;
surveyOwnerEmail = '';

private subscription = new Subscription();

readonly roleOptions = ROLE_OPTIONS;

roles = Role;
Expand All @@ -46,16 +44,15 @@ export class ShareListComponent {
readonly authService: AuthService,
readonly draftSurveyService: DraftSurveyService
) {
this.subscription.add(
this.draftSurveyService
.getSurvey$()
.subscribe(survey => this.onSurveyLoaded(survey))
);
effect(() => {
const survey = this.survey();
if (survey) {
this.onSurveyLoaded(survey);
}
});
}

private async onSurveyLoaded(survey: Survey): Promise<void> {
this.survey = survey;

const owner = await this.authService.getUser(survey.ownerId);

this.surveyOwnerEmail = owner?.email || '';
Expand Down Expand Up @@ -88,8 +85,4 @@ export class ShareListComponent {
Map(aclUpdate.map(entry => [entry.email, entry.role]))
);
}

ngOnDestroy() {
this.subscription.unsubscribe();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
</mat-card-header>

<mat-card-content>
<ground-share-list></ground-share-list>
<ground-share-list [survey]="survey()"></ground-share-list>
</mat-card-content>
</mat-card>

Expand All @@ -37,12 +37,12 @@
</mat-card-header>

<mat-card-content>
<ground-general-access-control></ground-general-access-control>
<ground-general-access-control [survey]="survey()"></ground-general-access-control>
</mat-card-content>
</mat-card>

<mat-card>
<ground-data-visibility-control class="floating-button"></ground-data-visibility-control>
<ground-data-visibility-control class="floating-button" [survey]="survey()"></ground-data-visibility-control>

<mat-card-header>
<mat-card-title i18n="@@app.cards.dataVisibility.title">Data visibility</mat-card-title>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatCardModule } from '@angular/material/card';
import { MatDialogModule } from '@angular/material/dialog';
import { MatIconModule } from '@angular/material/icon';
import { NEVER } from 'rxjs';

import { DraftSurveyService } from 'app/services/draft-survey/draft-survey.service';

import { ShareSurveyComponent } from './share-survey.component';

Expand All @@ -15,6 +18,12 @@ describe('ShareSurveyComponent', () => {
imports: [MatIconModule, MatDialogModule, MatCardModule],
declarations: [ShareSurveyComponent],
schemas: [NO_ERRORS_SCHEMA],
providers: [
{
provide: DraftSurveyService,
useValue: { getSurvey$: () => NEVER },
},
],
}).compileComponents();

fixture = TestBed.createComponent(ShareSurveyComponent);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Component } from '@angular/core';
import { Component, inject } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { MatDialog } from '@angular/material/dialog';

import { ShareDialogComponent } from 'app/components/shared/share-dialog/share-dialog.component';
import { DraftSurveyService } from 'app/services/draft-survey/draft-survey.service';

@Component({
selector: 'share-survey',
Expand All @@ -10,12 +12,16 @@ import { ShareDialogComponent } from 'app/components/shared/share-dialog/share-d
standalone: false,
})
export class ShareSurveyComponent {
constructor(private dialog: MatDialog) {}
private draftSurveyService = inject(DraftSurveyService);
private dialog = inject(MatDialog);

survey = toSignal(this.draftSurveyService.getSurvey$());

openShareDialog(): void {
this.dialog.open(ShareDialogComponent, {
width: '580px',
autoFocus: false,
data: { survey: this.survey() },
});
}
}
Loading