-BootstrapVue -VueAwesome

- All non-modals no longer reference Bootstrap or Font Awesome (#20)
- Removed "full request" button from journal page (#16)
- Added role attributes in many places
This commit is contained in:
Daniel J. Summers
2018-08-16 21:57:54 -05:00
parent 96f2f2f7e0
commit 5bba499251
13 changed files with 267 additions and 221 deletions

View File

@@ -1,12 +1,12 @@
<template lang="pug">
#app
#app(role='application')
navigation
#content.container
#content
router-view
vue-progress-bar
toast(ref='toast')
footer
p.text-right.text-muted
footer.mpj-text-right.mpj-muted-text
p
| myPrayerJournal v{{ version }}
br
em: small.
@@ -45,9 +45,27 @@ export default {
<style>
html, body {
background-color: whitesmoke;
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
font-size: 1rem;
}
body {
padding-top: 60px;
padding-top: 50px;
margin: 0;
}
p {
margin-bottom: 0;
}
button,
a[role="button"] {
border: solid 1px #050;
border-radius: .5rem;
background-color: whitesmoke;
}
button:hover,
a[role="button"]:hover {
background-color: #050;
color: white;
text-decoration: none;
}
footer {
border-top: solid 1px lightgray;
@@ -59,14 +77,59 @@ footer p {
}
a:link, a:visited {
color: #050;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.mpj-main-content {
max-width: 60rem;
margin: auto;
}
.mpj-main-content-wide {
margin: .5rem;
}
@media screen and (max-width: 21rem) {
.mpj-main-content-wide {
margin: 0;
}
}
.mpj-request-text {
white-space: pre-line;
}
.bg-mpj {
.mpj-request-log {
width: 100%;
}
.mpj-request-log thead th {
border-top: solid 1px lightgray;
border-bottom: solid 2px lightgray;
text-align: left;
}
.mpj-request-log tbody td {
border-bottom: dotted 1px lightgray;
vertical-align: top;
}
.mpj-bg {
background-image: -webkit-gradient(linear, left top, left bottom, from(#050), to(whitesmoke));
background-image: -webkit-linear-gradient(top, #050, whitesmoke);
background-image: -moz-linear-gradient(top, #050, whitesmoke);
background-image: linear-gradient(to bottom, #050, whitesmoke);
}
.mpj-text-center {
text-align: center;
}
.mpj-text-nowrap {
white-space: nowrap;
}
.mpj-text-right {
text-align: right;
color: rgba(0, 0, 0, .60);
}
.mpj-muted-text {
color: rgba(0, 0, 0, .60);
}
.mpj-margin {
margin-left: 1rem;
margin-right: 1rem;
}
</style>

View File

@@ -1,5 +1,5 @@
<template lang="pug">
article
article.mpj-main-content(role='main')
page-title(title='Answered Requests')
p(v-if='!loaded') Loading answered requests...
div(v-if='loaded').mpj-answered-list
@@ -9,12 +9,12 @@ article
| {{ req.text }}
br
br
b-btn(:to='{ name: "AnsweredDetail", params: { id: req.requestId }}'
size='sm'
variant='outline-secondary')
icon(name='search')
router-link(:to='{ name: "AnsweredDetail", params: { id: req.requestId }}'
role='button'
title='View Full Request')
md-icon(icon='description')
= ' View Full Request'
small.text-muted: em.
small.mpj-muted-text: em.
&nbsp; Answered #[date-from-now(:value='req.asOf')]
</template>

View File

@@ -1,16 +1,23 @@
<template lang="pug">
article
article.mpj-main-content(role='main')
page-title(title='Answered Request')
p(v-if='!request') Loading request...
template(v-if='request')
p.
Answered {{ formatDate(answered) }} (#[date-from-now(:value='answered')]) &nbsp;
#[small: em.text-muted prayed {{ prayedCount }} times, open {{ openDays }} days]
#[small: em.mpj-muted-text prayed {{ prayedCount }} times, open {{ openDays }} days]
p.mpj-request-text {{ lastText }}
b-table(small hover :fields='fields' :items='log')
template(slot='action' scope='data').
{{ data.item.status }} on #[span.text-nowrap {{ formatDate(data.item.asOf) }}]
template(slot='text' scope='data' v-if='data.item.text') {{ data.item.text.fields[0] }}
br
table.mpj-request-log
thead
tr
th Action
th Update / Notes
tbody
tr(v-for='item in log' :key='item.asOf')
td {{ item.status }} on #[span.mpj-text-nowrap {{ formatDate(item.asOf) }}]
td(v-if='item.text').mpj-request-text {{ item.text.fields[0] }}
td(v-else) &nbsp;
p(v-else) Loading request...
</template>
<script>
@@ -32,11 +39,7 @@ export default {
},
data () {
return {
request: null,
fields: [
{ key: 'action', label: 'Action' },
{ key: 'text', label: 'Update / Notes' }
]
request: null
}
},
computed: {

View File

@@ -1,5 +1,5 @@
<template lang="pug">
article
article.mpj-main-content(role='main')
page-title(title='Welcome!'
hideOnPage='true')
p &nbsp;

View File

@@ -1,11 +1,11 @@
<template lang="pug">
article
article.mpj-main-content-wide(role='main')
page-title(:title='title')
p(v-if='isLoadingJournal') Loading your prayer journal...
template(v-if='!isLoadingJournal')
new-request
br
b-row(v-if='journal.length > 0')
.mpj-journal(v-if='journal.length > 0')
request-card(v-for='request in journal'
:key='request.requestId'
:request='request'
@@ -67,3 +67,11 @@ export default {
}
}
</script>
<style>
.mpj-journal {
display: flex;
flex-flow: row wrap;
justify-content: center;
}
</style>

View File

@@ -1,32 +1,38 @@
<template lang="pug">
b-navbar(toggleable='sm'
type='dark'
variant='mpj'
fixed='top')
b-nav-toggle(target='nav_collapse')
b-navbar-brand(to='/')
nav.mpj-top-nav.mpj-bg(role='menubar')
router-link.title(:to="{ name: 'Home' }"
role='menuitem')
span(style='font-weight:100;') my
span(style='font-weight:600;') Prayer
span(style='font-weight:700;') Journal
b-collapse#nav_collapse(is-nav)
b-navbar-nav
b-nav-item(v-if='isAuthenticated'
to='/journal') Journal
b-nav-item(v-if='hasSnoozed'
to='/snoozed') Snoozed
b-nav-item(v-if='isAuthenticated'
to='/answered') Answered
b-nav-item(v-if='isAuthenticated'): a(@click.stop='logOff()') Log Off
b-nav-item(v-if='!isAuthenticated'): a(@click.stop='logOn()') Log On
b-nav-item(href='https://bit-badger.github.io/myPrayerJournal/'
target='_blank'
@click.stop='') Docs
router-link(v-if='isAuthenticated'
:to="{ name: 'Journal' }"
role='menuitem') Journal
router-link(v-if='hasSnoozed'
:to="{ name: 'Snoozed' }"
role='menuitem') Snoozed
router-link(v-if='isAuthenticated'
:to="{ name: 'Answered' }"
role='menuitem') Answered
a(v-if='isAuthenticated'
href='#'
role='menuitem'
@click.stop='logOff()') Log Off
a(v-if='!isAuthenticated'
href='#'
role='menuitem'
@click.stop='logOn()') Log On
a(href='https://bit-badger.github.io/myPrayerJournal/'
target='_blank'
role='menuitem'
@click.stop='') Docs
</template>
<script>
'use strict'
import { mapState } from 'vuex'
import AuthService from '@/auth/AuthService'
export default {
@@ -54,3 +60,34 @@ export default {
}
}
</script>
<style>
.mpj-top-nav {
position: fixed;
display: flex;
flex-flow: row wrap;
align-items: center;
top: 0;
left: 0;
width: 100%;
padding-left: .5rem;
min-height: 50px;
}
.mpj-top-nav a:link,
.mpj-top-nav a:visited {
text-decoration: none;
color: rgba(255, 255, 255, .75);
padding-left: 1rem;
}
.mpj-top-nav a:link.router-link-active,
.mpj-top-nav a:visited.router-link-active,
.mpj-top-nav a:hover {
color: white;
}
.mpj-top-nav .title {
font-size: 1.25rem;
color: white;
padding-left: 1.25rem;
padding-right: 1.25rem;
}
</style>

View File

@@ -1,21 +1,19 @@
<template lang="pug">
article
article.mpj-main-content(role='main')
page-title(title='Snoozed Requests')
p(v-if='!loaded') Loading journal...
div(v-if='loaded').mpj-snoozed-list
p.text-center(v-if='requests.length === 0'): em.
p.mpj-text-center(v-if='requests.length === 0'): em.
No snoozed requests found; return to #[router-link(:to='{ name: "Journal" } ') your journal]
p.mpj-snoozed-text(v-for='req in requests' :key='req.requestId')
p.mpj-request-text(v-for='req in requests' :key='req.requestId')
| {{ req.text }}
br
br
b-btn(@click='cancelSnooze(req.requestId)'
size='sm'
variant='outline-secondary')
icon(name='times')
button(@click='cancelSnooze(req.requestId)')
md-icon(icon='restore')
= ' Cancel Snooze'
small.text-muted: em.
small.mpj-muted-text: em.
&nbsp; Snooze expires #[date-from-now(:value='req.snoozedUntil')]
p(v-else) Loading journal...
</template>
<script>

View File

@@ -0,0 +1,15 @@
<template lang="pug">
i.material-icons(v-html='icon')
</template>
<script>
export default {
name: 'md-icon',
props: {
icon: {
type: String,
required: true
}
}
}
</script>

View File

@@ -1,7 +1,7 @@
<template lang="pug">
div
b-btn(@click='openDialog()' size='sm' variant='primary')
icon(name='plus')
button(@click='openDialog()')
md-icon(icon='add_box')
| &nbsp; Add a New Request
b-modal(v-model='showNewVisible'
header-bg-variant='mpj'
@@ -16,8 +16,26 @@ div
v-model='form.requestText'
:rows='10'
@blur='trimText()')
b-form-group(label='Recurrence')
| After prayer, request reappears
b-radio(v-model='form.recur.typ'
label='Immediately'
value='immediately'
checked='checked'
@click='checkRadios')
b-radio(v-model='form.recur.typ'
label='Every...'
value='other'
@click='checkRadios')
b-input(v-model='form.recur.count'
placeholder='##')
b-select(v-model='form.recur.other')
b-option(value='hours') hours
b-option(value='days') days
b-option(value='weeks') weeks
div.w-100.text-right(slot='modal-footer')
b-btn(variant='primary'
:disabled='!isValid'
@click='saveRequest()') Save
| &nbsp; &nbsp;
b-btn(variant='outline-secondary'
@@ -36,7 +54,12 @@ export default {
return {
showNewVisible: false,
form: {
requestText: ''
requestText: '',
recur: {
typ: 'immediate',
other: '',
count: ''
}
},
formLabelWidth: '120px'
}
@@ -44,6 +67,12 @@ export default {
mounted () {
this.$refs.toast.setOptions({ position: 'bottom right' })
},
computed: {
isValid () {
// TODO disallow submission if recurrence is too long
return true
}
},
methods: {
closeDialog () {
this.form.requestText = ''

View File

@@ -1,19 +1,17 @@
<template lang="pug">
b-col(v-if="!isSnoozed" md='6' lg='4')
.mpj-request-card
b-card-header.text-center.py-1.
#[b-btn(@click='markPrayed()' variant='outline-primary' title='Pray' size='sm'): icon(name='check')]
#[b-btn(@click.stop='showEdit()' variant='outline-secondary' title='Edit' size='sm'): icon(name='pencil')]
#[b-btn(@click.stop='showNotes()' variant='outline-secondary' title='Add Notes' size='sm'): icon(name='file-text-o')]
#[b-btn(@click.stop='showFull()' variant='outline-secondary' title='View Full Request' size='sm'): icon(name='search')]
#[b-btn(@click.stop='snooze()' variant='outline-secondary' title='Snooze Request' size='sm'): icon(name='clock-o')]
b-card-body.p-0
p.card-text.mpj-request-text.mb-1.px-3.pt-3
| {{ request.text }}
p.card-text.p-0.pr-1.text-right: small.text-muted: em
= '(last activity '
date-from-now(:value='request.asOf')
| )
.mpj-request-card
header.mpj-card-header.mpj-bg(role='toolbar').
#[button.pray(@click='markPrayed()' title='Pray' size='sm'): md-icon(icon='done')]
#[button(@click.stop='showEdit()' title='Edit' size='sm'): md-icon(icon='edit')]
#[button(@click.stop='showNotes()' title='Add Notes' size='sm'): md-icon(icon='comment')]
#[button(@click.stop='snooze()' title='Snooze Request' size='sm'): md-icon(icon='schedule')]
div
p.card-text.mpj-request-text
| {{ request.text }}
p.as-of.mpj-text-right: small.mpj-muted-text: em
= '(last activity '
date-from-now(:value='request.asOf')
| )
</template>
<script>
@@ -29,8 +27,8 @@ export default {
events: { required: true }
},
computed: {
isSnoozed () {
return Date.now() < this.request.snoozedUntil
shouldDisplay () {
return Date.now() >= this.request.showAfter
}
},
methods: {
@@ -63,6 +61,39 @@ export default {
.mpj-request-card {
border: solid 1px darkgray;
border-radius: 5px;
margin-bottom: 15px;
width: 20rem;
margin: .5rem;
}
@media screen and (max-width: 20rem) {
.mpj-request-card {
width: 100%;
}
}
.mpj-card-header {
display: flex;
flex-flow: row;
justify-content: center;
}
.mpj-card-header button {
background-color: rgba(255, 255, 255, .75);
border-radius: .25rem;
margin: .25rem;
border: solid #050 1px;
font-size: .8rem;
}
.mpj-card-header button:hover {
cursor: pointer;
background-color: white;
color: #050;
}
.mpj-card-header button.pray {
background-color: white;
}
.mpj-request-card .card-text {
margin-left: 1rem;
margin-right: 1rem;
}
.mpj-request-card .as-of {
margin-right: .25rem;
}
</style>

View File

@@ -1,33 +1,20 @@
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import BootstrapVue from 'bootstrap-vue'
import Icon from 'vue-awesome/components/Icon'
import VueProgressBar from 'vue-progressbar'
import VueToast from 'vue-toast'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import 'bootstrap/dist/css/bootstrap.css'
import 'vue-toast/dist/vue-toast.min.css'
// Only import the icons we need; the whole set is ~500K!
import 'vue-awesome/icons/check'
import 'vue-awesome/icons/clock-o'
import 'vue-awesome/icons/file-text-o'
import 'vue-awesome/icons/pencil'
import 'vue-awesome/icons/plus'
import 'vue-awesome/icons/search'
import 'vue-awesome/icons/times'
import App from './App'
import router from './router'
import store from './store'
import DateFromNow from './components/common/DateFromNow'
import MaterialDesignIcon from './components/common/MaterialDesignIcon'
import PageTitle from './components/common/PageTitle'
Vue.config.productionTip = false
Vue.use(BootstrapVue)
Vue.use(VueProgressBar, {
color: 'yellow',
failedColor: 'red',
@@ -39,8 +26,8 @@ Vue.use(VueProgressBar, {
}
})
Vue.component('icon', Icon)
Vue.component('date-from-now', DateFromNow)
Vue.component('md-icon', MaterialDesignIcon)
Vue.component('page-title', PageTitle)
Vue.component('toast', VueToast)