Updated compose; added smooth transitions

This commit is contained in:
Dan Elbert 2019-11-10 10:40:26 -06:00
parent eeb8e84344
commit ccb87d7019
14 changed files with 215 additions and 118 deletions

View File

@ -8,7 +8,7 @@ gem 'bootsnap', '>= 1.1.0', require: false
gem 'jbuilder', '~> 2.9'
gem 'oj', '~> 3.9.1'
gem 'oj', '~> 3.9.2'
gem 'kaminari', '~> 1.1.1'
gem 'unitwise', '~> 2.2.0'
@ -23,7 +23,7 @@ gem 'tzinfo-data'
group :development, :test do
gem 'puma', '~> 4.1.1'
gem 'puma', '~> 4.3.0'
gem 'sqlite3', '~> 1.4.1'
gem 'guard', '~> 2.15.0'

View File

@ -49,11 +49,11 @@ GEM
builder (3.2.3)
coderay (1.1.2)
concurrent-ruby (1.1.5)
crass (1.0.4)
crass (1.0.5)
dalli (2.7.10)
database_cleaner (1.7.0)
diff-lcs (1.3)
erubi (1.8.0)
erubi (1.9.0)
factory_bot (5.0.2)
activesupport (>= 4.2.0)
factory_bot_rails (5.0.2)
@ -77,7 +77,7 @@ GEM
guard (~> 2.1)
guard-compat (~> 1.1)
rspec (>= 2.99.0, < 4.0)
i18n (1.6.0)
i18n (1.7.0)
concurrent-ruby (~> 1.0)
jbuilder (2.9.1)
activesupport (>= 4.2.0)
@ -94,11 +94,10 @@ GEM
kaminari-core (= 1.1.1)
kaminari-core (1.1.1)
liner (0.2.4)
listen (3.1.5)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
ruby_dep (~> 1.2)
loofah (2.2.3)
listen (3.2.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
loofah (2.3.1)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
lumberjack (1.0.13)
@ -112,22 +111,22 @@ GEM
mimemagic (0.3.3)
mini_mime (1.0.2)
mini_portile2 (2.4.0)
minitest (5.11.3)
minitest (5.13.0)
msgpack (1.3.1)
nenv (0.3.0)
nio4r (2.5.1)
nokogiri (1.10.4)
nio4r (2.5.2)
nokogiri (1.10.5)
mini_portile2 (~> 2.4.0)
notiffany (0.1.3)
nenv (~> 0.1)
shellany (~> 0.0)
oj (3.9.1)
oj (3.9.2)
parslet (1.8.2)
pg (1.1.4)
pry (0.12.2)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
puma (4.1.1)
puma (4.3.0)
nio4r (~> 2.0)
rack (2.0.7)
rack-proxy (0.6.5)
@ -154,15 +153,15 @@ GEM
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.2.0)
loofah (~> 2.2, >= 2.2.2)
rails-html-sanitizer (1.3.0)
loofah (~> 2.3)
railties (5.2.3)
actionpack (= 5.2.3)
activesupport (= 5.2.3)
method_source
rake (>= 0.8.7)
thor (>= 0.19.0, < 2.0)
rake (12.3.3)
rake (13.0.0)
rb-fsevent (0.10.3)
rb-inotify (0.10.0)
ffi (~> 1.0)
@ -173,13 +172,13 @@ GEM
rspec-mocks (~> 3.8.0)
rspec-core (3.8.2)
rspec-support (~> 3.8.0)
rspec-expectations (3.8.4)
rspec-expectations (3.8.6)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-mocks (3.8.1)
rspec-mocks (3.8.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-rails (3.8.2)
rspec-rails (3.8.3)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
@ -187,11 +186,10 @@ GEM
rspec-expectations (~> 3.8.0)
rspec-mocks (~> 3.8.0)
rspec-support (~> 3.8.0)
rspec-support (3.8.2)
ruby_dep (1.5.0)
rspec-support (3.8.3)
shellany (0.0.1)
signed_multiset (0.2.1)
sprockets (3.7.2)
sprockets (4.0.0)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.2.1)
@ -231,9 +229,9 @@ DEPENDENCIES
guard-rspec
jbuilder (~> 2.9)
kaminari (~> 1.1.1)
oj (~> 3.9.1)
oj (~> 3.9.2)
pg (~> 1.1.4)
puma (~> 4.1.1)
puma (~> 4.3.0)
rails (= 5.2.3)
rails-controller-testing
redcarpet (~> 3.5.0)

