Ind.ie is now Small Technology Foundation.
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>
<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'>
<!-- Name and bio and, if signed out, the remote follow button -->
<div class='profile-information'>
<h1 class='profile-name'>{{name}}</h1>
<p class='profile-bio'>{{bio}}</p>
<button v-if='!signedIn && configured' id='follow-button' @click='followButtonPress' class='button'>Follow</button>
</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>
<script>
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: {
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 },
bio () { return this.$store.state.bio },
profileImage () { return this.$store.state.profileImage },
signedIn () { return this.$store.state.signedIn },
configured () { return this.$store.state.configured },
// Live header theming.
headerStyles () {
let styles = {
backgroundColor: this.$store.state.backgroundColour
......@@ -28,7 +99,28 @@ export default {
return styles
}
},
watch: {
$route: function () {
console.log(`Header: Route changed to ${this.$route.path}.`)
}
},
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 () {
this.$emit('followButtonPress')
}
......@@ -37,9 +129,7 @@ export default {
</script>
<style>
.profile
{
.profile {
/* Note: the background colour and image are dynamically set on the
header itself, based on the site configuration settings. */
align-items: center;
......@@ -52,8 +142,7 @@ export default {
width: 100%;
}
.profile-information
{
.profile-information {
background-color: rgba(0,0,0,0.55);
margin-top: 1em;
/* offset background against padding on profile__material */
......@@ -62,8 +151,7 @@ export default {
padding: 0.25rem 0;
}
.profile-name
{
.profile-name {
font-size: 3em;
/* numbered font weights won’t work in all browsers, will default to bold weight */
......@@ -72,14 +160,12 @@ export default {
margin: 0;
}
.profile-bio
{
.profile-bio {
margin: 0 auto 0.25em;
max-width: 42em;
}
.profile-image
{
.profile-image {
/* make image circular with a white border */
border: 0.2em solid white;
border-radius: 50%;
......@@ -93,10 +179,45 @@ export default {
width: 40%;
}
#follow-button
{
#follow-button {
position: absolute;
top: 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>
......@@ -47,8 +47,7 @@ export default {
</script>
<style>
body
{
body {
font-family: 'Helvetica Neue', 'Helvetica', sans-serif;
/* minimum font size, no fonts should be smaller than 1em */
font-size: 1em;
......@@ -57,6 +56,12 @@ body
margin: 0;
}
main {
margin-right: auto;
margin-left: auto;
max-width: 42em;
}
/* scale up font size when we reach 76 characters per line */
@media only screen and (min-width: 35em) {
body
......@@ -79,92 +84,76 @@ Typography for all “content” (which is mirrored inside editor)
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-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;
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;
}
h2, .ql-editor h2, .ql-snow .ql-editor h2
{
h2, .ql-editor h2, .ql-snow .ql-editor h2 {
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;
}
h4, .ql-editor h4, .ql-snow .ql-editor h4
{
h4, .ql-editor h4, .ql-snow .ql-editor h4 {
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;
}
h6, .ql-editor h6, .ql-snow .ql-editor h6
{
h6, .ql-editor h6, .ql-snow .ql-editor h6 {
font-size: 1.1em;
}
p, ul, ol, blockquote, 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;
}
ul, 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;
}
li,
.ql-editor li,
.ql-snow .ql-editor li
{
.ql-snow .ql-editor li {
margin-bottom: 0.25em;
}
/* space created by ql-editor for bullet/number */
.ql-editor li::before
{
.ql-editor li::before {
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;
}
.ql-editor li.ql-indent-1:not(.ql-direction-rtl)
{
.ql-editor li.ql-indent-1:not(.ql-direction-rtl) {
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;
}
.ql-editor li.ql-indent-3:not(.ql-direction-rtl)
{
.ql-editor li.ql-indent-3:not(.ql-direction-rtl) {
padding-left: 4.5rem;
}
/* placeholder message inside editor */
.ql-editor.ql-blank::before
{
.ql-editor.ql-blank::before {
margin-top: 1em;
}
......@@ -178,8 +167,7 @@ BULMA-OVERRIDING STYLES
Buttons
- - - - - - - - - - - - */
.button
{
.button {
/* override Bulma default that prevents font scaling */
font-size: 1em;
}
......@@ -188,8 +176,7 @@ Buttons
Controls
- - - - - - - - - - - - */
.control
{
.control {
/* override Bulma default that prevents font scaling */
font-size: 1em;
}
......@@ -207,8 +194,7 @@ Tabs
Form inputs
- - - - - - - - - - - - */
.input, .taginput .taginput-container.is-focusable, .textarea
{
.input, .taginput .taginput-container.is-focusable, .textarea {
/* override Bulma default that prevents font scaling */
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 @@
<!-- Site header -->
<indie-header @followButtonPress='followModalActive = true' />
<!-- Main tabs with currently hard-coded content. -->
<b-tabs v-model='activeTab' position='is-centered' class='block'>
<b-tab-item label='Me' :disabled='!configured'>
<!-- <content-type-filter /> -->
<textComposer ref='textComposer' @composerChange='composerChange' @post='post' v-show='signedIn'/>
<pre style='word-break: break-word;' v-show='signedIn && debug'>{{ composerContent }}</pre>
<transition-group name='list' tag='div' @enter='clearTextComposer'>
<div v-for='post in posts' :key='post.id'>
<!-- <span>ID: {{post.id}}</span> -->
<span v-html='post.content'></span>
</div>
</transition-group>
</b-tab-item>
<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>
<!-- <content-type-filter /> -->
<!-- Main page content -->
<main>
<textComposer ref='textComposer' @composerChange='composerChange' @post='post' v-show='signedIn'/>
<pre style='word-break: break-word;' v-show='signedIn && debug'>{{ composerContent }}</pre>
<transition-group name='list' tag='div' @enter='clearTextComposer'>
<div v-for='post in posts' :key='post.id'>
<!-- <span>ID: {{post.id}}</span> -->
<span v-html='post.content'></span>
</div>
</transition-group>
</main>
<!-- 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="Settings" v-show='signedIn || !configured'><settings /></b-tab-item>
<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-tab-item>
</b-tabs>
</b-tab-item> -->
<!-- Follow modal -->
<!-- Follow modal: TODO move to header -->
<follow-modal :isActive='followModalActive' @close='followModalActive = false' />
</div>
</template>
......@@ -36,8 +37,7 @@ import 'font-awesome/css/font-awesome.min.css'
import indieHeader from '~/components/indieHeader'
import followModal from '~/components/followModal'
import contentTypeFilter from '~/components/contentTypeFilter'
import settings from '~/components/settings'
import search from '~/components/search'
import textComposer from '~/components/textComposer'
const Tabs = Object.freeze({
......@@ -53,8 +53,6 @@ export default {
indieHeader,
followModal,
contentTypeFilter,
settings,
search,
textComposer
},
......@@ -112,32 +110,6 @@ export default {
</script>
<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 {
transition: all 1s;
}
......@@ -145,9 +117,4 @@ nav.tabs
opacity: 1;
transform: translateY(-7em);
}
div.compose {
/* This will not be necessary when/if we use the content filter component. */
margin-top: 1em;
}
</style>
<template>
<div class='page'>
<indie-header @followButtonPress='followModalActive = true' />
<main>
<b-message type='is-info' has-icon>
<strong>Nothing yet.</strong> Additional features will be listed here.
</b-message>
</main>
</div>
</template>
<script>
import indieHeader from '~/components/indieHeader'
export default {
components: {
indieHeader
}
}
</script>
<style>
</style>
<template>
<div class='page's>
<indie-header @followButtonPress='followModalActive = true' />
<main>
<search />
</main>
</div>
</template>
<script>
import indieHeader from '~/components/indieHeader'
import search from '~/components/search'
export default {
components: {
indieHeader,
search
}
}
</script>
<style>
</style>
<template>
<div class='page'>
<indie-header @followButtonPress='followModalActive = true' />
<main>
<settings />
</main>
</div>
</template>
<script>
import indieHeader from '~/components/indieHeader'
import settings from '~/components/settings'
export default {
components: {
indieHeader,
settings
}
}
</script>
<style>
</style>
......@@ -3,7 +3,7 @@
const siteConfiguration = require('../assets/data.json')
// Mock: sign-in state
siteConfiguration.signedIn = false
siteConfiguration.signedIn = true
siteConfiguration.configured = false
export const state = () => (siteConfiguration)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment