Commit daa6f4b1 authored by Anton Koch's avatar Anton Koch
Browse files

Merge branch '616-MbCard' into 'master'

Resolve "Rework MbCard"

See merge request !169
parents e571ca77 ad5db3fd
<template lang="pug">
q-card.full-width.bg-transparent(v-if="parsedData" flat ref="card")
q-card.mb-card.full-width.mb-bg-bg-light(
v-if="parsedData"
@mouseover="hover = true"
@mouseleave="hover = false"
flat
ref="card"
)
// preview image -----------------------------------------------------------------------------------------------------
// Preview image -----------------------------------------------------------------------------------------------------
mb-img(
v-if="parsedData.previewSrc"
:src="parsedData.previewSrc"
:rounded="true"
v-if="visibleData.preview"
:src="visibleData.preview"
:ratio="16/10"
:cover="true"
:clickable="true"
@mouseenter.native="handleMouseover"
@mouseleave.native="cacheHover = false"
@mouseenter.native="handleMouseoverForOverlay"
@mouseleave.native="overlayCacheHover = false"
)
// CONTENT
// Title -------------------------------------------------------------------------------------------------------------
mb-headline(:title="parsedData.title" :icon-name="parsedData.iconName")
// tags --------------------------------------------------------------------------------------------------------------
card-tag-container(v-if="containerWidth >= containerBreakpoints.xs" :tags="parsedData.tags")
// Author ------------------------------------------------------------------------------------------------------------
card-author-container(v-if="containerWidth >= containerBreakpoints.xs" :author="parsedData.author")
// ACL ---------------------------------------------------------------------------------------------------------------
card-acl-container(v-if="containerWidth >= containerBreakpoints.xs" :acl="parsedData.acl")
// Last Update -------------------------------------------------------------------------------------------------------
card-last-update-container(v-if="containerWidth >= containerBreakpoints.xs" :last-update="parsedData.lastUpdate")
// Collections -------------------------------------------------------------------------------------------------------
card-collections-container(v-if="containerWidth >= containerBreakpoints.xs" :collections="parsedData.collections")
.q-pa-md
// CONTENT ----------------------------------------------------------------------------------------------------------
// Title
mb-headline(
:title="parsedData.title"
:icon-name="visibleData.iconName"
)
// tags
card-tag-module(
v-if="containerWidth >= containerBreakpoints.xs"
:tags="visibleData.tags"
)
// Author
card-author-module(
v-if="containerWidth >= containerBreakpoints.xs"
:author="visibleData.author"
)
// ACL
card-acl-module(
v-if="containerWidth >= containerBreakpoints.xs"
:acl="visibleData.acl"
)
// Last Update
card-last-update-module(
v-if="containerWidth >= containerBreakpoints.xs"
:last-update="visibleData.updatedAt"
)
// Created at
card-created-at-module(
v-if="containerWidth >= containerBreakpoints.xs"
:created-at="visibleData.createdAt"
)
// Collections
card-collections-module(
v-if="containerWidth >= containerBreakpoints.xs"
:collections="visibleData.collections"
)
// OVERLAY -----------------------------------------------------------------------------------------------------------
transition(name="card-scale")
mb-card-overlay(
v-if="hover && $q.screen.gt.sm && cardStyle && cardStyle !== 'media'"
:data="data"
v-model="hover"
v-if="overlayHover && $q.screen.gt.sm && contentType !== 'assets'"
:data="parsedData"
v-model="overlayHover"
)
// MORE BUTTON HAS TO BE LAST Before the Resize Observer -------------------------------------------------------------
mb-card-more-option(@mouseenter="cacheHover = false" :data="parsedData")
transition(name="fade")
mb-card-more-option(
v-if="hover"
@mouseenter="cacheHover = false"
:data="data"
:no-delete="noDelete"
:content-type="contentType"
)
// Resize Observer is the last ---------------------------------------------------------------------------------------
q-resize-observer(@resize="handleResize")
</template>
<script>
import MbCardDataProvider from 'components/MbComponents/MbCard/mb-card-data-provider.js'
import CardCollectionsContainer from 'components/MbComponents/MbCard/Sub/Containers/CardCollectionsContainer'
import CardLastUpdateContainer from 'components/MbComponents/MbCard/Sub/Containers/CardLastUpdateContainer'
import CardAuthorContainer from 'components/MbComponents/MbCard/Sub/Containers/CardAuthorContainer'
import CardTagContainer from 'components/MbComponents/MbCard/Sub/Containers/CardTagContainer'
import CardCollectionsModule from 'components/MbComponents/MbCard/Modules/CardCollectionsModule'
import CardLastUpdateModule from 'components/MbComponents/MbCard/Modules/CardLastUpdateModule'
import CardAuthorModule from 'components/MbComponents/MbCard/Modules/CardAuthorModule'
import CardTagModule from 'components/MbComponents/MbCard/Modules/CardTagModule'
import MbCardMoreOption from 'components/MbComponents/MbCard/Sub/MbCardMoreOption'
import CardAclContainer from 'components/MbComponents/MbCard/Sub/Containers/CardAclContainer'
import CardAclModule from 'components/MbComponents/MbCard/Modules/CardAclModule'
import MbCardOverlay from 'components/MbComponents/MbCard/Sub/MbCardOverlay'
import CardCreatedAtModule from 'components/MbComponents/MbCard/Modules/CardCreatedAtModule'
export default {
name: 'MbCard',
extends: MbCardDataProvider,
components: {
CardCreatedAtModule,
MbCardOverlay,
CardAclContainer,
CardAclModule,
MbCardMoreOption,
CardTagContainer,
CardAuthorContainer,
CardLastUpdateContainer,
CardCollectionsContainer
CardTagModule,
CardAuthorModule,
CardLastUpdateModule,
CardCollectionsModule
},
data () {
return {
hover: false,
cacheHover: false,
overlayHover: false,
overlayCacheHover: false,
containerWidth: undefined,
containerBreakpoints: {
xs: 160,
......@@ -76,15 +117,15 @@ export default {
}
},
methods: {
handleMouseover () {
handleMouseoverForOverlay () {
// Current Hover is used to check if the hover is persistent
this.cacheHover = true
this.overlayCacheHover = true
setTimeout(() => {
// Check current hover again after 700ms to see if hover is persistent and only then trigger the hover overlay
if (this.cacheHover) {
this.hover = true
if (this.overlayCacheHover) {
this.overlayHover = true
// Set current hover to false again
this.cacheHover = false
this.overlayCacheHover = false
}
}, 700)
},
......
......@@ -5,7 +5,7 @@
<script>
export default {
name: 'CardAclContainer',
name: 'CardAclModule',
props: ['acl']
}
</script>
......
<template lang="pug">
.q-my-sm.text-caption(v-if="author") {{$t('general.author')}}
.text-caption(v-html="author")
.q-my-sm.text-caption(v-if="author") {{$t('general.author')}}&bnsp;
span(v-html="author")
</template>
<script>
export default {
name: 'CardAuthorContainer',
name: 'CardAuthorModule',
props: ['author']
}
</script>
......
......@@ -5,7 +5,7 @@
<script>
export default {
name: 'CardCollectionsContainer',
name: 'CardCollectionsModule',
props: ['collections']
}
</script>
......
<template lang="pug">
.q-my-sm.text-caption.mb-text-fg-light(v-if="createdAt") {{$t('general.created')}}
| &nbsp;{{ DateTime.fromISO(createdAt).toLocaleString(DateTime.DATETIME_SHORT) }}
</template>
<script>
import { DateTime } from 'luxon'
export default {
name: 'CardCreatedAtModule',
props: ['createdAt'],
data () {
return { DateTime }
}
}
</script>
<style scoped>
</style>
<template lang="pug">
.q-my-sm.text-caption.mb-text-fg-light(v-if="lastUpdate") {{$t('general.updated')}}
| &nbsp;{{ DateTime.fromISO(lastUpdate).toLocaleString(DateTime.DATETIME_SHORT) }}
</template>
<script>
import { DateTime } from 'luxon'
export default {
name: 'CardLastUpdateModule',
props: ['lastUpdate'],
data () {
return { DateTime }
}
}
</script>
<style scoped>
</style>
......@@ -12,7 +12,7 @@
<script>
export default {
name: 'CardTagContainer',
name: 'CardTagModule',
props: ['tags']
}
</script>
......
<template lang="pug">
.q-my-sm.text-caption(v-if="lastUpdate") {{$t('general.updated')}}
.text-caption(v-html="lastUpdate")
</template>
<script>
export default {
name: 'CardLastUpdateContainer',
props: ['lastUpdate']
}
</script>
<style scoped>
</style>
......@@ -3,24 +3,45 @@
mb-icon-btn(
icon-name="more_vert"
:background="true"
@click.native="moreDialog = true"
size="sm"
)
mb-dialog(v-model="moreDialog" :label="$t('general.options')")
dialog-card-more-content
mb-popup-proxy(:offset="[-30,-30]")
.mb-bg-bg
component(
:is="`${contentType}ActionsContent`"
:props="data"
:no-delete="noDelete"
@deleteItem="onDeleteItem"
)
</template>
<script>
import ProjectsActionsContent
from 'components/MbComponents/MbTable/MbTableData/ActionsContents/ProjectsActionsContent'
import GroupsActionsContent from 'components/MbComponents/MbTable/MbTableData/ActionsContents/GroupsActionsContent'
import DialogCardMoreContent from 'components/MbComponents/MbDialog/DialogContents/MbCard/DialogCardMoreContent'
export default {
name: 'CardMoreOption',
components: {
DialogCardMoreContent
DialogCardMoreContent,
ProjectsActionsContent,
GroupsActionsContent
},
props: ['data'],
data () {
return {
moreDialog: false
props: ['data', 'noDelete', 'contentType'],
methods: {
onDeleteItem (obj) {
// giving deleteItem a value opens confirm-delete
this.deleteItem = obj
},
async remove () {
// remove row
await this.$store.dispatch(`${this.resource}/remove`, this.props.row._id)
// close confirm-delete
this.deleteItem = null
// update table
this.$emit('update')
}
}
}
......
<template lang="pug">
.mb-project-overlay-wrapper(:class="{'no-left': noLeft, 'no-right': noRight}")
.mb-project-overlay.mb-bg-bg-light(
.mb-card-overlay-wrapper.mb-border-a-light(:class="{'no-left': noLeft, 'no-right': noRight}")
.mb-card-overlay.mb-bg-bg-light(
@mouseleave="handleMouse"
ref="overlay"
)
mb-img(
v-if="data.previewSrc || data.row.preview"
:src="data.previewSrc || data.row.preview"
:src="'https://picsum.photos/200/300'"
:ratio="16/10"
:cover="true"
:disable-lazy="true"
)
.overlay-content.q-pa-md
mb-headline(:title="this.data.title || this.data.row.title")
mb-headline.q-mb-sm(
:title="this.data.title"
:icon-name="this.data.iconName"
)
//card-headline(:data="{ title: this.data.title || this.data.row.title }")
.action-buttons.q-mt-md.flex.justify-end
mb-icon-btn.q-mr-xs(icon-name="stream" :background="true" :tooltip="$t('timelines.annotate.live')" :outline="true")
mb-icon-btn.q-mr-xs(icon-name="create" :background="true" :tooltip="$t('timelines.annotate.post')" :outline="true")
mb-icon-btn.q-mr-xs(icon-name="settings" :background="true" :tooltip="$t('general.edit')" :outline="true")
mb-icon-btn.q-mr-xs(icon-name="delete" :background="true" :tooltip="$t('general.delete')" :outline="true")
.text-caption Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
.row.q-mt-md
.col-5
card-created-at-module(v-if="data.createdAt" :created-at="data.createdAt")
card-last-update-module(v-if="data.updatedAt" :last-update="data.updatedAt")
.col-7
.action-buttons.q-mt-md.flex.justify-end
mb-icon-btn.q-mr-xs(icon-name="stream" :background="true" :tooltip="$t('timelines.annotations.live')" :outline="true")
mb-icon-btn.q-mr-xs(icon-name="create" :background="true" :tooltip="$t('timelines.annotations.post')" :outline="true")
mb-icon-btn.q-mr-xs(icon-name="settings" :background="true" :tooltip="$t('general.edit')" :outline="true")
mb-icon-btn.q-mr-xs(icon-name="delete" :background="true" :tooltip="$t('general.delete')" :outline="true")
</template>
<script>
import CardCollectionsModule from 'components/MbComponents/MbCard/Modules/CardCollectionsModule'
import CardLastUpdateModule from 'components/MbComponents/MbCard/Modules/CardLastUpdateModule'
import CardAuthorModule from 'components/MbComponents/MbCard/Modules/CardAuthorModule'
import CardTagModule from 'components/MbComponents/MbCard/Modules/CardTagModule'
import CardAclModule from 'components/MbComponents/MbCard/Modules/CardAclModule'
import CardCreatedAtModule from 'components/MbComponents/MbCard/Modules/CardCreatedAtModule'
export default {
name: 'MbCardOverlay',
props: ['value', 'data'],
components: {
CardCreatedAtModule,
CardAclModule,
CardTagModule,
CardAuthorModule,
CardLastUpdateModule,
CardCollectionsModule
},
data () {
return {
popUpValue: true,
......@@ -53,8 +76,8 @@ export default {
</script>
<style lang="stylus" scoped>
.mb-project-overlay-wrapper
z-index 1000
.mb-card-overlay-wrapper
z-index 9000
position absolute
top 50%
left 50%
......@@ -66,10 +89,9 @@ export default {
left unset
right 0
transform translate(0, -50%)
.mb-project-overlay
.mb-card-overlay
position relative
width 450px
height auto
max-width 100vw
max-height 100vh
</style>
......@@ -2,114 +2,95 @@ export default {
name: 'MbCardDataProvider',
props: {
data: { type: Object },
cardStyle: { type: String, default: 'project' },
visibleColumns: { type: Array, default: () => { return ['default'] } }
contentType: { type: String, default: 'assets' },
visibleColumns: Array,
noDelete: Boolean
},
computed: {
visibleColumnKeys () {
if (this.visibleColumns) {
const requiredColumns = this.data.cols.map(col => {
return col.required ? col.name : null
})
return this.visibleColumns.concat(requiredColumns)
}
else {
return undefined
}
},
parsedData () {
if (this.data) {
return {
type: this.getType(),
previewSrc: this.getPreview(),
preview: this.getPreview(),
title: this.getTitle(),
tags: this.getTags(),
author: this.getAuthor(),
acl: this.getACL(),
collections: this.getCollections(),
lastUpdate: this.getLastUpdate(),
props: this.getProps(),
updatedAt: this.getLastUpdate(),
createdAt: this.getCreated(),
iconName: this.getIconName()
}
}
},
visibleData () {
if (this.parsedData) {
if (this.visibleColumns) {
const visibleData = Object.assign({}, this.parsedData)
Object.keys(this.parsedData).forEach(key => {
const exceptions = ['iconName']
if (!this.visibleColumnKeys.includes(key) && !exceptions.includes(key)) visibleData[key] = undefined
})
return visibleData
}
else {
return this.parsedData
}
}
}
},
methods: {
// Methods can be simpliefied but has to be checked with real data
getType () {
return this.data.type
},
getTitle () {
if (this.visibleColumns.includes('title')) {
return this.data.row.title
}
else if (this.visibleColumns.includes('default')) {
return this.data.title
}
else {
return null
}
return this.data.row
? this.data.row.title
: this.data.title
},
getPreview () {
if (this.visibleColumns.includes('preview')) {
return this.data.row.preview
}
else if (this.visibleColumns.includes('default')) {
return this.data.previewSrc
}
else {
return null
}
return 'https://picsum.photos/200/300'
},
getTags () {
if (this.visibleColumns.includes('tags')) {
return this.data.row.tags
}
else if (this.visibleColumns.includes('default')) {
return this.data.tags
}
else {
return null
}
return this.data.row
? this.data.row.tags
: this.data.title
},
getAuthor () {
if (this.visibleColumns.includes('author')) {
return this.data.row.author
}
else if (this.visibleColumns.includes('default')) {
return this.data.author
}
else {
return null
}
return this.data.row
? this.data.row.author
: this.data.author
},
getACL () {
if (this.visibleColumns.includes('acl')) {
return this.data.row.acl
}
else if (this.visibleColumns.includes('default')) {
return this.data.acl
}
else {
return null
}
return this.data.row
? this.data.row.acl
: this.data.acl
},
getCollections () {
if (this.visibleColumns.includes('collections')) {
return this.data.row.collections
}
else if (this.visibleColumns.includes('default')) {
return this.data.collections
}
else {
return null
}
return this.data.row
? this.data.row.collections
: this.data.collections
},
getLastUpdate () {
if (this.visibleColumns.includes('lastUpdate')) {
return this.data.row.lastUpdate
}
else if (this.visibleColumns.includes('default')) {
return this.data.lastUpdate
}
else {
return null
}
return this.data.row
? this.data.row.updatedAt
: this.data.updatedAt
},
getProps () {
return this.data.props
getCreated () {
return this.data.row
? this.data.row.createdAt
: this.data.createdAt
},
getIconName () {
return this.data.iconName
return 'celebration'
}
}
}
......@@ -11,7 +11,7 @@ q-btn(
:disable="disable"
unelevated
)
mb-tooltip(v-if="tooltip") {{tooltip}}
mb-tooltip.tooltip(v-if="tooltip") {{tooltip}}
slot
</template>