Skip to content

Commit b8b7237

Browse files
authored
Merge pull request #45 from navikt/files-download
Files download
2 parents 94cfe95 + 972ebfe commit b8b7237

15 files changed

+159
-61
lines changed

xp-archive/client/contentFilesView/ContentFilesView.tsx

-5
This file was deleted.

xp-archive/client/contentHtmlView/ContentHtmlView.tsx

-17
This file was deleted.

xp-archive/client/contentJsonView/ContentJsonView.module.css

-3
This file was deleted.

xp-archive/client/contentJsonView/contentJsonView.tsx

+1-7
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,10 @@ import { collapseAllNested, JsonView } from 'react-json-view-lite';
33
import { Content } from 'shared/types';
44
import 'react-json-view-lite/dist/index.css';
55

6-
import style from './ContentJsonView.module.css';
7-
86
type Props = {
97
json: Content;
108
};
119

1210
export const ContentJsonView = ({ json }: Props) => {
13-
return (
14-
<div className={style.wrapper}>
15-
<JsonView data={json} clickToExpandNode={true} shouldExpandNode={collapseAllNested} />
16-
</div>
17-
);
11+
return <JsonView data={json} clickToExpandNode={true} shouldExpandNode={collapseAllNested} />;
1812
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import React from 'react';
2+
import { HtmlView } from './htmlView/HtmlView';
3+
import { Content } from 'shared/types';
4+
import { FilePreviewWrapper } from './filePreview/FilePreviewWrapper';
5+
6+
type Props = {
7+
html: string | undefined;
8+
content: Content;
9+
};
10+
11+
export const ContentPreview = ({ html, content }: Props) => {
12+
if (content.attachment) {
13+
return (
14+
<FilePreviewWrapper
15+
name={content.attachment.name}
16+
id={content._id}
17+
versionId={content._versionKey}
18+
/>
19+
);
20+
}
21+
22+
if (html) {
23+
return <HtmlView html={html} />;
24+
}
25+
26+
return <div>Ingenting å forhåndsvise</div>;
27+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
.iframe {
3+
height: 100%;
4+
width: 100%;
5+
border: none;
6+
}
7+
8+
.image {
9+
max-width:100%;
10+
min-width: 10rem;
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import React from 'react';
2+
import { Link } from '@navikt/ds-react';
3+
import { DownloadIcon } from '@navikt/aksel-icons';
4+
import { FileResponse } from '@common/shared/fetchUtils';
5+
import style from './FilePreview.module.css';
6+
7+
const iframeFiletype = ['application/pdf'];
8+
const imageFiletype = ['image/png', 'image/jpeg', 'image/svg+xml'];
9+
10+
type Props = {
11+
name: string;
12+
file: FileResponse;
13+
};
14+
15+
export const FilePreview = ({ name, file }: Props) => {
16+
const blob = new Blob([file.data], { type: file.mimeType });
17+
const blobURL = URL.createObjectURL(blob);
18+
19+
if (iframeFiletype.includes(file.mimeType)) {
20+
return <iframe className={style.iframe} src={blobURL} title={name} />;
21+
}
22+
23+
return (
24+
<>
25+
{imageFiletype.includes(file.mimeType) ? (
26+
<img className={style.image} alt="" src={blobURL} />
27+
) : null}
28+
<div>
29+
<Link href={blobURL} target={'_blank'}>
30+
{name} <DownloadIcon title="Last ned fil" />
31+
</Link>
32+
</div>
33+
</>
34+
);
35+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import React from 'react';
2+
import { Loader } from '@navikt/ds-react';
3+
import { useAppState } from 'client/context/appState/useAppState';
4+
import { useFetchAttachment } from 'client/hooks/useFetchAttachment';
5+
import { FilePreview } from './FilePreview';
6+
7+
type Props = {
8+
name: string;
9+
id: string;
10+
versionId: string;
11+
};
12+
13+
export const FilePreviewWrapper = ({ name, id, versionId }: Props) => {
14+
const { selectedLocale } = useAppState();
15+
16+
const { data, isLoading } = useFetchAttachment({
17+
id,
18+
versionId,
19+
locale: selectedLocale,
20+
});
21+
22+
return (
23+
<>
24+
{isLoading ?? <Loader />}
25+
{data && <FilePreview name={name} file={data} />}
26+
</>
27+
);
28+
};

xp-archive/client/contentHtmlView/ContentHtmlView.module.css xp-archive/client/contentPreview/htmlView/HtmlView.module.css

-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
.content {
2-
height: 100%;
3-
}
41

52
.iframe {
63
height: 100%;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React from 'react';
2+
import style from './HtmlView.module.css';
3+
4+
type Props = {
5+
html: string;
6+
};
7+
8+
export const HtmlView = ({ html }: Props) => {
9+
return <iframe title={'HTML-visning'} srcDoc={html} className={style.iframe}></iframe>;
10+
};

xp-archive/client/contentTree/NavigationBar.tsx

+8-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ export const NavigationBar = () => {
2121

2222
return (
2323
<div>
24+
<Alert
25+
variant={'warning'}
26+
size={'small'}
27+
inline={true}
28+
style={{ marginBottom: '1rem' }}
29+
>
30+
{'Obs: dette arkivet er under utvikling og er ikke klart til bruk!'}
31+
</Alert>
2432
<Heading size={'small'}>{'Innhold'}</Heading>
2533
<Tabs defaultValue="no" onChange={(locale) => setSelectedLocale(locale as Locale)}>
2634
<Tabs.List>
@@ -34,9 +42,6 @@ export const NavigationBar = () => {
3442
</Tabs.Panel>
3543
))}
3644
</Tabs>
37-
<Alert variant={'warning'} size={'small'} inline={true} style={{ marginTop: '1.5rem' }}>
38-
{'Obs: dette arkivet er under utvikling og er ikke klart til bruk!'}
39-
</Alert>
4045
</div>
4146
);
4247
};

xp-archive/client/contentView/ContentView.module.css

+6
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,10 @@
66
.top {
77
display: flex;
88
justify-content: space-between;
9+
gap: 1.5rem;
10+
}
11+
12+
.main {
13+
height: 100%;
14+
margin-top: 1rem;
915
}

xp-archive/client/contentView/ContentView.tsx

+10-16
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,19 @@ import { useFetchContent } from '../hooks/useFetchContent';
33
import { Heading, Loader } from '@navikt/ds-react';
44
import { useAppState } from '../context/appState/useAppState';
55
import { ViewSelector, ViewVariant } from 'client/viewSelector/ViewSelector';
6-
import { ContentHtmlView } from 'client/contentHtmlView/ContentHtmlView';
6+
import { ContentPreview } from 'client/contentPreview/ContentPreview';
77
import { ContentJsonView } from 'client/contentJsonView/contentJsonView';
8-
import { ContentFilesView } from 'client/contentFilesView/ContentFilesView';
98
import { VersionSelector } from 'client/versionSelector/VersionSelector';
109
import { ContentServiceResponse } from 'shared/types';
1110

1211
import style from './ContentView.module.css';
1312

14-
const getDefaultView = (data: ContentServiceResponse | null | undefined): ViewVariant => {
15-
if (data?.html) return 'html';
16-
return 'json';
17-
};
18-
1913
const getDisplayComponent = (viewVariant: ViewVariant, data: ContentServiceResponse) => {
20-
const translations: Record<ViewVariant, React.ReactElement> = {
21-
html: <ContentHtmlView html={data.html} />,
14+
const components: Record<ViewVariant, React.ReactElement> = {
15+
preview: <ContentPreview html={data.html} content={data.json} />,
2216
json: <ContentJsonView json={data.json} />,
23-
files: <ContentFilesView />,
2417
};
25-
return translations[viewVariant];
18+
return components[viewVariant];
2619
};
2720

2821
export const ContentView = () => {
@@ -36,11 +29,12 @@ export const ContentView = () => {
3629
versionId: selectedVersion?.versionId ?? undefined,
3730
});
3831

39-
const [selectedView, setSelectedView] = useState<ViewVariant>('json');
32+
const hasPreview = !!data?.html || !!data?.json.attachment;
33+
const [selectedView, setSelectedView] = useState<ViewVariant>('preview');
4034

4135
useEffect(() => {
42-
setSelectedView(getDefaultView(data));
43-
}, [data]);
36+
setSelectedView(hasPreview ? 'preview' : 'json');
37+
}, [hasPreview]);
4438

4539
if (isLoading) {
4640
return <Loader />;
@@ -56,12 +50,12 @@ export const ContentView = () => {
5650
<ViewSelector
5751
selectedView={selectedView}
5852
setSelectedView={setSelectedView}
59-
hasHtml={!!data.html}
53+
hasPreview={hasPreview}
6054
/>
6155
</div>
6256
<VersionSelector versions={data.versions} />
6357
</div>
64-
{getDisplayComponent(selectedView, data)}
58+
<div className={style.main}>{getDisplayComponent(selectedView, data)}</div>
6559
</div>
6660
) : null}
6761
</>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { fetchFile } from '@common/shared/fetchUtils';
2+
import useSWRImmutable from 'swr/immutable';
3+
4+
const ATTACHMENT_API = `${import.meta.env.VITE_APP_ORIGIN}/xp/api/attachment`;
5+
6+
type FetchAttachmentParams = { id: string; locale: string; versionId: string };
7+
8+
const fetchAttachment = async (params: FetchAttachmentParams) => {
9+
if (!params.id) return;
10+
return fetchFile(ATTACHMENT_API, {
11+
params,
12+
});
13+
};
14+
15+
export const useFetchAttachment = ({ id, locale, versionId }: FetchAttachmentParams) => {
16+
return useSWRImmutable({ id, locale, versionId }, fetchAttachment);
17+
};

xp-archive/client/viewSelector/ViewSelector.tsx

+6-7
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,27 @@ import React from 'react';
22
import { ToggleGroup } from '@navikt/ds-react';
33
import style from './ViewSelector.module.css';
44

5-
const viewVariants = ['html', 'json', 'files'] as const;
5+
const viewVariants = ['preview', 'json'] as const;
66
export type ViewVariant = (typeof viewVariants)[number];
77

88
const getDisplayname = (viewVariant: ViewVariant) => {
99
const translations: Record<ViewVariant, string> = {
10-
html: 'Nettside',
10+
preview: 'Forhåndsvisning',
1111
json: 'JSON',
12-
files: 'Filer',
1312
};
1413
return translations[viewVariant];
1514
};
1615

1716
type Props = {
1817
selectedView: ViewVariant;
1918
setSelectedView(selectedView: ViewVariant): void;
20-
hasHtml: boolean;
19+
hasPreview: boolean;
2120
};
2221

23-
export const ViewSelector = ({ selectedView, setSelectedView, hasHtml }: Props) => {
22+
export const ViewSelector = ({ selectedView, setSelectedView, hasPreview }: Props) => {
2423
const updateSelectedView = (viewVariantString: string) => {
2524
const viewVariant = viewVariantString as ViewVariant;
26-
if (viewVariant === 'html' && !hasHtml) {
25+
if (viewVariant === 'preview' && !hasPreview) {
2726
return;
2827
}
2928
setSelectedView(viewVariant);
@@ -35,7 +34,7 @@ export const ViewSelector = ({ selectedView, setSelectedView, hasHtml }: Props)
3534
<ToggleGroup.Item
3635
key={view}
3736
value={view}
38-
className={`${view === 'html' && !hasHtml ? style.disabled : ''}`}
37+
className={`${view === 'preview' && !hasPreview ? style.disabled : ''}`}
3938
>
4039
{getDisplayname(view)}
4140
</ToggleGroup.Item>

0 commit comments

Comments
 (0)