Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get flag details on details page #1634

Merged
merged 7 commits into from
Jun 11, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ export class FeatureFlagsDataService {
const url = this.environment.api.getPaginatedFlags;
return this.http.post<FeatureFlagsPaginationInfo>(url, params);
// mock
// return of({ nodes: mockFeatureFlags, total: 2 }).pipe(delay(2000));
// // return of({ nodes: mockFeatureFlags, total: 2 }).pipe(delay(2000));
}

fetchFeatureFlagById(id: string) {
const url = `${this.environment.api.featureFlag}/${id}`;
return this.http.get(url);
}

addFeatureFlag(params: AddFeatureFlagRequest): Observable<FeatureFlag> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
selectHasInitialFeatureFlagsDataLoaded,
selectIsLoadingAddFeatureFlag,
selectActiveDetailsTabIndex,
selectSelectedFeatureFlag,
// selectIsLoadingFeatureFlagDetail,
} from './store/feature-flags.selectors';
import * as FeatureFlagsActions from './store/feature-flags.actions';
import { actionFetchContextMetaData } from '../experiments/store/experiments.actions';
Expand All @@ -25,10 +27,14 @@ export class FeatureFlagsService {
allFeatureFlags$ = this.store$.pipe(select(selectAllFeatureFlagsSortedByDate));
isAllFlagsFetched$ = this.store$.pipe(select(selectIsAllFlagsFetched));
isLoadingAddFeatureFlag$ = this.store$.pipe(select(selectIsLoadingAddFeatureFlag));

featureFlagsListLengthChange$ = this.allFeatureFlags$.pipe(
pairwise(),
filter(([prevEntities, currEntities]) => prevEntities.length !== currEntities.length)
);

selectedFeatureFlag$ = this.store$.pipe(select(selectSelectedFeatureFlag));

activeDetailsTabIndex$ = this.store$.pipe(select(selectActiveDetailsTabIndex));
appContexts$ = this.experimentService.contextMetaData$.pipe(
map((contextMetaData) => {
Expand All @@ -40,6 +46,10 @@ export class FeatureFlagsService {
this.store$.dispatch(FeatureFlagsActions.actionFetchFeatureFlags({ fromStarting }));
}

fetchFeatureFlagById(featureFlagId: string) {
this.store$.dispatch(FeatureFlagsActions.actionFetchFeatureFlagById({ featureFlagId }));
}

fetchContextMetaData() {
this.store$.dispatch(actionFetchContextMetaData({ isLoadingContextMetaData: true }));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ export const actionFetchFeatureFlagsSuccess = createAction(

export const actionFetchFeatureFlagsFailure = createAction('[Feature Flags] Fetch Feature Flags Paginated Failure');

export const actionFetchFeatureFlagById = createAction(
'[Feature Flags] Fetch Feature Flags By Id',
props<{ featureFlagId: string }>()
);

export const actionFetchFeatureFlagByIdSuccess = createAction(
'[Feature Flags] Fetch Feature Flags By Id Success',
props<{ flag: FeatureFlag }>()
);

export const actionFetchFeatureFlagByIdFailure = createAction('[Feature Flags] Fetch Feature Flags By Id Failure');

export const actionSetIsLoadingFeatureFlags = createAction(
'[Feature Flags] Set Is Loading Flags',
props<{ isLoadingFeatureFlags: boolean }>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { FeatureFlagsDataService } from '../feature-flags.data.service';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { Injectable } from '@angular/core';
import * as FeatureFlagsActions from './feature-flags.actions';
import { catchError, switchMap, map, filter, withLatestFrom, tap, first } from 'rxjs/operators';
import { FeatureFlagsPaginationParams, NUMBER_OF_FLAGS } from './feature-flags.model';
import { catchError, switchMap, map, filter, withLatestFrom, tap, first, mergeMap } from 'rxjs/operators';
import { FeatureFlag, FeatureFlagsPaginationParams, NUMBER_OF_FLAGS } from './feature-flags.model';
import { Router } from '@angular/router';
import { Store, select } from '@ngrx/store';
import { AppState } from '../../core.module';
Expand All @@ -15,6 +15,7 @@ import {
selectSortAs,
selectSearchString,
} from './feature-flags.selectors';
import { of } from 'rxjs';
KD1712 marked this conversation as resolved.
Show resolved Hide resolved

@Injectable()
export class FeatureFlagsEffects {
Expand Down Expand Up @@ -99,7 +100,6 @@ export class FeatureFlagsEffects {
)
);


fetchFeatureFlagsOnSearchString$ = createEffect(
() =>
this.actions$.pipe(
Expand Down Expand Up @@ -129,5 +129,21 @@ export class FeatureFlagsEffects {
{ dispatch: false }
);

fetchFeatureFlagById$ = createEffect(() =>
this.actions$.pipe(
ofType(FeatureFlagsActions.actionFetchFeatureFlagById),
map((action) => action.featureFlagId),
filter((featureFlagId) => !!featureFlagId),
switchMap((featureFlagId) =>
this.featureFlagsDataService.fetchFeatureFlagById(featureFlagId).pipe(
map((data: FeatureFlag) => {
return FeatureFlagsActions.actionFetchFeatureFlagByIdSuccess({ flag: data });
}),
catchError(() => [FeatureFlagsActions.actionFetchFeatureFlagByIdFailure()])
)
)
)
);

private getSearchString$ = () => this.store$.pipe(select(selectSearchString)).pipe(first());
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const { selectIds, selectEntities, selectAll, selectTotal } = adapter.get
export const initialState: FeatureFlagState = adapter.getInitialState({
isLoadingAddFeatureFlag: false,
isLoadingFeatureFlags: false,
isLoadingFeatureFlagDetail: false,
hasInitialFeatureFlagsDataLoaded: false,
activeDetailsTabIndex: 0,
skipFlags: 0,
Expand Down Expand Up @@ -39,6 +40,13 @@ const reducer = createReducer(
});
}),
on(FeatureFlagsActions.actionFetchFeatureFlagsFailure, (state) => ({ ...state, isLoadingFeatureFlags: false })),
on(FeatureFlagsActions.actionFetchFeatureFlagByIdSuccess, (state, { flag }) => {
return adapter.addOne(flag, {
...state,
isLoadingFeatureFlags: false,
});
}),
on(FeatureFlagsActions.actionFetchFeatureFlagByIdFailure, (state) => ({ ...state, isLoadingFeatureFlags: false })),
on(FeatureFlagsActions.actionSetIsLoadingFeatureFlags, (state, { isLoadingFeatureFlags }) => ({
...state,
isLoadingFeatureFlags,
Expand All @@ -59,6 +67,10 @@ const reducer = createReducer(
on(FeatureFlagsActions.actionSetActiveDetailsTabIndex, (state, { activeDetailsTabIndex }) => ({
...state,
activeDetailsTabIndex,
})),
on(FeatureFlagsActions.actionFetchFeatureFlagById, (state) => ({
...state,
isLoadingFeatureFlags: true,
}))
);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
<app-common-section-card-list>
<app-feature-flag-overview-details-section-card section-card></app-feature-flag-overview-details-section-card>
<app-feature-flag-inclusions-section-card *ngIf="(activeTabIndex$ | async) === 0" section-card
>inclusions-card</app-feature-flag-inclusions-section-card
>
<app-feature-flag-exclusions-section-card *ngIf="(activeTabIndex$ | async) === 0" section-card
>exclusions-card</app-feature-flag-exclusions-section-card
>
<app-feature-flag-exposures-section-card *ngIf="(activeTabIndex$ | async) === 1" section-card
>exposures-card</app-feature-flag-exposures-section-card
>
</app-common-section-card-list>
<div class="content-container">
<mat-spinner *ngIf="!featureFlag"></mat-spinner>
Copy link
Collaborator

@danoswaltCL danoswaltCL Jun 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we sub to the feature flag directly with an async pipe in template, we can do this and eliminate half of the component code:

<ng-container *ngIf="(featureFlag$ | async) as featureFlag; else loading">
  <app-common-section-card-list class="common-section-card-list">
    <app-feature-flag-overview-details-section-card [data]="featureFlag" section-card></app-feature-flag-overview-details-section-card>
    <app-feature-flag-inclusions-section-card [data]="featureFlag" *ngIf="(activeTabIndex$ | async) === 0" section-card>inclusions-card</app-feature-flag-inclusions-section-card>
    <app-feature-flag-exclusions-section-card [data]="featureFlag" *ngIf="(activeTabIndex$ | async) === 0" section-card>exclusions-card</app-feature-flag-exclusions-section-card>
    <app-feature-flag-exposures-section-card [data]="featureFlag" *ngIf="(activeTabIndex$ | async) === 1" section-card>exposures-card</app-feature-flag-exposures-section-card>
  </app-common-section-card-list>
</ng-container>

<ng-template #loading>
  <mat-spinner></mat-spinner>
</ng-template>

Copy link
Collaborator

@danoswaltCL danoswaltCL Jun 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then in component code, you just need this, no need to manage anything about this subscription by hand, the "filter" pipe isn't really doing anything very helpful, and change detector ref can be eliminated

featureFlag$ = this.featureFlagsService.selectedFeatureFlag$

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah i'll need this as an observable like suggested above in order to complete some work I'm currently doing, let me know if this suggestion works for you, I tried it in my local and it works fine.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes works for me too

<app-common-section-card-list class="common-section-card-list" *ngIf="featureFlag">
<app-feature-flag-overview-details-section-card
[data]="featureFlag"
section-card
></app-feature-flag-overview-details-section-card>
<app-feature-flag-inclusions-section-card [data]="featureFlag" *ngIf="(activeTabIndex$ | async) === 0" section-card
>inclusions-card</app-feature-flag-inclusions-section-card
>
<app-feature-flag-exclusions-section-card [data]="featureFlag" *ngIf="(activeTabIndex$ | async) === 0" section-card
>exclusions-card</app-feature-flag-exclusions-section-card
>
<app-feature-flag-exposures-section-card [data]="featureFlag" *ngIf="(activeTabIndex$ | async) === 1" section-card
>exposures-card</app-feature-flag-exposures-section-card
>
</app-common-section-card-list>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.content-container {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}

.common-section-card-list {
width: 100%;
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { CommonSectionCardListComponent } from '../../../../../../shared-standalone-component-lib/components';
import { CommonModule } from '@angular/common';
import { FeatureFlagInclusionsSectionCardComponent } from './feature-flag-inclusions-section-card/feature-flag-inclusions-section-card.component';
import { FeatureFlagExclusionsSectionCardComponent } from './feature-flag-exclusions-section-card/feature-flag-exclusions-section-card.component';
import { FeatureFlagExposuresSectionCardComponent } from './feature-flag-exposures-section-card/feature-flag-exposures-section-card.component';
import { FeatureFlagOverviewDetailsSectionCardComponent } from './feature-flag-overview-details-section-card/feature-flag-overview-details-section-card.component';
import { FeatureFlagsService } from '../../../../../../core/feature-flags/feature-flags.service';
import { filter, Subscription } from 'rxjs';
import { FeatureFlag } from '../../../../../../core/feature-flags/store/feature-flags.model';
import { ActivatedRoute } from '@angular/router';
import { SharedModule } from '../../../../../../shared/shared.module';

@Component({
selector: 'app-feature-flag-details-page-content',
Expand All @@ -17,13 +21,38 @@ import { FeatureFlagsService } from '../../../../../../core/feature-flags/featur
FeatureFlagExclusionsSectionCardComponent,
FeatureFlagExposuresSectionCardComponent,
FeatureFlagOverviewDetailsSectionCardComponent,
SharedModule,
],
templateUrl: './feature-flag-details-page-content.component.html',
styleUrl: './feature-flag-details-page-content.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FeatureFlagDetailsPageContentComponent {
export class FeatureFlagDetailsPageContentComponent implements OnInit, OnDestroy {
activeTabIndex$ = this.featureFlagsService.activeDetailsTabIndex$;
featureFlag: FeatureFlag;
featureFlagSub: Subscription;
featureFlagIdSub: Subscription;

constructor(private featureFlagsService: FeatureFlagsService) {}
constructor(
private featureFlagsService: FeatureFlagsService,
private _Activatedroute: ActivatedRoute,
private changeDetectorRef: ChangeDetectorRef
) {}
ngOnInit() {
this.featureFlagIdSub = this._Activatedroute.paramMap.subscribe((params) => {
const featureFlagIdFromParams = params.get('flagId');
this.featureFlagsService.fetchFeatureFlagById(featureFlagIdFromParams);
});

this.featureFlagSub = this.featureFlagsService.selectedFeatureFlag$
.pipe(filter((featureFlag) => !!featureFlag))
.subscribe((featureFlag) => {
this.featureFlag = featureFlag;
this.changeDetectorRef.detectChanges();
});
}
ngOnDestroy() {
this.featureFlagSub.unsubscribe();
this.featureFlagIdSub.unsubscribe();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import {
CommonSectionCardActionButtonsComponent,
CommonSectionCardComponent,
Expand All @@ -7,8 +7,10 @@ import {
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { of } from 'rxjs';
import { FeatureFlag } from '../../../../../../../core/feature-flags/store/feature-flags.model';
import { IMenuButtonItem } from 'upgrade_types';


@Component({
selector: 'app-feature-flag-exclusions-section-card',
standalone: true,
Expand All @@ -24,6 +26,7 @@ import { IMenuButtonItem } from 'upgrade_types';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FeatureFlagExclusionsSectionCardComponent {
@Input() data: FeatureFlag;
tableRowCount$ = of(1);
menuButtonItems: IMenuButtonItem[] = [
{ name: 'Edit', disabled: false },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { CommonSectionCardComponent } from '../../../../../../../shared-standalone-component-lib/components';
import { FeatureFlag } from '../../../../../../../core/feature-flags/store/feature-flags.model';

@Component({
selector: 'app-feature-flag-exposures-section-card',
Expand All @@ -9,4 +10,6 @@ import { CommonSectionCardComponent } from '../../../../../../../shared-standalo
styleUrl: './feature-flag-exposures-section-card.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FeatureFlagExposuresSectionCardComponent {}
export class FeatureFlagExposuresSectionCardComponent {
@Input() data: FeatureFlag;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ import {
import { TranslateModule } from '@ngx-translate/core';
import { CommonModule } from '@angular/common';
import { of } from 'rxjs';

import { FeatureFlag } from '../../../../../../../core/feature-flags/store/feature-flags.model';

import { IMenuButtonItem } from 'upgrade_types';


@Component({
selector: 'app-feature-flag-inclusions-section-card',
standalone: true,
Expand All @@ -24,10 +28,14 @@ import { IMenuButtonItem } from 'upgrade_types';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FeatureFlagInclusionsSectionCardComponent {

@Input() data: FeatureFlag;

menuButtonItems: IMenuButtonItem[] = [
{ name: 'Edit', disabled: false },
{ name: 'Delete', disabled: false },
];

tableRowCount$ = of(1);
isSectionCardExpanded = true;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
.full-width {
width: 100%; // TODO try not to set here, should be in the common parent...
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import {
CommonSectionCardActionButtonsComponent,
CommonSectionCardComponent,
Expand Down Expand Up @@ -29,6 +29,7 @@ import {
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FeatureFlagOverviewDetailsSectionCardComponent {
@Input() data: FeatureFlag;
//temp mock data
featureFlag: FeatureFlag = {
createdAt: '2021-09-08T08:00:00.000Z',
Expand Down Expand Up @@ -59,15 +60,15 @@ export class FeatureFlagOverviewDetailsSectionCardComponent {
isSectionCardExpanded = true;

ngOnInit() {
this.flagName = this.featureFlag.name;
this.flagCreatedAt = this.featureFlag.createdAt;
this.flagUpdatedAt = this.featureFlag.updatedAt;
this.flagStatus = this.featureFlag.status;
this.flagName = this.data.name;
this.flagCreatedAt = this.data.createdAt;
this.flagUpdatedAt = this.data.updatedAt;
this.flagStatus = this.data.status;
this.flagOverviewDetails = {
['Key']: this.featureFlag.key,
['Description']: this.featureFlag.description,
['App Context']: this.featureFlag.context[0],
['Tags']: this.featureFlag.tags,
['Key']: this.data.key,
['Description']: this.data.description,
['App Context']: this.data.context[0],
['Tags']: this.data.tags,
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<app-common-page>
<app-common-page class="app-common-page">
<app-feature-flag-details-page-header header></app-feature-flag-details-page-header>
<app-feature-flag-details-page-content content></app-feature-flag-details-page-content>
</app-common-page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
app-common-page {
display: block;
padding: 2px 0;
overflow: auto;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
border: 1px solid var(--light-grey);
border-radius: 4px;
background-color: var(--white);

overflow: hidden;
.header {
height: 96px;
display: flex;
Expand Down
Loading