From d0ddf566075414053a64218f4e3906e049dde639 Mon Sep 17 00:00:00 2001 From: ali Date: Tue, 28 Mar 2023 07:02:16 +1100 Subject: [PATCH 1/5] flag copy and other bug fixes --- ui/app/pages/environments/environments.tsx | 2 +- ui/app/pages/flags/constants.ts | 4 +-- ui/app/pages/flags/flags.tsx | 3 +- ui/app/pages/projects/api.ts | 4 +-- ui/components/page-layout/page-layout.tsx | 5 ++- ui/components/table/table.tsx | 37 +++++++++++++++++++++- 6 files changed, 45 insertions(+), 10 deletions(-) diff --git a/ui/app/pages/environments/environments.tsx b/ui/app/pages/environments/environments.tsx index efec7f22..7fa329a5 100644 --- a/ui/app/pages/environments/environments.tsx +++ b/ui/app/pages/environments/environments.tsx @@ -34,7 +34,7 @@ export const useEnvironments = () => { await configureAxios(instanceKey!) return fetchEnvironments(workspaceKey!, projectKey!) }, - enabled: !!instanceKey && !!workspaceKey, + enabled: !!instanceKey && !!workspaceKey && !!projectKey, } ) return query diff --git a/ui/app/pages/flags/constants.ts b/ui/app/pages/flags/constants.ts index d9572961..a149bc90 100644 --- a/ui/app/pages/flags/constants.ts +++ b/ui/app/pages/flags/constants.ts @@ -10,8 +10,8 @@ export const flagsColumn = [ }, { title: 'Key', - dataIndex: 'key', - key: 'key', + dataIndex: 'flagKey', + key: 'flagKey', }, { title: 'Description', diff --git a/ui/app/pages/flags/flags.tsx b/ui/app/pages/flags/flags.tsx index bcc203a9..9ef6c642 100644 --- a/ui/app/pages/flags/flags.tsx +++ b/ui/app/pages/flags/flags.tsx @@ -54,6 +54,7 @@ const convertFlags = ({ flags, environment }: { flags: Flag[]; environment: Envi return Object.values(flags).map((flag: Flag, index: number) => { return { id: index, + key: flag.attributes.key, title: flag.attributes.name, href: `${flag.attributes.key}/environments/${environment?.attributes.key}`, name: {flag.attributes.name}, @@ -68,7 +69,7 @@ const convertFlags = ({ flags, environment }: { flags: Flag[]; environment: Envi ), action: , - key: flag.attributes.key, + flagKey: flag.attributes.key, } }) } diff --git a/ui/app/pages/projects/api.ts b/ui/app/pages/projects/api.ts index 9c282fc9..28119f82 100644 --- a/ui/app/pages/projects/api.ts +++ b/ui/app/pages/projects/api.ts @@ -20,8 +20,8 @@ export const fetchProjects = async (workspaceKey: string) => { return result.data } -export const deleteProject = async (ProjectKey: string) => { - return axios.delete(`/projects/${ProjectKey}`) +export const deleteProject = async ({ workspaceKey, projectKey }: { workspaceKey: string; projectKey: string }) => { + return axios.delete(`/projects/${workspaceKey}/${projectKey}`) } export const createProject = async (name: string, description: string, tags: string[], workspaceKey: string) => { diff --git a/ui/components/page-layout/page-layout.tsx b/ui/components/page-layout/page-layout.tsx index f2201b4f..872ffd84 100644 --- a/ui/components/page-layout/page-layout.tsx +++ b/ui/components/page-layout/page-layout.tsx @@ -2,7 +2,6 @@ import React, { createElement, Fragment, ReactNode, useEffect } from 'react' import { Link, Outlet, useLocation, useMatches, useParams } from 'react-router-dom' import flag from '../../assets/flagbaseLogo.svg' -import flagOld from '../../assets/flag.svg' import { useState } from 'react' import { Disclosure, Transition, Popover, Dialog } from '@headlessui/react' import { @@ -11,7 +10,6 @@ import { ChevronDownIcon, ChevronRightIcon, XMarkIcon, - CodeBracketIcon } from '@heroicons/react/24/outline' import { useInstances } from '../../app/pages/instances/instances' import { @@ -36,6 +34,7 @@ import { Flag } from '../../app/pages/flags/api' import { useVariations } from '../../app/pages/variations/variations' import { useSDKs } from '../../app/pages/sdks/sdks' import { Footer } from './footer' +import { CopyRow } from '../table' import CodeUsageModal from '../code-usage-modal' const instancesDescription = `An "instance" refers to a Flagbase core installation, running on a single VPS or clustered in a datacenter.` @@ -552,7 +551,7 @@ export const PageHeadings = () => { } else if (instanceKey && workspaceKey && projectKey && flagKey) { setPageHeading({ title: activeFlag?.attributes.name || flagKey, - subtitle: 'Feature Flag', + subtitle: , backHref: `/${instanceKey}/workspaces/${workspaceKey}/projects/${projectKey}/flags`, tabs: [ { diff --git a/ui/components/table/table.tsx b/ui/components/table/table.tsx index fc132e26..199b938b 100644 --- a/ui/components/table/table.tsx +++ b/ui/components/table/table.tsx @@ -1,9 +1,11 @@ -import React from 'react' +import React, { useState } from 'react' import { Table as AntdTable, TableColumnProps, TableProps as AntdTableProps, TableColumnType } from 'antd' import styled from '@emotion/styled' import EmptyState from '../empty-state' import Button from '../button/button' import { useNavigate } from 'react-router-dom' +import { DocumentDuplicateIcon } from '@heroicons/react/20/solid' +import { Notification } from '../notification/notification' export type TableProps = { loading: boolean @@ -18,6 +20,37 @@ const StyledTable = styled(AntdTable)` } ` +export const CopyRow = ({ text }: { text: string }) => { + const [copied, setCopied] = useState(false) + return ( +
+
{text}
+ + setCopied(show)} + /> +
+ ) +} + const Table: React.FC = ({ loading, columns, @@ -40,6 +73,8 @@ const Table: React.FC = ({ onRow={(record, rowIndex) => { return { onClick: (event) => { + event.preventDefault() + console.log('record', record, rowIndex) const { href } = record if (href) { navigate(href) From ded5d70dca538d1ba318f0bdc3a57af2b8cbc275 Mon Sep 17 00:00:00 2001 From: ali Date: Tue, 28 Mar 2023 21:15:03 +1100 Subject: [PATCH 2/5] fix delete project --- ui/app/pages/projects/projects.edit.tsx | 2 +- ui/app/pages/projects/projects.tsx | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ui/app/pages/projects/projects.edit.tsx b/ui/app/pages/projects/projects.edit.tsx index e775e326..c8f64b06 100644 --- a/ui/app/pages/projects/projects.edit.tsx +++ b/ui/app/pages/projects/projects.edit.tsx @@ -62,7 +62,7 @@ const EditProject = () => { throw new Error('Missing required params') } - const { mutate: remove } = useRemoveProject(instanceKey, workspaceKey) + const { mutate: remove } = useRemoveProject() const { mutate: update, isSuccess, error } = useUpdateProject(instanceKey) if (!project) { diff --git a/ui/app/pages/projects/projects.tsx b/ui/app/pages/projects/projects.tsx index 67998cb3..3e256fe8 100644 --- a/ui/app/pages/projects/projects.tsx +++ b/ui/app/pages/projects/projects.tsx @@ -64,11 +64,13 @@ export const convertProjects = ({ }) } -export const useRemoveProject = (instanceKey: string, workspaceKey: string) => { +export const useRemoveProject = () => { + const { instanceKey, workspaceKey } = useFlagbaseParams() const queryClient = useQueryClient() const mutation = useMutation({ + mutationKey: ['projects', instanceKey, workspaceKey], mutationFn: async (projectKey: string) => { - await deleteProject(projectKey) + await deleteProject({ projectKey, workspaceKey }) }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['projects', instanceKey, workspaceKey] }) @@ -77,9 +79,11 @@ export const useRemoveProject = (instanceKey: string, workspaceKey: string) => { return mutation } -export const useAddProject = (instanceKey: string, workspaceKey: string) => { +export const useAddProject = () => { + const { instanceKey, workspaceKey } = useFlagbaseParams() const queryClient = useQueryClient() const mutation = useMutation({ + mutationKey: ['projects', instanceKey, workspaceKey], mutationFn: async (values: Omit) => { await createProject(values.name, values.description, values.tags, workspaceKey) }, @@ -99,7 +103,6 @@ export const useProjects = (options?: any) => { return fetchProjects(workspaceKey!) }, enabled: !!instanceKey && !!workspaceKey, - refetchOnWindowFocus: false, }) return query } From 6ae6b72ec6a626cd7020b66c94924d0317626ee1 Mon Sep 17 00:00:00 2001 From: Ali Shaikh Date: Tue, 28 Mar 2023 23:51:40 +1100 Subject: [PATCH 3/5] trying to fix targeting --- ui/app/pages/flags/api.tsx | 7 ++++--- ui/app/pages/instances/instances.constants.tsx | 7 ++++++- ui/app/pages/targeting/targeting.tsx | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/ui/app/pages/flags/api.tsx b/ui/app/pages/flags/api.tsx index abc214ae..1231ed9f 100644 --- a/ui/app/pages/flags/api.tsx +++ b/ui/app/pages/flags/api.tsx @@ -1,5 +1,6 @@ import { axios } from '../../lib/axios' import { FlagbaseParams } from '../../lib/use-flagbase-params' +import { TargetingResponse, TargetingRuleResponse } from '../targeting/api' import { UpdateBody } from '../workspaces/api' export type Flag = { @@ -77,7 +78,7 @@ export const fetchTargeting = async ({ projectKey, environmentKey, flagKey, -}: Partial) => { +}: Partial): Promise => { const { data } = await axios.get(`/targeting/${workspaceKey}/${projectKey}/${environmentKey}/${flagKey}`) return data } @@ -87,7 +88,7 @@ export const fetchTargetingRules = async ({ projectKey, environmentKey, flagKey, -}: Partial) => { +}: Partial): Promise => { const { data } = await axios.get(`/targeting/${workspaceKey}/${projectKey}/${environmentKey}/${flagKey}/rules`) return data } @@ -98,7 +99,7 @@ export const fetchTargetingRule = async ({ environmentKey, flagKey, ruleKey, -}: Partial) => { +}: Partial): Promise => { const { data } = await axios.get( `/targeting/${workspaceKey}/${projectKey}/${environmentKey}/${flagKey}/rules/${ruleKey}` ) diff --git a/ui/app/pages/instances/instances.constants.tsx b/ui/app/pages/instances/instances.constants.tsx index 55f1c734..c07a9a99 100644 --- a/ui/app/pages/instances/instances.constants.tsx +++ b/ui/app/pages/instances/instances.constants.tsx @@ -22,7 +22,12 @@ export const instanceColumns = [ export const InstanceSchema = Yup.object().shape({ key: Yup.string().min(2, 'Too Short!').max(50, 'Too Long!').required('This field is required'), - connectionString: Yup.string().min(2, 'Too Short!').max(50, 'Too Long!').required('This field is required'), + connectionUrl: Yup.string() + .matches( + /((https?):\/\/)?(www.)?[a-z0-9]+(\.[a-z]{2,}){1,3}(#?\/?[a-zA-Z0-9#]+)*\/?(\?[a-zA-Z0-9-_]+=[a-zA-Z0-9-%]+&?)?$/, + 'Enter correct url!' + ) + .required('Please enter website'), accessKey: Yup.string().min(2, 'Too Short!').max(50, 'Too Long!').required('This field is required'), accessSecret: Yup.string().min(2, 'Too Short!').max(50, 'Too Long!').required('This field is required'), }) diff --git a/ui/app/pages/targeting/targeting.tsx b/ui/app/pages/targeting/targeting.tsx index 785e342d..3eb134ad 100644 --- a/ui/app/pages/targeting/targeting.tsx +++ b/ui/app/pages/targeting/targeting.tsx @@ -23,11 +23,11 @@ import EmptyState from '../../../components/empty-state' import CodeUsageModal from '../../../components/code-usage-modal' import { useMutation, useQuery, useQueryClient } from 'react-query' import { getTargetingKey, getTargetingRulesKey } from '../../router/loaders' -import { configureAxios } from '../../lib/axios' import { fetchTargeting, fetchTargetingRules } from '../flags/api' import { useVariations } from '../variations/variations' import { TargetingRules } from './targeting-rules' import { useNotification } from '../../hooks/use-notification' +import { configureAxios } from '../../lib/axios' type VariationResponse = { type: 'variation' From e0f0c4f9b7185cc9e9f405b9cdd53b6f894f72ef Mon Sep 17 00:00:00 2001 From: ali Date: Thu, 30 Mar 2023 00:19:06 +1100 Subject: [PATCH 4/5] notification provider --- ui/app/notifications/index.tsx | 17 +++++++++++++++++ ui/app/pages/instances/instances.constants.tsx | 7 ++++--- ui/app/pages/instances/instances.modal.tsx | 11 ++++++++--- 3 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 ui/app/notifications/index.tsx diff --git a/ui/app/notifications/index.tsx b/ui/app/notifications/index.tsx new file mode 100644 index 00000000..9299b281 --- /dev/null +++ b/ui/app/notifications/index.tsx @@ -0,0 +1,17 @@ +import React from 'react' +import { useQuery } from 'react-query' +import { useFlagbaseParams } from '../lib/use-flagbase-params' + +const Notifications = () => { + const { instanceKey, workspaceKey } = useFlagbaseParams() + + const { isSuccess, isError } = useQuery({ + queryKey: ['projects', instanceKey, workspaceKey], + }) + + console.log('test', isSuccess, isError) + + return <> +} + +export default Notifications diff --git a/ui/app/pages/instances/instances.constants.tsx b/ui/app/pages/instances/instances.constants.tsx index c07a9a99..b001d4ca 100644 --- a/ui/app/pages/instances/instances.constants.tsx +++ b/ui/app/pages/instances/instances.constants.tsx @@ -21,13 +21,14 @@ export const instanceColumns = [ ] export const InstanceSchema = Yup.object().shape({ + name: Yup.string().min(2, 'Too Short!').max(50, 'Too Long!').required('This field is required'), key: Yup.string().min(2, 'Too Short!').max(50, 'Too Long!').required('This field is required'), - connectionUrl: Yup.string() + connectionString: Yup.string() .matches( /((https?):\/\/)?(www.)?[a-z0-9]+(\.[a-z]{2,}){1,3}(#?\/?[a-zA-Z0-9#]+)*\/?(\?[a-zA-Z0-9-_]+=[a-zA-Z0-9-%]+&?)?$/, - 'Enter correct url!' + 'Please enter a valid Flagbase instance URL' ) - .required('Please enter website'), + .required('Please enter a valid Flagbase instance URL'), accessKey: Yup.string().min(2, 'Too Short!').max(50, 'Too Long!').required('This field is required'), accessSecret: Yup.string().min(2, 'Too Short!').max(50, 'Too Long!').required('This field is required'), }) diff --git a/ui/app/pages/instances/instances.modal.tsx b/ui/app/pages/instances/instances.modal.tsx index 7596e9c4..b149ed54 100644 --- a/ui/app/pages/instances/instances.modal.tsx +++ b/ui/app/pages/instances/instances.modal.tsx @@ -20,10 +20,10 @@ export const AddNewInstanceModal = ({ visible, setVisible }: ReactState) => { const { isSuccess, isError } = mutation const onSubmit = (values: OmittedInstance, { setSubmitting }: FormikHelpers) => { - setIsLoading(true); + setIsLoading(true) mutation.mutate(values) setSubmitting(false) - setTimeout(() => setIsLoading(false), 2000); + setTimeout(() => setIsLoading(false), 2000) } useEffect(() => { @@ -106,7 +106,12 @@ export const AddNewInstanceModal = ({ visible, setVisible }: ReactState) => { placeholder="Secret" type="password" /> - From d96ce02dd2aff9bf2e6b6c9a916141dc299c606e Mon Sep 17 00:00:00 2001 From: Ali S Date: Fri, 7 Apr 2023 14:37:30 +1000 Subject: [PATCH 5/5] remove console logs --- ui/app/notifications/index.tsx | 17 ----------------- ui/components/table/table.tsx | 1 - 2 files changed, 18 deletions(-) delete mode 100644 ui/app/notifications/index.tsx diff --git a/ui/app/notifications/index.tsx b/ui/app/notifications/index.tsx deleted file mode 100644 index 9299b281..00000000 --- a/ui/app/notifications/index.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react' -import { useQuery } from 'react-query' -import { useFlagbaseParams } from '../lib/use-flagbase-params' - -const Notifications = () => { - const { instanceKey, workspaceKey } = useFlagbaseParams() - - const { isSuccess, isError } = useQuery({ - queryKey: ['projects', instanceKey, workspaceKey], - }) - - console.log('test', isSuccess, isError) - - return <> -} - -export default Notifications diff --git a/ui/components/table/table.tsx b/ui/components/table/table.tsx index 199b938b..5b06bd8e 100644 --- a/ui/components/table/table.tsx +++ b/ui/components/table/table.tsx @@ -74,7 +74,6 @@ const Table: React.FC = ({ return { onClick: (event) => { event.preventDefault() - console.log('record', record, rowIndex) const { href } = record if (href) { navigate(href)