@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,160 @@
|
|
|
1
|
+
import React, { Component } from "react";
|
|
2
|
+
import { Connect } from '@selkirk-systems/state-management';
|
|
3
|
+
import PhotoStore from "../stores/PhotosStore";
|
|
4
|
+
import { ImageIcon } from "lucide-react";
|
|
5
|
+
import { Column } from "@selkirk-systems/layout";
|
|
6
|
+
import { Skeleton } from "primereact/skeleton";
|
|
7
|
+
import memoizee from "memoizee";
|
|
8
|
+
import { showImageViewerDialog } from "../actions/AttachmentActions";
|
|
9
|
+
import { createProxiedURL } from "@selkirk-systems/selkirk-utils";
|
|
10
|
+
import { Typography } from "@selkirk-systems/selkirk-components";
|
|
11
|
+
|
|
12
|
+
import '../css/attachments.css';
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class PhotoGallery extends React.Component {
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
static subscribe = [PhotoStore];
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
static defaultProps = {
|
|
22
|
+
baseURL: "",
|
|
23
|
+
items: [],
|
|
24
|
+
fetching: false
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
static storeStateToProps = {
|
|
29
|
+
|
|
30
|
+
items: ( props, state ) => sortAndSplitImages( state.photos ),
|
|
31
|
+
fetching: ( props, state ) => state.fetching
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
render() {
|
|
36
|
+
|
|
37
|
+
const { baseURL, items, fetching, ...other } = this.props;
|
|
38
|
+
|
|
39
|
+
const count = items[0].length + items[1].length + items[2].length + items[3].length;
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<div className="photo-gallery paralax-content" {...other}>
|
|
43
|
+
{count < 1 && !fetching &&
|
|
44
|
+
<Column center className='text-secondary' >
|
|
45
|
+
<ImageIcon mt="-xxxl" mb='sm' style={{ width: '75px', height: '75px', strokeWidth: 1 }} />
|
|
46
|
+
<Typography style={{ fontWeight: 500 }} variant="subtitle2">NO PHOTOS FOUND.</Typography>
|
|
47
|
+
</Column>
|
|
48
|
+
}
|
|
49
|
+
{fetching && <Skeleton width="100%" height={window.innerHeight - 300} />}
|
|
50
|
+
{
|
|
51
|
+
!fetching && getImagesByColumn( items, 0, fetching )
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
{
|
|
55
|
+
!fetching && getImagesByColumn( items, 1, fetching )
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
{
|
|
59
|
+
!fetching && getImagesByColumn( items, 2, fetching )
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
{
|
|
63
|
+
!fetching && getImagesByColumn( items, 3, fetching )
|
|
64
|
+
}
|
|
65
|
+
</div>
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class Image extends Component {
|
|
75
|
+
state = {
|
|
76
|
+
loaded: false
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
handleImageLoaded = ( e ) => {
|
|
80
|
+
this.setState( { loaded: true } )
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
render() {
|
|
84
|
+
const { loaded } = this.state;
|
|
85
|
+
|
|
86
|
+
const styles = this.props.styles || {};
|
|
87
|
+
|
|
88
|
+
if ( !loaded ) {
|
|
89
|
+
styles.height = 0;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<React.Fragment>
|
|
94
|
+
{
|
|
95
|
+
!loaded && <div style={{ position: 'absolute', top: "2px", left: "2px", right: "2px", bottom: "2px" }}>
|
|
96
|
+
<Skeleton width="100%" height="100%" />
|
|
97
|
+
</div>
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
<img alt={this.props.alt} {...this.props} styles={styles} onLoad={this.handleImageLoaded} />
|
|
101
|
+
|
|
102
|
+
</React.Fragment>
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
function getImagesByColumn( items, col ) {
|
|
111
|
+
|
|
112
|
+
if ( ( !items ) || ( !items[col].length ) ) return null;
|
|
113
|
+
|
|
114
|
+
let columnStyle = {};
|
|
115
|
+
|
|
116
|
+
if ( items[1].length === 0 ) {
|
|
117
|
+
columnStyle = {
|
|
118
|
+
flex: '100%,1',
|
|
119
|
+
maxWidth: '100%'
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return (
|
|
124
|
+
<div className="photo-column" style={columnStyle}>
|
|
125
|
+
{
|
|
126
|
+
items[col].map( ( p ) => {
|
|
127
|
+
const finalUrl = createProxiedURL( p.links ? p.links[0].href : p._links.self.href )
|
|
128
|
+
return (
|
|
129
|
+
<div className="photo" key={p.id} onClick={() => showImageViewerDialog( p.name, finalUrl )}>
|
|
130
|
+
<Image alt={p.name} src={finalUrl} />
|
|
131
|
+
</div>
|
|
132
|
+
)
|
|
133
|
+
} )
|
|
134
|
+
}
|
|
135
|
+
</div>
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
const sortAndSplitImages = memoizee( ( arrayOfPhotos ) => {
|
|
141
|
+
|
|
142
|
+
if ( !arrayOfPhotos ) return [];
|
|
143
|
+
|
|
144
|
+
const ret = {
|
|
145
|
+
0: [],
|
|
146
|
+
1: [],
|
|
147
|
+
2: [],
|
|
148
|
+
3: []
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const sortedByCreationTimestamp = arrayOfPhotos.filter( ( p ) => p.mimeType.indexOf( "image" ) >= 0 ).sort( ( a, b ) => a.creationTimestamp - b.creationTimestamp ).reverse();
|
|
152
|
+
|
|
153
|
+
Object.values( sortedByCreationTimestamp ).forEach( ( photo, i ) => {
|
|
154
|
+
ret[i % 4].push( photo );
|
|
155
|
+
} )
|
|
156
|
+
|
|
157
|
+
return ret;
|
|
158
|
+
} );
|
|
159
|
+
|
|
160
|
+
export default Connect( PhotoGallery );
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import ImageUploadStore from '../stores/ImageUploadStore';
|
|
3
|
+
import { Connect } from '@selkirk-systems/state-management';
|
|
4
|
+
import { Column, Row } from '@selkirk-systems/layout';
|
|
5
|
+
import { AlertTriangle, CheckCircle2 } from 'lucide-react';
|
|
6
|
+
import { Typography, Paper } from '@selkirk-systems/selkirk-components';
|
|
7
|
+
import { ProgressBar } from 'primereact/progressbar';
|
|
8
|
+
import clsx from 'clsx';
|
|
9
|
+
import MIME_TYPE_ICONS from './MimeTypeIcons';
|
|
10
|
+
import UnknownFileTypeImage from './Icons/UnknownFileTypeImage';
|
|
11
|
+
import PhotoFileTypeImage from './Icons/PhotoFileTypeImage';
|
|
12
|
+
|
|
13
|
+
class ResponsiveImageUploadList extends React.Component {
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
static subscribe = [ImageUploadStore];
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
static defaultProps = {
|
|
20
|
+
files: []
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
static storeStateToProps = {
|
|
25
|
+
files: ( props, state ) => state.uploads
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
render() {
|
|
30
|
+
|
|
31
|
+
const { files, ...other } = this.props;
|
|
32
|
+
|
|
33
|
+
return Object.keys( files ).map( ( key, i ) => {
|
|
34
|
+
|
|
35
|
+
const file = files[key];
|
|
36
|
+
|
|
37
|
+
const FileType = file.mimeType.indexOf( "image" ) >= 0 ? <PhotoFileTypeImage /> : MIME_TYPE_ICONS[file.mimeType] || <UnknownFileTypeImage />
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<Paper key={file.id} elevation={0} onClick={( e ) => e.stopPropagation()} {...other}>
|
|
41
|
+
<Column gap="sm">
|
|
42
|
+
<Row gap="md" align="center" xs="auto 1fr auto">
|
|
43
|
+
{FileType}
|
|
44
|
+
<Typography variant="body1">{file.title}</Typography>
|
|
45
|
+
{!file.error && file.progress >= 100 &&
|
|
46
|
+
<CheckCircle2 mr='sm' className='success-color' />
|
|
47
|
+
}
|
|
48
|
+
{file.error && <AlertTriangle style={{ color: 'red' }} />}
|
|
49
|
+
</Row>
|
|
50
|
+
<ProgressBar className={clsx( "uploading-progress", { 'error': file.error } )} value={file.progress} />
|
|
51
|
+
</Column>
|
|
52
|
+
</Paper>
|
|
53
|
+
)
|
|
54
|
+
} )
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
export default Connect( ResponsiveImageUploadList );
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { closeImageUploadDialog, uploadFiles, invokeUploadInput } from '../actions/ImageUploadActions';
|
|
3
|
+
import ResponsiveImageUploadList from './ResponsiveImageUploadList';
|
|
4
|
+
import { Connect } from '@selkirk-systems/state-management';
|
|
5
|
+
import { Dialog } from 'primereact/dialog';
|
|
6
|
+
import { Button } from 'primereact/button';
|
|
7
|
+
import { UploadCloud, UploadIcon } from 'lucide-react';
|
|
8
|
+
import { Column } from '@selkirk-systems/layout';
|
|
9
|
+
import { Typography } from '@selkirk-systems/selkirk-components';
|
|
10
|
+
import ImageUploadStore from '../stores/ImageUploadStore';
|
|
11
|
+
import { FILE_ACCEPT } from '../constants/PhotosConstants';
|
|
12
|
+
import { ConfirmDialog } from 'primereact/confirmdialog';
|
|
13
|
+
|
|
14
|
+
class UploadImageDialog extends React.Component {
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
static subscribe = [ImageUploadStore];
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
static defaultProps = {
|
|
21
|
+
url: null,
|
|
22
|
+
show: false
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
static storeStateToProps = {
|
|
27
|
+
show: ( props, state ) => state.showImageUploadDialog
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
render() {
|
|
32
|
+
|
|
33
|
+
const { show, url, ...other } = this.props;
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<Dialog
|
|
38
|
+
header="Upload"
|
|
39
|
+
visible={show}
|
|
40
|
+
icons={<Button
|
|
41
|
+
text
|
|
42
|
+
type='button'
|
|
43
|
+
style={{ color: 'inherit' }}
|
|
44
|
+
onClick={invokeUploadInput}
|
|
45
|
+
>
|
|
46
|
+
<UploadIcon />
|
|
47
|
+
</Button>
|
|
48
|
+
}
|
|
49
|
+
onHide={closeImageUploadDialog}
|
|
50
|
+
position="bottom"
|
|
51
|
+
maximized
|
|
52
|
+
transitionOptions={
|
|
53
|
+
{
|
|
54
|
+
onExited: this.handledExited
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
{...other}
|
|
58
|
+
>
|
|
59
|
+
<form>
|
|
60
|
+
<input
|
|
61
|
+
type="file"
|
|
62
|
+
id="fileupload"
|
|
63
|
+
accept={FILE_ACCEPT}
|
|
64
|
+
multiple="multiple"
|
|
65
|
+
ref={fileInputEl =>
|
|
66
|
+
( this.fileInputEl = fileInputEl )
|
|
67
|
+
}
|
|
68
|
+
onChange={() =>
|
|
69
|
+
uploadFiles( url, this.fileInputEl.files )
|
|
70
|
+
}
|
|
71
|
+
/>
|
|
72
|
+
</form>
|
|
73
|
+
<Column fill xs="200px 1fr" gap="md" onClick={invokeUploadInput}>
|
|
74
|
+
<Column gap="sm" center pt='xl'>
|
|
75
|
+
<UploadCloud style={{ width: 85, height: 85, strokeWidth: 2 }} />
|
|
76
|
+
<Typography variant="h6" style={{ fontWeight: 600 }}>Upload your files</Typography>
|
|
77
|
+
<Typography variant="subtitle1">Tap here to choose a file from your device</Typography>
|
|
78
|
+
</Column>
|
|
79
|
+
<Column gap="sm" justify="top" pl='md' pr='md'>
|
|
80
|
+
<ResponsiveImageUploadList p='sm' />
|
|
81
|
+
</Column>
|
|
82
|
+
</Column>
|
|
83
|
+
<ConfirmDialog />
|
|
84
|
+
</Dialog>
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
export default Connect( UploadImageDialog );
|
|
93
|
+
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// this is a bit funky as attachments was referencing the messages package locally - once messages is added to npm this should be removed
|
|
2
|
+
export const SHOW_MESSAGES = "SHOW_MESSAGES";
|
|
3
|
+
export const CLEAR_ALL_MESSAGES = "CLEAR_ALL_MESSAGES";
|
|
4
|
+
export const ADD_IGNORE_ERROR = "ADD_IGNORE_ERROR";
|
|
5
|
+
export const REMOVE_IGNORE_ERROR_BY_ID = "REMOVE_IGNORE_ERROR_BY_ID";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const SHOW_IMAGE_VIEWER_DIALOG = "SHOW_IMAGE_VIEWER_DIALOG";
|
|
2
|
+
export const HIDE_IMAGE_VIEWER_DIALOG = "HIDE_IMAGE_VIEWER_DIALOG";
|
|
3
|
+
|
|
4
|
+
export const FETCH_PHOTOS = "FETCH_PHOTOS";
|
|
5
|
+
export const FETCHED_PHOTOS = "FETCHED_PHOTOS";
|
|
6
|
+
export const CLEAR_PHOTOS = "CLEAR_PHOTOS";
|
|
7
|
+
|
|
8
|
+
export const SHOW_IMAGE_UPLOAD_DIALOG = "SHOW_IMAGE_UPLOAD_DIALOG";
|
|
9
|
+
export const HIDE_IMAGE_UPLOAD_DIALOG = "HIDE_IMAGE_UPLOAD_DIALOG";
|
|
10
|
+
export const SET_UPLOAD_PROGRESS = "SET_UPLOAD_PROGRESS";
|
|
11
|
+
export const DELETE_IMAGE = "DELETE_IMAGE";
|
|
12
|
+
export const DELETED_IMAGE = "DELETED_IMAGE";
|
|
13
|
+
export const IMAGE_UPLOAD_COMPLETE = "IMAGE_UPLOAD_COMPLETE";
|
|
14
|
+
export const CLEAR_UPLOADS = "CLEAR_UPLOADS";
|
|
15
|
+
export const CANCEL_UPLOAD = "CANCEL_UPLOAD";
|
|
16
|
+
export const FILE_DOWNLOAD = "FILE_DOWNLOAD";
|
|
17
|
+
export const FILE_DOWNLOADED = "FILE_DOWNLOADED";
|
|
18
|
+
export const FILE_DELETE = "FILE_DELETE";
|
|
19
|
+
export const FILE_DELETED = "FILE_DELETED";
|
|
20
|
+
|
|
21
|
+
export const FILE_ACCEPT = "image/*,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/pdf,application/msword,application/vnd.ms-excel,text/plain,application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#root .attachments {
|
|
2
|
+
overflow-x: hidden;
|
|
3
|
+
overflow-y: auto;
|
|
4
|
+
perspective: 2px;
|
|
5
|
+
}
|
|
6
|
+
.attachments .bg img {
|
|
7
|
+
width: 56px;
|
|
8
|
+
opacity: 0.7;
|
|
9
|
+
}
|
|
10
|
+
.attachments .paralax-content {
|
|
11
|
+
position: relative;
|
|
12
|
+
z-index: 2;
|
|
13
|
+
background: #ffffff;
|
|
14
|
+
transform-style: preserve-3d;
|
|
15
|
+
position: relative;
|
|
16
|
+
min-height: 40px;
|
|
17
|
+
display: flex;
|
|
18
|
+
}
|
|
19
|
+
.attachments .file-gallery>*,
|
|
20
|
+
.attachments .photo-gallery{
|
|
21
|
+
background-color: whitesmoke;
|
|
22
|
+
}
|
|
23
|
+
.attachments .paralax-spacer {
|
|
24
|
+
background: transparent;
|
|
25
|
+
height: 175px;
|
|
26
|
+
transform-style: preserve-3d;
|
|
27
|
+
position: relative;
|
|
28
|
+
}
|
|
29
|
+
.attachments .p-tabview-nav-container{
|
|
30
|
+
width:100%;
|
|
31
|
+
}
|
|
32
|
+
.attachments .p-tabview .p-tabview-nav li.p-tabview-selected{
|
|
33
|
+
color:var(--icon);
|
|
34
|
+
}
|
|
35
|
+
.attachments .p-tabview .p-tabview-nav li.p-highlight .p-tabview-nav-link {
|
|
36
|
+
background: white;
|
|
37
|
+
border-top: none;
|
|
38
|
+
border-right: none;
|
|
39
|
+
border-left: none;
|
|
40
|
+
border-bottom-width: 5px;
|
|
41
|
+
}
|
|
42
|
+
.attachments .p-tabview-nav a{
|
|
43
|
+
border-bottom-width:0;
|
|
44
|
+
}
|
|
45
|
+
.file-gallery {
|
|
46
|
+
}
|
|
47
|
+
.photo-gallery {
|
|
48
|
+
display: flex;
|
|
49
|
+
flex-wrap: wrap;
|
|
50
|
+
padding: 2px;
|
|
51
|
+
}
|
|
52
|
+
.photo-column {
|
|
53
|
+
display: flex;
|
|
54
|
+
flex: 33.333%;
|
|
55
|
+
max-width: 33.333%;
|
|
56
|
+
flex-direction: column;
|
|
57
|
+
}
|
|
58
|
+
.photo-column > * {
|
|
59
|
+
flex: 1 1 auto;
|
|
60
|
+
}
|
|
61
|
+
.photo {
|
|
62
|
+
overflow: hidden;
|
|
63
|
+
border-radius: 10px;
|
|
64
|
+
padding: 2px;
|
|
65
|
+
min-width: 50%;
|
|
66
|
+
min-height: 150px;
|
|
67
|
+
position: relative;
|
|
68
|
+
background: white;
|
|
69
|
+
border: 2px solid white;
|
|
70
|
+
}
|
|
71
|
+
.photo img {
|
|
72
|
+
width: 100%;
|
|
73
|
+
height: 100%;
|
|
74
|
+
object-fit: cover;
|
|
75
|
+
vertical-align: middle;
|
|
76
|
+
border-radius: 5px;
|
|
77
|
+
}
|
|
78
|
+
input[type="file"] {
|
|
79
|
+
display: none;
|
|
80
|
+
}
|
|
81
|
+
.attachments .parallax {
|
|
82
|
+
content: " ";
|
|
83
|
+
position: absolute;
|
|
84
|
+
top: 0;
|
|
85
|
+
right: 0;
|
|
86
|
+
bottom: 0;
|
|
87
|
+
left: 0;
|
|
88
|
+
transform: translateZ(-1px) scale(1.5);
|
|
89
|
+
background-size: 100%;
|
|
90
|
+
z-index: -1;
|
|
91
|
+
}
|
|
92
|
+
.attachments .bg {
|
|
93
|
+
margin: 0 -1px;
|
|
94
|
+
background-position: -60px -6px;
|
|
95
|
+
color: rgba(255, 255, 255, 0.9);
|
|
96
|
+
}
|
|
97
|
+
.attachments .bg > * {
|
|
98
|
+
backdrop-filter: blur(3px); /* blur effect to the backdrop */
|
|
99
|
+
-webkit-backdrop-filter: blur(3px);
|
|
100
|
+
height: 180px;
|
|
101
|
+
}
|
|
102
|
+
@media (min-width: 600px) {
|
|
103
|
+
.photo-gallery > *:last-child {
|
|
104
|
+
display: grid;
|
|
105
|
+
grid-auto-flow: column;
|
|
106
|
+
grid-auto-columns: minmax(33.333%, 1fr);
|
|
107
|
+
max-width: 100%;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.photo-gallery > *:last-child > * {
|
|
111
|
+
max-height: 250px;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.photo-gallery > *:last-child > *:only-child {
|
|
115
|
+
max-height: 250px;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@media (max-width: 600px) {
|
|
120
|
+
.photo-column {
|
|
121
|
+
flex: 50%;
|
|
122
|
+
max-width: 50%;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* .photo-gallery>*:last-child{
|
|
126
|
+
display:flex;
|
|
127
|
+
flex-wrap: wrap;
|
|
128
|
+
flex:100%;
|
|
129
|
+
max-width:100%;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.photo-gallery>*:last-child>*{
|
|
133
|
+
flex:50%;
|
|
134
|
+
max-width:50%;
|
|
135
|
+
} */
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
@media (max-width: 300px) {
|
|
139
|
+
.photo-column {
|
|
140
|
+
flex: 100%;
|
|
141
|
+
max-width: 100%;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
.image-viewer {
|
|
2
|
+
position: fixed;
|
|
3
|
+
top: 0;
|
|
4
|
+
left: 0;
|
|
5
|
+
right: 0;
|
|
6
|
+
bottom: 0;
|
|
7
|
+
z-index: 9999;
|
|
8
|
+
background: black;
|
|
9
|
+
color: white;
|
|
10
|
+
}
|
|
11
|
+
.image-viewer .title {
|
|
12
|
+
white-space: nowrap;
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
text-overflow: ellipsis;
|
|
15
|
+
}
|
|
16
|
+
.image-viewer .icon {
|
|
17
|
+
color: white;
|
|
18
|
+
z-index: 1;
|
|
19
|
+
}
|
|
20
|
+
.image-viewer .top.actions {
|
|
21
|
+
top: 0;
|
|
22
|
+
left: 0;
|
|
23
|
+
right: 0;
|
|
24
|
+
}
|
|
25
|
+
.image-viewer .bottom.actions {
|
|
26
|
+
bottom: 0;
|
|
27
|
+
left: 0;
|
|
28
|
+
right: 0;
|
|
29
|
+
}
|
|
30
|
+
.image-viewer .actions {
|
|
31
|
+
position: absolute;
|
|
32
|
+
padding: 10px 15px;
|
|
33
|
+
width: 100%;
|
|
34
|
+
z-index: 1;
|
|
35
|
+
background-color: rgba(0, 0, 0, 0.88);
|
|
36
|
+
}
|
|
37
|
+
.image-viewer img {
|
|
38
|
+
position: absolute;
|
|
39
|
+
top: 0;
|
|
40
|
+
left: 0;
|
|
41
|
+
width: 100%;
|
|
42
|
+
height: 100%;
|
|
43
|
+
object-fit: contain;
|
|
44
|
+
z-index: 0;
|
|
45
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Components
|
|
2
|
+
export { default as PhotoGallery } from './components/PhotoGallery';
|
|
3
|
+
export { default as FileList } from './components/FileList';
|
|
4
|
+
export { default as UploadImageDialog } from './components/UploadImageDialog';
|
|
5
|
+
export { default as ImageViewerDialog } from './components/ImageViewerDialog';
|
|
6
|
+
export { default as FileDownloadIcon } from './components/FileDownloadIcon';
|
|
7
|
+
export { default as FileDeleteIcon } from './components/FileDeleteIcon';
|
|
8
|
+
export { default as MimeTypeIcons } from './components/MimeTypeIcons';
|
|
9
|
+
|
|
10
|
+
// Actions
|
|
11
|
+
export { showImageViewerDialog, hideImageViewerDialog } from './actions/AttachmentActions';
|
|
12
|
+
export { fetchPhotos, deleteImage, clearPhotos } from './actions/PhotoActions';
|
|
13
|
+
export { showImageUploadDialog, closeImageUploadDialog, invokeUploadInput, uploadFiles, deleteImageById } from './actions/ImageUploadActions';
|
|
14
|
+
export { downloadFile, deleteFile } from './actions/FileActions';
|
|
15
|
+
|
|
16
|
+
// Stores
|
|
17
|
+
export { default as PhotosStore } from './stores/PhotosStore';
|
|
18
|
+
export { default as ImageUploadStore } from './stores/ImageUploadStore';
|
|
19
|
+
export { default as DownloadStore } from './stores/DownloadStore';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { FILE_DELETE, FILE_DELETED, FILE_DOWNLOAD, FILE_DOWNLOADED } from "../constants/PhotosConstants";
|
|
2
|
+
import { CreateStore, setValues, withPayload } from "@selkirk-systems/state-management";
|
|
3
|
+
|
|
4
|
+
const DownloadStore = CreateStore( {
|
|
5
|
+
|
|
6
|
+
name: "DownloadStore",
|
|
7
|
+
|
|
8
|
+
events: {
|
|
9
|
+
[FILE_DOWNLOAD]: withPayload().setValues( "downloading" ),
|
|
10
|
+
[FILE_DOWNLOADED]: setValues( "downloading", null ),
|
|
11
|
+
[FILE_DELETE]: withPayload().setValues( "deleting" ),
|
|
12
|
+
[FILE_DELETED]: setValues( "deleting", null )
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
state: {
|
|
16
|
+
downloading: null,
|
|
17
|
+
deleting: null
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
} );
|
|
22
|
+
|
|
23
|
+
export default DownloadStore;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { CLEAR_UPLOADS, HIDE_IMAGE_UPLOAD_DIALOG, SET_UPLOAD_PROGRESS, SHOW_IMAGE_UPLOAD_DIALOG } from "../constants/PhotosConstants";
|
|
2
|
+
import update from "@mbernal/simple-immutable";
|
|
3
|
+
import { CreateStore, setFalse, setValues, withPayload } from "@selkirk-systems/state-management";
|
|
4
|
+
|
|
5
|
+
const ImageUploadStore = CreateStore( {
|
|
6
|
+
|
|
7
|
+
name: "ImageUploadStore",
|
|
8
|
+
|
|
9
|
+
events: {
|
|
10
|
+
[SET_UPLOAD_PROGRESS]: ( action, state ) => {
|
|
11
|
+
|
|
12
|
+
return update( state, {
|
|
13
|
+
'merge uploads': { [action.payload.id]: action.payload }
|
|
14
|
+
} )
|
|
15
|
+
|
|
16
|
+
},
|
|
17
|
+
[CLEAR_UPLOADS]: setValues( "uploads", {} ),
|
|
18
|
+
[SHOW_IMAGE_UPLOAD_DIALOG]: withPayload().setValues( "imageUploadTag" ).setTrue( "showImageUploadDialog" ),
|
|
19
|
+
[HIDE_IMAGE_UPLOAD_DIALOG]: setFalse( "showImageUploadDialog" ),
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
state: {
|
|
23
|
+
showImageUploadDialog: false,
|
|
24
|
+
imageUploadTag: null,
|
|
25
|
+
uploads: {}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
} );
|
|
30
|
+
|
|
31
|
+
export default ImageUploadStore;
|