Adds new style to Tainacan Header and Subheader. Removes SecondaryMenu and creates TitleRow to hold title and breadrumbs in repository-level pages. Adds contraction functionality to PrimaryMenu. Adds event listing to Collection level (needs fixes). Several adjustments on css values to match recent design. New Implementation of ItemListing still needs improvements for resposiviness!

This commit is contained in:
mateuswetah 2018-04-30 17:51:04 -03:00
parent 167b021a9d
commit 9170a11825
19 changed files with 490 additions and 591 deletions

View File

@ -2,8 +2,15 @@
<div
id="tainacan-admin-app"
class="columns is-fullheight">
<primary-menu/>
<tainacan-header/>
<primary-menu
:active-route="activeRoute"
:is-menu-compressed="isMenuCompressed"/>
<button
id="menu-compress-button"
@click="isMenuCompressed = !isMenuCompressed">
<b-icon :icon="isMenuCompressed ? 'menu-right' : 'menu-left'" />
</button>
<tainacan-header :is-menu-compressed="isMenuCompressed"/>
<div class="column is-main-content">
<router-view/>
</div>
@ -18,6 +25,8 @@
name: "AdminPage",
data(){
return {
isMenuCompressed: false,
activeRoute: '/collections'
}
},
components: {
@ -25,7 +34,15 @@
TainacanHeader
},
created() {
this.$userPrefs.init()
this.$userPrefs.init();
this.isMenuCompressed = (this.$route.params.collectionId != undefined);
this.activeRoute = this.$route.name;
},
watch: {
'$route' (to) {
this.isMenuCompressed = (to.params.collectionId != undefined);
this.activeRoute = to.name;
}
}
}
</script>
@ -63,7 +80,7 @@
margin: $header-height auto 0 auto;
position: relative;
overflow-y: auto;
height: calc(100% - 58px);
height: calc(100% - 52px);
@media screen and (max-width: 769px) {
& {
@ -77,5 +94,24 @@
}
}
#menu-compress-button {
position: absolute;
z-index: 99999;
top: 70px;
max-width: 23px;
height: 21px;
width: 23px;
border: none;
background-color: $primary-light;
color: $tertiary;
padding: 0px;
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
.icon {
margin-top: -1px;
}
}
</style>

View File

@ -1,15 +1,14 @@
<template>
<div class="page-container">
<div class="page-container-small">
<div class="tainacan-page-title">
<h2>{{ $i18n.get('title_item_edition') }}</h2>
<a class="is-secondary">{{ $i18n.get('return') }}</a>
<a class="back-link is-secondary">{{ $i18n.get('return') }}</a>
<hr>
</div>
<form
v-if="!isLoading"
class="tainacan-form"
label-width="120px">
<div class="columns">
<div class="column is-4">
<!-- Document -------------------------------- -->

View File

