@abi-software/gallery 0.3.2-beta → 0.3.2

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.
@@ -1,324 +1,325 @@
1
- <template>
2
- <el-card :shadow="shadow" :body-style="bodyStyle" :style="{ padding: '0px', maxWidth: width + 'rem' }" class="card">
3
- <div v-loading="!isReady">
4
- <div :style="imageContainerStyle">
5
- <img v-if="useDefaultImg" src="../assets/logo-sparc-wave-primary.svg" svg-inline :style="imageStyle" />
6
- <img v-else :src="thumbnail" alt="thumbnail loading ..." :style="imageStyle" />
7
- </div>
8
- <div v-if="false" class="image-overlay">
9
- <div
10
- class="triangle-right-corner"
11
- :style="`border-left-width: ${triangleHeight * 1.2}rem; border-top-width: ${triangleHeight}rem;`"
12
- @click="openLinkInNewTab"
13
- />
14
- <el-tooltip class="item" :content="`View ${data.type}`" placement="left">
15
- <img
16
- class="triangle-icon"
17
- :style="`height: ${triangleHeight * 0.25}rem;top: ${triangleHeight * 0.15}rem;right: ${triangleHeight * 0.15}rem`"
18
- :src="typeIcon"
19
- @click="openLinkInNewTab"
20
- />
21
- </el-tooltip>
22
- </div>
23
- <div v-if="showCardDetails" class="details">
24
- <p v-if="!data.hideType">
25
- <b>{{ data.type }}</b>
26
- </p>
27
- <el-popover
28
- ref="galleryPopover"
29
- :disabled="disableTooltip"
30
- :content="data.title"
31
- placement="top"
32
- trigger="hover"
33
- popper-class="gallery-popper"
34
- />
35
- <!--use v-show here to make sure el popover always have a starting location -->
36
- <p v-show="!data.hideTitle" ref="titleText" v-popover:galleryPopover class="title">
37
- {{ data.title }}
38
- </p>
39
- <p v-show="data.hideTitle" class="title text-placeholder" />
40
- <el-button class="button" @click.prevent="cardClicked"> View {{ data.type }}</el-button>
41
- </div>
42
- </div>
43
- </el-card>
44
- </template>
45
-
46
- <script>
47
- // import { SvgIcon } from '@abi-software/svg-sprite'
48
- import Vue from 'vue'
49
- import { Button, Card, Popover } from 'element-ui'
50
- import GalleryHelper from '../mixins/GalleryHelpers'
51
- Vue.use(Button)
52
- Vue.use(Card)
53
- Vue.use(Popover)
54
-
55
- function isValidHttpUrl(string) {
56
- let url = undefined
57
-
58
- try {
59
- url = new URL(string)
60
- } catch (_) {
61
- return false
62
- }
63
- return url.protocol === 'http:' || url.protocol === 'https:'
64
- }
65
-
66
- export default {
67
- name: 'GalleryCard',
68
- mixins: [GalleryHelper],
69
- props: {
70
- data: {
71
- type: Object,
72
- required: true,
73
- },
74
- width: {
75
- type: Number,
76
- default: 3,
77
- },
78
- height: {
79
- type: Number,
80
- default: 3,
81
- },
82
- showCardDetails: {
83
- type: Boolean,
84
- },
85
- bodyStyle: {
86
- type: Object,
87
- default: () => {
88
- return { padding: '20px', background: '#ffffff' }
89
- },
90
- },
91
- imageStyle: {
92
- type: Object,
93
- default: () => {
94
- return {}
95
- },
96
- },
97
- imageContainerStyle: {
98
- type: Object,
99
- default: () => {
100
- return {}
101
- },
102
- },
103
- shadow: {
104
- type: String,
105
- default: 'always',
106
- },
107
- },
108
- data() {
109
- return {
110
- ro: null,
111
- triangleSize: 4,
112
- thumbnail: undefined,
113
- useDefaultImg: false,
114
- disableTooltip: false,
115
- tooltipCalculated: false,
116
- }
117
- },
118
- computed: {
119
- isReady() {
120
- return this.data.title && (this.thumbnail || this.useDefaultImg) && (this.data.link || this.data.userData)
121
- },
122
- imageHeight() {
123
- return this.showCardDetails ? this.height * 0.525 : this.height
124
- },
125
- imageWidth() {
126
- return this.width - 2 * this.marginDetails
127
- },
128
- triangleHeight() {
129
- return this.height * 0.237
130
- },
131
- marginDetails() {
132
- return this.height * 0.076
133
- },
134
- typeIcon() {
135
- return undefined
136
- },
137
- },
138
- watch: {
139
- data: {
140
- deep: true,
141
- immediate: true,
142
- handler: function () {
143
- this.thumbnail = undefined
144
- this.useDefaultImg = false
145
- this.tooltipCalculated = false
146
- this.disableTooltip = false
147
- if (this.data.thumbnail) {
148
- if (isValidHttpUrl(this.data.thumbnail) && this.data.mimetype) {
149
- this.downloadThumbnail(this.data.thumbnail, { fetchAttempts: 0 })
150
- } else {
151
- this.thumbnail = this.data.thumbnail
152
- }
153
- } else {
154
- this.useDefaultImg = true
155
- }
156
- //Dynamically check title length to determine if popover should be shown
157
- this.$nextTick(() => {
158
- this.calculateShowTooltip()
159
- })
160
- },
161
- },
162
- },
163
- updated: function () {
164
- if (!this.tooltipCalculated) {
165
- this.$nextTick(() => {
166
- this.calculateShowTooltip()
167
- })
168
- }
169
- },
170
- methods: {
171
- /**
172
- * Open a new link if link is provide.
173
- * Fire an event if userData is provide.
174
- */
175
- cardClicked: function () {
176
- if (this.data.link) {
177
- const link = document.createElement('a')
178
- link.href = this.data.link
179
- link.target = '_blank'
180
- document.body.appendChild(link)
181
- link.click()
182
- link.remove()
183
- }
184
- if (this.data.userData) {
185
- this.$emit('card-clicked', this.data.userData)
186
- }
187
- },
188
- /**
189
- * handle thumbnail downloading,, it will use a default svg image if fails
190
- */
191
- downloadThumbnail: function (url, info) {
192
- this.getRequest(url, {}, 11000)
193
- .then(
194
- (response) => {
195
- let data = response.data
196
- if (data.startsWith('data:')) {
197
- this.thumbnail = response.data
198
- } else {
199
- if (this.data.mimetype) {
200
- this.thumbnail = `data:${this.data.mimetype};base64,${response.data}`
201
- } else {
202
- this.thumbnail = response.data
203
- }
204
- }
205
- },
206
- (reason) => {
207
- if (reason.message.includes('timeout') && reason.message.includes('exceeded') && info.fetchAttempts < 3) {
208
- info.fetchAttempts += 1
209
- this.downloadThumbnail(url, info)
210
- } else {
211
- this.useDefaultImg = true
212
- }
213
- }
214
- )
215
- .catch((error) => {
216
- console.error(error)
217
- this.useDefaultImg = true
218
- })
219
- },
220
- //dynamically calculate if tooltip is required
221
- calculateShowTooltip: function () {
222
- if (this.data.hideTitle) {
223
- this.disableTooltip = true
224
- this.tooltipCalculated = true
225
- } else {
226
- const ele = this.$refs.titleText
227
- //Check if title text is rendered yet
228
- if (ele && ele.offsetParent) {
229
- this.tooltipCalculated = true
230
- if (ele.offsetWidth >= ele.scrollWidth) this.disableTooltip = true
231
- else this.disableTooltip = false
232
- } else {
233
- //text not rendered yet
234
- if (this.data.title.length > 20) this.disableTooltip = false
235
- else this.disableTooltip = true
236
- }
237
- }
238
- },
239
- },
240
- }
241
- </script>
242
-
243
- <style scoped>
244
- .button,
245
- .button:hover,
246
- .button:focus {
247
- z-index: 10;
248
- font-family: Asap;
249
- font-size: 14px;
250
- font-weight: normal;
251
- font-stretch: normal;
252
- font-style: normal;
253
- line-height: normal;
254
- letter-spacing: normal;
255
- background-color: #8300bf;
256
- border: #8300bf;
257
- color: white;
258
- cursor: pointer;
259
- margin-top: 8px;
260
- }
261
-
262
- .button:hover {
263
- background: #8300bf;
264
- box-shadow: -3px 2px 4px 0 rgba(0, 0, 0, 0.25);
265
- color: #fff;
266
- }
267
-
268
- .card {
269
- position: relative;
270
- }
271
- .details {
272
- text-align: left;
273
- }
274
-
275
- .text-placeholder {
276
- height: 1rem;
277
- }
278
-
279
- .title {
280
- overflow-x: hidden;
281
- text-overflow: ellipsis;
282
- white-space: nowrap;
283
- }
284
-
285
- p.bold {
286
- font-weight: bold;
287
- }
288
-
289
- .image-overlay {
290
- position: absolute;
291
- top: 0;
292
- right: 0;
293
- }
294
-
295
- .triangle-icon {
296
- position: absolute;
297
- }
298
-
299
- .triangle-right-corner {
300
- width: 0;
301
- height: 0;
302
- border-left: solid transparent;
303
- border-top: solid #8300bf;
304
- }
305
- </style>
306
-
307
- <style>
308
- .gallery-popper {
309
- background: #f3ecf6 !important;
310
- border: 1px solid #8300bf;
311
- border-radius: 4px;
312
- color: #303133 !important;
313
- font-size: 12px;
314
- line-height: 1rem;
315
- height: 1rem;
316
- padding: 10px;
317
- }
318
- .gallery-popper.el-popper[x-placement^='top'] .popper__arrow {
319
- border-top-color: #8300bf !important;
320
- }
321
- .gallery-popper.el-popper[x-placement^='top'] .popper__arrow:after {
322
- border-top-color: #f3ecf6 !important;
323
- }
324
- </style>
1
+ <template>
2
+ <el-card :shadow="shadow" :body-style="bodyStyle" :style="{ padding: '0px', maxWidth: width + 'rem' }" class="card">
3
+ <div v-loading="!isReady">
4
+ <div class="cursor-pointer" :style="imageContainerStyle" @click.prevent="cardClicked">
5
+ <img v-if="useDefaultImg" src="../assets/logo-sparc-wave-primary.svg" svg-inline :style="imageStyle" />
6
+ <img v-else :src="thumbnail" alt="thumbnail loading ..." :style="imageStyle" />
7
+ </div>
8
+ <div v-if="false" class="image-overlay">
9
+ <div
10
+ class="triangle-right-corner"
11
+ :style="`border-left-width: ${triangleHeight * 1.2}rem; border-top-width: ${triangleHeight}rem;`"
12
+ @click="openLinkInNewTab"
13
+ />
14
+ <el-tooltip class="item" :content="`View ${data.type}`" placement="left">
15
+ <img
16
+ class="triangle-icon"
17
+ :style="`height: ${triangleHeight * 0.25}rem;top: ${triangleHeight * 0.15}rem;right: ${triangleHeight * 0.15}rem`"
18
+ :src="typeIcon"
19
+ @click="openLinkInNewTab"
20
+ />
21
+ </el-tooltip>
22
+ </div>
23
+ <div v-if="showCardDetails" class="details">
24
+ <p v-if="!data.hideType">
25
+ <b>{{ data.type }}</b>
26
+ </p>
27
+ <el-popover
28
+ ref="galleryPopover"
29
+ :disabled="disableTooltip"
30
+ :content="data.title"
31
+ placement="top"
32
+ trigger="hover"
33
+ popper-class="gallery-popper"
34
+ />
35
+ <!--use v-show here to make sure el popover always have a starting location -->
36
+ <p v-show="!data.hideTitle" ref="titleText" v-popover:galleryPopover class="title">
37
+ {{ data.title }}
38
+ </p>
39
+ <p v-show="data.hideTitle" class="title text-placeholder" />
40
+ <el-button class="button" @click.prevent="cardClicked"> View {{ data.type }}</el-button>
41
+ </div>
42
+ </div>
43
+ </el-card>
44
+ </template>
45
+
46
+ <script>
47
+ // import { SvgIcon } from '@abi-software/svg-sprite'
48
+ import Vue from 'vue'
49
+ import { Button, Card, Popover, Tooltip, Loading } from 'element-ui'
50
+ import GalleryHelper from '../mixins/GalleryHelpers'
51
+ Vue.use(Button)
52
+ Vue.use(Card)
53
+ Vue.use(Popover)
54
+ Vue.use(Tooltip)
55
+ Vue.use(Loading)
56
+
57
+ function isValidHttpUrl(string) {
58
+ let url = undefined
59
+
60
+ try {
61
+ url = new URL(string)
62
+ } catch (_) {
63
+ return false
64
+ }
65
+ return url.protocol === 'http:' || url.protocol === 'https:'
66
+ }
67
+
68
+ export default {
69
+ name: 'GalleryCard',
70
+ mixins: [GalleryHelper],
71
+ props: {
72
+ data: {
73
+ type: Object,
74
+ required: true,
75
+ },
76
+ width: {
77
+ type: Number,
78
+ default: 3,
79
+ },
80
+ height: {
81
+ type: Number,
82
+ default: 3,
83
+ },
84
+ showCardDetails: {
85
+ type: Boolean,
86
+ },
87
+ bodyStyle: {
88
+ type: Object,
89
+ default: () => {
90
+ return { padding: '20px', background: '#ffffff' }
91
+ },
92
+ },
93
+ imageStyle: {
94
+ type: Object,
95
+ default: () => {
96
+ return {}
97
+ },
98
+ },
99
+ imageContainerStyle: {
100
+ type: Object,
101
+ default: () => {
102
+ return {}
103
+ },
104
+ },
105
+ shadow: {
106
+ type: String,
107
+ default: 'always',
108
+ },
109
+ },
110
+ data() {
111
+ return {
112
+ ro: null,
113
+ triangleSize: 4,
114
+ thumbnail: undefined,
115
+ useDefaultImg: false,
116
+ disableTooltip: false,
117
+ tooltipCalculated: false,
118
+ }
119
+ },
120
+ computed: {
121
+ isReady() {
122
+ return this.data.title && (this.thumbnail || this.useDefaultImg) && (this.data.link || this.data.userData)
123
+ },
124
+ imageHeight() {
125
+ return this.showCardDetails ? this.height * 0.525 : this.height
126
+ },
127
+ imageWidth() {
128
+ return this.width - 2 * this.marginDetails
129
+ },
130
+ triangleHeight() {
131
+ return this.height * 0.237
132
+ },
133
+ marginDetails() {
134
+ return this.height * 0.076
135
+ },
136
+ typeIcon() {
137
+ return undefined
138
+ },
139
+ },
140
+ watch: {
141
+ data: {
142
+ deep: true,
143
+ immediate: true,
144
+ handler: function () {
145
+ this.thumbnail = undefined
146
+ this.useDefaultImg = false
147
+ this.tooltipCalculated = false
148
+ this.disableTooltip = false
149
+ if (this.data.thumbnail) {
150
+ if (isValidHttpUrl(this.data.thumbnail) && this.data.mimetype) {
151
+ this.downloadThumbnail(this.data.thumbnail, { fetchAttempts: 0 })
152
+ } else {
153
+ this.thumbnail = this.data.thumbnail
154
+ }
155
+ } else {
156
+ this.useDefaultImg = true
157
+ }
158
+ //Dynamically check title length to determine if popover should be shown
159
+ this.$nextTick(() => {
160
+ this.calculateShowTooltip()
161
+ })
162
+ },
163
+ },
164
+ },
165
+ methods: {
166
+ /**
167
+ * Open a new link if link is provide.
168
+ * Fire an event if userData is provide.
169
+ */
170
+ cardClicked: function () {
171
+ if (this.data.link) {
172
+ const link = document.createElement('a')
173
+ link.href = this.data.link
174
+ link.target = '_blank'
175
+ document.body.appendChild(link)
176
+ link.click()
177
+ link.remove()
178
+ }
179
+ if (this.data.userData) {
180
+ this.$emit('card-clicked', this.data.userData)
181
+ }
182
+ },
183
+ /**
184
+ * handle thumbnail downloading,, it will use a default svg image if fails
185
+ */
186
+ downloadThumbnail: function (url, info) {
187
+ this.getRequest(url, {}, 11000).then(
188
+ (response) => {
189
+ let data = response.data
190
+ if (typeof data === 'string' && data.startsWith('data:')) {
191
+ this.thumbnail = response.data
192
+ } else {
193
+ if (this.data.mimetype) {
194
+ this.thumbnail = `data:${this.data.mimetype};base64,${response.data}`
195
+ } else {
196
+ this.thumbnail = response.data
197
+ }
198
+ }
199
+ },
200
+ (reason) => {
201
+ if (reason.message.includes('timeout') && reason.message.includes('exceeded') && info.fetchAttempts < 3) {
202
+ info.fetchAttempts += 1
203
+ this.downloadThumbnail(url, info)
204
+ } else {
205
+ this.useDefaultImg = true
206
+ }
207
+ }
208
+ )
209
+ },
210
+ //dynamically calculate if tooltip is required
211
+ calculateShowTooltip: function () {
212
+ if (this.data.hideTitle) {
213
+ this.disableTooltip = true
214
+ this.tooltipCalculated = true
215
+ } else {
216
+ const ele = this.$refs.titleText
217
+ //Check if title text is rendered yet
218
+ if (ele && ele.offsetParent) {
219
+ this.tooltipCalculated = true
220
+ if (ele.offsetWidth >= ele.scrollWidth) this.disableTooltip = true
221
+ else this.disableTooltip = false
222
+ } else {
223
+ //text not rendered yet
224
+ if (this.data.title.length > 20) this.disableTooltip = false
225
+ else this.disableTooltip = true
226
+ }
227
+ }
228
+ },
229
+ },
230
+ updated: function () {
231
+ if (!this.tooltipCalculated) {
232
+ this.$nextTick(() => {
233
+ this.calculateShowTooltip()
234
+ })
235
+ }
236
+ },
237
+ }
238
+ </script>
239
+
240
+ <style scoped>
241
+ .button,
242
+ .button:hover,
243
+ .button:focus {
244
+ z-index: 10;
245
+ font-family: Asap;
246
+ font-size: 14px;
247
+ font-weight: normal;
248
+ font-stretch: normal;
249
+ font-style: normal;
250
+ line-height: normal;
251
+ letter-spacing: normal;
252
+ background-color: #8300bf;
253
+ border: #8300bf;
254
+ color: white;
255
+ cursor: pointer;
256
+ margin-top: 8px;
257
+ }
258
+
259
+ .button:hover {
260
+ background: #8300bf;
261
+ box-shadow: -3px 2px 4px 0 rgba(0, 0, 0, 0.25);
262
+ color: #fff;
263
+ }
264
+
265
+ .card {
266
+ position: relative;
267
+ }
268
+ .details {
269
+ text-align: left;
270
+ }
271
+
272
+ .cursor-pointer {
273
+ cursor: pointer;
274
+ }
275
+
276
+ .text-placeholder {
277
+ height: 1rem;
278
+ }
279
+
280
+ .title {
281
+ overflow-x: hidden;
282
+ text-overflow: ellipsis;
283
+ white-space: nowrap;
284
+ }
285
+
286
+ p.bold {
287
+ font-weight: bold;
288
+ }
289
+
290
+ .image-overlay {
291
+ position: absolute;
292
+ top: 0;
293
+ right: 0;
294
+ }
295
+
296
+ .triangle-icon {
297
+ position: absolute;
298
+ }
299
+
300
+ .triangle-right-corner {
301
+ width: 0;
302
+ height: 0;
303
+ border-left: solid transparent;
304
+ border-top: solid #8300bf;
305
+ }
306
+ </style>
307
+
308
+ <style>
309
+ .gallery-popper {
310
+ background: #f3ecf6 !important;
311
+ border: 1px solid #8300bf;
312
+ border-radius: 4px;
313
+ color: #303133 !important;
314
+ font-size: 12px;
315
+ line-height: 1rem;
316
+ height: 1rem;
317
+ padding: 10px;
318
+ }
319
+ .gallery-popper.el-popper[x-placement^='top'] .popper__arrow {
320
+ border-top-color: #8300bf !important;
321
+ }
322
+ .gallery-popper.el-popper[x-placement^='top'] .popper__arrow:after {
323
+ border-top-color: #f3ecf6 !important;
324
+ }
325
+ </style>