@selkirk-systems/attachments 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -0
- package/dist/actions/AttachmentActions.js +11 -0
- package/dist/actions/FileActions.js +37 -0
- package/dist/actions/ImageUploadActions.js +99 -0
- package/dist/actions/PhotoActions.js +53 -0
- package/dist/components/FileDeleteIcon.js +30 -0
- package/dist/components/FileDownloadIcon.js +34 -0
- package/dist/components/FileList.js +111 -0
- package/dist/components/Icons/ExcelFileTypeImage.js +8 -0
- package/dist/components/Icons/HTMLFileTypeImage.js +7 -0
- package/dist/components/Icons/JSONFileTypeImage.js +7 -0
- package/dist/components/Icons/PDFFileTypeImage.js +7 -0
- package/dist/components/Icons/PhotoFileTypeImage.js +6 -0
- package/dist/components/Icons/PowerPointTypeImage.js +7 -0
- package/dist/components/Icons/TextFileTypeImage.js +7 -0
- package/dist/components/Icons/UnknownFileTypeImage.js +7 -0
- package/dist/components/Icons/WordFileTypeImage.js +7 -0
- package/dist/components/Icons/ZipFileTypeImage.js +7 -0
- package/dist/components/ImageViewerDialog.js +78 -0
- package/dist/components/MimeTypeIcons.js +28 -0
- package/dist/components/PhotoGallery.js +130 -0
- package/dist/components/ResponsiveImageUploadList.js +57 -0
- package/dist/components/UploadImageDialog.js +85 -0
- package/dist/constants/MessageConstants.js +5 -0
- package/dist/constants/PhotosConstants.js +18 -0
- package/dist/css/attachments.css +143 -0
- package/dist/css/image-viewer.css +45 -0
- package/dist/img/PowerPoint-filetype.png +0 -0
- package/dist/img/blue-pattern-bg.jpg +0 -0
- package/dist/img/excel-filetype.png +0 -0
- package/dist/img/html-filetype.png +0 -0
- package/dist/img/json-filetype.png +0 -0
- package/dist/img/pdf-filetype.png +0 -0
- package/dist/img/photo-filetype.png +0 -0
- package/dist/img/txt-filetype.png +0 -0
- package/dist/img/unknown-filetype.png +0 -0
- package/dist/img/word-filetype.png +0 -0
- package/dist/img/zip-filetype.png +0 -0
- package/dist/index.js +19 -0
- package/dist/stores/DownloadStore.js +16 -0
- package/dist/stores/ImageUploadStore.js +24 -0
- package/dist/stores/PhotosStore.js +59 -0
- package/lib/actions/AttachmentActions.js +14 -0
- package/lib/actions/FileActions.js +34 -0
- package/lib/actions/ImageUploadActions.js +134 -0
- package/lib/actions/PhotoActions.js +65 -0
- package/lib/components/FileDeleteIcon.jsx +42 -0
- package/lib/components/FileDownloadIcon.jsx +42 -0
- package/lib/components/FileList.jsx +111 -0
- package/lib/components/Icons/ExcelFileTypeImage.jsx +6 -0
- package/lib/components/Icons/HTMLFileTypeImage.jsx +5 -0
- package/lib/components/Icons/JSONFileTypeImage.jsx +5 -0
- package/lib/components/Icons/PDFFileTypeImage.jsx +5 -0
- package/lib/components/Icons/PhotoFileTypeImage.jsx +5 -0
- package/lib/components/Icons/PowerPointTypeImage.jsx +5 -0
- package/lib/components/Icons/TextFileTypeImage.jsx +5 -0
- package/lib/components/Icons/UnknownFileTypeImage.jsx +5 -0
- package/lib/components/Icons/WordFileTypeImage.jsx +5 -0
- package/lib/components/Icons/ZipFileTypeImage.jsx +5 -0
- package/lib/components/ImageViewerDialog.jsx +72 -0
- package/lib/components/MimeTypeIcons.jsx +30 -0
- package/lib/components/PhotoGallery.jsx +160 -0
- package/lib/components/ResponsiveImageUploadList.jsx +61 -0
- package/lib/components/UploadImageDialog.jsx +93 -0
- package/lib/constants/MessageConstants.js +5 -0
- package/lib/constants/PhotosConstants.js +21 -0
- package/lib/css/attachments.css +143 -0
- package/lib/css/image-viewer.css +45 -0
- package/lib/img/PowerPoint-filetype.png +0 -0
- package/lib/img/blue-pattern-bg.jpg +0 -0
- package/lib/img/excel-filetype.png +0 -0
- package/lib/img/html-filetype.png +0 -0
- package/lib/img/json-filetype.png +0 -0
- package/lib/img/pdf-filetype.png +0 -0
- package/lib/img/photo-filetype.png +0 -0
- package/lib/img/txt-filetype.png +0 -0
- package/lib/img/unknown-filetype.png +0 -0
- package/lib/img/word-filetype.png +0 -0
- package/lib/img/zip-filetype.png +0 -0
- package/lib/index.js +19 -0
- package/lib/stores/DownloadStore.js +23 -0
- package/lib/stores/ImageUploadStore.js +31 -0
- package/lib/stores/PhotosStore.js +81 -0
- package/package.json +50 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { FILE_DELETE, FILE_DELETED, FILE_DOWNLOAD, FILE_DOWNLOADED } from "../constants/PhotosConstants";
|
|
2
|
+
import DownloadStore from "../stores/DownloadStore";
|
|
3
|
+
import { fetch } from "@selkirk-systems/fetch";
|
|
4
|
+
import { dispatch } from "@selkirk-systems/state-management";
|
|
5
|
+
|
|
6
|
+
export const downloadFile = ( url, mimeType, fileName ) => {
|
|
7
|
+
|
|
8
|
+
const { downloading } = DownloadStore.getState();
|
|
9
|
+
|
|
10
|
+
if ( downloading ) return;
|
|
11
|
+
|
|
12
|
+
dispatch( FILE_DOWNLOAD, { url: url, mimeType: mimeType, fileName: fileName } );
|
|
13
|
+
|
|
14
|
+
return fetch( url, { contentType: mimeType, downloadFileName: fileName } )
|
|
15
|
+
.finally( () => {
|
|
16
|
+
dispatch( FILE_DOWNLOADED )
|
|
17
|
+
} )
|
|
18
|
+
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const deleteFile = ( url, fileName ) => {
|
|
22
|
+
|
|
23
|
+
const { deleting } = DownloadStore.getState();
|
|
24
|
+
|
|
25
|
+
if ( deleting ) return;
|
|
26
|
+
|
|
27
|
+
dispatch( FILE_DELETE, { fileName: fileName } );
|
|
28
|
+
|
|
29
|
+
return fetch( url, { method: "DELETE" } )
|
|
30
|
+
.finally( () => {
|
|
31
|
+
dispatch( FILE_DELETED, { fileName: fileName } )
|
|
32
|
+
} )
|
|
33
|
+
|
|
34
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/* eslint-disable no-loop-func */
|
|
2
|
+
import { dispatch } from "@selkirk-systems/state-management";
|
|
3
|
+
import { CLEAR_UPLOADS, DELETED_IMAGE, DELETE_IMAGE, HIDE_IMAGE_UPLOAD_DIALOG, IMAGE_UPLOAD_COMPLETE, SET_UPLOAD_PROGRESS, SHOW_IMAGE_UPLOAD_DIALOG } from "../constants/PhotosConstants";
|
|
4
|
+
import { ADD_ERROR, fetch } from "@selkirk-systems/fetch";
|
|
5
|
+
import { createProxiedURL } from "@selkirk-systems/selkirk-utils";
|
|
6
|
+
import PhotoStore from "../stores/PhotosStore";
|
|
7
|
+
import { confirmDialog } from "primereact/confirmdialog";
|
|
8
|
+
import { extractDataArray } from "@selkirk-systems/selkirk-utils";
|
|
9
|
+
|
|
10
|
+
export const closeImageUploadDialog = () => {
|
|
11
|
+
|
|
12
|
+
dispatch( HIDE_IMAGE_UPLOAD_DIALOG );
|
|
13
|
+
dispatch( CLEAR_UPLOADS );
|
|
14
|
+
|
|
15
|
+
}
|
|
16
|
+
export const showImageUploadDialog = ( tag ) => {
|
|
17
|
+
|
|
18
|
+
dispatch( SHOW_IMAGE_UPLOAD_DIALOG, tag );
|
|
19
|
+
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const invokeUploadInput = () => {
|
|
23
|
+
|
|
24
|
+
const element = document.querySelector( "input[type='file']" );
|
|
25
|
+
|
|
26
|
+
if ( !element ) return;
|
|
27
|
+
|
|
28
|
+
element.click();
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
export const deleteImageById = ( id ) => {
|
|
32
|
+
|
|
33
|
+
dispatch( DELETE_IMAGE, id )
|
|
34
|
+
|
|
35
|
+
return fetch( `/image/${id}`, { method: "DELETE" } )
|
|
36
|
+
.then( response => {
|
|
37
|
+
dispatch( DELETED_IMAGE, id );
|
|
38
|
+
} );
|
|
39
|
+
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const uploadFiles = ( url, files ) => {
|
|
43
|
+
|
|
44
|
+
return new Promise( ( resolve, reject ) => {
|
|
45
|
+
const uploads = [];
|
|
46
|
+
|
|
47
|
+
const { photos } = PhotoStore.getState();
|
|
48
|
+
|
|
49
|
+
if ( !url ) return;
|
|
50
|
+
|
|
51
|
+
for ( let file of files ) {
|
|
52
|
+
const exists = photos.find( ( p ) => p.name === file.name );
|
|
53
|
+
|
|
54
|
+
if ( exists ) {
|
|
55
|
+
confirmDialog( {
|
|
56
|
+
message: `${file.name} already exists. \n Do you want to replace it?`,
|
|
57
|
+
header: 'Confirm Upload',
|
|
58
|
+
position: 'center',
|
|
59
|
+
accept: () => {
|
|
60
|
+
uploadFinalFile( file );
|
|
61
|
+
}
|
|
62
|
+
} );
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
uploadFinalFile( file );
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function uploadFinalFile( file ) {
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
const caption = file.name;
|
|
73
|
+
const formData = new FormData();
|
|
74
|
+
const finalURL = new URL( `${url}?force=true&name=${file.name}` );
|
|
75
|
+
|
|
76
|
+
formData.append( "file", file, file.name );
|
|
77
|
+
|
|
78
|
+
const options = {
|
|
79
|
+
headers: {
|
|
80
|
+
accept: "*/*",
|
|
81
|
+
'content-length': file.size
|
|
82
|
+
},
|
|
83
|
+
form: formData,
|
|
84
|
+
method: "POST",
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
dispatch( SET_UPLOAD_PROGRESS, {
|
|
88
|
+
id: caption,
|
|
89
|
+
title: caption,
|
|
90
|
+
mimeType: file.type,
|
|
91
|
+
progress: 10,
|
|
92
|
+
response: null
|
|
93
|
+
} )
|
|
94
|
+
|
|
95
|
+
uploads.push(
|
|
96
|
+
fetch( finalURL, options )
|
|
97
|
+
.then( ( [response] ) => {
|
|
98
|
+
if ( response.status.code > 299 || response.status.code < 200 ) {
|
|
99
|
+
throw response
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
response.data = extractDataArray( response.data );
|
|
103
|
+
|
|
104
|
+
dispatch( SET_UPLOAD_PROGRESS, {
|
|
105
|
+
id: caption,
|
|
106
|
+
title: caption,
|
|
107
|
+
mimeType: file.type,
|
|
108
|
+
progress: 100,
|
|
109
|
+
response: response
|
|
110
|
+
} )
|
|
111
|
+
} )
|
|
112
|
+
.catch( response => {
|
|
113
|
+
dispatch( SET_UPLOAD_PROGRESS, {
|
|
114
|
+
id: caption,
|
|
115
|
+
title: caption,
|
|
116
|
+
mimeType: file.type,
|
|
117
|
+
progress: 100,
|
|
118
|
+
error: response.data
|
|
119
|
+
} )
|
|
120
|
+
return dispatch( ADD_ERROR, response );
|
|
121
|
+
} )
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
Promise.all( uploads )
|
|
126
|
+
.finally( () => {
|
|
127
|
+
dispatch( IMAGE_UPLOAD_COMPLETE );
|
|
128
|
+
resolve();
|
|
129
|
+
} )
|
|
130
|
+
|
|
131
|
+
} );
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { fetch } from "@selkirk-systems/fetch";
|
|
2
|
+
import { DELETED_IMAGE, DELETE_IMAGE, FETCHED_PHOTOS, FETCH_PHOTOS } from "../constants/PhotosConstants";
|
|
3
|
+
import { dispatch } from "@selkirk-systems/state-management";
|
|
4
|
+
import { hideImageViewerDialog } from "./AttachmentActions";
|
|
5
|
+
import { ADD_IGNORE_ERROR, REMOVE_IGNORE_ERROR_BY_ID } from "../constants/MessageConstants";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
export const fetchPhotos = ( url ) => {
|
|
9
|
+
|
|
10
|
+
dispatch( FETCH_PHOTOS );
|
|
11
|
+
|
|
12
|
+
//Filestore requires both of these set to application/json to get json details
|
|
13
|
+
//Proxy web server defaults to accept:'*/*' which does not work so we have to override here.
|
|
14
|
+
const options = {
|
|
15
|
+
skipCache: true,
|
|
16
|
+
headers: {
|
|
17
|
+
'Accept': "application/json",
|
|
18
|
+
'content-type': 'application/json'
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
dispatch(ADD_IGNORE_ERROR,[{id:url.toString(),statusCodes:[404]}]);
|
|
23
|
+
|
|
24
|
+
return fetch( url, options ).then( ( [response] ) => {
|
|
25
|
+
|
|
26
|
+
dispatch(REMOVE_IGNORE_ERROR_BY_ID,[{id:url.toString()}]);
|
|
27
|
+
|
|
28
|
+
if ( response.status.code > 299 || response.status.code < 200 ) {
|
|
29
|
+
dispatch( FETCHED_PHOTOS, [] )
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const onlyFiles = getAllFiles( response.data.children );
|
|
34
|
+
|
|
35
|
+
dispatch( FETCHED_PHOTOS, onlyFiles )
|
|
36
|
+
|
|
37
|
+
} )
|
|
38
|
+
}
|
|
39
|
+
export const clearPhotos = ()=>{
|
|
40
|
+
dispatch(FETCHED_PHOTOS,[]);
|
|
41
|
+
}
|
|
42
|
+
export const deleteImage = ( url, name ) => {
|
|
43
|
+
|
|
44
|
+
dispatch( DELETE_IMAGE, name );
|
|
45
|
+
|
|
46
|
+
return fetch( url, { method: "DELETE" } )
|
|
47
|
+
.then( response => {
|
|
48
|
+
dispatch( DELETED_IMAGE, name );
|
|
49
|
+
hideImageViewerDialog();
|
|
50
|
+
} );
|
|
51
|
+
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function getAllFiles( children ) {
|
|
55
|
+
let ret = [];
|
|
56
|
+
|
|
57
|
+
children.forEach( c => {
|
|
58
|
+
if ( c.nodeType === 'FILE' ) ret.push( c );
|
|
59
|
+
|
|
60
|
+
if ( c.children && c.children.length ) ret = ret.concat( getAllFiles( c.children ) )
|
|
61
|
+
} )
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
return ret;
|
|
65
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { Connect } from '@selkirk-systems/state-management';
|
|
3
|
+
import { Trash2 } from 'lucide-react';
|
|
4
|
+
import { ProgressSpinner } from '@selkirk-systems/selkirk-components';
|
|
5
|
+
import { Button } from 'primereact/button';
|
|
6
|
+
import DownloadStore from '../stores/DownloadStore';
|
|
7
|
+
|
|
8
|
+
class FileDownloadIcon extends React.Component {
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
static subscribe = [DownloadStore];
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
static defaultProps = {
|
|
15
|
+
deleting: false,
|
|
16
|
+
name: ''
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
static storeStateToProps = {
|
|
21
|
+
deleting: ( props, state ) => state.deleting
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
render() {
|
|
26
|
+
const { deleting, name, ...other } = this.props;
|
|
27
|
+
|
|
28
|
+
const isDeleting = deleting && deleting.fileName === name;
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<Button text type='button' {...other} >
|
|
32
|
+
{isDeleting && <ProgressSpinner />}
|
|
33
|
+
{!isDeleting && <Trash2 />}
|
|
34
|
+
</Button>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
export default Connect( FileDownloadIcon );
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { Connect } from '@selkirk-systems/state-management';
|
|
3
|
+
import { Download } from 'lucide-react';
|
|
4
|
+
import { ProgressSpinner } from '@selkirk-systems/selkirk-components';
|
|
5
|
+
import { Button } from 'primereact/button';
|
|
6
|
+
import DownloadStore from '../stores/DownloadStore';
|
|
7
|
+
|
|
8
|
+
class FileDownloadIcon extends React.Component {
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
static subscribe = [DownloadStore];
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
static defaultProps = {
|
|
15
|
+
downloading: false,
|
|
16
|
+
name: ''
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
static storeStateToProps = {
|
|
21
|
+
downloading: ( props, state ) => state.downloading
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
render() {
|
|
26
|
+
const { downloading, name, ...other } = this.props;
|
|
27
|
+
|
|
28
|
+
const isDownloading = downloading && downloading.fileName === name;
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<Button text type='button' {...other} >
|
|
32
|
+
{isDownloading && <ProgressSpinner style={{ color: 'inherit' }} />}
|
|
33
|
+
{!isDownloading && <Download />}
|
|
34
|
+
</Button>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
export default Connect( FileDownloadIcon );
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import React, { Component } from "react";
|
|
2
|
+
import { Connect } from '@selkirk-systems/state-management';
|
|
3
|
+
import PhotoStore from "../stores/PhotosStore";
|
|
4
|
+
import { FileIcon, Trash2 } from "lucide-react";
|
|
5
|
+
import { Column, Row } from "@selkirk-systems/layout";
|
|
6
|
+
import { Skeleton } from "primereact/skeleton";
|
|
7
|
+
import memoizee from "memoizee";
|
|
8
|
+
import { fetchPhotos } from "../actions/PhotoActions";
|
|
9
|
+
import { Typography, Paper } from "@selkirk-systems/selkirk-components";
|
|
10
|
+
import UploadImageDialog from "./UploadImageDialog";
|
|
11
|
+
import { deleteFile, downloadFile } from "../actions/FileActions";
|
|
12
|
+
import { createProxiedURL } from "@selkirk-systems/selkirk-utils";
|
|
13
|
+
import FileDownloadIcon from "./FileDownloadIcon";
|
|
14
|
+
import UnknownFileTypeImage from "./Icons/UnknownFileTypeImage";
|
|
15
|
+
import MIME_TYPE_ICONS from "./MimeTypeIcons";
|
|
16
|
+
import { sortByProp } from "@selkirk-systems/selkirk-utils";
|
|
17
|
+
import { Button } from "primereact/button";
|
|
18
|
+
import FileDeleteIcon from "./FileDeleteIcon";
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class PhotoGallery extends React.Component {
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
static subscribe = [PhotoStore];
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
static defaultProps = {
|
|
28
|
+
baseURL: "",
|
|
29
|
+
items: [],
|
|
30
|
+
fetching: false
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
static storeStateToProps = {
|
|
35
|
+
|
|
36
|
+
items: ( props, state ) => filesOnly( state.photos ),
|
|
37
|
+
fetching: ( props, state ) => state.fetching
|
|
38
|
+
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
handleFileClick = ( file ) => ( e ) => {
|
|
42
|
+
|
|
43
|
+
e.stopPropagation();
|
|
44
|
+
|
|
45
|
+
downloadFile( createProxiedURL( file._links.self.href ), file.mimeType, file.name );
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
handleFileDelete = ( file ) => ( e ) => {
|
|
50
|
+
|
|
51
|
+
e.stopPropagation();
|
|
52
|
+
|
|
53
|
+
const href = file.links ? file.links[0].href : file._links.self.href;
|
|
54
|
+
|
|
55
|
+
deleteFile( createProxiedURL( href ), file.name )
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
render() {
|
|
59
|
+
|
|
60
|
+
const { baseURL, items, fetching, ...other } = this.props;
|
|
61
|
+
|
|
62
|
+
const count = items.length;
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<div className="file-gallery paralax-content" {...other}>
|
|
66
|
+
{count < 1 && !fetching &&
|
|
67
|
+
<Column center className='text-secondary' >
|
|
68
|
+
<FileIcon mt="-xxxl" mb='sm' style={{ width: '75px', height: '75px', strokeWidth: 1 }} />
|
|
69
|
+
<Typography style={{ fontWeight: 500 }} variant="subtitle2">NO FILES FOUND.</Typography>
|
|
70
|
+
</Column>
|
|
71
|
+
}
|
|
72
|
+
{fetching && <Skeleton width="100%" height={window.innerHeight - 300} />}
|
|
73
|
+
{count > 0 &&
|
|
74
|
+
<div p='md' style={{ flex: "1 1 auto" }}>
|
|
75
|
+
{
|
|
76
|
+
items.map( ( f, i ) => {
|
|
77
|
+
return (
|
|
78
|
+
<Paper mb='sm' p='sm' key={f.id} elevation={1} {...other}>
|
|
79
|
+
<Row align='center' xs="auto 1fr auto auto">
|
|
80
|
+
{MIME_TYPE_ICONS[f.mimeType] || <UnknownFileTypeImage />}
|
|
81
|
+
<Column gap='xs' ml='sm'>
|
|
82
|
+
<Typography variant="body1">{f.name}</Typography>
|
|
83
|
+
<Row className='text-secondary' gap='sm' justify='left'>
|
|
84
|
+
<Typography variant='caption'>Size: </Typography>
|
|
85
|
+
<Typography variant='caption'>{f.sizeInKB < 1000 ? `${f.sizeInKB.toFixed( 3 )} KB` : `${( f.sizeInKB / 1000 ).toFixed( 3 )} MB`}</Typography>
|
|
86
|
+
</Row>
|
|
87
|
+
</Column>
|
|
88
|
+
<FileDownloadIcon size="small" onClick={this.handleFileClick( f )} name={f.name} />
|
|
89
|
+
<FileDeleteIcon size="small" onClick={this.handleFileDelete( f )} name={f.name} />
|
|
90
|
+
</Row>
|
|
91
|
+
</Paper>
|
|
92
|
+
)
|
|
93
|
+
} )
|
|
94
|
+
}
|
|
95
|
+
</div>
|
|
96
|
+
}
|
|
97
|
+
</div >
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
const filesOnly = memoizee( ( files ) => {
|
|
106
|
+
return sortByProp( files.filter( ( f ) => f.mimeType.indexOf( "image" ) < 0 ), "name" ).reverse();
|
|
107
|
+
} )
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
export default Connect( PhotoGallery );
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { deleteImage } from '../actions/PhotoActions';
|
|
3
|
+
import PhotosStore from '../stores/PhotosStore';
|
|
4
|
+
import { Connect } from '@selkirk-systems/state-management';
|
|
5
|
+
import { Dialog } from 'primereact/dialog';
|
|
6
|
+
import { Trash2, XIcon } from 'lucide-react';
|
|
7
|
+
import { Button } from 'primereact/button';
|
|
8
|
+
import { ProgressSpinner, Typography } from '@selkirk-systems/selkirk-components';
|
|
9
|
+
|
|
10
|
+
import '../css/image-viewer.css';
|
|
11
|
+
import { Row } from '@selkirk-systems/layout';
|
|
12
|
+
import { hideImageViewerDialog } from '../actions/AttachmentActions';
|
|
13
|
+
|
|
14
|
+
class ImageViewerDialog extends React.Component {
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
static subscribe = [PhotosStore];
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
static defaultProps = {
|
|
21
|
+
imageViewer: {},
|
|
22
|
+
deleting: false
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
static storeStateToProps = {
|
|
27
|
+
imageViewer: ( props, state ) => state.imageViewer,
|
|
28
|
+
deleting: ( props, state ) => state.deleting
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
render() {
|
|
33
|
+
|
|
34
|
+
const { imageViewer, deleting, ...other } = this.props;
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<Dialog
|
|
38
|
+
visible={imageViewer.name}
|
|
39
|
+
maximized
|
|
40
|
+
onHide={hideImageViewerDialog}
|
|
41
|
+
transitionOptions={
|
|
42
|
+
{
|
|
43
|
+
onExited: this.handledExited
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
{...other}
|
|
47
|
+
>
|
|
48
|
+
<div className="image-viewer">
|
|
49
|
+
<Row className="top actions" align="center" xs="1fr auto" gap="md" fill={false}>
|
|
50
|
+
<Typography ml='sm' className="title" variant="body1">{imageViewer.name}</Typography>
|
|
51
|
+
<Button mr='-sm' type='button' style={{ color: 'inherit' }} onClick={hideImageViewerDialog} text><XIcon /></Button>
|
|
52
|
+
</Row>
|
|
53
|
+
<Row className="bottom actions" center fill={false}>
|
|
54
|
+
<Button disabled={deleting} type='button' onClick={() => deleteImage( imageViewer.url, imageViewer.name )} text className="delete icon">
|
|
55
|
+
{deleting ?
|
|
56
|
+
<ProgressSpinner style={{ width: 18, height: 18, color: 'white' }} />
|
|
57
|
+
:
|
|
58
|
+
<Trash2 />
|
|
59
|
+
}
|
|
60
|
+
</Button>
|
|
61
|
+
</Row>
|
|
62
|
+
<img alt="test" src={imageViewer.url} />
|
|
63
|
+
</div>
|
|
64
|
+
</Dialog>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
export default Connect( ImageViewerDialog );
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import PDFFileTypeImage from "./Icons/PDFFileTypeImage";
|
|
2
|
+
import TextFileTypeImage from "./Icons/TextFileTypeImage";
|
|
3
|
+
import WordFileTypeImage from "./Icons/WordFileTypeImage";
|
|
4
|
+
import ExcelFileTypeImage from "./Icons/ExcelFileTypeImage";
|
|
5
|
+
import PowerPointTypeImage from "./Icons/PowerPointTypeImage";
|
|
6
|
+
import HTMLFileTypeImage from "./Icons/HTMLFileTypeImage";
|
|
7
|
+
import JsonFileTypeImage from "./Icons/JSONFileTypeImage";
|
|
8
|
+
import ZipFileTypeImage from "./Icons/ZipFileTypeImage";
|
|
9
|
+
import React from "react";
|
|
10
|
+
|
|
11
|
+
const MIME_TYPE_ICONS = {
|
|
12
|
+
'application/pdf': <PDFFileTypeImage />,
|
|
13
|
+
'application/msword': <WordFileTypeImage />,
|
|
14
|
+
'application/vnd.ms-word': <WordFileTypeImage />,
|
|
15
|
+
'application/vnd.oasis.opendocument.text': <WordFileTypeImage />,
|
|
16
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml': <WordFileTypeImage />,
|
|
17
|
+
'application/vnd.ms-excel': <ExcelFileTypeImage />,
|
|
18
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml': <ExcelFileTypeImage />,
|
|
19
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': <ExcelFileTypeImage />,
|
|
20
|
+
'application/vnd.oasis.opendocument.spreadsheet': <ExcelFileTypeImage />,
|
|
21
|
+
'application/vnd.ms-powerpoint': <PowerPointTypeImage />,
|
|
22
|
+
'application/vnd.openxmlformats-officedocument.presentationml': <PowerPointTypeImage />,
|
|
23
|
+
'application/vnd.oasis.opendocument.presentation': <PowerPointTypeImage />,
|
|
24
|
+
'text/plain': <TextFileTypeImage />,
|
|
25
|
+
'text/html': <HTMLFileTypeImage />,
|
|
26
|
+
'application/json': <JsonFileTypeImage />,
|
|
27
|
+
'application/zip': <ZipFileTypeImage />
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default MIME_TYPE_ICONS;
|