@abi-software/gallery 0.3.1 → 0.3.2-beta

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,319 +1,324 @@
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" class="title" v-popover:galleryPopover>
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
- methods: {
164
- /**
165
- * Open a new link if link is provide.
166
- * Fire an event if userData is provide.
167
- */
168
- cardClicked: function () {
169
- if (this.data.link) {
170
- const link = document.createElement('a')
171
- link.href = this.data.link
172
- link.target = '_blank'
173
- document.body.appendChild(link)
174
- link.click()
175
- link.remove()
176
- }
177
- if (this.data.userData) {
178
- this.$emit('card-clicked', this.data.userData)
179
- }
180
- },
181
- /**
182
- * handle thumbnail downloading,, it will use a default svg image if fails
183
- */
184
- downloadThumbnail: function (url, info) {
185
- this.getRequest(url, {}, 11000).then(
186
- (response) => {
187
- let data = response.data
188
- if (data.startsWith('data:')) {
189
- this.thumbnail = response.data
190
- } else {
191
- if (this.data.mimetype) {
192
- this.thumbnail = `data:${this.data.mimetype};base64,${response.data}`
193
- } else {
194
- this.thumbnail = response.data
195
- }
196
- }
197
- },
198
- (reason) => {
199
- if (reason.message.includes('timeout') && reason.message.includes('exceeded') && info.fetchAttempts < 3) {
200
- info.fetchAttempts += 1
201
- this.downloadThumbnail(url, info)
202
- } else {
203
- this.useDefaultImg = true
204
- }
205
- }
206
- )
207
- },
208
- //dynamically calculate if tooltip is required
209
- calculateShowTooltip: function () {
210
- if (this.data.hideTitle) {
211
- this.disableTooltip = true
212
- this.tooltipCalculated = true
213
- } else {
214
- const ele = this.$refs.titleText
215
- //Check if title text is rendered yet
216
- if (ele && ele.offsetParent) {
217
- this.tooltipCalculated = true
218
- if (ele.offsetWidth >= ele.scrollWidth) this.disableTooltip = true
219
- else this.disableTooltip = false
220
- } else {
221
- //text not rendered yet
222
- if (this.data.title.length > 20) this.disableTooltip = false
223
- else this.disableTooltip = true
224
- }
225
- }
226
- },
227
- },
228
- updated: function () {
229
- if (!this.tooltipCalculated) {
230
- this.$nextTick(() => {
231
- this.calculateShowTooltip()
232
- })
233
- }
234
- },
235
- }
236
- </script>
237
-
238
- <style scoped>
239
- .button,
240
- .button:hover,
241
- .button:focus {
242
- z-index: 10;
243
- font-family: Asap;
244
- font-size: 14px;
245
- font-weight: normal;
246
- font-stretch: normal;
247
- font-style: normal;
248
- line-height: normal;
249
- letter-spacing: normal;
250
- background-color: #8300bf;
251
- border: #8300bf;
252
- color: white;
253
- cursor: pointer;
254
- margin-top: 8px;
255
- }
256
-
257
- .button:hover {
258
- background: #8300bf;
259
- box-shadow: -3px 2px 4px 0 rgba(0, 0, 0, 0.25);
260
- color: #fff;
261
- }
262
-
263
- .card {
264
- position: relative;
265
- }
266
- .details {
267
- text-align: left;
268
- }
269
-
270
- .text-placeholder {
271
- height: 1rem;
272
- }
273
-
274
- .title {
275
- overflow-x: hidden;
276
- text-overflow: ellipsis;
277
- white-space: nowrap;
278
- }
279
-
280
- p.bold {
281
- font-weight: bold;
282
- }
283
-
284
- .image-overlay {
285
- position: absolute;
286
- top: 0;
287
- right: 0;
288
- }
289
-
290
- .triangle-icon {
291
- position: absolute;
292
- }
293
-
294
- .triangle-right-corner {
295
- width: 0;
296
- height: 0;
297
- border-left: solid transparent;
298
- border-top: solid #8300bf;
299
- }
300
- </style>
301
-
302
- <style>
303
- .gallery-popper {
304
- background: #f3ecf6 !important;
305
- border: 1px solid #8300bf;
306
- border-radius: 4px;
307
- color: #303133 !important;
308
- font-size: 12px;
309
- line-height: 1rem;
310
- height: 1rem;
311
- padding: 10px;
312
- }
313
- .gallery-popper.el-popper[x-placement^='top'] .popper__arrow {
314
- border-top-color: #8300bf !important;
315
- }
316
- .gallery-popper.el-popper[x-placement^='top'] .popper__arrow:after {
317
- border-top-color: #f3ecf6 !important;
318
- }
319
- </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 :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>