Skip to content

Commit 5307d7b

Browse files
committed
wip
1 parent e03e543 commit 5307d7b

File tree

5 files changed

+170
-12
lines changed

5 files changed

+170
-12
lines changed

ui/web-v2/src/components/CancelScheduleDialog/index.tsx

+10-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { shallowEqual, useDispatch, useSelector } from 'react-redux';
77
import { messages } from '../../lang/messages';
88
import { Modal } from '../Modal';
99
import RevertSvg from '../../assets/svg/revert.svg';
10+
import { updateFeature } from '../../modules/features';
1011

1112
interface CancelScheduleDialogProps {
1213
open: boolean;
@@ -20,6 +21,10 @@ export const CancelScheduleDialog: FC<CancelScheduleDialogProps> = ({
2021
const dispatch = useDispatch<AppDispatch>();
2122
const { formatMessage: f } = useIntl();
2223

24+
const handleCancel = () => {
25+
// dispatch(updateFeature({ id: 1, status: 'scheduled' }));
26+
onClose();
27+
};
2328
return (
2429
<Modal open={open} onClose={onClose}>
2530
<Dialog.Title
@@ -47,7 +52,11 @@ export const CancelScheduleDialog: FC<CancelScheduleDialogProps> = ({
4752
>
4853
{f(messages.button.cancel)}
4954
</button>
50-
<button type="button" className="btn bg-[#EB1726]" onClick={() => {}}>
55+
<button
56+
type="button"
57+
className="btn bg-[#EB1726]"
58+
onClick={handleCancel}
59+
>
5160
Revert
5261
</button>
5362
</div>

ui/web-v2/src/components/FeatureTargetingForm/index.tsx

+59-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ import { AppState } from '../../modules';
4646
import {
4747
selectById as selectFeatureById,
4848
selectAll as selectAllFeatures,
49-
listFeatures
49+
listFeatures,
50+
updateFeature
5051
} from '../../modules/features';
5152
import { useCurrentEnvironment, useIsEditable } from '../../modules/me';
5253
import {
@@ -69,6 +70,7 @@ import { CancelScheduleDialog } from '../CancelScheduleDialog';
6970
import { Dialog } from '@headlessui/react';
7071
import ProjectSvg from '../../assets/svg/project.svg';
7172
import { Overlay } from '../Overlay';
73+
import { Modal } from '../Modal';
7274

7375
interface FeatureTargetingFormProps {
7476
featureId: string;
@@ -78,6 +80,7 @@ interface FeatureTargetingFormProps {
7880
export const FeatureTargetingForm: FC<FeatureTargetingFormProps> = memo(
7981
({ featureId, onOpenConfirmDialog }) => {
8082
const { formatMessage: f } = useIntl();
83+
const dispatch = useDispatch<AppDispatch>();
8184
const editable = useIsEditable();
8285
const methods = useFormContext<TargetingForm>();
8386
const {
@@ -183,14 +186,63 @@ export const FeatureTargetingForm: FC<FeatureTargetingFormProps> = memo(
183186
);
184187
};
185188

189+
const handleApplyNow = () => {
190+
setIsApplyNowOpen(false);
191+
dispatch(
192+
updateFeature({
193+
environmentId: currentEnvironment.id,
194+
id: featureId,
195+
applyScheduleUpdate: true
196+
})
197+
);
198+
};
199+
186200
const [open, setOpen] = useState(false);
201+
const [isApplyNowOpen, setIsApplyNowOpen] = useState(false);
187202
const [isSeeChangesModalOpen, setIsSeeChangesModalOpen] = useState(false);
188203

189204
const disabled = false;
190205

206+
console.log({
207+
feature
208+
});
209+
191210
return (
192211
<div className="p-10 bg-gray-100">
193212
<CancelScheduleDialog open={open} onClose={() => setOpen(false)} />
213+
<Modal open={isApplyNowOpen} onClose={() => setIsApplyNowOpen(false)}>
214+
<Dialog.Title
215+
as="h3"
216+
className="text-lg font-medium leading-6 text-gray-900"
217+
>
218+
Apply Changes
219+
</Dialog.Title>
220+
<div className="py-6 flex justify-center">Icon</div>
221+
<div className="mt-2 text-center px-5">
222+
<p className="text-sm text-gray-500">
223+
Apply changes now description.
224+
</p>
225+
</div>
226+
<div className="pt-10">
227+
<div className="flex justify-end">
228+
<button
229+
type="button"
230+
className="btn-cancel mr-3"
231+
disabled={false}
232+
onClick={() => setIsApplyNowOpen(false)}
233+
>
234+
{f(messages.button.cancel)}
235+
</button>
236+
<button
237+
type="button"
238+
className="btn btn-submit"
239+
onClick={handleApplyNow}
240+
>
241+
Apply Now
242+
</button>
243+
</div>
244+
</div>
245+
</Modal>
194246
<div className="bg-blue-50 p-4 border-l-4 border-blue-400 mb-7 inline-block">
195247
<div className="flex">
196248
<div className="flex-shrink-0">
@@ -207,7 +259,12 @@ export const FeatureTargetingForm: FC<FeatureTargetingFormProps> = memo(
207259
<div className="flex items-center">
208260
<div className="flex items-center text-primary border-r border-gray-300 pr-4 space-x-2">
209261
<CheckIcon className="w-5 h-5" />
210-
<button className="text-sm font-normal">Apply Now</button>
262+
<button
263+
className="text-sm font-normal"
264+
onClick={() => setIsApplyNowOpen(true)}
265+
>
266+
Apply Now
267+
</button>
211268
</div>
212269
<div className="flex items-center text-primary border-r border-gray-300 px-4 space-x-2">
213270
<PencilIcon className="w-4 h-4" />

ui/web-v2/src/modules/features.ts

+42-7
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ import {
2626
UnarchiveFeatureCommand,
2727
Command
2828
} from '../proto/feature/command_pb';
29-
import { Feature } from '../proto/feature/feature_pb';
29+
import {
30+
Feature,
31+
ScheduleUpdate,
32+
ScheduleUpdateListValue
33+
} from '../proto/feature/feature_pb';
3034
import {
3135
ArchiveFeatureRequest,
3236
CreateFeatureRequest,
@@ -42,7 +46,9 @@ import {
4246
UpdateFeatureVariationsRequest,
4347
ListTagsRequest,
4448
ListTagsResponse,
45-
UpdateFeatureRequest
49+
UpdateFeatureRequest,
50+
TagChange,
51+
ChangeType
4652
} from '../proto/feature/service_pb';
4753
import { Variation, VariationListValue } from '../proto/feature/variation_pb';
4854
import { AppState } from '.';
@@ -280,8 +286,9 @@ export const updateFeatureDetails = createAsyncThunk<
280286
export interface UpdateFeatureParams {
281287
environmentId: string;
282288
id: string;
283-
comment: string;
289+
comment?: string;
284290
enabled?: boolean;
291+
applyScheduleUpdate?: boolean;
285292
prerequisitesList?: {
286293
featureId: string;
287294
variationId: string;
@@ -331,9 +338,10 @@ export interface UpdateFeatureParams {
331338
}[];
332339
name?: string;
333340
description?: string;
334-
tags?: string[];
341+
tags?: Array<TagChange>;
335342
archived?: boolean;
336343
resetSampling?: boolean;
344+
feature?: Feature;
337345
}
338346

339347
export const updateFeature = createAsyncThunk<
@@ -344,18 +352,28 @@ export const updateFeature = createAsyncThunk<
344352
const request = new UpdateFeatureRequest();
345353
request.setEnvironmentId(params.environmentId);
346354
request.setId(params.id);
347-
request.setComment(params.comment);
348355

349356
console.log('params', params);
350357

358+
if (params.comment) {
359+
request.setComment(params.comment);
360+
}
361+
362+
if (params.applyScheduleUpdate) {
363+
request.setApplyScheduleUpdate(
364+
new BoolValue().setValue(params.applyScheduleUpdate)
365+
);
366+
}
367+
351368
if (params.enabled !== undefined) {
352369
console.log('Enabled set');
353370
request.setEnabled(new BoolValue().setValue(params.enabled));
354371
}
355372

356373
if (params.prerequisitesList) {
357374
console.log('pre-requisites set');
358-
request.setPrerequisites(mapToPrerequisites(params.prerequisitesList));
375+
// request.setPrerequisiteChangesList(params.prerequisitesList);
376+
// request.setPrerequisites(mapToPrerequisites(params.prerequisitesList));
359377
}
360378

361379
if (params.targets) {
@@ -395,7 +413,8 @@ export const updateFeature = createAsyncThunk<
395413

396414
if (params.tags) {
397415
console.log('tags set');
398-
request.setTags(mapTags(params.tags));
416+
request.setTagChangesList(params.tags);
417+
// request.setTags(mapTags(params.tags));
399418
}
400419

401420
if (params.archived !== undefined) {
@@ -410,6 +429,22 @@ export const updateFeature = createAsyncThunk<
410429
);
411430
}
412431

432+
// const scheduleUpdateListValue = new ScheduleUpdateListValue();
433+
// const scheduleUpdate = new ScheduleUpdate();
434+
435+
// const today = new Date();
436+
// today.setDate(today.getDate() + 1);
437+
438+
// scheduleUpdate.setUpdateAt(today.getTime());
439+
440+
// // const feature = new Feature();
441+
// // feature.setId(params.id);
442+
// // feature.setName('test 1');
443+
444+
// scheduleUpdate.setFeature(params.feature);
445+
// scheduleUpdateListValue.setValueList([scheduleUpdate]);
446+
// request.setScheduleUpdates(scheduleUpdateListValue);
447+
413448
await featureGrpc.updateFeature(request);
414449
});
415450

ui/web-v2/src/pages/feature/settings.tsx

+33-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { settingsFormSchema } from './formSchema';
3434
import { listTags } from '../../modules/tags';
3535
import { ListTagsRequest } from '../../proto/tag/service_pb';
3636
import { Tag } from '../../proto/tag/tag_pb';
37+
import { ChangeType, TagChange } from '../../proto/feature/service_pb';
3738

3839
interface FeatureSettingsPageProps {
3940
featureId: string;
@@ -109,14 +110,45 @@ export const FeatureSettingsPage: FC<FeatureSettingsPageProps> = memo(
109110
});
110111
};
111112

113+
const tags = [];
114+
115+
if (dirtyFields.tags) {
116+
const addTags = data.tags?.filter(
117+
(tag) => !feature.tagsList.includes(tag)
118+
);
119+
if (addTags?.length) {
120+
const output = addTags.map((tag) => {
121+
const addTagChange = new TagChange();
122+
addTagChange.setTag(tag);
123+
addTagChange.setChangeType(ChangeType.CREATE);
124+
return addTagChange;
125+
});
126+
tags.push(...output);
127+
}
128+
129+
const removeTags = feature.tagsList.filter(
130+
(tag) => !data.tags?.includes(tag)
131+
);
132+
133+
if (removeTags?.length) {
134+
const output = removeTags.map((tag) => {
135+
const removeTagChange = new TagChange();
136+
removeTagChange.setTag(tag);
137+
removeTagChange.setChangeType(ChangeType.DELETE);
138+
return removeTagChange;
139+
});
140+
tags.push(...output);
141+
}
142+
}
143+
112144
if (saveFeatureType === SaveFeatureType.SCHEDULE) {
113145
await prepareUpdate(updateFeature, {
114146
environmentId: currentEnvironment.id,
115147
id: feature.id,
116148
comment: data.comment,
117149
name: dirtyFields.name ? data.name : undefined,
118150
description: dirtyFields.description ? data.description : undefined,
119-
tags: dirtyFields.tags ? data.tags : undefined
151+
tags: tags.length ? tags : undefined
120152
});
121153
} else {
122154
const commands: UpdateDetailCommands = {};

ui/web-v2/src/pages/feature/targeting.tsx

+26-1
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,30 @@ export const FeatureTargetingPage: FC<FeatureTargetingPageProps> = memo(
181181
field && JSON.stringify(field).includes('true');
182182

183183
if (saveFeatureType === SaveFeatureType.SCHEDULE) {
184+
const defaultValues = getDefaultValues(
185+
feature,
186+
currentEnvironment.requireComment
187+
);
188+
189+
let prerequisitesList = [];
190+
if (hasDirtyField(dirtyFields.prerequisites)) {
191+
// handle remove feature
192+
defaultValues.prerequisites.filter((o) => {
193+
if (
194+
!data.prerequisites.some((v) => v.featureId === o.featureId)
195+
) {
196+
// const command = new RemovePrerequisiteCommand();
197+
// command.setFeatureId(o.featureId);
198+
// commands.push(
199+
// createCommand({
200+
// message: command,
201+
// name: 'RemovePrerequisiteCommand'
202+
// })
203+
// );
204+
}
205+
});
206+
}
207+
184208
const updatePayload = {
185209
environmentId: currentEnvironment.id,
186210
id: featureId,
@@ -195,7 +219,8 @@ export const FeatureTargetingPage: FC<FeatureTargetingPageProps> = memo(
195219
data.defaultStrategy,
196220
offVariation:
197221
hasDirtyField(dirtyFields.offVariation) && data.offVariation,
198-
resetSampling: data.resetSampling
222+
resetSampling: data.resetSampling,
223+
feature: feature
199224
};
200225

201226
await prepareUpdate(updateFeature, updatePayload);

0 commit comments

Comments
 (0)