@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.
Files changed (84) hide show
  1. package/README.md +0 -0
  2. package/dist/actions/AttachmentActions.js +11 -0
  3. package/dist/actions/FileActions.js +37 -0
  4. package/dist/actions/ImageUploadActions.js +99 -0
  5. package/dist/actions/PhotoActions.js +53 -0
  6. package/dist/components/FileDeleteIcon.js +30 -0
  7. package/dist/components/FileDownloadIcon.js +34 -0
  8. package/dist/components/FileList.js +111 -0
  9. package/dist/components/Icons/ExcelFileTypeImage.js +8 -0
  10. package/dist/components/Icons/HTMLFileTypeImage.js +7 -0
  11. package/dist/components/Icons/JSONFileTypeImage.js +7 -0
  12. package/dist/components/Icons/PDFFileTypeImage.js +7 -0
  13. package/dist/components/Icons/PhotoFileTypeImage.js +6 -0
  14. package/dist/components/Icons/PowerPointTypeImage.js +7 -0
  15. package/dist/components/Icons/TextFileTypeImage.js +7 -0
  16. package/dist/components/Icons/UnknownFileTypeImage.js +7 -0
  17. package/dist/components/Icons/WordFileTypeImage.js +7 -0
  18. package/dist/components/Icons/ZipFileTypeImage.js +7 -0
  19. package/dist/components/ImageViewerDialog.js +78 -0
  20. package/dist/components/MimeTypeIcons.js +28 -0
  21. package/dist/components/PhotoGallery.js +130 -0
  22. package/dist/components/ResponsiveImageUploadList.js +57 -0
  23. package/dist/components/UploadImageDialog.js +85 -0
  24. package/dist/constants/MessageConstants.js +5 -0
  25. package/dist/constants/PhotosConstants.js +18 -0
  26. package/dist/css/attachments.css +143 -0
  27. package/dist/css/image-viewer.css +45 -0
  28. package/dist/img/PowerPoint-filetype.png +0 -0
  29. package/dist/img/blue-pattern-bg.jpg +0 -0
  30. package/dist/img/excel-filetype.png +0 -0
  31. package/dist/img/html-filetype.png +0 -0
  32. package/dist/img/json-filetype.png +0 -0
  33. package/dist/img/pdf-filetype.png +0 -0
  34. package/dist/img/photo-filetype.png +0 -0
  35. package/dist/img/txt-filetype.png +0 -0
  36. package/dist/img/unknown-filetype.png +0 -0
  37. package/dist/img/word-filetype.png +0 -0
  38. package/dist/img/zip-filetype.png +0 -0
  39. package/dist/index.js +19 -0
  40. package/dist/stores/DownloadStore.js +16 -0
  41. package/dist/stores/ImageUploadStore.js +24 -0
  42. package/dist/stores/PhotosStore.js +59 -0
  43. package/lib/actions/AttachmentActions.js +14 -0
  44. package/lib/actions/FileActions.js +34 -0
  45. package/lib/actions/ImageUploadActions.js +134 -0
  46. package/lib/actions/PhotoActions.js +65 -0
  47. package/lib/components/FileDeleteIcon.jsx +42 -0
  48. package/lib/components/FileDownloadIcon.jsx +42 -0
  49. package/lib/components/FileList.jsx +111 -0
  50. package/lib/components/Icons/ExcelFileTypeImage.jsx +6 -0
  51. package/lib/components/Icons/HTMLFileTypeImage.jsx +5 -0
  52. package/lib/components/Icons/JSONFileTypeImage.jsx +5 -0
  53. package/lib/components/Icons/PDFFileTypeImage.jsx +5 -0
  54. package/lib/components/Icons/PhotoFileTypeImage.jsx +5 -0
  55. package/lib/components/Icons/PowerPointTypeImage.jsx +5 -0
  56. package/lib/components/Icons/TextFileTypeImage.jsx +5 -0
  57. package/lib/components/Icons/UnknownFileTypeImage.jsx +5 -0
  58. package/lib/components/Icons/WordFileTypeImage.jsx +5 -0
  59. package/lib/components/Icons/ZipFileTypeImage.jsx +5 -0
  60. package/lib/components/ImageViewerDialog.jsx +72 -0
  61. package/lib/components/MimeTypeIcons.jsx +30 -0
  62. package/lib/components/PhotoGallery.jsx +160 -0
  63. package/lib/components/ResponsiveImageUploadList.jsx +61 -0
  64. package/lib/components/UploadImageDialog.jsx +93 -0
  65. package/lib/constants/MessageConstants.js +5 -0
  66. package/lib/constants/PhotosConstants.js +21 -0
  67. package/lib/css/attachments.css +143 -0
  68. package/lib/css/image-viewer.css +45 -0
  69. package/lib/img/PowerPoint-filetype.png +0 -0
  70. package/lib/img/blue-pattern-bg.jpg +0 -0
  71. package/lib/img/excel-filetype.png +0 -0
  72. package/lib/img/html-filetype.png +0 -0
  73. package/lib/img/json-filetype.png +0 -0
  74. package/lib/img/pdf-filetype.png +0 -0
  75. package/lib/img/photo-filetype.png +0 -0
  76. package/lib/img/txt-filetype.png +0 -0
  77. package/lib/img/unknown-filetype.png +0 -0
  78. package/lib/img/word-filetype.png +0 -0
  79. package/lib/img/zip-filetype.png +0 -0
  80. package/lib/index.js +19 -0
  81. package/lib/stores/DownloadStore.js +23 -0
  82. package/lib/stores/ImageUploadStore.js +31 -0
  83. package/lib/stores/PhotosStore.js +81 -0
  84. package/package.json +50 -0
