Add navigational page block
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -15,3 +15,4 @@ export const Report = require('./Report.png')
|
||||
export const Progress = require('./Progress.png')
|
||||
export const Nylas = require('./Nylas.jpg')
|
||||
export const Geometry = require('./Geometry.png')
|
||||
export const Navigation = require('./Navigation.png')
|
||||
|
||||
@@ -149,6 +149,11 @@ export default {
|
||||
block: new compose.PageBlockGeometry(),
|
||||
image: images.Geometry,
|
||||
},
|
||||
{
|
||||
label: this.$t('navigation.label'),
|
||||
block: new compose.PageBlockNavigation(),
|
||||
image: images.Navigation,
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
<template>
|
||||
<wrap
|
||||
:scrollable-body="false"
|
||||
v-bind="$props"
|
||||
v-on="$listeners"
|
||||
>
|
||||
<div class="h-100 w-100 card overflow-hidden bg-transparent">
|
||||
<b-nav
|
||||
:tabs="options.display.appearance === 'tabs'"
|
||||
:pills="options.display.appearance === 'pills'"
|
||||
:small="options.display.appearance === 'small'"
|
||||
:fill="options.display.fillJustify === 'fill'"
|
||||
:justify="options.display.fillJustify === 'justify'"
|
||||
:align="options.display.alignment"
|
||||
class="border-0 h-100"
|
||||
>
|
||||
<b-nav-item
|
||||
v-for="(navItem, index) in options.navigationItems"
|
||||
:key="`navItem-${index}`"
|
||||
:disabled="!navItem.options.enabled"
|
||||
:style="{ order: index, color: navItem.options.textColor, background: navItem.options.backgroundColor, justifyContent: options.display.alignment }"
|
||||
:link-attrs="{ style: `color: ${navItem.options.textColor}` }"
|
||||
:target="selectTargetOption(navItem.options.item.target)"
|
||||
:href="redirectForNavItem(navItem)"
|
||||
class="d-flex align-items-center"
|
||||
>
|
||||
<template v-if="navItem.type === 'dropdown' || isComposeDropdownPage(navItem)">
|
||||
<b-button
|
||||
:id="`dropdown-popover-${index}-${block.blockID}`"
|
||||
class="text-decoration-none"
|
||||
variant="link"
|
||||
:style="{ color: navItem.options.textColor, background: navItem.options.backgroundColor }"
|
||||
>
|
||||
{{ displayDropdownText(navItem) }}
|
||||
<span class="ml-1">
|
||||
<font-awesome-icon
|
||||
:icon="['fas', 'chevron-down']"
|
||||
size="sm"
|
||||
/>
|
||||
</span>
|
||||
</b-button>
|
||||
|
||||
<b-popover
|
||||
ref="dropdown-popover"
|
||||
:target="`dropdown-popover-${index}-${block.blockID}`"
|
||||
:placement="navItem.options.item.align"
|
||||
delay="0"
|
||||
boundary="window"
|
||||
triggers="click blur"
|
||||
>
|
||||
<template
|
||||
v-if="navItem.type === 'dropdown'"
|
||||
>
|
||||
<div
|
||||
v-for="(dropdown, dIndex) in navItem.options.item.dropdown.items"
|
||||
:key="`dropdown-${dIndex}`"
|
||||
>
|
||||
<a
|
||||
class="dropdown-item"
|
||||
:href="dropdown.url"
|
||||
:disabled="navItem.options.disabled"
|
||||
:target="selectTargetOption(dropdown.target)"
|
||||
:style="{ order: dIndex * 2 }"
|
||||
>
|
||||
{{ dropdown.label }}
|
||||
</a>
|
||||
|
||||
<hr
|
||||
v-if="dropdown.delimiter"
|
||||
class="my-1"
|
||||
:style="{ order: dIndex + 1 }"
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<div
|
||||
v-for="(dropdown, dIndex) in getSubPages(navItem.options.item.pageID)"
|
||||
:key="`dropdown-${dIndex}`"
|
||||
>
|
||||
<b-link
|
||||
:to="{ name: 'page', params: { pageID: dropdown.pageID } }"
|
||||
:target="selectTargetOption(navItem.options.item.target)"
|
||||
:style="{ order: dIndex * 2 }"
|
||||
:disabled="navItem.options.disabled"
|
||||
class="dropdown-item"
|
||||
style="white-space: normal"
|
||||
>
|
||||
{{ dropdown.title }}
|
||||
</b-link>
|
||||
</div>
|
||||
</template>
|
||||
</b-popover>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
{{ navItem.options.item.label }}
|
||||
</template>
|
||||
</b-nav-item>
|
||||
</b-nav>
|
||||
</div>
|
||||
</wrap>
|
||||
</template>
|
||||
<script>
|
||||
import { NoID } from '@cortezaproject/corteza-js'
|
||||
import { mapGetters } from 'vuex'
|
||||
import base from '../base'
|
||||
|
||||
export default {
|
||||
extends: base,
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
pages: 'page/set',
|
||||
}),
|
||||
},
|
||||
|
||||
methods: {
|
||||
isComposeDropdownPage (navItem) {
|
||||
return (navItem.type === 'compose' && navItem.options.item.displaySubPages)
|
||||
},
|
||||
|
||||
getSubPages (selfID) {
|
||||
return this.pages.filter(value => value.selfID === selfID && value.moduleID === NoID) || []
|
||||
},
|
||||
|
||||
selectTargetOption (target) {
|
||||
switch (target) {
|
||||
case 'sameTab':
|
||||
return '_self'
|
||||
case 'newTab':
|
||||
return '_blank'
|
||||
}
|
||||
},
|
||||
|
||||
displayDropdownText (navItem) {
|
||||
if (navItem.type === 'dropdown') {
|
||||
return navItem.options.item.dropdown.label
|
||||
}
|
||||
|
||||
return navItem.options.item.label
|
||||
},
|
||||
|
||||
redirectForNavItem (navItem) {
|
||||
if (navItem.type === 'dropdown' || this.isComposeDropdownPage(navItem)) {
|
||||
return
|
||||
} else if (navItem.type === 'compose') {
|
||||
const slug = this.$route.params.slug
|
||||
const pageID = navItem.options.item.pageID
|
||||
|
||||
return `ns/${slug}/pages/${pageID}`
|
||||
}
|
||||
|
||||
return navItem.options.item.url
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,274 @@
|
||||
<template>
|
||||
<div>
|
||||
<b-tab :title="$t('navigation.label')">
|
||||
<div class="mb-3">
|
||||
<h5 class="text-primary">
|
||||
{{ $t("navigation.displayOptions") }}
|
||||
</h5>
|
||||
|
||||
<b-row class="justify-content-between">
|
||||
<b-col
|
||||
cols="12"
|
||||
sm="4"
|
||||
class="mb-2 mb-sm-0"
|
||||
>
|
||||
<b-form-group
|
||||
horizontal
|
||||
:label="$t('navigation.appearance')"
|
||||
>
|
||||
<b-form-radio-group
|
||||
v-model="options.display.appearance"
|
||||
buttons
|
||||
button-variant="outline-secondary"
|
||||
:options="appearanceOptions"
|
||||
/>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
|
||||
<b-col
|
||||
sm="4"
|
||||
class="mb-2 mb-sm-0"
|
||||
>
|
||||
<b-form-group
|
||||
horizontal
|
||||
:label="$t('navigation.fillJustify')"
|
||||
>
|
||||
<b-form-radio-group
|
||||
v-model="options.display.fillJustify"
|
||||
buttons
|
||||
button-variant="outline-secondary"
|
||||
|
||||
:options="fillJustifyOptions"
|
||||
/>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
|
||||
<b-col
|
||||
sm="4"
|
||||
class="mb-2 mb-sm-0"
|
||||
>
|
||||
<b-form-group
|
||||
horizontal
|
||||
:label="$t('navigation.alignment')"
|
||||
>
|
||||
<b-form-radio-group
|
||||
v-model="options.display.alignment"
|
||||
buttons
|
||||
button-variant="outline-secondary"
|
||||
:options="alignmentOptions"
|
||||
/>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</div>
|
||||
|
||||
<div class="mb-3 mt-2">
|
||||
<div class="d-flex align-items-center mb-4">
|
||||
<h5 class="text-primary mb-0">
|
||||
{{ $t("navigation.navigationItems") }}
|
||||
</h5>
|
||||
|
||||
<b-button
|
||||
variant="link"
|
||||
class="d-flex align-items-center text-decoration-none"
|
||||
@click="addNavigationItem"
|
||||
>
|
||||
<font-awesome-icon
|
||||
:icon="['fas', 'plus']"
|
||||
size="sm"
|
||||
class="mr-1"
|
||||
/>
|
||||
{{ $t("navigation.add") }}
|
||||
</b-button>
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
<draggable
|
||||
v-model="block.options.navigationItems"
|
||||
group="sort"
|
||||
handle=".grab"
|
||||
>
|
||||
<div
|
||||
v-for="(item, index) in block.options.navigationItems"
|
||||
:key="index"
|
||||
>
|
||||
<hr v-if="index">
|
||||
|
||||
<b-table-simple
|
||||
borderless
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: auto" />
|
||||
<th>
|
||||
{{ $t("navigation.type") }}
|
||||
</th>
|
||||
<th>
|
||||
{{ $t("navigation.color") }}
|
||||
</th>
|
||||
<th>
|
||||
{{ $t("navigation.background") }}
|
||||
</th>
|
||||
<th class="text-center">
|
||||
{{ $t("navigation.enabled") }}
|
||||
</th>
|
||||
<th style="width: auto;min-width: 100px" />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="align-middle">
|
||||
<font-awesome-icon
|
||||
:icon="['fas', 'bars']"
|
||||
class="grab text-grey"
|
||||
/>
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
<b-form-select
|
||||
v-model="item.type"
|
||||
:options="navigationItemTypes"
|
||||
/>
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
<b-form-input
|
||||
v-model="item.options.textColor"
|
||||
type="color"
|
||||
debounce="300"
|
||||
class="w-100"
|
||||
/>
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
<b-form-input
|
||||
v-model="item.options.backgroundColor"
|
||||
type="color"
|
||||
debounce="300"
|
||||
class="w-100"
|
||||
/>
|
||||
</td>
|
||||
<td class="align-middle text-center">
|
||||
<b-form-checkbox
|
||||
v-model="item.options.enabled"
|
||||
switch
|
||||
class="mb-0"
|
||||
/>
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
<c-input-confirm
|
||||
button-class="px-2"
|
||||
size="md"
|
||||
@confirmed="options.navigationItems.splice(index, 1)"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<component
|
||||
:is="item.type"
|
||||
:item="item"
|
||||
:namespace="namespace"
|
||||
@update="(value) => item = value"
|
||||
/>
|
||||
</tbody>
|
||||
</b-table-simple>
|
||||
</div>
|
||||
</draggable>
|
||||
</div>
|
||||
</div>
|
||||
</b-tab>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import base from '../base'
|
||||
import Draggable from 'vuedraggable'
|
||||
import { compose } from '@cortezaproject/corteza-js'
|
||||
import Text from './NavTypes/Text.vue'
|
||||
import Url from './NavTypes/Url.vue'
|
||||
import Compose from './NavTypes/ComposePage.vue'
|
||||
import Dropdown from './NavTypes/Dropdown.vue'
|
||||
|
||||
export default {
|
||||
i18nOptions: {
|
||||
namespaces: 'block',
|
||||
},
|
||||
|
||||
components: {
|
||||
Draggable,
|
||||
TextSection: Text,
|
||||
Url,
|
||||
Compose,
|
||||
Dropdown,
|
||||
},
|
||||
|
||||
extends: base,
|
||||
|
||||
data () {
|
||||
return {
|
||||
appearanceOptions: [
|
||||
{ value: 'tabs', text: this.$t('navigation.tabs') },
|
||||
{ value: 'pills', text: this.$t('navigation.pills') },
|
||||
{ value: 'small', text: this.$t('navigation.small') },
|
||||
],
|
||||
|
||||
alignmentOptions: [
|
||||
{ value: 'left', text: this.$t('navigation.left') },
|
||||
{ value: 'center', text: this.$t('navigation.center') },
|
||||
{ value: 'right', text: this.$t('navigation.right') },
|
||||
],
|
||||
|
||||
fillJustifyOptions: [
|
||||
{ value: 'fill', text: this.$t('navigation.fill') },
|
||||
{ value: 'justify', text: this.$t('navigation.justify') },
|
||||
],
|
||||
|
||||
backgroundColors: [
|
||||
{ value: 'primary', text: this.$t('navigation.primary') },
|
||||
{ value: 'secondary', text: this.$t('navigation.secondary') },
|
||||
{ value: 'success', text: this.$t('navigation.success') },
|
||||
{ value: 'warning', text: this.$t('navigation.warning') },
|
||||
{ value: 'danger', text: this.$t('navigation.danger') },
|
||||
{ value: 'info', text: this.$t('navigation.info') },
|
||||
],
|
||||
|
||||
navigationItemTypes: [
|
||||
{ value: 'url', text: this.$t('navigation.url') },
|
||||
{ value: 'compose', text: this.$t('navigation.composePage') },
|
||||
{ value: 'dropdown', text: this.$t('navigation.dropdown') },
|
||||
{ value: 'text-section', text: this.$t('navigation.text') },
|
||||
],
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
addNavigationItem () {
|
||||
this.block.options.navigationItems.push(
|
||||
compose.PageBlockNavigation.makeNavigationItem({
|
||||
type: 'compose',
|
||||
options: {
|
||||
backgroundColor: '#ffffff',
|
||||
item: {
|
||||
align: 'bottom',
|
||||
target: 'sameTab',
|
||||
dropdown: {
|
||||
label: '',
|
||||
items: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
th {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,115 @@
|
||||
<template>
|
||||
<tr>
|
||||
<td />
|
||||
<td>
|
||||
<b-form-group :label="$t('navigation.fieldLabel')">
|
||||
<b-form-input
|
||||
v-model="options.item.label"
|
||||
type="text"
|
||||
/>
|
||||
</b-form-group>
|
||||
</td>
|
||||
<td>
|
||||
<b-form-group :label="$t('navigation.composePage')">
|
||||
<vue-select
|
||||
key="pageID"
|
||||
v-model="options.item.pageID"
|
||||
:placeholder="$t('navigation.none')"
|
||||
:options="tree"
|
||||
append-to-body
|
||||
label="title"
|
||||
:reduce="f => f.pageID"
|
||||
option-value="pageID"
|
||||
option-text="title"
|
||||
class="bg-white"
|
||||
@input="updateLabelValue"
|
||||
/>
|
||||
</b-form-group>
|
||||
</td>
|
||||
<td>
|
||||
<b-form-group :label="$t('navigation.openIn')">
|
||||
<b-form-select
|
||||
v-model="options.item.target"
|
||||
:options="targetOptions"
|
||||
/>
|
||||
</b-form-group>
|
||||
</td>
|
||||
<td
|
||||
v-if="selectedPageChildren(options.item.pageID)"
|
||||
cols="12"
|
||||
sm="6"
|
||||
class="align-middle text-center"
|
||||
>
|
||||
<b-form-group class="m-0">
|
||||
<b-form-checkbox
|
||||
v-model="options.item.displaySubPages"
|
||||
switch
|
||||
size="sm"
|
||||
>
|
||||
{{ $t('navigation.displaySubPages') }}
|
||||
</b-form-checkbox>
|
||||
</b-form-group>
|
||||
</td>
|
||||
<td />
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import base from './base'
|
||||
|
||||
import { VueSelect } from 'vue-select'
|
||||
import { compose } from '@cortezaproject/corteza-js'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
VueSelect,
|
||||
},
|
||||
|
||||
extends: base,
|
||||
|
||||
props: {
|
||||
namespace: {
|
||||
type: compose.Namespace,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
tree: [],
|
||||
targetOptions: [
|
||||
{ value: 'sameTab', text: this.$t('navigation.sameTab') },
|
||||
{ value: 'newTab', text: this.$t('navigation.newTab') },
|
||||
],
|
||||
}
|
||||
},
|
||||
|
||||
created () {
|
||||
this.loadTree()
|
||||
},
|
||||
|
||||
methods: {
|
||||
selectedPageChildren (pageID) {
|
||||
const tree = this.tree ? this.tree.find(t => t.pageID === pageID) : {}
|
||||
return tree && tree.children ? tree.children.length > 0 : false
|
||||
},
|
||||
|
||||
loadTree () {
|
||||
const { namespaceID } = this.namespace
|
||||
this.$ComposeAPI
|
||||
.pageTree({ namespaceID })
|
||||
.then(tree => {
|
||||
this.tree = tree.map(p => new compose.Page(p))
|
||||
})
|
||||
.catch(this.toastErrorHandler(this.$t('notification:page.loadFailed')))
|
||||
},
|
||||
|
||||
updateLabelValue (pageID) {
|
||||
if (!this.options.item.label) {
|
||||
const composePage = this.tree.find(t => t.pageID === pageID)
|
||||
this.options.item.label = composePage ? composePage.title : ''
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,148 @@
|
||||
<template>
|
||||
<tr>
|
||||
<td />
|
||||
|
||||
<td
|
||||
colspan="4"
|
||||
class="p-0"
|
||||
>
|
||||
<div class="d-flex">
|
||||
<th>
|
||||
<b-form-group :label="$t('navigation.fieldLabel')">
|
||||
<b-form-input
|
||||
v-model="options.item.dropdown.label"
|
||||
type="text"
|
||||
/>
|
||||
</b-form-group>
|
||||
</th>
|
||||
|
||||
<th>
|
||||
<b-form-group
|
||||
horizontal
|
||||
:label="$t('navigation.drop')"
|
||||
>
|
||||
<b-form-radio-group
|
||||
v-model="options.item.align"
|
||||
buttons
|
||||
button-variant="outline-secondary"
|
||||
size="sm"
|
||||
:options="aligns"
|
||||
/>
|
||||
</b-form-group>
|
||||
</th>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center mb-4 mb-3 px-3">
|
||||
<h6 class="text-primary mb-0">
|
||||
{{ $t("navigation.dropdownItems") }}
|
||||
</h6>
|
||||
|
||||
<b-button
|
||||
variant="link"
|
||||
class="text-decoration-none"
|
||||
@click="options.item.dropdown.items.push({ text: '', url: '', target: 'sameTab' })"
|
||||
>
|
||||
<font-awesome-icon
|
||||
:icon="['fas', 'plus']"
|
||||
size="sm"
|
||||
class="mr-1"
|
||||
/>
|
||||
{{ $t("navigation.add") }}
|
||||
</b-button>
|
||||
</div>
|
||||
|
||||
<div class="px-3">
|
||||
<table
|
||||
v-if="options.item.dropdown.items.length > 0"
|
||||
class="table table-sm table-borderless table-responsive-lg"
|
||||
>
|
||||
<tr>
|
||||
<th>
|
||||
{{ $t("navigation.text") }}
|
||||
</th>
|
||||
<th>
|
||||
{{ $t("navigation.url") }}
|
||||
</th>
|
||||
<th class="text-center">
|
||||
{{ $t('navigation.openIn') }}
|
||||
</th>
|
||||
<th class="text-center">
|
||||
{{ $t("navigation.delimiter") }}
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<tr
|
||||
v-for="(item, dropIndex) in options.item.dropdown.items"
|
||||
:key="`drop-${dropIndex}`"
|
||||
>
|
||||
<th>
|
||||
<b-form-group class="mb-0">
|
||||
<b-form-input
|
||||
v-model="item.label"
|
||||
type="text"
|
||||
/>
|
||||
</b-form-group>
|
||||
</th>
|
||||
|
||||
<th>
|
||||
<b-form-group class="mb-0">
|
||||
<b-form-input
|
||||
v-model="item.url"
|
||||
type="text"
|
||||
/>
|
||||
</b-form-group>
|
||||
</th>
|
||||
|
||||
<th class="align-middle text-center">
|
||||
<b-form-group class="mb-0">
|
||||
<b-form-select
|
||||
v-model="item.target"
|
||||
:options="targetOptions"
|
||||
/>
|
||||
</b-form-group>
|
||||
</th>
|
||||
|
||||
<th class="align-middle text-center">
|
||||
<b-form-group class="mb-0">
|
||||
<b-form-checkbox
|
||||
v-model="item.delimiter"
|
||||
switch
|
||||
size="sm"
|
||||
/>
|
||||
</b-form-group>
|
||||
</th>
|
||||
|
||||
<th class="align-middle text-center">
|
||||
<c-input-confirm
|
||||
@confirmed="options.item.dropdown.items.splice(dropIndex, 1)"
|
||||
/>
|
||||
</th>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import base from './base'
|
||||
|
||||
export default {
|
||||
extends: base,
|
||||
|
||||
data () {
|
||||
return {
|
||||
aligns: [
|
||||
{ value: 'right', text: this.$t('navigation.right') },
|
||||
{ value: 'left', text: this.$t('navigation.left') },
|
||||
{ value: 'bottom', text: this.$t('navigation.bottom') },
|
||||
{ value: 'top', text: this.$t('navigation.top') },
|
||||
],
|
||||
targetOptions: [
|
||||
{ value: 'sameTab', text: this.$t('navigation.sameTab') },
|
||||
{ value: 'newTab', text: this.$t('navigation.newTab') },
|
||||
],
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<tr>
|
||||
<td />
|
||||
<td>
|
||||
<b-form-group :label="$t('navigation.fieldLabel')">
|
||||
<b-form-input
|
||||
v-model="options.item.label"
|
||||
type="text"
|
||||
/>
|
||||
</b-form-group>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import base from './base'
|
||||
|
||||
export default {
|
||||
extends: base,
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<tr>
|
||||
<td />
|
||||
<td>
|
||||
<b-form-group :label="$t('navigation.fieldLabel')">
|
||||
<b-form-input
|
||||
v-model="options.item.label"
|
||||
type="text"
|
||||
/>
|
||||
</b-form-group>
|
||||
</td>
|
||||
<td>
|
||||
<b-form-group :label="$t('navigation.url')">
|
||||
<b-form-input
|
||||
v-model="options.item.url"
|
||||
type="text"
|
||||
/>
|
||||
</b-form-group>
|
||||
</td>
|
||||
<td>
|
||||
<b-form-group :label="$t('navigation.openIn')">
|
||||
<b-form-select
|
||||
v-model="options.item.target"
|
||||
:options="openInType"
|
||||
/>
|
||||
</b-form-group>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import base from './base'
|
||||
|
||||
export default {
|
||||
extends: base,
|
||||
|
||||
data () {
|
||||
return {
|
||||
value: {},
|
||||
openInType: [
|
||||
{ value: 'sameTab', text: this.$t('navigation.sameTab') },
|
||||
{ value: 'newTab', text: this.$t('navigation.newTab') },
|
||||
],
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,25 @@
|
||||
<script>
|
||||
export default {
|
||||
i18nOptions: {
|
||||
namespaces: 'block',
|
||||
},
|
||||
|
||||
props: {
|
||||
item: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
options: {
|
||||
get () {
|
||||
return this.item.options
|
||||
},
|
||||
set (options) {
|
||||
this.item.options = options
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -75,7 +75,6 @@ export default {
|
||||
get () {
|
||||
return this.block.options
|
||||
},
|
||||
|
||||
set (options) {
|
||||
this.block.options = options
|
||||
},
|
||||
|
||||
@@ -36,6 +36,8 @@ import NylasBase from './Nylas/NylasBase'
|
||||
import NylasConfigurator from './Nylas/NylasConfigurator'
|
||||
import GeometryBase from './GeometryBase'
|
||||
import GeometryConfigurator from './GeometryConfigurator/index'
|
||||
import NavigationConfigurator from './Navigation/Configurator'
|
||||
import NavigationBase from './Navigation/Base'
|
||||
|
||||
/**
|
||||
* List of all known page block components
|
||||
@@ -77,6 +79,8 @@ const Registry = {
|
||||
NylasConfigurator,
|
||||
GeometryBase,
|
||||
GeometryConfigurator,
|
||||
NavigationConfigurator,
|
||||
NavigationBase,
|
||||
}
|
||||
|
||||
const defaultMode = 'Base'
|
||||
|
||||
@@ -16,7 +16,7 @@ export { PageBlockReport } from './report'
|
||||
export { PageBlockProgress } from './progress'
|
||||
export { PageBlockNylas } from './nylas'
|
||||
export { PageBlockGeometry } from './geometry'
|
||||
|
||||
export { PageBlockNavigation } from './navigation'
|
||||
|
||||
export function PageBlockMaker<T extends PageBlock> (i: { kind: string }): T {
|
||||
const PageBlockTemp = Registry.get(i.kind)
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import { PageBlock, PageBlockInput, Registry } from '../base'
|
||||
import NavigationItem, { NavigationItemInput } from './navigation-item'
|
||||
|
||||
const kind = 'Navigation'
|
||||
|
||||
interface DisplayOptions {
|
||||
appearance: string;
|
||||
alignment: string;
|
||||
fillJustify: string;
|
||||
}
|
||||
|
||||
interface Options {
|
||||
display: DisplayOptions;
|
||||
navigationItems: NavigationItem[];
|
||||
}
|
||||
|
||||
const defaults: Readonly<Options> = Object.freeze({
|
||||
display: {
|
||||
appearance: 'tabs',
|
||||
alignment: 'center',
|
||||
fillJustify: 'justify',
|
||||
},
|
||||
navigationItems: [],
|
||||
})
|
||||
|
||||
export class PageBlockNavigation extends PageBlock {
|
||||
readonly kind = kind;
|
||||
|
||||
options: Options = { ...defaults };
|
||||
|
||||
constructor (i?: PageBlockInput) {
|
||||
super(i)
|
||||
this.applyOptions(i?.options as Partial<Options>)
|
||||
}
|
||||
|
||||
applyOptions (o?: Partial<Options>): void {
|
||||
if (!o) return
|
||||
|
||||
this.options.navigationItems = (o.navigationItems || []).map(f => new NavigationItem(f))
|
||||
|
||||
if (o.display) {
|
||||
this.options.display = o.display
|
||||
}
|
||||
}
|
||||
|
||||
static makeNavigationItem (item?: NavigationItemInput): NavigationItem {
|
||||
return new NavigationItem(item)
|
||||
}
|
||||
}
|
||||
|
||||
Registry.set(kind, PageBlockNavigation)
|
||||
@@ -0,0 +1,72 @@
|
||||
import { Apply } from '../../../../cast'
|
||||
|
||||
interface DropdownItem {
|
||||
label: string;
|
||||
url: string;
|
||||
delimiter: boolean;
|
||||
target: string;
|
||||
}
|
||||
|
||||
interface Dropdown {
|
||||
label: string;
|
||||
items: DropdownItem[]
|
||||
}
|
||||
|
||||
interface ItemOptions {
|
||||
label: string;
|
||||
url: string;
|
||||
target: string;
|
||||
delimiter: boolean;
|
||||
pageID: string;
|
||||
displaySubPages: boolean;
|
||||
dropdown: Dropdown;
|
||||
align: string;
|
||||
}
|
||||
|
||||
interface NavigationItemOptions {
|
||||
enabled: boolean;
|
||||
textColor: string;
|
||||
backgroundColor: string;
|
||||
item: ItemOptions;
|
||||
}
|
||||
|
||||
export type NavigationItemInput = Partial<NavigationItem> | NavigationItem
|
||||
|
||||
const defOptions = {
|
||||
enabled: true,
|
||||
textColor: '#0B344E',
|
||||
backgroundColor: '',
|
||||
item: {
|
||||
label: '',
|
||||
url: '',
|
||||
target: '',
|
||||
delimiter: false,
|
||||
pageID: '',
|
||||
displaySubPages: false,
|
||||
align: 'bottom',
|
||||
dropdown: {
|
||||
label: "",
|
||||
items: []
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export default class NavigationItem {
|
||||
public type = ''
|
||||
|
||||
public options: NavigationItemOptions = { ...defOptions }
|
||||
|
||||
constructor (i?: NavigationItemInput) {
|
||||
this.apply(i)
|
||||
}
|
||||
|
||||
apply (i?: NavigationItemInput): void {
|
||||
if (!i) return
|
||||
|
||||
Apply(this, i, String, 'type')
|
||||
|
||||
if (i.options) {
|
||||
this.options = { ...this.options, ...i.options }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -505,6 +505,56 @@ comment:
|
||||
footnote: 'Field value will be used as reference'
|
||||
navigation:
|
||||
chart: Charts
|
||||
label: Navigation
|
||||
displayOptions: Display options
|
||||
appearance: Appearance
|
||||
alignment: Alignment
|
||||
fillJustify: Fill and Justify
|
||||
fieldLabel: Label
|
||||
enabled: Enabled
|
||||
openIn: Open in
|
||||
navigationItems: Navigation items
|
||||
type: Type
|
||||
disabled: Disabled
|
||||
color: Color
|
||||
background: Background
|
||||
url: URL
|
||||
drop: Dropdown position
|
||||
add: Add
|
||||
composePage: Compose page
|
||||
tabs: Tabs
|
||||
pills: Pills
|
||||
small: Small
|
||||
center: Center
|
||||
left: Left
|
||||
right: Right
|
||||
bottom: Bottom
|
||||
top: Top
|
||||
fill: Fill
|
||||
justify: Justify
|
||||
primary: Primary
|
||||
secondary: Secondary
|
||||
success: Success
|
||||
warning: Warning
|
||||
danger: Danger
|
||||
info: Info
|
||||
text: Text
|
||||
dropdown: Dropdown
|
||||
multi: Multiline
|
||||
sameTab: Same tab
|
||||
selectOpenInType: Select open in type
|
||||
newTab: New tab
|
||||
dropdownItems: Dropdown items
|
||||
delimiter: Delimiter
|
||||
none: None
|
||||
displaySubPages: Display sub-pages
|
||||
selectBackground: Select background
|
||||
preview:
|
||||
preview: Preview
|
||||
label: Label
|
||||
home: Home
|
||||
dropdown: dropdown
|
||||
about: about
|
||||
report:
|
||||
label: Report
|
||||
scenario:
|
||||
|
||||
Reference in New Issue
Block a user