View File

@ -1,14 +1,16 @@
<template>
<div>
<div id="app">
<vue-progress-bar></vue-progress-bar>
<app-navbar></app-navbar>
<section id="app" class="">
<section id="main" class="">
<div class="container">
<transition name="fade" mode="out-in">
<router-view v-if="!hasError"></router-view>
<div v-else>
<h1>Error!</h1>
<p>{{error}}</p>
</div>
</transition>
</div>
</section>
</div>
@ -30,7 +32,8 @@
...mapState({
hasError: state => state.error !== null,
error: state => state.error,
authChecked: state => state.authChecked
authChecked: state => state.authChecked,
initialLoad: state => state.initialLoad
})
},
@ -41,6 +44,14 @@
} else {
this.$Progress.finish();
}
},
initialLoad(val) {
if (val) {
this.$nextTick(() => {
document.body.classList.remove("loading");
});
}
}
},
@ -57,6 +68,14 @@
}
},
mounted() {
if (this.initialLoad) {
this.$nextTick(() => {
document.body.classList.remove("loading");
});
}
},
components: {
}
}

View File

@ -0,0 +1,20 @@
<template>
<div class="app-loading">
Imagine I'm a spinner...
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
.app-loading {
position: absolute;
display: none;
}
</style>

View File

@ -1,5 +1,5 @@
<template>
<nav v-show="totalPages > 1" class="pagination" role="navigation" :aria-label="pagedItemName + ' page navigation'">
<nav v-show="totalPages > 1 || showWithSinglePage" class="pagination" role="navigation" :aria-label="pagedItemName + ' page navigation'">
<a class="pagination-previous" :title="isFirstPage ? 'This is the first page' : ''" :disabled="isFirstPage" @click.prevent="changePage(currentPage - 1)">Previous</a>
<a class="pagination-next" :title="isLastPage ? 'This is the last page' : ''" :disabled="isLastPage" @click.prevent="changePage(currentPage + 1)">Next page</a>
<ul class="pagination-list">
@ -41,6 +41,12 @@
required: false,
type: Number,
default: 1
},
showWithSinglePage: {
required: false,
type: Boolean,
default: true
}
},

View File

@ -28,7 +28,7 @@
<th colspan="4"></th>
</tr>
</thead>
<tbody>
<transition-group tag="tbody" name="fade" mode="out-in">
<tr v-for="i in foods" :key="i.id">
<td><router-link :to="{name: 'food', params: { id: i.id } }">{{i.name}}</router-link></td>
<td><app-icon v-if="i.usda" icon="check"></app-icon></td>
@ -43,7 +43,7 @@
</button>
</td>
</tr>
</tbody>
</transition-group>
</table>
<app-pager :current-page="currentPage" :total-pages="totalPages" paged-item-name="food" @changePage="changePage"></app-pager>

View File

@ -6,6 +6,11 @@
<app-pager :current-page="currentPage" :total-pages="totalPages" paged-item-name="recipe" @changePage="changePage"></app-pager>
<app-loading v-if="localLoading"></app-loading>
<table class="table is-fullwidth" :class="{ small: mediaQueries.touch }">
<thead>
<tr>
@ -36,7 +41,7 @@
<td colspan="5"></td>
</tr>
</thead>
<tbody>
<transition-group name="fade" tag="tbody">
<tr v-for="r in recipes" :key="r.id">
<td><router-link :to="{name: 'recipe', params: { id: r.id } }">{{r.name}}</router-link></td>
<td>
@ -78,11 +83,10 @@
</app-dropdown>
</td>
</tr>
</tbody>
</transition-group>
</table>
<app-pager :current-page="currentPage" :total-pages="totalPages" paged-item-name="recipe" @changePage="changePage"></app-pager>
<app-confirm :open="showConfirmRecipeDelete" :message="confirmRecipeDeleteMessage" :cancel="recipeDeleteCancel" :confirm="recipeDeleteConfirm"></app-confirm>
</div>
@ -92,7 +96,8 @@
import api from "../lib/Api";
import debounce from "lodash/debounce";
import { mapState } from "vuex";
import { mapMutations, mapState } from "vuex";
import AppLoading from "./AppLoading";
export default {
data() {
@ -161,6 +166,10 @@
},
methods: {
...mapMutations([
"setInitialLoad"
]),
changePage(idx) {
this.search.page = idx;
},
@ -220,7 +229,7 @@
created() {
this.$watch("search",
() => this.getList(),
() => this.getList().then(() => this.setInitialLoad(true)),
{
deep: true,
immediate: true
@ -229,6 +238,7 @@
},
components: {
AppLoading
}
}

View File

@ -80,4 +80,5 @@ document.addEventListener('DOMContentLoaded', () => {
},
components: { App }
});
});

