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

fix(archive): correct nested data structure for GraphQL archive queries #519

Merged
merged 3 commits into from
Sep 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
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
68 changes: 36 additions & 32 deletions src/app/Recordings/ArchivedRecordingsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ import { addFilterIntent, addTargetIntent, deleteAllFiltersIntent, deleteCategor
import { RootState, StateDispatch } from '@app/Shared/Redux/ReduxStore';
import { hashCode } from '@app/utils/utils';

export interface ArchivedRecordingsTableProps {
export interface ArchivedRecordingsTableProps {
target: Observable<Target>;
isUploadsTable: boolean;
isNestedTable: boolean;
Expand All @@ -74,7 +74,7 @@ export const ArchivedRecordingsTable: React.FunctionComponent<ArchivedRecordings
const context = React.useContext(ServiceContext);
const addSubscription = useSubscriptions();
const dispatch = useDispatch<StateDispatch>();

const [targetConnectURL, setTargetConnectURL] = React.useState("");
const [recordings, setRecordings] = React.useState([] as ArchivedRecording[]);
const [filteredRecordings, setFilteredRecordings] = React.useState([] as ArchivedRecording[]);
Expand All @@ -84,7 +84,7 @@ export const ArchivedRecordingsTable: React.FunctionComponent<ArchivedRecordings
const [showUploadModal, setShowUploadModal] = React.useState(false);
const [showDetailsPanel, setShowDetailsPanel] = React.useState(false);
const [isLoading, setIsLoading] = React.useState(false);

const targetRecordingFilters = useSelector((state: RootState) => {
const filters = state.recordingFilters.list.filter((targetFilter: TargetRecordingFilters) => targetFilter.target === targetConnectURL);
return filters.length > 0? filters[0].archived.filters: emptyArchivedRecordingFilters;
Expand Down Expand Up @@ -122,11 +122,13 @@ export const ArchivedRecordingsTable: React.FunctionComponent<ArchivedRecordings
return context.api.graphql<any>(`
query {
archivedRecordings(filter: { sourceTarget: "${connectUrl}" }) {
name
downloadUrl
reportUrl
metadata {
labels
data {
name
downloadUrl
reportUrl
metadata {
labels
}
}
}
}`)
Expand All @@ -136,11 +138,13 @@ export const ArchivedRecordingsTable: React.FunctionComponent<ArchivedRecordings
return context.api.graphql<any>(`
query {
archivedRecordings(filter: { sourceTarget: "uploads" }) {
name
downloadUrl
reportUrl
metadata {
labels
data {
name
downloadUrl
reportUrl
metadata {
labels
}
}
}
}`)
Expand All @@ -152,7 +156,7 @@ export const ArchivedRecordingsTable: React.FunctionComponent<ArchivedRecordings
addSubscription(
queryUploadedRecordings()
.pipe(
map(v => v.data.archivedRecordings as ArchivedRecording[])
map(v => v.data.archivedRecordings.data as ArchivedRecording[])
)
.subscribe(handleRecordings)
);
Expand All @@ -165,7 +169,7 @@ export const ArchivedRecordingsTable: React.FunctionComponent<ArchivedRecordings
concatMap(target =>
queryTargetRecordings(target.connectUrl)
),
map(v => v.data.archivedRecordings as ArchivedRecording[]),
map(v => v.data.archivedRecordings.data as ArchivedRecording[]),
)
.subscribe(handleRecordings)
);
Expand All @@ -175,7 +179,7 @@ export const ArchivedRecordingsTable: React.FunctionComponent<ArchivedRecordings
const handleClearFilters = React.useCallback(() => {
dispatch(deleteAllFiltersIntent(targetConnectURL, true));
}, [dispatch, deleteAllFiltersIntent, targetConnectURL]);

const updateFilters = React.useCallback((target, {filterValue, filterKey, deleted = false, deleteOptions}) => {
if (deleted) {
if (deleteOptions && deleteOptions.all) {
Expand Down Expand Up @@ -250,8 +254,8 @@ export const ArchivedRecordingsTable: React.FunctionComponent<ArchivedRecordings
return;
}
setRecordings(old => old.map(
o => o.name == event.message.recordingName
? { ...o, metadata: { labels: event.message.metadata.labels } }
o => o.name == event.message.recordingName
? { ...o, metadata: { labels: event.message.metadata.labels } }
: o));
})
);
Expand Down Expand Up @@ -294,7 +298,7 @@ export const ArchivedRecordingsTable: React.FunctionComponent<ArchivedRecordings
forkJoin(tasks).subscribe()
);
}, [filteredRecordings, checkedIndices, context.reports, context.api, addSubscription]);

