Add option to magnify certain page blocks
This commit is contained in:
@@ -113,6 +113,16 @@
|
||||
</b-input-group>
|
||||
</b-col>
|
||||
</b-form-group>
|
||||
|
||||
<b-form-group
|
||||
v-if="block.options.magnifyOption !== undefined"
|
||||
:label="$t('general.magnifyLabel')"
|
||||
>
|
||||
<b-form-select
|
||||
v-model="block.options.magnifyOption"
|
||||
:options="magnifyOptions"
|
||||
/>
|
||||
</b-form-group>
|
||||
</div>
|
||||
</b-tab>
|
||||
|
||||
@@ -172,6 +182,14 @@ export default {
|
||||
isNew () {
|
||||
return this.block.blockID === NoID
|
||||
},
|
||||
|
||||
magnifyOptions () {
|
||||
return [
|
||||
{ value: '', text: this.$t('general.magnifyOptions.disabled') },
|
||||
{ value: 'modal', text: this.$t('general.magnifyOptions.modal') },
|
||||
{ value: 'fullscreen', text: this.$t('general.magnifyOptions.fullscreen') },
|
||||
]
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
@@ -1,25 +1,22 @@
|
||||
<template>
|
||||
<div class="h-100 p-2">
|
||||
<div class="h-100">
|
||||
<b-card
|
||||
no-body
|
||||
class="h-100 border-0 shadow"
|
||||
:class="blockClass"
|
||||
>
|
||||
<b-card-header
|
||||
v-if="headerSet || block.title || block.description"
|
||||
v-if="headerSet || block.title || block.description || hasMagnifyIcon || block.options.refreshRate >= 5"
|
||||
class="border-0 text-nowrap px-3"
|
||||
:class="{ 'p-0': !(block.title || block.description)}"
|
||||
header-bg-variant="white"
|
||||
:header-text-variant="block.style.variants.headerText"
|
||||
>
|
||||
<div
|
||||
v-if="!headerSet"
|
||||
>
|
||||
<div
|
||||
v-if="block.title"
|
||||
class="d-flex justify-content-between align-items-center"
|
||||
>
|
||||
<div class="d-flex">
|
||||
<h5
|
||||
v-if="block.title"
|
||||
class="text-truncate mb-0"
|
||||
>
|
||||
{{ block.title }}
|
||||
@@ -27,13 +24,27 @@
|
||||
<slot name="title-badge" />
|
||||
</h5>
|
||||
|
||||
<font-awesome-icon
|
||||
v-if="block.options.refreshRate >= 5"
|
||||
:icon="['fa', 'sync']"
|
||||
class="h6 text-secondary mb-0"
|
||||
role="button"
|
||||
@click="$emit('refreshBlock')"
|
||||
/>
|
||||
<div
|
||||
v-if="block.options.refreshRate >= 5 || hasMagnifyIcon"
|
||||
class="ml-auto"
|
||||
>
|
||||
<font-awesome-icon
|
||||
v-if="block.options.refreshRate >= 5"
|
||||
:icon="['fa', 'sync']"
|
||||
class="h6 text-secondary"
|
||||
role="button"
|
||||
@click="$emit('refreshBlock')"
|
||||
/>
|
||||
|
||||
<font-awesome-icon
|
||||
v-if="hasMagnifyIcon"
|
||||
:icon="['fas', isBlockOpened ? 'times' : 'search-plus']"
|
||||
:title="$t(isBlockOpened ? '' : 'general.label.magnify')"
|
||||
class="h6 text-secondary ml-2"
|
||||
role="button"
|
||||
@click="$root.$emit('magnify-page-block', isBlockOpened ? undefined : block.blockID)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<b-card-text
|
||||
@@ -105,6 +116,14 @@ export default {
|
||||
]
|
||||
},
|
||||
|
||||
hasMagnifyIcon () {
|
||||
return this.block.options.magnifyOption
|
||||
},
|
||||
|
||||
isBlockOpened () {
|
||||
return this.block.blockID === this.$route.query.blockID
|
||||
},
|
||||
|
||||
headerSet () {
|
||||
return !!this.$scopedSlots.header
|
||||
},
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
<template>
|
||||
<div class="h-100 p-2">
|
||||
<div class="h-100">
|
||||
<div
|
||||
class="d-flex flex-column position-relative h-100 border-0"
|
||||
:class="blockClass"
|
||||
>
|
||||
<div
|
||||
v-if="headerSet || block.title || block.description"
|
||||
v-if="(headerSet || block.title || block.description || hasMagnifyIcon || block.options.refreshRate >= 5)"
|
||||
:class="`card-header bg-transparent border-0 text-nowrap px-3 text-${block.style.variants.headerText}`"
|
||||
>
|
||||
<div
|
||||
v-if="!headerSet"
|
||||
>
|
||||
<div
|
||||
v-if="block.title"
|
||||
class="d-flex justify-content-between align-items-center"
|
||||
class="d-flex"
|
||||
>
|
||||
<h5
|
||||
class="text-truncate mb-0"
|
||||
@@ -23,13 +22,27 @@
|
||||
<slot name="title-badge" />
|
||||
</h5>
|
||||
|
||||
<font-awesome-icon
|
||||
v-if="block.options.refreshRate >= 5"
|
||||
:icon="['fa', 'sync']"
|
||||
class="h6 text-secondary mb-0"
|
||||
role="button"
|
||||
@click="$emit('refreshBlock')"
|
||||
/>
|
||||
<div
|
||||
v-if="block.options.refreshRate >= 5 || hasMagnifyIcon"
|
||||
class="ml-auto"
|
||||
>
|
||||
<font-awesome-icon
|
||||
v-if="block.options.refreshRate >= 5"
|
||||
:icon="['fa', 'sync']"
|
||||
class="h6 text-secondary"
|
||||
role="button"
|
||||
@click="$emit('refreshBlock')"
|
||||
/>
|
||||
|
||||
<font-awesome-icon
|
||||
v-if="hasMagnifyIcon"
|
||||
:icon="['fas', isBlockOpened ? 'times' : 'search-plus']"
|
||||
:title="$t(isBlockOpened ? '' : 'general.label.magnify')"
|
||||
class="h6 text-secondary ml-2"
|
||||
role="button"
|
||||
@click="$root.$emit('magnify-page-block', isBlockOpened ? undefined : block.blockID)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<b-card-text
|
||||
@@ -101,6 +114,14 @@ export default {
|
||||
]
|
||||
},
|
||||
|
||||
hasMagnifyIcon () {
|
||||
return this.block.options.magnifyOption
|
||||
},
|
||||
|
||||
isBlockOpened () {
|
||||
return this.block.blockID === this.$route.query.blockID
|
||||
},
|
||||
|
||||
headerSet () {
|
||||
return !!this.$scopedSlots.header
|
||||
},
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
<template>
|
||||
<b-modal
|
||||
v-model="showBlockModal"
|
||||
scrollable
|
||||
body-class="card p-0"
|
||||
footer-class="p-0"
|
||||
:content-class="contentClass"
|
||||
:dialog-class="dialogClass"
|
||||
hide-header
|
||||
hide-footer
|
||||
size="xl"
|
||||
@hidden="hideModal"
|
||||
>
|
||||
<page-block
|
||||
v-if="showBlockModal"
|
||||
:block="block"
|
||||
v-bind="$props"
|
||||
v-on="$listeners"
|
||||
/>
|
||||
</b-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { compose } from '@cortezaproject/corteza-js'
|
||||
import PageBlock from 'corteza-webapp-compose/src/components/PageBlocks'
|
||||
|
||||
export default {
|
||||
i18nOptions: {
|
||||
namespaces: 'block',
|
||||
},
|
||||
|
||||
name: 'MagnificationModal',
|
||||
|
||||
components: {
|
||||
PageBlock,
|
||||
},
|
||||
|
||||
props: {
|
||||
namespace: {
|
||||
type: compose.Namespace,
|
||||
required: true,
|
||||
},
|
||||
|
||||
page: {
|
||||
type: compose.Page,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
showBlockModal: false,
|
||||
block: undefined,
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
dialogClass () {
|
||||
return this.block && this.block.options.magnifyOption === 'fullscreen' ? 'h-100 mw-100 m-0 mh-100' : 'h-100'
|
||||
},
|
||||
|
||||
contentClass () {
|
||||
return this.block && this.block.options.magnifyOption === 'fullscreen' ? 'mh-100' : ''
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
'$route.query.blockID': {
|
||||
immediate: true,
|
||||
handler (blockID, oldBlockID) {
|
||||
if (blockID && !oldBlockID) {
|
||||
this.showModal(blockID)
|
||||
} else if (!blockID && oldBlockID) {
|
||||
this.hideModal()
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
created () {
|
||||
this.$root.$on('magnify-page-block', this.showModal)
|
||||
},
|
||||
|
||||
beforeDestroy () {
|
||||
this.$root.$off('magnify-page-block')
|
||||
},
|
||||
|
||||
methods: {
|
||||
showModal (blockID) {
|
||||
if (blockID) {
|
||||
this.block = this.page.blocks.find(block => block.blockID === blockID)
|
||||
this.showBlockModal = true
|
||||
this.$router.push({ query: { blockID } })
|
||||
} else {
|
||||
this.hideModal()
|
||||
}
|
||||
},
|
||||
|
||||
hideModal () {
|
||||
this.showBlockModal = false
|
||||
this.$router.push({ query: {} })
|
||||
this.block = undefined
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -10,6 +10,7 @@
|
||||
>
|
||||
<page-block
|
||||
v-bind="{ ...$attrs, block, page, boundingRect, blockIndex: index }"
|
||||
class="p-2"
|
||||
v-on="$listeners"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
faDownload,
|
||||
faFileExport,
|
||||
faSearch,
|
||||
faSearchPlus,
|
||||
faBars,
|
||||
faCloudDownloadAlt,
|
||||
faTimes,
|
||||
@@ -104,6 +105,7 @@ library.add(
|
||||
faEdit,
|
||||
faTrashAlt,
|
||||
faSearch,
|
||||
faSearchPlus,
|
||||
faBars,
|
||||
faCloudDownloadAlt,
|
||||
faTimes,
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
v-bind="{ ...$attrs, ...$props, page, block, boundingRect, blockIndex: index }"
|
||||
:record="record"
|
||||
:module="module"
|
||||
class="p-2"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -66,6 +66,11 @@
|
||||
:namespace="namespace"
|
||||
/>
|
||||
|
||||
<magnification-modal
|
||||
:namespace="namespace"
|
||||
:page="page"
|
||||
/>
|
||||
|
||||
<attachment-modal />
|
||||
</div>
|
||||
</template>
|
||||
@@ -74,6 +79,7 @@ import { mapActions } from 'vuex'
|
||||
import Grid from 'corteza-webapp-compose/src/components/Public/Page/Grid'
|
||||
import AttachmentModal from 'corteza-webapp-compose/src/components/Public/Page/Attachment/Modal'
|
||||
import RecordModal from 'corteza-webapp-compose/src/components/Public/Record/Modal'
|
||||
import MagnificationModal from 'corteza-webapp-compose/src/components/Public/Page/Block/Modal'
|
||||
import PageTranslator from 'corteza-webapp-compose/src/components/Admin/Page/PageTranslator'
|
||||
import { compose, NoID } from '@cortezaproject/corteza-js'
|
||||
|
||||
@@ -87,6 +93,7 @@ export default {
|
||||
AttachmentModal,
|
||||
RecordModal,
|
||||
PageTranslator,
|
||||
MagnificationModal,
|
||||
},
|
||||
|
||||
props: {
|
||||
|
||||
@@ -28,6 +28,7 @@ export class PageBlock {
|
||||
kind = ''
|
||||
|
||||
public options = {}
|
||||
|
||||
public style: PageBlockStyle = {
|
||||
variants: {
|
||||
headerText: 'dark',
|
||||
|
||||
@@ -36,6 +36,7 @@ class CalendarOptions {
|
||||
public header: Partial<CalendarOptionsHeader> = {}
|
||||
public locale = 'en-gb'
|
||||
public refreshRate = 0
|
||||
public magnifyOption = ''
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,6 +59,9 @@ export class PageBlockCalendar extends PageBlock {
|
||||
applyOptions (o?: Partial<CalendarOptions>): void {
|
||||
if (!o) return
|
||||
Apply(this.options, o, Number, 'refreshRate')
|
||||
|
||||
Apply(this.options, o, String, 'magnifyOption')
|
||||
|
||||
this.options.defaultView = PageBlockCalendar.handleLegacyView(o.defaultView) || 'dayGridMonth'
|
||||
this.options.feeds = (o.feeds || []).map(f => new Feed(f))
|
||||
this.options.header = merge(
|
||||
|
||||
@@ -6,11 +6,13 @@ const kind = 'Chart'
|
||||
interface Options {
|
||||
chartID: string;
|
||||
refreshRate: number;
|
||||
magnifyOption: string
|
||||
}
|
||||
|
||||
const defaults: Readonly<Options> = Object.freeze({
|
||||
chartID: NoID,
|
||||
refreshRate: 0,
|
||||
magnifyOption: ''
|
||||
})
|
||||
|
||||
export class PageBlockChart extends PageBlock {
|
||||
@@ -28,6 +30,8 @@ export class PageBlockChart extends PageBlock {
|
||||
|
||||
Apply(this.options, o, CortezaID, 'chartID')
|
||||
Apply(this.options, o, Number, 'refreshRate')
|
||||
Apply(this.options, o, String, 'magnifyOption')
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ interface Options {
|
||||
referenceField: string;
|
||||
sortDirection: string;
|
||||
refreshRate: number;
|
||||
magnifyOption: string
|
||||
}
|
||||
|
||||
const defaults: Readonly<Options> = Object.freeze({
|
||||
@@ -20,6 +21,7 @@ const defaults: Readonly<Options> = Object.freeze({
|
||||
sortDirection: '',
|
||||
referenceField: '',
|
||||
refreshRate: 0,
|
||||
magnifyOption: ''
|
||||
})
|
||||
|
||||
export class PageBlockComment extends PageBlock {
|
||||
@@ -35,7 +37,7 @@ export class PageBlockComment extends PageBlock {
|
||||
applyOptions (o?: Partial<Options>): void {
|
||||
if (!o) return
|
||||
Apply(this.options, o, CortezaID, 'moduleID')
|
||||
Apply(this.options, o, String, 'titleField', 'contentField', 'referenceField', 'filter', 'sortDirection')
|
||||
Apply(this.options, o, String, 'titleField', 'contentField', 'referenceField', 'filter', 'sortDirection', 'magnifyOption')
|
||||
Apply(this.options, o, Number, 'refreshRate')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,12 @@ const kind = 'Content'
|
||||
|
||||
interface Options {
|
||||
body: string;
|
||||
magnifyOption: string
|
||||
}
|
||||
|
||||
const defaults: Readonly<Options> = Object.freeze({
|
||||
body: '',
|
||||
magnifyOption: ''
|
||||
})
|
||||
|
||||
export class PageBlockContent extends PageBlock {
|
||||
@@ -24,7 +26,7 @@ export class PageBlockContent extends PageBlock {
|
||||
applyOptions (o?: Partial<Options>): void {
|
||||
if (!o) return
|
||||
|
||||
Apply(this.options, o, String, 'body')
|
||||
Apply(this.options, o, String, 'body', 'magnifyOption')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ interface Options {
|
||||
borderRadius?: number;
|
||||
margin?: number;
|
||||
backgroundColor?: string;
|
||||
magnifyOption: string;
|
||||
}
|
||||
|
||||
const PageBlockFileDefaultMode = 'list'
|
||||
@@ -39,6 +40,7 @@ const defaults: Readonly<Options> = Object.freeze({
|
||||
borderRadius: undefined,
|
||||
margin: undefined,
|
||||
backgroundColor: undefined,
|
||||
magnifyOption: ''
|
||||
})
|
||||
|
||||
export class PageBlockFile extends PageBlock {
|
||||
@@ -59,7 +61,7 @@ export class PageBlockFile extends PageBlock {
|
||||
}
|
||||
|
||||
Apply(this.options, o, Boolean, 'hideFileName')
|
||||
Apply(this.options, o, String, 'backgroundColor')
|
||||
Apply(this.options, o, String, 'backgroundColor', 'magnifyOption')
|
||||
Apply(this.options, o, Number, 'height', 'width', 'maxHeight', 'maxWidth', 'borderRadius', 'margin')
|
||||
|
||||
if (o.mode) {
|
||||
|
||||
@@ -8,6 +8,7 @@ interface Options {
|
||||
src: string;
|
||||
wrap: PageBlockWrap;
|
||||
refreshRate: number;
|
||||
magnifyOption: string;
|
||||
}
|
||||
|
||||
const defaults: Readonly<Options> = Object.freeze({
|
||||
@@ -15,6 +16,7 @@ const defaults: Readonly<Options> = Object.freeze({
|
||||
src: '',
|
||||
wrap: 'Plain',
|
||||
refreshRate: 0,
|
||||
magnifyOption: '',
|
||||
})
|
||||
|
||||
export class PageBlockIFrame extends PageBlock {
|
||||
@@ -30,7 +32,7 @@ export class PageBlockIFrame extends PageBlock {
|
||||
applyOptions (o?: Partial<Options>): void {
|
||||
if (!o) return
|
||||
|
||||
Apply(this.options, o, String, 'srcField', 'src', 'wrap')
|
||||
Apply(this.options, o, String, 'srcField', 'src', 'wrap', 'magnifyOption')
|
||||
Apply(this.options, o, Number, 'refreshRate')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ interface Options {
|
||||
allowExport: boolean;
|
||||
perPage: number;
|
||||
recordDisplayOption: string;
|
||||
magnifyOption: string;
|
||||
|
||||
fullPageNavigation: boolean;
|
||||
showTotalCount: boolean;
|
||||
@@ -70,6 +71,7 @@ const defaults: Readonly<Options> = Object.freeze({
|
||||
allowExport: false,
|
||||
perPage: 20,
|
||||
recordDisplayOption: 'sameTab',
|
||||
magnifyOption: '',
|
||||
|
||||
fullPageNavigation: true,
|
||||
showTotalCount: true,
|
||||
@@ -105,7 +107,7 @@ export class PageBlockRecordList extends PageBlock {
|
||||
if (!o) return
|
||||
|
||||
Apply(this.options, o, CortezaID, 'moduleID')
|
||||
Apply(this.options, o, String, 'prefilter', 'presort', 'selectMode', 'positionField', 'refField')
|
||||
Apply(this.options, o, String, 'prefilter', 'presort', 'selectMode', 'positionField', 'refField', 'recordDisplayOption', 'magnifyOption')
|
||||
Apply(this.options, o, Number, 'perPage', 'refreshRate')
|
||||
|
||||
if (o.fields) {
|
||||
|
||||
@@ -17,6 +17,7 @@ interface Options {
|
||||
// referenced fields (records, users) we want to expand
|
||||
expRefFields: string[];
|
||||
refreshRate: number;
|
||||
magnifyOption: string;
|
||||
}
|
||||
|
||||
const defaults: Readonly<Options> = Object.freeze({
|
||||
@@ -24,6 +25,7 @@ const defaults: Readonly<Options> = Object.freeze({
|
||||
displayedFields: [],
|
||||
expRefFields: [],
|
||||
refreshRate: 0,
|
||||
magnifyOption: '',
|
||||
})
|
||||
|
||||
export class PageBlockRecordRevisions extends PageBlock {
|
||||
@@ -41,6 +43,7 @@ export class PageBlockRecordRevisions extends PageBlock {
|
||||
|
||||
Apply(this.options, o, Boolean, 'preload')
|
||||
Apply(this.options, o, Number, 'refreshRate')
|
||||
Apply(this.options, o, String, 'magnifyOption')
|
||||
|
||||
// set new values to displayed fields
|
||||
if (Array.isArray(o?.displayedFields)) {
|
||||
|
||||
@@ -8,6 +8,7 @@ interface Options {
|
||||
scenarioID: string;
|
||||
elementID: string;
|
||||
refreshRate: number;
|
||||
magnifyOption: string;
|
||||
}
|
||||
|
||||
const defaults: Readonly<Options> = Object.freeze({
|
||||
@@ -15,6 +16,7 @@ const defaults: Readonly<Options> = Object.freeze({
|
||||
scenarioID: NoID,
|
||||
elementID: NoID,
|
||||
refreshRate: 0,
|
||||
magnifyOption: ''
|
||||
})
|
||||
|
||||
export class PageBlockReport extends PageBlock {
|
||||
@@ -32,6 +34,7 @@ export class PageBlockReport extends PageBlock {
|
||||
|
||||
Apply(this.options, o, CortezaID, 'reportID', 'scenarioID', 'elementID')
|
||||
Apply(this.options, o, Number, 'refreshRate')
|
||||
Apply(this.options, o, String, 'magnifyOption')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -112,6 +112,11 @@ general:
|
||||
descriptionLabel: Description
|
||||
descriptionPlaceholder: Block description
|
||||
headerStyle: Block header style (color)
|
||||
magnifyLabel: Block Magnification
|
||||
magnifyOptions:
|
||||
disabled: Disabled
|
||||
modal: Modal
|
||||
fullscreen: Fullscreen
|
||||
wrap: Display block as a card
|
||||
refresh:
|
||||
label: Block auto-refresh interval
|
||||
@@ -130,6 +135,7 @@ general:
|
||||
remove: Remove
|
||||
save: Save
|
||||
search: Search
|
||||
magnify: Magnify Block
|
||||
module: Module
|
||||
style:
|
||||
danger: Danger variant
|
||||
|
||||
Reference in New Issue
Block a user