View File

@ -28,12 +28,20 @@ import TheUserEditor from './components/TheUserEditor';
import TheAdminUserList from './components/TheAdminUserList';
import TheAdminUserEditor from './components/TheAdminUserEditor';
import $store from './store';
Vue.use(Router);
const router = new Router({
routes: []
});
router.afterEach((to, from) => {
if (to.meta.handleInitialLoad !== true && $store.state.initialLoad === false) {
$store.commit("setInitialLoad", true);
}
});
router.addRoutes(
[
{
@ -43,7 +51,10 @@ router.addRoutes(
{
path: '/recipes',
name: 'recipeList',
component: TheRecipeList
component: TheRecipeList,
meta: {
handleInitialLoad: true
}
},
{
path: '/recipes/new',

View File

@ -8,6 +8,7 @@ Vue.use(Vuex);
export default new Vuex.Store({
strict: process.env.NODE_ENV !== 'production',
state: {
initialLoad: false,
updateAvailable: false,
loadingCount: 0,
error: null,
@ -76,6 +77,10 @@ export default new Vuex.Store({
state.updateAvailable = value;
},
setInitialLoad(state, value) {
state.initialLoad = value;
},
setLoading(state, value) {
if (value) {
state.loadingCount = state.loadingCount + 1;

View File

@ -1,11 +1,22 @@
.fade-enter-active, .fade-leave-active {
transition: opacity .5s, max-height .5s;
max-height: 300px;
//max-height: 300px;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0;
max-height: 0;
//max-height: 0;
}
.fade-leave-active {
transition: all 0.125s;
}
.fade-enter-active {
transition: all 0.75s;
}
.fade-move {
//transition: transform 1s;
}

View File

@ -32,7 +32,7 @@ body {
padding-bottom: 2rem;
}
#app {
#main {
padding-top: 1rem;
.container {

View File

@ -7,7 +7,7 @@
<meta name ="theme-color" content="#79A736">
<link rel="manifest" href="/manifest.json">
<!-- generics -->
<%# generics %>
<link rel="icon" href="/logo_32.png" sizes="32x32">
<link rel="icon" href="/logo_57.png" sizes="57x57">
<link rel="icon" href="/logo_76.png" sizes="76x76">
@ -16,27 +16,43 @@
<link rel="icon" href="/logo_192.png" sizes="192x192">
<link rel="icon" href="/logo_228.png" sizes="228x228">
<!-- Android -->
<%# Android %>
<link rel="shortcut icon" sizes="196x196" href="/logo_196.png">
<!-- iOS -->
<%# iOS %>
<link rel="apple-touch-icon" href="/logo_120.png" sizes="120x120">
<link rel="apple-touch-icon" href="/logo_152.png" sizes="152x152">
<link rel="apple-touch-icon" href="/logo_180.png" sizes="180x180">
<!-- Windows 8 IE 10-->
<%# Windows 8 IE 10 %>
<meta name="msapplication-TileColor" content="#4a4a4a">
<meta name="msapplication-TileImage" content="/logo_144.png">
<!— Windows 8.1 + IE11 and above —>
<%# Windows 8.1 + IE11 and above %>
<meta name="msapplication-config" content="/browserconfig.xml" />
<title>Parsley</title>
<style type="text/css">
body.loading {
background-color: #79A736;
}
#app {
transition: opacity 0.5s ease-in;
}
body.loading #app {
opacity: 0;
}
</style>
<%= stylesheet_pack_tag 'application' %>
</head>
<body>
<body class="loading">
<div id="app" data-url="<%= root_url %>">
<div id="app-placeholder">

View File

@ -42,8 +42,8 @@ self.addEventListener('fetch', function(event) {
var isCacheThenNetwork = event.request.headers.get("Cache-Then-Network") === "true";
var x, asset;
// Any non-GET or non-http(s) request should be ignored
if (event.request.method !== 'GET' || event.request.url.indexOf('http') !== 0) {
// Any non-GET or non-http(s) or dev server request should be ignored
if (event.request.method !== 'GET' || event.request.url.indexOf('http') !== 0 || reqUrl.pathname.indexOf("/sockjs-node") === 0) {
return;
}