@ -1,32 +1,17 @@
<template>
<nav
id="primary-menu"
:class="isCompressed ? 'is-compressed' : ''"
:class="isMenuCompressed ? 'is-compressed' : ''"
role="navigation"
:aria-label="$i18n.get('label_main_menu')"
class="column is-sidebar-menu">
<aside class="menu">
<div class="menu-header">
<ul class="menu-list"><li>
<router-link
tag="a"
to="/">
<b-icon
size="is-medium"
icon="chevron-left"/>
<img
class="tainacan-logo"
alt="Tainacan Logo"
:src="logoHeader">
</router-link>
</li></ul>
</div>
<ul class="menu-list">
<li><router-link
tag="a"
to="/collections"
:class="activeRoute == 'CollectionsPage' || isCompressed ? 'is-active':''">
:class="activeRoute == 'CollectionsPage' || isMenuCompressed ? 'is-active':''">
<b-icon
size="is-small"
icon="folder-multiple"/> <span class="menu-text">{{ $i18n.getFrom('collections', 'name') }}</span>
@ -70,7 +55,7 @@
:class="activeRoute == 'EventsPage' ? 'is-active':''">
<b-icon
size="is-small"
icon="bell"/> <span class="menu-text">{{ $i18n.get('events') }}</span>
icon="calendar"/> <span class="menu-text">{{ $i18n.get('events') }}</span>
</router-link></li>
</ul>
</aside>
@ -80,22 +65,9 @@
<script>
export default {
name: 'PrimaryMenu',
data(){
return {
logoHeader: tainacan_plugin.base_url + '/admin/images/tainacan_logo_header.png',
isCompressed: false,
activeRoute: '/collections'
}
},
watch: {
'$route' (to) {
this.isCompressed = (to.params.collectionId != undefined);
this.activeRoute = to.name;
}
},
created () {
this.isCompressed = (this.$route.params.collectionId != undefined);
this.activeRoute = this.$route.name;
props: {
isMenuCompressed: false,
activeRoute: '/collections'
}
}
</script>
@ -105,32 +77,13 @@ export default {
@import "../../scss/_variables.scss";
#primary-menu {
background-color: $secondary;
padding: 0px;
background-color: $primary;
padding: 100px 0px 0px 0px;
-webkit-transition: max-width 0.2s linear; /* Safari */
transition: max-width 0.2s linear;
max-width: $side-menu-width;
z-index: 99;
.menu { padding-top: 0px; }
.menu-header {
background-color: rgba(0,0,0,0.1);
height: $header-height;
a { padding: 1.45em 2.5em }
.icon {
position: absolute;
opacity: 0;
visibility: hidden;
transition: opacity 0.2s linear, visibility 0.2s linear;
-webkit-transition: opacity 0.2s linear, visibility 0.2s linear;
}
.tainacan-logo {
max-height: 28px;
opacity: 1;
visibility: visible;
transition: opacity 0.15s linear, visibility 0.15s linear;
-webkit-transition: opacity 0.15s linear, visibility 0.15s linear;
}
}
.separator {
height: 2px;
background-color: $separator-color;
@ -138,13 +91,6 @@ export default {
margin: 1.75em 0;
}
li{
&.search-area {
visibility: visible;
opacity: 1;
padding-top: 1.8em;
.field { padding: 0 1.8em 0.5em; }
.menu-text { font-size: 0.85em; }
}
a {
color: white;
white-space: nowrap;
@ -155,14 +101,13 @@ export default {
-webkit-transition: padding 0.2s linear; /* Safari */
transition: padding 0.2s linear;
}
a:hover {
background-color: $primary;
color: $tertiary
}
a.is-active {
a:hover, a.is-active {
background-color: $primary;
color: $tertiary;
}
a:focus{
box-shadow: none;
}
.menu-text {
padding-left: 0.7em;
opacity: 1;
@ -173,27 +118,11 @@ export default {
}
&.is-compressed {
max-width: 42px;
max-width: 44px;
.menu-header {
a { padding: 1.67em 0.3em }
.icon {
visibility: visible;
opacity: 1;
}
.tainacan-logo {
visibility: hidden;
opacity: 0;
}
}
.search-area {
visibility: hidden;
opacity: 0;
}
a {
padding-left: 0.8em;
padding-right: 0.8em;
color: rgba(255,255,255,0.4);
}
.menu-text {
visibility: hidden;
@ -217,41 +146,10 @@ export default {
align-items: stretch;
justify-content: space-evenly;
.separator { display: none; }
.search-area {
flex-basis: 100%;
padding-top: 1.0em !important;
.field {
padding: 0 0.8em !important;
margin-bottom: 0px;
}
}
a{
padding: 0.8em !important;
text-align: center;
}
li + li {
.menu-text{
display: none !important;
}
}
}
&.is-compressed {
.menu-header {
.icon {
visibility: hidden !important;
opacity: 0 !important;
}
.tainacan-logo {
visibility: visible !important;
opacity: 1 !important;
}
}
.search-area {
display: none;
}
}
}
}

View File

@ -1,211 +0,0 @@
<template>
<nav
id="secondary-menu"
role="navigation"
:aria-label="$i18n.get('label_collection_menu')"
class="column is-sidebar-menu">
<aside class="menu">
<div class="menu-header">
<ul class="menu-list"><li>
<router-link
tag="a"
to="/"
target='_blank'>
<b-icon
size="is-medium"
icon="chevron-left"/>
<img
class="tainacan-logo"
alt="Tainacan Logo"
:src="logoHeader">
</router-link>
</li></ul>
</div>
<ul class="menu-list">
<li class="search-area">
<b-field>
<b-input
:placeholder="$i18n.getFrom('items', 'search_items')"
type="search"
size="is-small"
icon="magnify"/>
</b-field>
<router-link
tag="a"
to="">
<b-icon
size="is-small"
icon="magnify"/> <span class="menu-text">{{ $i18n.get('advanced_search') }}</span>
</router-link>
</li>
<li class="separator"/>
<li><router-link
tag="a"
:to="{ path: $routerHelper.getCollectionItemsPath(id, '') }"
:class="activeRoute == 'ItemPage' || activeRoute == 'CollectionItemsPage' || activeRoute == 'ItemEditionForm' || activeRoute == 'ItemCreatePage' ? 'is-active':''"
:aria-label="$i18n.get('label_collection_fields')">
<b-icon
size="is-small"
icon="file-multiple"/> <span class="menu-text">{{ $i18n.getFrom('items', 'name') }}</span>
</router-link></li>
<li><router-link
tag="a"
:to="{ path: $routerHelper.getCollectionEditPath(id) }"
:class="activeRoute == 'CollectionEditionForm' ? 'is-active':''"
:aria-label="$i18n.getFrom('collections','edit_item')">
<b-icon
size="is-small"
icon="pencil"/> <span class="menu-text">{{ $i18n.get('edit') }}</span>
</router-link></li>
<li><router-link
tag="a"
:to="{ path: $routerHelper.getCollectionFieldsPath(id) }"
:class="activeRoute == 'FieldsList' ? 'is-active':''"
:aria-label="$i18n.get('label_collection_fields')">
<b-icon
size="is-small"
icon="format-list-checks"/> <span class="menu-text">{{ $i18n.getFrom('fields', 'name') }}</span>
</router-link></li>
<li><router-link
tag="a"
:to="{ path: $routerHelper.getCollectionFiltersPath(id) }"
:class="activeRoute == 'FiltersList' ? 'is-active':''"
:aria-label="$i18n.get('label_collection_filters')">
<b-icon
size="is-small"
icon="filter"/> <span class="menu-text">{{ $i18n.getFrom('filters', 'name') }}</span>
</router-link></li>
</ul>
</aside>
</nav>
</template>
<script>
export default {
name: 'SecondaryMenu',
data(){
return {
logoHeader: tainacan_plugin.base_url + '/admin/images/tainacan_logo_header.png',
activeRoute: 'ItemsList'
}
},
props: {
id: Number
},
watch: {
'$route' (to) {
this.activeRoute = to.name;
}
},
created () {
this.activeRoute = this.$route.name;
}
}
</script>
<style lang="scss" scoped>
@import "../../scss/_variables.scss";
#secondary-menu {
background-color: $primary;
padding: 0px;
-webkit-transition: max-width 0.3s linear; /* Safari */
transition: max-width 0.3s linear;
max-width: $side-menu-width;
z-index: 9;
.menu-header {
background-color: rgba(0,0,0,0.1);
height: $header-height;
a { padding: 1.45em 2.5em }
.icon {
position: absolute;
opacity: 0;
visibility: hidden;
transition: opacity 0.2s linear, visibility 0.2s linear;
-webkit-transition: opacity 0.2s linear, visibility 0.2s linear;
}
.tainacan-logo {
max-height: 28px;
opacity: 1;
visibility: visible;
transition: opacity 0.15s linear, visibility 0.15s linear;
-webkit-transition: opacity 0.15s linear, visibility 0.15s linear;
}
}
.separator {
height: 2px;
background-color: rgba(0,0,0,0.15);
width: 100%;
margin: 1.75em 0;
}
li{
&.search-area {
visibility: visible;
opacity: 1;
padding-top: 1.8em;
.field { padding: 0 1.8em 0.5em; }
.menu-text { font-size: 0.85em; }
}
a {
color: white;
white-space: nowrap;
overflow: hidden;
padding: 0.75em 1.8em;
line-height: 1.5em;
border-radius: 0px;
-webkit-transition: padding 0.3s linear; /* Safari */
transition: padding 0.3s linear;
}
a:hover {
background-color: rgba(255,255,255,0.4);
color: $tertiary;
}
a.is-active {
background-color: rgba(255,255,255,0.4);
color: $tertiary;
}
.menu-text {
padding-left: 0.7em;
opacity: 1;
visibility: visible;
transition: opacity 0.3s linear, visibility 0.3s linear;
-webkit-transition: opacity 0.3s linear, visibility 0.3s linear;
}
}
@media screen and (max-width: 769px) {
width: 100% !important;
max-width: 100% !important;
.separator, .menu-header { display: none; }
ul {
flex-flow: wrap;
display: flex;
align-items: stretch;
justify-content: space-evenly;
a {
padding: 0.5em 0.7em !important;
text-align: center;
}
.menu-text {
padding-left: 0.3em !important;
}
.search-area {
flex-basis: 100%;
padding-top: 1.0em !important;
.field {
padding: 0 0.8em !important;
margin-bottom: 0px;
}
}
}
}
}
</style>

View File

@ -2,33 +2,38 @@
<div
id="tainacan-header"
class="level"
:class="{'secondary-page': onSecondaryPage}">
:class="{'menu-compressed': isMenuCompressed}">
<div class="level-left">
<div class="level-item">
<h1 class="has-text-weight-bold is-uppercase"><b-icon
size="is-small"
:icon="currentIcon"/>{{ pageTitle }}</h1>
<nav class="breadcrumbs">
<router-link
tag="a"
:to="$routerHelper.getCollectionsPath()">{{ $i18n.get('repository') }}</router-link> >
<span
v-for="(pathItem, index) in arrayRealPath"
:key="index">
<router-link
tag="a"
:to="'/' + arrayRealPath.slice(0, index + 1).join('/')">
{{ arrayViewPath[index] }}
</router-link>
<span v-if="index != arrayRealPath.length - 1"> > </span>
</span>
</nav>
<router-link
tag="a"
to="/">
<img
class="tainacan-logo"
alt="Tainacan Logo"
:src="logoHeader">
</router-link>
</div>
</div>
<div class="level-right">
<a class="level-item">
<a
v-show="!showSearch"
@click="showSearch = true;"
class="level-item">
<b-icon icon="magnify"/>
</a>
<span
@mouseleave="searchTerm.length <= 0 ? showSearch = false : showSearch = true"
v-show="showSearch"
class="search-area">
<b-input
:placeholder="$i18n.get('instruction_search_repository')"
type="search"
size="is-small"
v-model="searchTerm"
icon="magnify" />
<a href="">{{ $i18n.get('advanced_search') }}</a>
</span>
<a
class="level-item"
:href="wordpressAdmin">
@ -39,102 +44,19 @@
</template>
<script>
import { mapActions, mapGetters } from 'vuex';
export default {
name: 'TainacanHeader',
data(){
return {
logoHeader: tainacan_plugin.base_url + '/admin/images/tainacan_logo_header.png',
wordpressAdmin: window.location.origin + window.location.pathname.replace('admin.php', ''),
onSecondaryPage: false,
pageTitle: '',
arrayRealPath: [],
arrayViewPath: [],
activeRouteName: '',
currentIcon: ''
showSearch: false,
searchTerm: ''
}
},
methods: {
...mapActions('collection', [
'fetchCollectionName'
]),
...mapGetters('collection', [
'getCollectionName'
]),
...mapActions('item', [
'fetchItemTitle'
]),
...mapGetters('item', [
'getItemTitle'
]),
...mapActions('category', [
'fetchCategoryName'
]),
...mapGetters('category', [
'getCategoryName'
]),
...mapActions('event', [
'fetchEventTitle'
]),
generateViewPath() {
for (let i = 0; i < this.arrayRealPath.length; i++) {
this.arrayViewPath.push('');
if (!isNaN(this.arrayRealPath[i]) && i > 0) {
switch(this.arrayRealPath[i-1]) {
case 'collections':
this.fetchCollectionName(this.arrayRealPath[i])
.then(collectionName => this.arrayViewPath.splice(i, 1, collectionName))
.catch((error) => this.$console.error(error));
break;
case 'items':
this.fetchItemTitle(this.arrayRealPath[i])
.then(itemTitle => this.arrayViewPath.splice(i, 1, itemTitle))
.catch((error) => this.$console.error(error));
break;
case 'categories':
this.fetchCategoryName(this.arrayRealPath[i])
.then(categoryName => this.arrayViewPath.splice(i, 1, categoryName))
.catch((error) => this.$console.error(error));
break;
case 'events':
this.fetchEventTitle(this.arrayRealPath[i])
.then(eventName => this.arrayViewPath.splice(i, 1, eventName))
.catch((error) => this.$console.error(error));
break;
}
} else {
this.arrayViewPath.splice(i, 1, this.$i18n.get(this.arrayRealPath[i]));
}
}
}
},
watch: {
'$route' (to) {
this.onSecondaryPage = (to.params.collectionId != undefined);
this.pageTitle = this.$route.meta.title;
this.currentIcon = this.$route.meta.icon;
this.arrayRealPath = to.path.split("/");
this.arrayRealPath = this.arrayRealPath.filter((item) => item.length != 0);
this.generateViewPath();
}
},
created() {
this.onSecondaryPage = (this.$route.params.collectionId != undefined);
this.pageTitle = this.$route.meta.title;
this.currentIcon = this.$route.meta.icon;
this.arrayRealPath = this.$route.path.split("/");
this.arrayRealPath = this.arrayRealPath.filter((item) => item.length != 0);
this.generateViewPath();
props: {
isMenuCompressed: false
}
}
</script>
@ -149,33 +71,64 @@ export default {
height: $header-height;
max-height: $header-height;
width: 100%;
border-bottom: 0.5px solid #ddd;
padding: 1.0em;
padding: 12px;
vertical-align: middle;
left: 0;
right: 0;
position: absolute;
z-index: 9;
z-index: 999;
color: white;
.icon {
padding-right: 1.3em;
margin-left: -1.3em;
}
.breadcrumbs {
font-size: 0.85em;
}
.level-left {
.level-item {
display: inline-block;
margin-left: 268px;
}
margin-left: -12px;
.level-item{
height: 52px;
width: 180px;
transition: margin 0.15s linear;
-webkit-transition: margin 0.15s linear;
margin-left: 0px;
cursor: pointer;
&:hover{
background-color: #257887;
}
&:focus {
box-shadow: none;
}
.tainacan-logo {
max-height: 22px;
padding: 0px 28px;
}
}
}
&.secondary-page {
.level-item {
margin-left: 87px;
.level-right {
padding-right: 12px;
a{
color: white;
}
a:hover {
color: $tertiary;
}
.search-area {
display: flex;
align-items: center;
input {
margin: 0px 12px;
}
.icon {
color: $tertiary;
}
a {
margin: 0px 12px;
font-size: 12px;
}
}
}
&.menu-compressed {
.level-left .level-item {
margin-left: 44px;
}
}
@ -191,7 +144,7 @@ export default {
}
top: 206px;
&.secondary-page {
&.menu-compressed {
top: 237px !important;
}
margin-bottom: 0px !important;

View File

@ -1,13 +1,10 @@
<template>
<div
id="tainacan-subheader"
class="level"
:class="{'secondary-page': onSecondaryPage}">
class="level secondary-page">
<div class="level-left">
<div class="level-item">
<h1 class="has-text-weight-bold is-uppercase has-text-tertiary"><b-icon
size="is-small"
:icon="currentIcon"/>{{ pageTitle }}</h1>
<h1>{{ getCollectionName() }}</h1>
<nav class="breadcrumbs">
<router-link
tag="a"
@ -30,12 +27,12 @@
tag="a"
:to="{ path: $routerHelper.getCollectionItemsPath(id, '') }"
:class="activeRoute == 'ItemPage' || activeRoute == 'CollectionItemsPage' || activeRoute == 'ItemEditionForm' || activeRoute == 'ItemCreatePage' ? 'is-active':''"
:aria-label="$i18n.get('label_collection_fields')">
:aria-label="$i18n.get('label_collection_items')">
<b-icon
size="is-small"
icon="file-multiple"/>
icon="folder-outline"/>
<br>
<span class="menu-text">{{ $i18n.getFrom('items', 'name') }}</span>
<span class="menu-text">{{ $i18n.getFrom('collections', 'singular_name') }}</span>
</router-link></li>
<li class="level-item"><router-link
tag="a"
@ -70,6 +67,17 @@
<br>
<span class="menu-text">{{ $i18n.getFrom('filters', 'name') }}</span>
</router-link></li>
<li class="level-item"><router-link
tag="a"
:to="{ path: $routerHelper.getCollectionEventsPath(id) }"
:class="activeRoute == 'EventsList' ? 'is-active':''"
:aria-label="$i18n.get('label_collection_events')">
<b-icon
size="is-small"
icon="calendar"/>
<br>
<span class="menu-text">{{ $i18n.get('events') }}</span>
</router-link></li>
</ul>
</div>
@ -87,7 +95,6 @@ export default {
arrayRealPath: [],
arrayViewPath: [],
activeRouteName: '',
currentIcon: ''
}
},
props: {
@ -97,9 +104,7 @@ export default {
'$route' (to) {
this.activeRoute = to.name;
this.onSecondaryPage = (to.params.collectionId != undefined);
this.pageTitle = this.$route.meta.title;
this.currentIcon = this.$route.meta.icon;
this.arrayRealPath = to.path.split("/");
this.arrayRealPath = this.arrayRealPath.filter((item) => item.length != 0);
@ -170,9 +175,7 @@ export default {
created() {
this.activeRoute = this.$route.name;
this.onSecondaryPage = (this.$route.params.collectionId != undefined);
this.pageTitle = this.$route.meta.title;
this.currentIcon = this.$route.meta.icon;
this.arrayRealPath = this.$route.path.split("/");
this.arrayRealPath = this.arrayRealPath.filter((item) => item.length != 0);
@ -192,7 +195,6 @@ export default {
height: $subheader-height;
max-height: $subheader-height;
width: 100%;
border-bottom: 0.5px solid #ddd;
padding: 1.0em;
margin: 0px;
vertical-align: middle;
@ -200,41 +202,65 @@ export default {
right: 0;
z-index: 9;
.icon {
padding-right: 1.3em;
margin-left: -1.3em;
h1 {
font-size: 18px;
font-weight: 500;
color: $tertiary;
line-height: 22px;
margin-bottom: 12px;
max-width: 450px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.breadcrumbs {
font-size: 0.85em;
font-size: 12px;
line-height: 12px;
}
.level-left {
margin-left: 5px;
.level-item {
display: inline-block;
margin-left: 45px;
}
}
li{
margin-right: 0px;
a {
color: $secondary;
color: $tertiary;
text-align: center;
white-space: nowrap;
overflow: hidden;
padding: 1.0em 1.8em;
padding: 1.0em 10px;
min-width: 75px;
line-height: 1.5em;
border-radius: 0px;
-webkit-transition: padding 0.3s linear; /* Safari */
transition: padding 0.3s linear;
position: relative;
overflow: inherit;
}
a:hover {
background-color: rgba(255,255,255,0.4);
color: $tertiary;
}
a:hover,
a.is-active {
background-color: rgba(255,255,255,0.6);
color: $tertiary;
background-color: #d1f1f2;
}
a:focus{
box-shadow: none;
}
a.is-active:after {
position: absolute;
content: '';
width: 0;
height: 0;
bottom: -1px;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 11px solid white;
left: calc(50% - 10px);
-moz-transform: scale(0.999);
-webkit-backface-visibility: hidden;
}
.icon {
margin: 0;

View File

@ -0,0 +1,160 @@
<template>
<div
class="tainacan-page-title"
id="title-row">
<h1>{{ pageTitle }}</h1>
<hr>
<nav class="breadcrumbs">
<router-link
tag="a"
:to="$routerHelper.getCollectionsPath()">{{ $i18n.get('repository') }}</router-link> >
<span
v-for="(pathItem, index) in arrayRealPath"
:key="index">
<router-link
tag="a"
:to="'/' + arrayRealPath.slice(0, index + 1).join('/')">
{{ arrayViewPath[index] }}
</router-link>
<span v-if="index != arrayRealPath.length - 1"> > </span>
</span>
</nav>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex';
export default {
name: 'TitleRow',
data(){
return {
wordpressAdmin: window.location.origin + window.location.pathname.replace('admin.php', ''),
onSecondaryPage: false,
pageTitle: '',
arrayRealPath: [],
arrayViewPath: [],
activeRouteName: ''
}
},
methods: {
...mapActions('collection', [
'fetchCollectionName'
]),
...mapGetters('collection', [
'getCollectionName'
]),
...mapActions('item', [
'fetchItemTitle'
]),
...mapGetters('item', [
'getItemTitle'
]),
...mapActions('category', [
'fetchCategoryName'
]),
...mapGetters('category', [
'getCategoryName'
]),
...mapActions('event', [
'fetchEventTitle'
]),
generateViewPath() {
for (let i = 0; i < this.arrayRealPath.length; i++) {
this.arrayViewPath.push('');
if (!isNaN(this.arrayRealPath[i]) && i > 0) {
switch(this.arrayRealPath[i-1]) {
case 'collections':
this.fetchCollectionName(this.arrayRealPath[i])
.then(collectionName => this.arrayViewPath.splice(i, 1, collectionName))
.catch((error) => this.$console.error(error));
break;
case 'items':
this.fetchItemTitle(this.arrayRealPath[i])
.then(itemTitle => this.arrayViewPath.splice(i, 1, itemTitle))
.catch((error) => this.$console.error(error));
break;
case 'categories':
this.fetchCategoryName(this.arrayRealPath[i])
.then(categoryName => this.arrayViewPath.splice(i, 1, categoryName))
.catch((error) => this.$console.error(error));
break;
case 'events':
this.fetchEventTitle(this.arrayRealPath[i])
.then(eventName => this.arrayViewPath.splice(i, 1, eventName))
.catch((error) => this.$console.error(error));
break;
}
} else {
this.arrayViewPath.splice(i, 1, this.$i18n.get(this.arrayRealPath[i]));
}
}
}
},
watch: {
'$route' (to) {
this.onSecondaryPage = (to.params.collectionId != undefined);
this.pageTitle = this.$route.meta.title;
this.arrayRealPath = to.path.split("/");
this.arrayRealPath = this.arrayRealPath.filter((item) => item.length != 0);
this.generateViewPath();
}
},
created() {
this.onSecondaryPage = (this.$route.params.collectionId != undefined);
this.pageTitle = this.$route.meta.title;
this.arrayRealPath = this.$route.path.split("/");
this.arrayRealPath = this.arrayRealPath.filter((item) => item.length != 0);
this.generateViewPath();
}
}
</script>
<style lang="scss" scoped>
@import "../../scss/_variables.scss";
// Tainacan Header
#title-row {
.breadcrumbs {
font-size: 0.85em;
}
.level-left {
.level-item {
display: inline-block;
margin-left: 268px;
}
}
@media screen and (max-width: 769px) {
.level-left {
margin-left: 0px !important;
.level-item {
margin-left: 30px;
}
}
.level-right {
display: none;
}
top: 206px;
margin-bottom: 0px !important;
}
}
</style>

View File

@ -1,5 +1,29 @@
<template>
<span>
<div class="header-item">
<b-dropdown id="item-creation-options-dropdown">
<button
class="button is-secondary"
slot="trigger">
<span>{{ `${$i18n.get('add')} ${$i18n.get('item')}` }}</span>
<b-icon icon="menu-down"/>
</button>
<b-dropdown-item>
<router-link
id="a-create-item"
tag="div"
:to="{ path: $routerHelper.getNewItemPath(collectionId) }">
{{ $i18n.get('add_one_item') }}
</router-link>
</b-dropdown-item>
<b-dropdown-item>{{ $i18n.get('add_items_bulk') }}
</b-dropdown-item>
<b-dropdown-item>{{ $i18n.get('add_items_external_source') }}<br><small class="is-small">{{ $i18n.get() }}</small></b-dropdown-item>
</b-dropdown>
</div>
<div class="header-item">
<b-dropdown>
<button
@ -92,7 +116,9 @@
<style>
.header-item {
display: inline-block;
padding-right: 8em;
}
#item-creation-options-dropdown {
margin-right: 80px;
}
</style>

View File

@ -22,6 +22,7 @@ import CategoryEditionForm from '../components/edition/category-edition-form.vue
// Listing components
import FiltersList from '../components/lists/filters-list.vue'
import FieldsList from '../components/lists/fields-list.vue'
import EventsList from '../components/lists/events-list.vue'
Vue.use(VueRouter);
@ -45,8 +46,9 @@ const routes = [
{ path: 'items/:itemId', name: 'ItemPage', component: ItemPage, meta: {title: i18nGet('title_item_page'), icon: 'folder-multiple'} },
{ path: 'edit', component: CollectionEditionForm, name: 'CollectionEditionForm', meta: {title: i18nGet('title_collection_edition'), icon: 'folder-multiple'} },
{ path: 'fields', component: FieldsList, name: 'FieldsList', meta: {title: i18nGet('title_collection_fields_edition'), icon: 'folder-multiple'} },
{ path: 'filters', component: FiltersList, name: 'FiltersList', meta: {title: i18nGet('title_collection_page'), icon: 'folder-multiple'} }
]
{ path: 'filters', component: FiltersList, name: 'FiltersList', meta: {title: i18nGet('title_collection_filters_edition'), icon: 'folder-multiple'} },
{ path: 'events', component: EventsList, name: 'EventsList', meta: {title: i18nGet('title_collection_events'), icon: 'calendar'} }
]
},
{ path: '/items', name: 'ItemsPage', component: ItemsPage, meta: {title: i18nGet('title_items_page'), icon: 'file-multiple'} },
@ -61,8 +63,8 @@ const routes = [
{ path: '/categories/:categoryId/edit', name: 'CategoryEditionForm', component: CategoryEditionForm, meta: {title: i18nGet('title_category_edition_page'), icon: 'shape'} },
{ path: '/categories/:categoryId', name: 'CategoryPage', component: CategoryPage, meta: {title: i18nGet('title_category_page'), icon: 'shape'} },
{ path: '/events', name: 'EventsPage', component: EventsPage, meta: {title: i18nGet('title_events_page'), icon: 'bell'} },
{ path: '/events/:eventId', name: 'EventPage', component: EventPage, meta: {title: i18nGet('title_event_page'), icon: 'bell'} },
{ path: '/events', name: 'EventsPage', component: EventsPage, meta: {title: i18nGet('title_events_page'), icon: 'calendar'} },
{ path: '/events/:eventId', name: 'EventPage', component: EventPage, meta: {title: i18nGet('title_event_page'), icon: 'calendar'} },
{ path: '*', redirect: '/'}
];

View File

@ -168,6 +168,9 @@ RouterHelperPlugin.install = function (Vue, options = {}) {
getCollectionFiltersPath(collectionId) {
return '/collections/'+ collectionId + '/filters/';
},
getCollectionEventsPath(collectionId) {
return '/collections/'+ collectionId + '/events/';
},
getItemsPath(query) {
return '/items/?' + qs.stringify(query);
},

View File

@ -1,6 +1,7 @@
<template>
<div>
<div class="primary-page page-container-small">
<div class="primary-page page-container">
<title-row/>
<div
class="sub-header"
v-if="totalCategories > 0">
@ -69,6 +70,7 @@
<script>
import CategoriesList from "../../components/lists/categories-list.vue";
import TitleRow from '../../components/navigation/title-row.vue';
import { mapActions, mapGetters } from 'vuex';
//import moment from 'moment'
@ -83,7 +85,8 @@
}
},
components: {
CategoriesList
CategoriesList,
TitleRow
},
methods: {
...mapActions('category', [

View File

@ -1,5 +1,6 @@
<template>
<div class="primary-page page-container-small">
<div class="primary-page page-container">
<title-row/>
<div
class="sub-header"
v-if="totalCollections > 0">
@ -66,6 +67,7 @@
<script>
import CollectionsList from '../../components/lists/collections-list.vue';
import TitleRow from '../../components/navigation/title-row.vue';
import { mapActions, mapGetters } from 'vuex';
import moment from 'moment'
@ -80,7 +82,8 @@ export default {
}
},
components: {
CollectionsList
CollectionsList,
TitleRow
},
methods: {
...mapActions('collection', [

View File

@ -1,7 +1,7 @@
<template>
<div>
<div class="primary-page page-container-small">
<div class="primary-page page-container">
<title-row/>
<div class="columns above-subheader">
<div class="column table-container">
<events-list
@ -56,6 +56,7 @@
<script>
import EventsList from "../../components/lists/events-list.vue";
import TitleRow from '../../components/navigation/title-row.vue';
import { mapActions, mapGetters } from 'vuex';
import moment from 'moment'
@ -70,7 +71,8 @@
}
},
components: {
EventsList
EventsList,
TitleRow
},
methods: {
...mapActions('event', [

View File

@ -1,11 +1,13 @@
<template>
<div class="primary-page page-container">
<title-row/>
<fields-list/>
</div>
</template>
<script>
import FieldsList from '../../components/lists/fields-list.vue';
import TitleRow from '../../components/navigation/title-row.vue';
export default {
name: 'FieldsPage',
@ -14,7 +16,8 @@ export default {
}
},
components: {
FieldsList
FieldsList,
TitleRow
}
}
</script>

View File

@ -1,11 +1,13 @@
<template>
<div class="primary-page page-container">
<title-row/>
<filters-list/>
</div>
</template>
<script>
import FiltersList from '../../components/lists/filters-list.vue';
import TitleRow from '../../components/navigation/title-row.vue';
export default {
name: 'FiltersPage',
@ -14,7 +16,8 @@ export default {
}
},
components: {
FiltersList
FiltersList,
TitleRow
}
}
</script>

View File

@ -1,72 +1,55 @@
<template>
<div
class="page-container-small"
:class="{'primary-page': isRepositoryLevel}">
<div class="sub-header">
<b-loading
:is-full-page="false"
:active.sync="isLoadingFields"/>
<div class="header-item">
<b-dropdown>
<button
class="button is-secondary"
slot="trigger">
<span>{{ `${$i18n.get('add')} ${$i18n.get('item')}` }}</span>
<b-icon icon="menu-down"/>
</button>
<b-dropdown-item>
<router-link
id="a-create-item"
tag="div"
:to="{ path: $routerHelper.getNewItemPath(collectionId) }">
{{ $i18n.get('add_one_item') }}
</router-link>
</b-dropdown-item>
<b-dropdown-item>{{ $i18n.get('add_items_bulk') }}
</b-dropdown-item>
<b-dropdown-item>{{ $i18n.get('add_items_external_source') }}<br><small class="is-small">{{ $i18n.get() }}</small></b-dropdown-item>
</b-dropdown>
</div>
<search-control
v-if="fields.length > 0 && (items.length > 0 || isLoadingItems)"
:is-repository-level="isRepositoryLevel"
:collection-id="collectionId"
:table-fields="tableFields"
:pref-table-fields="prefTableFields"/>
</div>
<div :class="{'primary-page': isRepositoryLevel, 'page-container': isRepositoryLevel, 'page-container-small' :!isRepositoryLevel }">
<title-row v-if="isRepositoryLevel"/>
<div class="columns">
<aside class="column filters-menu">
<b-loading
:is-full-page="false"
:active.sync="isLoadingFilters"/>
<h3>{{ $i18n.get('filters') }}</h3>
<filters-items-list
v-if="!isLoadingFilters && filters.length > 0"
:filters="filters"/>
<section
v-else
class="is-grouped-centered section">
<div class="content has-text-gray has-text-centered">
<p>
<b-icon
icon="filter-outline"
size="is-large"/>
</p>
<p>{{ $i18n.get('info_there_is_no_filter' ) }}</p>
<router-link
id="button-create-filter"
:to="isRepositoryLevel ? $routerHelper.getNewFilterPath() : $routerHelper.getNewCollectionFilterPath(collectionId)"
tag="button"
class="button is-secondary is-centered">
{{ $i18n.getFrom('filters', 'new_item') }}
</router-link>
</div>
</section>
</aside>
<!-- SEARCH AND FILTERS --------------------- -->
<div
class="column"
style="max-width: 200px">
<aside class="filters-menu">
<b-loading
:is-full-page="false"
:active.sync="isLoadingFilters"/>
<h3>{{ $i18n.get('filters') }}</h3>
<filters-items-list
v-if="!isLoadingFilters && filters.length > 0"
:filters="filters"/>
<section
v-else
class="is-grouped-centered section">
<div class="content has-text-gray has-text-centered">
<p>
<b-icon
icon="filter-outline"
size="is-large"/>
</p>
<p>{{ $i18n.get('info_there_is_no_filter' ) }}</p>
<router-link
id="button-create-filter"
:to="isRepositoryLevel ? $routerHelper.getNewFilterPath() : $routerHelper.getNewCollectionFilterPath(collectionId)"
tag="button"
class="button is-secondary is-centered">
{{ $i18n.getFrom('filters', 'new_item') }}
</router-link>
</div>
</section>
</aside>
</div>
<div class="column">
<!-- SEARCH CONTROL ------------------------- -->
<div class="sub-header">
<b-loading
:is-full-page="false"
:active.sync="isLoadingFields"/>
<search-control
v-if="fields.length > 0 && (items.length > 0 || isLoadingItems)"
:is-repository-level="isRepositoryLevel"
:collection-id="collectionId"
:table-fields="tableFields"
:pref-table-fields="prefTableFields"/>
</div>
<!-- LISTING RESULTS ------------------------- -->
<div class="table-container above-subheader">
<b-loading
:is-full-page="false"
@ -111,6 +94,7 @@
import ItemsList from '../../components/lists/items-list.vue';
import FiltersItemsList from '../../components/search/filters-items-list.vue';
import Pagination from '../../components/search/pagination.vue'
import TitleRow from '../../components/navigation/title-row.vue';
import {mapActions, mapGetters} from 'vuex';
export default {
@ -133,7 +117,8 @@
SearchControl,
ItemsList,
FiltersItemsList,
Pagination
Pagination,
TitleRow
},
methods: {
...mapGetters('collection', [
@ -275,14 +260,16 @@
.page-container-small > .columns {
margin-top: 0;
&>.column {
padding: 0px;
}
}
.sub-header {
min-height: $subheader-height;
height: $subheader-height;
margin-left: -$page-small-side-padding;
margin-right: -$page-small-side-padding;
margin-left: -42px;
margin-right: -42px;
margin-top: -$page-small-top-padding;
padding-top: $page-small-top-padding;
padding-left: $page-small-side-padding;
@ -310,10 +297,12 @@
.filters-menu {
position: relative;
min-width: $side-menu-width;
width: $side-menu-width;
max-width: $side-menu-width;
background-color: $tainacan-input-color;
margin-left: -$page-small-side-padding;
margin-right: -$page-small-side-padding;
margin-top: -$page-small-top-padding;
padding: $page-small-side-padding;
.label {
@ -324,9 +313,11 @@
}
.table-container {
margin-right: -$page-small-side-padding;
padding: 3em 2.5em;
margin-right: -42px;
margin-left: -42px;
padding: 3em 55px;
position: relative;
box-sizing: content-box;
}
@media screen and (max-width: 769px) {

View File

@ -11,14 +11,14 @@ $tertiary: #1f2f56;
$tertiary-invert: findColorInvert($tertiary);
$primary-light:#A5CDD7;
$primary-lighter: lighten($primary-light, 15%);
$primary-lighter: #e6f6f8;
$primary-dark: #55A0AF;
$primary-darker: darken($primary-dark, 5%);
$success: #25a088;
$success-invert: findColorInvert($success);
$separator-color: #2a6e77;
$separator-color: #2b98a4;
$tainacan-input-color: #f0f0f0;
$draggable-border-color: #d8d8d8;
@ -53,16 +53,16 @@ $colors: map-merge($colors, $addColors);
$size-small: 0.85em; // 0.75em on Bulma.
// Tainacan Header and side menus
$header-height: 58px;
$subheader-height: 78px;
$side-menu-width: 222px;
$page-height: calc(100% - 58px);
$header-height: 52px;
$subheader-height: 82px;
$side-menu-width: 180px;
$page-height: calc(100% - 52px);
// Overall Pages padding:
$page-side-padding: 4em;
$page-top-padding: 1.5em;
$page-small-side-padding: 2em;
$page-small-top-padding: 1.5em;
$page-side-padding: 82px;
$page-top-padding: 27px;
$page-small-side-padding: 22px;
$page-small-top-padding: 27px;
$page-mobile-side-padding: 1em;
$page-mobile-top-padding: 0.5em;

View File

@ -64,7 +64,7 @@ html {
margin-top: $header-height;
height: $page-height !important;
}
.page-container{
.page-container {
padding: $page-top-padding $page-side-padding;
height: 100%;
overflow-y: auto;
@ -76,7 +76,7 @@ html {
}
.page-container-small{
padding: $page-small-top-padding $page-small-side-padding;
height: calc(100% - 78px);
height: calc(100% - 82px);
overflow-y: auto;
@media screen and (max-width: 769px) {
@ -91,16 +91,16 @@ html {
color: $tertiary;
display: inline-block;
}
a{
a.back-link{
font-weight: 500;
float: right;
}
hr{
margin-top: 2px;
margin-bottom: 60px;
margin: 3px 0px 4px 0px;
height: 1px;
background-color: $secondary;
}
margin-bottom: 60px;
}
.tainacan-modal-content {

View File

@ -74,6 +74,7 @@ return [
'title_category_edition_page' => __( 'Category Edition Page', 'tainacan' ),
'title_filter_edition' => __( 'Filter Edition Page', 'tainacan' ),
'title_collection_fields_edition' => __( 'Collection Fields Edition Page', 'tainacan' ),
'title_collection_filters_edition' => __( 'Collection Filters Edition Page', 'tainacan' ),
// Labels (used mainly on Aria Labels and Inputs)
'label_clean' => __( 'Clear', 'tainacan' ),
@ -189,6 +190,7 @@ return [
'instruction_select_document_file_for_item' => __( 'Select a document file for item', 'tainacan' ),
'instruction_insert_url' => __( 'Insert URL', 'tainacan' ),
'instruction_write_text' => __( 'Write Text', 'tainacan' ),
'instruction_search_repository' => __( 'Search on repository', 'tainacan' ),
// Info. Other feedback to user.
'info_name_is_required' => __( 'Name is required.', 'tainacan' ),