Verified Commit 21c5c927 authored by Aral Balkan's avatar Aral Balkan

Merge branch 'tabs-as-pages': tabs refactored as pages. Closes #14

parents 8ef21c97 71ccc539
<template> <template>
<header class='profile' :style='headerStyles'> <header>
<div class='profile' :style='headerStyles'>
<!-- Profile image -->
<img class='profile-image' v-if='profileImage' :src='profileImage' alt='Profile image'> <img class='profile-image' v-if='profileImage' :src='profileImage' alt='Profile image'>
<!-- Name and bio and, if signed out, the remote follow button -->
<div class='profile-information'> <div class='profile-information'>
<h1 class='profile-name'>{{name}}</h1> <h1 class='profile-name'>{{name}}</h1>
<p class='profile-bio'>{{bio}}</p> <p class='profile-bio'>{{bio}}</p>
<button v-if='!signedIn && configured' id='follow-button' @click='followButtonPress' class='button'>Follow</button> <button v-if='!signedIn && configured' id='follow-button' @click='followButtonPress' class='button'>Follow</button>
</div> </div>
</header> </div>
<!-- Main navigation -->
<nav class='tabs is-centered' style='background-color: white;'>
<ul>
<li :class='classesForRoute("/")'>
<nuxt-link to='/'>Me</nuxt-link>
</li>
<li :class='classesForRoute("/everyone")'>
<nuxt-link to='/everyone'>Everyone</nuxt-link>
</li>
<li :class='classesForRoute("/search")'>
<nuxt-link to='/search'>Search</nuxt-link>
</li>
<li :class='classesForRoute("/settings")' v-show='signedIn || !configured'>
<nuxt-link to='/settings'>Settings</nuxt-link>
</li>
<li :class='classesForRoute("/more")' v-show='signedIn || !configured'>
<nuxt-link to='/more'></nuxt-link>
</li>
</ul>
</nav>
</header>
</template> </template>
<script> <script>
export default { export default {
mounted () {
// Set the route to Settings if the site is not configured.
if (!this.configured) {
this.$router.push('settings')
return
}
//
// Check that a path that requires person to be signed in isn’t
// accessed. Note: this is a stopgap. We should be authenticating
// on the server not here.
//
// TODO: Issue #22
// https://source.ind.ie/indienet/site/issues/22
//
if (!this.signedIn) {
const route = this.$router.history.current.path
console.log(route)
if (route === '/settings' || route === '/more') {
this.$router.push('/')
}
return
}
},
data () {
return {
currentRoute: null
}
},
computed: { computed: {
disablingCriteriaForRoutes () {
return {
'/': !this.configured, // i.e., always enabled
'/everyone': !this.configured,
'/search': !this.configured,
'/settings': false,
'/more': !this.configured
}
},
// Vuex Store
name () { return this.$store.state.name }, name () { return this.$store.state.name },
bio () { return this.$store.state.bio }, bio () { return this.$store.state.bio },
profileImage () { return this.$store.state.profileImage }, profileImage () { return this.$store.state.profileImage },
signedIn () { return this.$store.state.signedIn }, signedIn () { return this.$store.state.signedIn },
configured () { return this.$store.state.configured }, configured () { return this.$store.state.configured },
// Live header theming.
headerStyles () { headerStyles () {
let styles = { let styles = {
backgroundColor: this.$store.state.backgroundColour backgroundColor: this.$store.state.backgroundColour
...@@ -28,7 +99,28 @@ export default { ...@@ -28,7 +99,28 @@ export default {
return styles return styles
} }
}, },
watch: {
$route: function () {
console.log(`Header: Route changed to ${this.$route.path}.`)
}
},
methods: { methods: {
// Returns the correct tab class object for the passed route based on the
// current route of the page that the header is rendering in.
classesForRoute (route) {
const classObject = {}
// Is this the active tab?
if (route === this.$route.path) classObject['is-active'] = true
// Is this tab disabled?
const disableTab = this.disablingCriteriaForRoutes[route]
if (disableTab) classObject['disabled'] = true
return classObject
},
// Signals that the follow button has been pressed.
followButtonPress () { followButtonPress () {
this.$emit('followButtonPress') this.$emit('followButtonPress')
} }
...@@ -37,9 +129,7 @@ export default { ...@@ -37,9 +129,7 @@ export default {
</script> </script>
<style> <style>
.profile {
.profile
{
/* Note: the background colour and image are dynamically set on the /* Note: the background colour and image are dynamically set on the
header itself, based on the site configuration settings. */ header itself, based on the site configuration settings. */
align-items: center; align-items: center;
...@@ -52,8 +142,7 @@ export default { ...@@ -52,8 +142,7 @@ export default {
width: 100%; width: 100%;
} }
.profile-information .profile-information {
{
background-color: rgba(0,0,0,0.55); background-color: rgba(0,0,0,0.55);
margin-top: 1em; margin-top: 1em;
/* offset background against padding on profile__material */ /* offset background against padding on profile__material */
...@@ -62,8 +151,7 @@ export default { ...@@ -62,8 +151,7 @@ export default {
padding: 0.25rem 0; padding: 0.25rem 0;
} }
.profile-name .profile-name {
{
font-size: 3em; font-size: 3em;
/* numbered font weights won’t work in all browsers, will default to bold weight */ /* numbered font weights won’t work in all browsers, will default to bold weight */
...@@ -72,14 +160,12 @@ export default { ...@@ -72,14 +160,12 @@ export default {
margin: 0; margin: 0;
} }
.profile-bio .profile-bio {
{
margin: 0 auto 0.25em; margin: 0 auto 0.25em;
max-width: 42em; max-width: 42em;
} }
.profile-image .profile-image {
{
/* make image circular with a white border */ /* make image circular with a white border */
border: 0.2em solid white; border: 0.2em solid white;
border-radius: 50%; border-radius: 50%;
...@@ -93,10 +179,45 @@ export default { ...@@ -93,10 +179,45 @@ export default {
width: 40%; width: 40%;
} }
#follow-button #follow-button {
{
position: absolute; position: absolute;
top: 1em; top: 1em;
right: 1em; right: 1em;
} }
/* Main navigation */
nav {
margin-bottom: 1em;
}
nav.tabs {
/* make navigation tab text bigger (ideally these will be h2s) */
font-size: 1.5em;
/* make navigation tabs very tall */
line-height: 2;
}
.tabs ul {
margin: 0;
}
.tabs li {
margin-bottom: 0;
}
/*
We cannot set both cursor: not-allowed and pointer-events: none on the same
element (the cursor does not show). So, instead, we set the cursor on the
parent li and turn off pointer events to disable the link for disabled tabs.
*/
.tabs li.disabled {
cursor:not-allowed;
}
.tabs li.disabled > a {
color: lightgray;
pointer-events:none;
}
</style> </style>
...@@ -47,8 +47,7 @@ export default { ...@@ -47,8 +47,7 @@ export default {
</script> </script>
<style> <style>
body body {
{
font-family: 'Helvetica Neue', 'Helvetica', sans-serif; font-family: 'Helvetica Neue', 'Helvetica', sans-serif;
/* minimum font size, no fonts should be smaller than 1em */ /* minimum font size, no fonts should be smaller than 1em */
font-size: 1em; font-size: 1em;
...@@ -57,6 +56,12 @@ body ...@@ -57,6 +56,12 @@ body
margin: 0; margin: 0;
} }
main {
margin-right: auto;
margin-left: auto;
max-width: 42em;
}
/* scale up font size when we reach 76 characters per line */ /* scale up font size when we reach 76 characters per line */
@media only screen and (min-width: 35em) { @media only screen and (min-width: 35em) {
body body
...@@ -79,92 +84,76 @@ Typography for all “content” (which is mirrored inside editor) ...@@ -79,92 +84,76 @@ Typography for all “content” (which is mirrored inside editor)
h1, h2, h3, h4, h5, h6, h1, h2, h3, h4, h5, h6,
.ql-editor h1, .ql-editor h2, .ql-editor h3, .ql-editor h4, .ql-editor h5, .ql-editor h6, .ql-editor h1, .ql-editor h2, .ql-editor h3, .ql-editor h4, .ql-editor h5, .ql-editor h6,
.ql-snow .ql-editor h1, .ql-snow .ql-editor h2, .ql-snow .ql-editor h3, .ql-snow .ql-editor h4, .ql-snow .ql-editor h5, .ql-snow .ql-editor h6 .ql-snow .ql-editor h1, .ql-snow .ql-editor h2, .ql-snow .ql-editor h3, .ql-snow .ql-editor h4, .ql-snow .ql-editor h5, .ql-snow .ql-editor h6 {
{
font-weight: bold; font-weight: bold;
margin: 1em 0 0.75em; margin: 1em 0 0.75em;
} }
h1, .ql-editor h1, .ql-snow .ql-editor h1 h1, .ql-editor h1, .ql-snow .ql-editor h1 {
{
font-size: 2.5em; font-size: 2.5em;
} }
h2, .ql-editor h2, .ql-snow .ql-editor h2 h2, .ql-editor h2, .ql-snow .ql-editor h2 {
{
font-size: 1.75em; font-size: 1.75em;
} }
h3, .ql-editor h3, .ql-snow .ql-editor h3 h3, .ql-editor h3, .ql-snow .ql-editor h3 {
{
font-size: 1.5em; font-size: 1.5em;
} }
h4, .ql-editor h4, .ql-snow .ql-editor h4 h4, .ql-editor h4, .ql-snow .ql-editor h4 {
{
font-size: 1.25em; font-size: 1.25em;
} }
h5, .ql-editor h5, .ql-snow .ql-editor h5 h5, .ql-editor h5, .ql-snow .ql-editor h5 {
{
font-size: 1.2em; font-size: 1.2em;
} }
h6, .ql-editor h6, .ql-snow .ql-editor h6 h6, .ql-editor h6, .ql-snow .ql-editor h6 {
{
font-size: 1.1em; font-size: 1.1em;
} }
p, ul, ol, blockquote, figure, p, ul, ol, blockquote, figure,
.ql-editor p, .ql-editor ul, .ql-editor ol, .ql-editor blockquote, .ql-editor figure, .ql-editor p, .ql-editor ul, .ql-editor ol, .ql-editor blockquote, .ql-editor figure,
.ql-snow .ql-editor p, .ql-snow .ql-editor ul, .ql-snow .ql-editor ol, .ql-snow .ql-editor blockquote, .ql-snow .ql-editor figure .ql-snow .ql-editor p, .ql-snow .ql-editor ul, .ql-snow .ql-editor ol, .ql-snow .ql-editor blockquote, .ql-snow .ql-editor figure {
{
margin: 1em 0 0.75em; margin: 1em 0 0.75em;
} }
ul, ol, ul, ol,
.ql-editor ul, .ql-editor ol, .ql-editor ul, .ql-editor ol,
.ql-snow .ql-editor ul, .ql-snow .ql-editor ol .ql-snow .ql-editor ul, .ql-snow .ql-editor ol {
{
padding-left: 0; padding-left: 0;
} }
li, li,
.ql-editor li, .ql-editor li,
.ql-snow .ql-editor li .ql-snow .ql-editor li {
{
margin-bottom: 0.25em; margin-bottom: 0.25em;
} }
/* space created by ql-editor for bullet/number */ /* space created by ql-editor for bullet/number */
.ql-editor li::before .ql-editor li::before {
{
width: 1rem; width: 1rem;
} }
.ql-editor ol li:not(.ql-direction-rtl), .ql-editor ul li:not(.ql-direction-rtl) .ql-editor ol li:not(.ql-direction-rtl), .ql-editor ul li:not(.ql-direction-rtl) {
{
padding-left: 1.5rem; padding-left: 1.5rem;
} }
.ql-editor li.ql-indent-1:not(.ql-direction-rtl) .ql-editor li.ql-indent-1:not(.ql-direction-rtl) {
{
padding-left: 2.5rem; padding-left: 2.5rem;
} }
.ql-editor li.ql-indent-2:not(.ql-direction-rtl) .ql-editor li.ql-indent-2:not(.ql-direction-rtl) {
{
padding-left: 3.5rem; padding-left: 3.5rem;
} }
.ql-editor li.ql-indent-3:not(.ql-direction-rtl) .ql-editor li.ql-indent-3:not(.ql-direction-rtl) {
{
padding-left: 4.5rem; padding-left: 4.5rem;
} }
/* placeholder message inside editor */ /* placeholder message inside editor */
.ql-editor.ql-blank::before .ql-editor.ql-blank::before {
{
margin-top: 1em; margin-top: 1em;
} }
...@@ -178,8 +167,7 @@ BULMA-OVERRIDING STYLES ...@@ -178,8 +167,7 @@ BULMA-OVERRIDING STYLES
Buttons Buttons
- - - - - - - - - - - - */ - - - - - - - - - - - - */
.button .button {
{
/* override Bulma default that prevents font scaling */ /* override Bulma default that prevents font scaling */
font-size: 1em; font-size: 1em;
} }
...@@ -188,8 +176,7 @@ Buttons ...@@ -188,8 +176,7 @@ Buttons
Controls Controls
- - - - - - - - - - - - */ - - - - - - - - - - - - */
.control .control {
{
/* override Bulma default that prevents font scaling */ /* override Bulma default that prevents font scaling */
font-size: 1em; font-size: 1em;
} }
...@@ -207,8 +194,7 @@ Tabs ...@@ -207,8 +194,7 @@ Tabs
Form inputs Form inputs
- - - - - - - - - - - - */ - - - - - - - - - - - - */
.input, .taginput .taginput-container.is-focusable, .textarea .input, .taginput .taginput-container.is-focusable, .textarea {
{
/* override Bulma default that prevents font scaling */ /* override Bulma default that prevents font scaling */
font-size: 1em; font-size: 1em;
} }
......
<template>
<div class='page'>
<indie-header @followButtonPress='followModalActive = true' />
<main>
<b-message type='is-info' has-icon><strong>Nothing yet.</strong> Federated posts will go here.</b-message>
</main>
</div>
</template>
<script>
import indieHeader from '~/components/indieHeader'
export default {
components: {
indieHeader
}
}
</script>
<style>
</style>
...@@ -3,28 +3,29 @@ ...@@ -3,28 +3,29 @@
<!-- Site header --> <!-- Site header -->
<indie-header @followButtonPress='followModalActive = true' /> <indie-header @followButtonPress='followModalActive = true' />
<!-- Main tabs with currently hard-coded content. --> <!-- <content-type-filter /> -->
<b-tabs v-model='activeTab' position='is-centered' class='block'>
<b-tab-item label='Me' :disabled='!configured'> <!-- Main page content -->
<!-- <content-type-filter /> --> <main>
<textComposer ref='textComposer' @composerChange='composerChange' @post='post' v-show='signedIn'/> <textComposer ref='textComposer' @composerChange='composerChange' @post='post' v-show='signedIn'/>
<pre style='word-break: break-word;' v-show='signedIn && debug'>{{ composerContent }}</pre> <pre style='word-break: break-word;' v-show='signedIn && debug'>{{ composerContent }}</pre>
<transition-group name='list' tag='div' @enter='clearTextComposer'> <transition-group name='list' tag='div' @enter='clearTextComposer'>
<div v-for='post in posts' :key='post.id'> <div v-for='post in posts' :key='post.id'>
<!-- <span>ID: {{post.id}}</span> --> <!-- <span>ID: {{post.id}}</span> -->
<span v-html='post.content'></span> <span v-html='post.content'></span>
</div> </div>
</transition-group> </transition-group>
</b-tab-item> </main>
<b-tab-item label="Everyone" :disabled='!configured'><b-message type='is-info' has-icon><strong>Nothing yet.</strong> Federated posts will go here.</b-message></b-tab-item>
<!-- REFACTORING: old tabs -->
<!-- <b-tab-item label="Everyone" :disabled='!configured'><b-message type='is-info' has-icon><strong>Nothing yet.</strong> Federated posts will go here.</b-message></b-tab-item>
<b-tab-item label='Search' :disabled='!configured'><search /></b-tab-item> <b-tab-item label='Search' :disabled='!configured'><search /></b-tab-item>
<b-tab-item label="Settings" v-show='signedIn || !configured'><settings /></b-tab-item> <b-tab-item label="Settings" v-show='signedIn || !configured'><settings /></b-tab-item>
<b-tab-item label="…" v-show='signedIn || !configured' :disabled='!configured'> <b-tab-item label="…" v-show='signedIn || !configured' :disabled='!configured'>
<b-message type='is-info' has-icon><strong>Nothing yet.</strong> Additional features will be listed here.</b-message> <b-message type='is-info' has-icon><strong>Nothing yet.</strong> Additional features will be listed here.</b-message>
</b-tab-item> </b-tab-item> -->
</b-tabs>
<!-- Follow modal --> <!-- Follow modal: TODO move to header -->
<follow-modal :isActive='followModalActive' @close='followModalActive = false' /> <follow-modal :isActive='followModalActive' @close='followModalActive = false' />
</div> </div>
</template> </template>
...@@ -36,8 +37,7 @@ import 'font-awesome/css/font-awesome.min.css' ...@@ -36,8 +37,7 @@ import 'font-awesome/css/font-awesome.min.css'
import indieHeader from '~/components/indieHeader' import indieHeader from '~/components/indieHeader'
import followModal from '~/components/followModal' import followModal from '~/components/followModal'
import contentTypeFilter from '~/components/contentTypeFilter' import contentTypeFilter from '~/components/contentTypeFilter'
import settings from '~/components/settings'
import search from '~/components/search'
import textComposer from '~/components/textComposer' import textComposer from '~/components/textComposer'
const Tabs = Object.freeze({ const Tabs = Object.freeze({
...@@ -53,8 +53,6 @@ export default { ...@@ -53,8 +53,6 @@ export default {
indieHeader, indieHeader,
followModal, followModal,
contentTypeFilter, contentTypeFilter,
settings,
search,
textComposer textComposer
}, },
...@@ -112,32 +110,6 @@ export default { ...@@ -112,32 +110,6 @@ export default {
</script> </script>
<style> <style>
.tab-content
{
margin-right: auto;
margin-left: auto;
max-width: 42em;
}
nav.tabs
{
/* make navigation tab text bigger (ideally these will be h2s) */
font-size: 1.5em;
/* make navigation tabs very tall */
line-height: 2;
}
.tabs ul
{
margin: 0;
}
.tabs li
{
margin-bottom: 0;
}
.list-enter-active, .list-leave-active { .list-enter-active, .list-leave-active {
transition: all 1s; transition: all 1s;
} }
...@@ -145,9 +117,4 @@ nav.tabs ...@@ -145,9 +117,4 @@ nav.tabs
opacity: 1; opacity: 1;
transform: translateY(-7em); transform: translateY(-7em);
} }
div.compose {
/* This will not be necessary when/if we use the content filter component. */
margin-top: 1em;
}
</style> </style>
<template>
<div class='page'>
<indie-header @followButtonPress='followModalActive = true' />