Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions backend/packages/Upgrade/src/api/services/SegmentService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@ export class SegmentService {
case SEGMENT_SEARCH_KEY.NAME:
searchString.push("coalesce(segment.name::TEXT,'')");
break;
case SEGMENT_SEARCH_KEY.STATUS:
searchString.push("coalesce(segment.status::TEXT,'')");
break;
case SEGMENT_SEARCH_KEY.CONTEXT:
searchString.push("coalesce(segment.context::TEXT,'')");
break;
Expand All @@ -250,6 +253,7 @@ export class SegmentService {
break;
default:
searchString.push("coalesce(segment.name::TEXT,'')");
searchString.push("coalesce(feature_flag.status::TEXT,'')");
searchString.push("coalesce(segment.context::TEXT,'')");
searchString.push("coalesce(segment.tags::TEXT,'')");
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export class FeatureFlagsEffects {
)
);

// actionCreateFeatureFlag dispatch POST feature flag
// actionAddFeatureFlag dispatch POST feature flag
addFeatureFlag$ = createEffect(() =>
this.actions$.pipe(
ofType(FeatureFlagsActions.actionAddFeatureFlag),
Expand Down Expand Up @@ -313,6 +313,7 @@ export class FeatureFlagsEffects {
)
)
);

exportFeatureFlagsDesign$ = createEffect(() =>
this.actions$.pipe(
ofType(FeatureFlagsActions.actionExportFeatureFlagDesign),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface CoreFeatureFlagDetails {
key: string;
description?: string;
context: string[];
tags: string[];
tags?: string[];
status: FEATURE_FLAG_STATUS;
filterMode: FILTER_MODE;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export class LocalStorageService {
searchString: segmentSearchString || null,
sortKey: (segmentSortKey as SEGMENT_SORT_KEY) || SEGMENT_SORT_KEY.NAME,
sortAs: (segmentSortType as SORT_AS_DIRECTION) || SORT_AS_DIRECTION.ASCENDING,
isLoadingUpsertSegment: false,
};

const state = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Inject, Injectable } from '@angular/core';
import { SegmentFile, SegmentInput } from './store/segments.model';
import { AddSegmentRequest, SegmentFile, SegmentInput } from './store/segments.model';
import { HttpClient, HttpParams } from '@angular/common/http';
import { ENV, Environment } from '../../../environments/environment-types';

Expand All @@ -17,6 +17,11 @@ export class SegmentsDataService {
return this.http.post(url, segment);
}

addSegment(segment: AddSegmentRequest) {
const url = this.environment.api.segments;
return this.http.post(url, segment);
}

getSegmentById(id: string) {
const url = `${this.environment.api.segments}/status/${id}`;
return this.http.get(url);
Expand All @@ -32,6 +37,11 @@ export class SegmentsDataService {
return this.http.post(url, segment);
}

modifySegment(segment: AddSegmentRequest) {
const url = this.environment.api.segments;
return this.http.post(url, segment);
}

exportSegments(segmentIds: string[]) {
let ids = new HttpParams();
segmentIds.forEach((id) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,19 @@ import {
selectSortKey,
selectSortAs,
selectSegmentLists,
selectAppContexts,
selectIsLoadingUpsertSegment,
} from './store/segments.selectors';
import {
AddSegmentRequest,
LIST_OPTION_TYPE,
Segment,
SegmentInput,
SegmentLocalStorageKeys,
UpdateSegmentRequest,
UpsertSegmentType,
} from './store/segments.model';
import { filter, map, tap, withLatestFrom } from 'rxjs/operators';
import { filter, map, pairwise, tap, withLatestFrom } from 'rxjs/operators';
import { Observable, combineLatest } from 'rxjs';
import { SegmentsDataService } from './segments.data.service';
import { SEGMENT_SEARCH_KEY, SORT_AS_DIRECTION, SEGMENT_SORT_KEY } from 'upgrade_types';
Expand All @@ -34,6 +38,8 @@ import { selectShouldUseLegacyUI } from './store/segments.selectors';
import { selectContextMetaData } from '../experiments/store/experiments.selectors';
import { selectSelectedFeatureFlag } from '../feature-flags/store/feature-flags.selectors';
import { CommonTextHelpersService } from '../../shared/services/common-text-helpers.service';
import { actionFetchContextMetaData } from '../experiments/store/experiments.actions';
import isEqual from 'lodash.isequal';

@Injectable({ providedIn: 'root' })
export class SegmentsService {
Expand All @@ -44,6 +50,15 @@ export class SegmentsService {
) {}

isLoadingSegments$ = this.store$.pipe(select(selectIsLoadingSegments));
isLoadingUpsertSegment$ = this.store$.pipe(select(selectIsLoadingUpsertSegment));
isSelectedSegmentUpdated$ = this.store$.pipe(
select(selectSelectedSegment),
pairwise(),
filter(([prev, curr]) => {
return prev && curr && !isEqual(prev, curr);
}),
map(([, curr]) => curr)
);
selectAllSegments$ = this.store$.pipe(select(selectAllSegments));
selectedSegment$ = this.store$.pipe(select(selectSelectedSegment));
shouldUseLegacyView$ = this.store$.pipe(select(selectShouldUseLegacyUI));
Expand All @@ -57,6 +72,7 @@ export class SegmentsService {
select(selectSegmentLists),
map((lists) => lists.length)
);
appContexts$ = this.store$.pipe(select(selectAppContexts));
allExperimentSegmentsInclusion$ = this.store$.pipe(select(selectExperimentSegmentsInclusion));
allExperimentSegmentsExclusion$ = this.store$.pipe(select(selectExperimentSegmentsExclusion));
allFeatureFlagSegmentsExclusion$ = this.store$.pipe(select(selectFeatureFlagSegmentsExclusion));
Expand Down Expand Up @@ -132,6 +148,10 @@ export class SegmentsService {
this.store$.dispatch(SegmentsActions.actionGetSegmentById({ segmentId }));
}

fetchContextMetaData() {
this.store$.dispatch(actionFetchContextMetaData({ isLoadingContextMetaData: true }));
}

isInitialSegmentsLoading() {
return combineLatest(this.store$.pipe(select(selectIsLoadingSegments)), this.allSegments$).pipe(
map(([isLoading, segments]) => !isLoading || !!segments.length)
Expand Down Expand Up @@ -178,6 +198,15 @@ export class SegmentsService {
);
}

addSegment(addSegmentRequest: AddSegmentRequest) {
this.store$.dispatch(SegmentsActions.actionAddSegment({ addSegmentRequest }));
}


modifySegment(updateSegmentRequest: UpdateSegmentRequest) {
this.store$.dispatch(SegmentsActions.actionUpdateSegment({ updateSegmentRequest }));
}

exportSegments(segmentIds: string[]) {
this.store$.dispatch(SegmentsActions.actionExportSegments({ segmentIds }));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { createAction, props } from '@ngrx/store';
import {
AddSegmentRequest,
Segment,
SegmentInput,
UpdateSegmentRequest,
UpsertSegmentType,
experimentSegmentInclusionExclusionData,
featureFlagSegmentInclusionExclusionData,
Expand Down Expand Up @@ -39,6 +41,27 @@ export const actionUpsertSegmentSuccess = createAction(

export const actionUpsertSegmentFailure = createAction('[Segments] Upsert Segment Failure');

export const actionAddSegment = createAction(
'[Segments] Add Segment',
props<{ addSegmentRequest: AddSegmentRequest }>()
);

export const actionAddSegmentSuccess = createAction('[Segments] Add Segment Success', props<{ response: Segment }>());

export const actionAddSegmentFailure = createAction('[Segments] Add Segment Failure');

export const actionUpdateSegment = createAction(
'[Segments] Update Segment',
props<{ updateSegmentRequest: UpdateSegmentRequest }>()
);

export const actionUpdateSegmentSuccess = createAction(
'[Segments] Update Segment Success',
props<{ response: Segment }>()
);

export const actionUpdateSegmentFailure = createAction('[Segments] Update Segment Failure');

export const actionGetSegmentById = createAction('[Segments] Get Segment By Id', props<{ segmentId: string }>());

export const actionGetSegmentByIdSuccess = createAction(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { select, Store } from '@ngrx/store';
import { catchError, filter, map, switchMap, withLatestFrom } from 'rxjs/operators';
import { catchError, filter, map, switchMap, tap, withLatestFrom } from 'rxjs/operators';
import { AppState } from '../../core.module';
import { SegmentsDataService } from '../segments.data.service';
import * as SegmentsActions from './segments.actions';
import { Segment, UpsertSegmentType } from './segments.model';
import { selectAllSegments } from './segments.selectors';
import JSZip from 'jszip';
import { SERVER_ERROR } from 'upgrade_types';

@Injectable()
export class SegmentsEffects {
Expand Down Expand Up @@ -81,6 +82,41 @@ export class SegmentsEffects {
)
);

// actionAddSegment dispatch POST segment
addSegment$ = createEffect(() =>
this.actions$.pipe(
ofType(SegmentsActions.actionAddSegment),
switchMap((action) => {
return this.segmentsDataService.addSegment(action.addSegmentRequest).pipe(
map((response: Segment) => SegmentsActions.actionAddSegmentSuccess({ response })),
tap(({ response }) => {
this.router.navigate(['/segments', 'detail', response.id]);
}),
catchError(() => {
return [SegmentsActions.actionAddSegmentFailure()];
})
);
})
)
);

updateSegment$ = createEffect(() =>
this.actions$.pipe(
ofType(SegmentsActions.actionUpdateSegment),
switchMap((action) => {
return this.segmentsDataService.modifySegment(action.updateSegmentRequest).pipe(
map((response: Segment) => SegmentsActions.actionUpdateSegmentSuccess({ response })),
tap(({ response }) => {
this.router.navigate(['/segments', 'detail', response.id]);
}),
catchError(() => {
return [SegmentsActions.actionUpdateSegmentFailure()];
})
);
})
)
);

deleteSegment$ = createEffect(() =>
this.actions$.pipe(
ofType(SegmentsActions.actionDeleteSegment),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
SEGMENT_SEARCH_KEY,
SORT_AS_DIRECTION,
SEGMENT_SORT_KEY,
FILTER_MODE,
FEATURE_FLAG_LIST_FILTER_MODE,
} from 'upgrade_types';
export { SEGMENT_STATUS };
Expand Down Expand Up @@ -111,6 +112,27 @@ export interface Segment {
status: SEGMENT_STATUS;
}

export interface CoreSegmentDetails {
id?: string;
name: string;
context: string;
description?: string;
tags?: string[];
userIds: string[];
groups: Group[];
subSegmentIds: string[];
status?: SEGMENT_STATUS;
type: SEGMENT_TYPE;
}

// Currently there is no difference between these types, but they semantically different and could diverge later
export type AddSegmentRequest = CoreSegmentDetails;

// so that we can throw an error if we try to update the id
export interface UpdateSegmentRequest extends AddSegmentRequest {
readonly id: string;
}

export interface SegmentInput {
createdAt: string;
updatedAt: string;
Expand Down Expand Up @@ -140,6 +162,7 @@ export enum SEGMENT_DETAILS_PAGE_ACTIONS {

export interface SegmentState extends EntityState<Segment> {
isLoadingSegments: boolean;
isLoadingUpsertSegment: boolean;
// TODO: remove any
allExperimentSegmentsInclusion: any;
allExperimentSegmentsExclusion: any;
Expand Down Expand Up @@ -249,3 +272,26 @@ export interface AddPrivateSegmentListRequest extends PrivateSegmentListRequest
export interface EditPrivateSegmentListRequest extends PrivateSegmentListRequest {
segment: EditPrivateSegmentListDetails;
}

export enum CommonTagInputType {
TAGS = 'tags',
VALUES = 'values',
}

export interface SegmentFormData {
name: string;
description: string;
appContext: string;
tags: string[];
}

export enum UPSERT_SEGMENT_ACTION {
ADD = 'add',
EDIT = 'edit',
DUPLICATE = 'duplicate',
}

export interface UpsertSegmentParams {
sourceSegment: Segment;
action: UPSERT_SEGMENT_ACTION;
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const initialState: SegmentState = adapter.getInitialState({
searchString: null,
sortKey: SEGMENT_SORT_KEY.NAME,
sortAs: SORT_AS_DIRECTION.ASCENDING,
isLoadingUpsertSegment: false,
});

const reducer = createReducer(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ export const selectSegmentById = createSelector(
(state, { segmentId }) => state.entities[segmentId]
);

export const selectAppContexts = createSelector(selectContextMetaData, (contextMetaData) =>
Object.keys(contextMetaData?.contextMetadata ?? [])
);

export const selectExperimentSegmentsInclusion = createSelector(
selectSegmentsState,
(state) => state.allExperimentSegmentsInclusion
Expand All @@ -38,6 +42,24 @@ export const selectFeatureFlagSegmentsExclusion = createSelector(
(state) => state.allFeatureFlagSegmentsExclusion
);

export const selectIsLoadingUpsertSegment = createSelector(
selectSegmentsState,
(state) => state.isLoadingUpsertSegment
);

// export const selectSelectedSegment = createSelector(
// selectRouterState,
// selectSegmentsState,
// (routerState, segmentState) => {
// // be very defensive here to make sure routerState is correct
// const segmentId = routerState?.state?.params?.segmentId;
// if (segmentId) {
// return segmentState.entities[segmentId];
// }
// return undefined;
// }
// );

export const selectSelectedSegment = createSelector(
selectRouterState,
selectSegmentsState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ export class UpsertFeatureFlagModalComponent {
@Inject(MAT_DIALOG_DATA)
public config: CommonModalConfig<UpsertFeatureFlagParams>,
public dialog: MatDialog,
private router: Router,
private formBuilder: FormBuilder,
private featureFlagsService: FeatureFlagsService,
private experimentService: ExperimentService,
Expand Down Expand Up @@ -211,7 +210,6 @@ export class UpsertFeatureFlagModalComponent {

sendRequest(action: UPSERT_FEATURE_FLAG_ACTION, sourceFlag?: FeatureFlag): void {
const formData: FeatureFlagFormData = this.featureFlagForm.value;

if (action === UPSERT_FEATURE_FLAG_ACTION.ADD || action === UPSERT_FEATURE_FLAG_ACTION.DUPLICATE) {
this.createAddRequest(formData);
} else if (action === UPSERT_FEATURE_FLAG_ACTION.EDIT && sourceFlag) {
Expand Down
Loading
Loading