const toggleExpanded = React.useCallback(
(id: string) => {
setExpandedRows((expandedRows) => {
Expand Down Expand Up @@ -355,7 +359,7 @@ export const ArchivedRecordingsTable: React.FunctionComponent<ArchivedRecordings
labelFilters: props.labelFilters
}
}
labels={parsedLabels}
labels={parsedLabels}
/>
</Td>
<RecordingActions
Expand All @@ -377,7 +381,7 @@ export const ArchivedRecordingsTable: React.FunctionComponent<ArchivedRecordings
handleToggle,
updateFilters,
tableColumns,
parsedLabels,
parsedLabels,
context.api,
context.api.uploadArchivedRecordingToGrafana,
targetConnectURL
Expand Down Expand Up @@ -408,7 +412,7 @@ export const ArchivedRecordingsTable: React.FunctionComponent<ArchivedRecordings
};

const RecordingsToolbar = React.useMemo(() => (
<ArchivedRecordingsToolbar
<ArchivedRecordingsToolbar
target={targetConnectURL}
checkedIndices={checkedIndices}
targetRecordingFilters={targetRecordingFilters}
Expand All @@ -418,17 +422,17 @@ export const ArchivedRecordingsTable: React.FunctionComponent<ArchivedRecordings
handleClearFilters={handleClearFilters}
handleEditLabels={handleEditLabels}
handleDeleteRecordings={handleDeleteRecordings}
handleShowUploadModal={() => setShowUploadModal(true)}
handleShowUploadModal={() => setShowUploadModal(true)}
isUploadsTable={props.isUploadsTable}/>
), [
targetConnectURL,
checkedIndices,
targetRecordingFilters,
recordings,
targetRecordingFilters,
recordings,
filteredRecordings,
updateFilters,
handleClearFilters,
handleEditLabels,
handleEditLabels,
handleDeleteRecordings,
setShowUploadModal,
props.isUploadsTable
Expand All @@ -445,7 +449,7 @@ export const ArchivedRecordingsTable: React.FunctionComponent<ArchivedRecordings

const LabelsPanel = React.useMemo(() => (
<RecordingLabelsPanel
setShowPanel={setShowDetailsPanel}
setShowPanel={setShowDetailsPanel}
isTargetRecording={false}
checkedIndices={checkedIndices}
/>
Expand Down Expand Up @@ -501,7 +505,7 @@ const ArchivedRecordingsToolbar: React.FunctionComponent<ArchivedRecordingsToolb
const [warningModalOpen, setWarningModalOpen] = React.useState(false);

const deletionDialogsEnabled = React.useMemo(
() => context.settings.deletionDialogsEnabledFor(DeleteWarningType.DeleteArchivedRecordings),
() => context.settings.deletionDialogsEnabledFor(DeleteWarningType.DeleteArchivedRecordings),
[context, context.settings, context.settings.deletionDialogsEnabledFor]);

const handleWarningModalClose = React.useCallback(() => {
Expand All @@ -517,7 +521,7 @@ const ArchivedRecordingsToolbar: React.FunctionComponent<ArchivedRecordingsToolb
}, [deletionDialogsEnabled, setWarningModalOpen, props.handleDeleteRecordings]);

const deleteArchivedWarningModal = React.useMemo(() => {
return <DeleteWarningModal
return <DeleteWarningModal
warningType={DeleteWarningType.DeleteArchivedRecordings}
visible={warningModalOpen}
onAccept={props.handleDeleteRecordings}
Expand All @@ -531,8 +535,8 @@ const ArchivedRecordingsToolbar: React.FunctionComponent<ArchivedRecordingsToolb
<RecordingFilters
target={props.target}
isArchived={true}
recordings={props.recordings}
filters={props.targetRecordingFilters}
recordings={props.recordings}
filters={props.targetRecordingFilters}
updateFilters={props.updateFilters} />
<ToolbarGroup variant="button-group">
<ToolbarItem>
Expand All @@ -543,7 +547,7 @@ const ArchivedRecordingsToolbar: React.FunctionComponent<ArchivedRecordingsToolb
</ToolbarItem>
</ToolbarGroup>
{ deleteArchivedWarningModal }
{props.isUploadsTable ?
{props.isUploadsTable ?
<ToolbarGroup variant="icon-button-group">
<ToolbarItem>
<Button variant="plain" aria-label="add" onClick={props.handleShowUploadModal}><PlusIcon /></Button>
Expand Down
16 changes: 9 additions & 7 deletions src/test/Recordings/ArchivedRecordingsTable.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ const mockRecording: ArchivedRecording = {

const mockArchivedRecordingsResponse = {
data: {
archivedRecordings: [mockRecording] as ArchivedRecording[],
archivedRecordings: {
data: [mockRecording] as ArchivedRecording[],
},
},
}

Expand Down Expand Up @@ -152,7 +154,7 @@ jest
.mockReturnValueOnce(of()) // removes a recording after receiving a notification
.mockReturnValueOnce(of())
.mockReturnValueOnce(of(mockDeleteNotification))

.mockReturnValue(of()); // all other tests

jest.spyOn(window, 'open').mockReturnValue(null);
Expand All @@ -161,9 +163,9 @@ describe('<ArchivedRecordingsTable />', () => {
let preloadedState: RootState;
beforeEach(() => {
history.go(-history.length);
preloadedState = {
preloadedState = {
recordingFilters: {
list: [
list: [
{
target: mockTarget.connectUrl,
active: {
Expand Down Expand Up @@ -374,9 +376,9 @@ describe('<ArchivedRecordingsTable />', () => {
}
);

expect(screen.getByText('someRecording')).toBeInTheDocument();
expect(screen.getByText('someRecording')).toBeInTheDocument();

const uploadButton = screen.getByLabelText('add');
const uploadButton = screen.getByLabelText('add');
expect(uploadButton).toHaveAttribute('type', 'button')

expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
Expand Down Expand Up @@ -429,7 +431,7 @@ describe('<ArchivedRecordingsTable />', () => {

expect(uploadInput.files).not.toBe(null);
expect(uploadInput.files![0]).toStrictEqual(mockFileUpload);

await waitFor(() => expect(submitButton).not.toBeDisabled());
await tlr.act(async () => {
userEvent.click(submitButton)
Expand Down