@@ -0,0 +1,130 @@
1
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
2
+ import React, { Component } from "react";
3
+ import { Connect } from '@selkirk-systems/state-management';
4
+ import PhotoStore from "../stores/PhotosStore";
5
+ import { ImageIcon } from "lucide-react";
6
+ import { Column } from "@selkirk-systems/layout";
7
+ import { Skeleton } from "primereact/skeleton";
8
+ import memoizee from "memoizee";
9
+ import { showImageViewerDialog } from "../actions/AttachmentActions";
10
+ import { createProxiedURL } from "@selkirk-systems/selkirk-utils";
11
+ import { Typography } from "@selkirk-systems/selkirk-components";
12
+ import '../css/attachments.css';
13
+ class PhotoGallery extends React.Component {
14
+ static subscribe = [PhotoStore];
15
+ static defaultProps = {
16
+ baseURL: "",
17
+ items: [],
18
+ fetching: false
19
+ };
20
+ static storeStateToProps = {
21
+ items: (props, state) => sortAndSplitImages(state.photos),
22
+ fetching: (props, state) => state.fetching
23
+ };
24
+ render() {
25
+ const {
26
+ baseURL,
27
+ items,
28
+ fetching,
29
+ ...other
30
+ } = this.props;
31
+ const count = items[0].length + items[1].length + items[2].length + items[3].length;
32
+ return /*#__PURE__*/React.createElement("div", _extends({
33
+ className: "photo-gallery paralax-content"
34
+ }, other), count < 1 && !fetching && /*#__PURE__*/React.createElement(Column, {
35
+ center: true,
36
+ className: "text-secondary"
37
+ }, /*#__PURE__*/React.createElement(ImageIcon, {
38
+ mt: "-xxxl",
39
+ mb: "sm",
40
+ style: {
41
+ width: '75px',
42
+ height: '75px',
43
+ strokeWidth: 1
44
+ }
45
+ }), /*#__PURE__*/React.createElement(Typography, {
46
+ style: {
47
+ fontWeight: 500
48
+ },
49
+ variant: "subtitle2"
50
+ }, "NO PHOTOS FOUND.")), fetching && /*#__PURE__*/React.createElement(Skeleton, {
51
+ width: "100%",
52
+ height: window.innerHeight - 300
53
+ }), !fetching && getImagesByColumn(items, 0, fetching), !fetching && getImagesByColumn(items, 1, fetching), !fetching && getImagesByColumn(items, 2, fetching), !fetching && getImagesByColumn(items, 3, fetching));
54
+ }
55
+ }
56
+ class Image extends Component {
57
+ state = {
58
+ loaded: false
59
+ };
60
+ handleImageLoaded = e => {
61
+ this.setState({
62
+ loaded: true
63
+ });
64
+ };
65
+ render() {
66
+ const {
67
+ loaded
68
+ } = this.state;
69
+ const styles = this.props.styles || {};
70
+ if (!loaded) {
71
+ styles.height = 0;
72
+ }
73
+ return /*#__PURE__*/React.createElement(React.Fragment, null, !loaded && /*#__PURE__*/React.createElement("div", {
74
+ style: {
75
+ position: 'absolute',
76
+ top: "2px",
77
+ left: "2px",
78
+ right: "2px",
79
+ bottom: "2px"
80
+ }
81
+ }, /*#__PURE__*/React.createElement(Skeleton, {
82
+ width: "100%",
83
+ height: "100%"
84
+ })), /*#__PURE__*/React.createElement("img", _extends({
85
+ alt: this.props.alt
86
+ }, this.props, {
87
+ styles: styles,
88
+ onLoad: this.handleImageLoaded
89
+ })));
90
+ }
91
+ }
92
+ function getImagesByColumn(items, col) {
93
+ if (!items || !items[col].length) return null;
94
+ let columnStyle = {};
95
+ if (items[1].length === 0) {
96
+ columnStyle = {
97
+ flex: '100%,1',
98
+ maxWidth: '100%'
99
+ };
100
+ }
101
+ return /*#__PURE__*/React.createElement("div", {
102
+ className: "photo-column",
103
+ style: columnStyle
104
+ }, items[col].map(p => {
105
+ const finalUrl = createProxiedURL(p.links ? p.links[0].href : p._links.self.href);
106
+ return /*#__PURE__*/React.createElement("div", {
107
+ className: "photo",
108
+ key: p.id,
109
+ onClick: () => showImageViewerDialog(p.name, finalUrl)
110
+ }, /*#__PURE__*/React.createElement(Image, {
111
+ alt: p.name,
112
+ src: finalUrl
113
+ }));
114
+ }));
115
+ }
116
+ const sortAndSplitImages = memoizee(arrayOfPhotos => {
117
+ if (!arrayOfPhotos) return [];
118
+ const ret = {
119
+ 0: [],
120
+ 1: [],
121
+ 2: [],
122
+ 3: []
123
+ };
124
+ const sortedByCreationTimestamp = arrayOfPhotos.filter(p => p.mimeType.indexOf("image") >= 0).sort((a, b) => a.creationTimestamp - b.creationTimestamp).reverse();
125
+ Object.values(sortedByCreationTimestamp).forEach((photo, i) => {
126
+ ret[i % 4].push(photo);
127
+ });
128
+ return ret;
129
+ });
130
+ export default Connect(PhotoGallery);
@@ -0,0 +1,57 @@
1
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
2
+ import React from 'react';
3
+ import ImageUploadStore from '../stores/ImageUploadStore';
4
+ import { Connect } from '@selkirk-systems/state-management';
5
+ import { Column, Row } from '@selkirk-systems/layout';
6
+ import { AlertTriangle, CheckCircle2 } from 'lucide-react';
7
+ import { Typography, Paper } from '@selkirk-systems/selkirk-components';
8
+ import { ProgressBar } from 'primereact/progressbar';
9
+ import clsx from 'clsx';
10
+ import MIME_TYPE_ICONS from './MimeTypeIcons';
11
+ import UnknownFileTypeImage from './Icons/UnknownFileTypeImage';
12
+ import PhotoFileTypeImage from './Icons/PhotoFileTypeImage';
13
+ class ResponsiveImageUploadList extends React.Component {
14
+ static subscribe = [ImageUploadStore];
15
+ static defaultProps = {
16
+ files: []
17
+ };
18
+ static storeStateToProps = {
19
+ files: (props, state) => state.uploads
20
+ };
21
+ render() {
22
+ const {
23
+ files,
24
+ ...other
25
+ } = this.props;
26
+ return Object.keys(files).map((key, i) => {
27
+ const file = files[key];
28
+ const FileType = file.mimeType.indexOf("image") >= 0 ? /*#__PURE__*/React.createElement(PhotoFileTypeImage, null) : MIME_TYPE_ICONS[file.mimeType] || /*#__PURE__*/React.createElement(UnknownFileTypeImage, null);
29
+ return /*#__PURE__*/React.createElement(Paper, _extends({
30
+ key: file.id,
31
+ elevation: 0,
32
+ onClick: e => e.stopPropagation()
33
+ }, other), /*#__PURE__*/React.createElement(Column, {
34
+ gap: "sm"
35
+ }, /*#__PURE__*/React.createElement(Row, {
36
+ gap: "md",
37
+ align: "center",
38
+ xs: "auto 1fr auto"
39
+ }, FileType, /*#__PURE__*/React.createElement(Typography, {
40
+ variant: "body1"
41
+ }, file.title), !file.error && file.progress >= 100 && /*#__PURE__*/React.createElement(CheckCircle2, {
42
+ mr: "sm",
43
+ className: "success-color"
44
+ }), file.error && /*#__PURE__*/React.createElement(AlertTriangle, {
45
+ style: {
46
+ color: 'red'
47
+ }
48
+ })), /*#__PURE__*/React.createElement(ProgressBar, {
49
+ className: clsx("uploading-progress", {
50
+ 'error': file.error
51
+ }),
52
+ value: file.progress
53
+ })));
54
+ });
55
+ }
56
+ }
57
+ export default Connect(ResponsiveImageUploadList);
@@ -0,0 +1,85 @@
1
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
2
+ import React from 'react';
3
+ import { closeImageUploadDialog, uploadFiles, invokeUploadInput } from '../actions/ImageUploadActions';
4
+ import ResponsiveImageUploadList from './ResponsiveImageUploadList';
5
+ import { Connect } from '@selkirk-systems/state-management';
6
+ import { Dialog } from 'primereact/dialog';
7
+ import { Button } from 'primereact/button';
8
+ import { UploadCloud, UploadIcon } from 'lucide-react';
9
+ import { Column } from '@selkirk-systems/layout';
10
+ import { Typography } from '@selkirk-systems/selkirk-components';
11
+ import ImageUploadStore from '../stores/ImageUploadStore';
12
+ import { FILE_ACCEPT } from '../constants/PhotosConstants';
13
+ import { ConfirmDialog } from 'primereact/confirmdialog';
14
+ class UploadImageDialog extends React.Component {
15
+ static subscribe = [ImageUploadStore];
16
+ static defaultProps = {
17
+ url: null,
18
+ show: false
19
+ };
20
+ static storeStateToProps = {
21
+ show: (props, state) => state.showImageUploadDialog
22
+ };
23
+ render() {
24
+ const {
25
+ show,
26
+ url,
27
+ ...other
28
+ } = this.props;
29
+ return /*#__PURE__*/React.createElement(Dialog, _extends({
30
+ header: "Upload",
31
+ visible: show,
32
+ icons: /*#__PURE__*/React.createElement(Button, {
33
+ text: true,
34
+ type: "button",
35
+ style: {
36
+ color: 'inherit'
37
+ },
38
+ onClick: invokeUploadInput
39
+ }, /*#__PURE__*/React.createElement(UploadIcon, null)),
40
+ onHide: closeImageUploadDialog,
41
+ position: "bottom",
42
+ maximized: true,
43
+ transitionOptions: {
44
+ onExited: this.handledExited
45
+ }
46
+ }, other), /*#__PURE__*/React.createElement("form", null, /*#__PURE__*/React.createElement("input", {
47
+ type: "file",
48
+ id: "fileupload",
49
+ accept: FILE_ACCEPT,
50
+ multiple: "multiple",
51
+ ref: fileInputEl => this.fileInputEl = fileInputEl,
52
+ onChange: () => uploadFiles(url, this.fileInputEl.files)
53
+ })), /*#__PURE__*/React.createElement(Column, {
54
+ fill: true,
55
+ xs: "200px 1fr",
56
+ gap: "md",
57
+ onClick: invokeUploadInput
58
+ }, /*#__PURE__*/React.createElement(Column, {
59
+ gap: "sm",
60
+ center: true,
61
+ pt: "xl"
62
+ }, /*#__PURE__*/React.createElement(UploadCloud, {
63
+ style: {
64
+ width: 85,
65
+ height: 85,
66
+ strokeWidth: 2
67
+ }
68
+ }), /*#__PURE__*/React.createElement(Typography, {
69
+ variant: "h6",
70
+ style: {
71
+ fontWeight: 600
72
+ }
73
+ }, "Upload your files"), /*#__PURE__*/React.createElement(Typography, {
74
+ variant: "subtitle1"
75
+ }, "Tap here to choose a file from your device")), /*#__PURE__*/React.createElement(Column, {
76
+ gap: "sm",
77
+ justify: "top",
78
+ pl: "md",
79
+ pr: "md"
80
+ }, /*#__PURE__*/React.createElement(ResponsiveImageUploadList, {
81
+ p: "sm"
82
+ }))), /*#__PURE__*/React.createElement(ConfirmDialog, null));
83
+ }
84
+ }
85
+ export default Connect(UploadImageDialog);
@@ -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,18 @@
1
+ export const SHOW_IMAGE_VIEWER_DIALOG = "SHOW_IMAGE_VIEWER_DIALOG";
2
+ export const HIDE_IMAGE_VIEWER_DIALOG = "HIDE_IMAGE_VIEWER_DIALOG";
3
+ export const FETCH_PHOTOS = "FETCH_PHOTOS";
4
+ export const FETCHED_PHOTOS = "FETCHED_PHOTOS";
5
+ export const CLEAR_PHOTOS = "CLEAR_PHOTOS";
6
+ export const SHOW_IMAGE_UPLOAD_DIALOG = "SHOW_IMAGE_UPLOAD_DIALOG";
7
+ export const HIDE_IMAGE_UPLOAD_DIALOG = "HIDE_IMAGE_UPLOAD_DIALOG";
8
+ export const SET_UPLOAD_PROGRESS = "SET_UPLOAD_PROGRESS";
9
+ export const DELETE_IMAGE = "DELETE_IMAGE";
10
+ export const DELETED_IMAGE = "DELETED_IMAGE";
11
+ export const IMAGE_UPLOAD_COMPLETE = "IMAGE_UPLOAD_COMPLETE";
12
+ export const CLEAR_UPLOADS = "CLEAR_UPLOADS";
13
+ export const CANCEL_UPLOAD = "CANCEL_UPLOAD";
14
+ export const FILE_DOWNLOAD = "FILE_DOWNLOAD";
15
+ export const FILE_DOWNLOADED = "FILE_DOWNLOADED";
16
+ export const FILE_DELETE = "FILE_DELETE";
17
+ export const FILE_DELETED = "FILE_DELETED";
18
+ 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/dist/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,16 @@
1
+ import { FILE_DELETE, FILE_DELETED, FILE_DOWNLOAD, FILE_DOWNLOADED } from "../constants/PhotosConstants";
2
+ import { CreateStore, setValues, withPayload } from "@selkirk-systems/state-management";
3
+ const DownloadStore = CreateStore({
4
+ name: "DownloadStore",
5
+ events: {
6
+ [FILE_DOWNLOAD]: withPayload().setValues("downloading"),
7
+ [FILE_DOWNLOADED]: setValues("downloading", null),
8
+ [FILE_DELETE]: withPayload().setValues("deleting"),
9
+ [FILE_DELETED]: setValues("deleting", null)
10
+ },
11
+ state: {
12
+ downloading: null,
13
+ deleting: null
14
+ }
15
+ });
16
+ export default DownloadStore;
@@ -0,0 +1,24 @@
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
+ const ImageUploadStore = CreateStore({
5
+ name: "ImageUploadStore",
6
+ events: {
7
+ [SET_UPLOAD_PROGRESS]: (action, state) => {
8
+ return update(state, {
9
+ 'merge uploads': {
10
+ [action.payload.id]: action.payload
11
+ }
12
+ });
13
+ },
14
+ [CLEAR_UPLOADS]: setValues("uploads", {}),
15
+ [SHOW_IMAGE_UPLOAD_DIALOG]: withPayload().setValues("imageUploadTag").setTrue("showImageUploadDialog"),
16
+ [HIDE_IMAGE_UPLOAD_DIALOG]: setFalse("showImageUploadDialog")
17
+ },
18
+ state: {
19
+ showImageUploadDialog: false,
20
+ imageUploadTag: null,
21
+ uploads: {}
22
+ }
23
+ });
24
+ export default ImageUploadStore;
@@ -0,0 +1,59 @@
1
+ import update from "@mbernal/simple-immutable";
2
+ import { CreateStore, setFalse, setStore, setTrue, setValues, withPayload } from "@selkirk-systems/state-management";
3
+ import { CLEAR_PHOTOS, DELETED_IMAGE, DELETE_IMAGE, FETCHED_PHOTOS, FETCH_PHOTOS, FILE_DELETED, FILE_DOWNLOAD, FILE_DOWNLOADED, HIDE_IMAGE_VIEWER_DIALOG, IMAGE_UPLOAD_COMPLETE, SET_UPLOAD_PROGRESS, SHOW_IMAGE_VIEWER_DIALOG } from "../constants/PhotosConstants";
4
+ const PhotoStore = CreateStore({
5
+ name: "PhotoStore",
6
+ events: {
7
+ [IMAGE_UPLOAD_COMPLETE]: setTrue("reload"),
8
+ [FETCH_PHOTOS]: setFalse("reload").setTrue("fetching"),
9
+ [FETCHED_PHOTOS]: withPayload().setValues("photos").setFalse("fetching"),
10
+ [CLEAR_PHOTOS]: setStore(() => init()),
11
+ [DELETE_IMAGE]: setTrue("deleting"),
12
+ [SHOW_IMAGE_VIEWER_DIALOG]: withPayload().setValues("imageViewer"),
13
+ [HIDE_IMAGE_VIEWER_DIALOG]: setValues("imageViewer", {}),
14
+ [SET_UPLOAD_PROGRESS]: (action, state) => {
15
+ const payload = action.payload;
16
+ if (payload.error || payload.progress !== 100) return state;
17
+ const matchIndex = state.photos.findIndex(p => p.name.toLowerCase() === payload.id.toLowerCase());
18
+ if (matchIndex >= 0) {
19
+ return update(state, {
20
+ [`set photos.${matchIndex}`]: payload.response.data[0]
21
+ });
22
+ }
23
+ return update(state, {
24
+ 'unshift photos': Array.isArray(payload.response.data) ? payload.response.data : [payload.response.data]
25
+ });
26
+ },
27
+ [FILE_DELETED]: (action, state) => {
28
+ const {
29
+ fileName
30
+ } = action.payload;
31
+ const index = state.photos.findIndex(p => p.name === fileName);
32
+ if (index < 0) return state;
33
+ return update(state, {
34
+ 'splice photos': [[index, 1]],
35
+ 'set deleting': false
36
+ });
37
+ },
38
+ [DELETED_IMAGE]: (action, state) => {
39
+ const name = action.payload;
40
+ const index = state.photos.findIndex(p => p.name === name);
41
+ if (index < 0) return state;
42
+ return update(state, {
43
+ 'splice photos': [[index, 1]],
44
+ 'set deleting': false
45
+ });
46
+ }
47
+ },
48
+ state: init()
49
+ });
50
+ function init() {
51
+ return {
52
+ imageViewer: {},
53
+ fetching: true,
54
+ deleting: false,
55
+ reload: false,
56
+ photos: []
57
+ };
58
+ }
59
+ export default PhotoStore;
@@ -0,0 +1,14 @@
1
+ import { HIDE_IMAGE_VIEWER_DIALOG, SHOW_IMAGE_VIEWER_DIALOG } from "../constants/PhotosConstants"
2
+ import { dispatch } from "@selkirk-systems/state-management"
3
+
4
+ export const showImageViewerDialog = ( name, url ) => {
5
+
6
+ dispatch( SHOW_IMAGE_VIEWER_DIALOG, { name: name, url: url } )
7
+
8
+ }
9
+
10
+ export const hideImageViewerDialog = () => {
11
+
12
+ dispatch( HIDE_IMAGE_VIEWER_DIALOG );
13
+
14
+ }