updates
This commit is contained in:
parent
0c4c5b899b
commit
532c9372ea
@ -16,20 +16,43 @@ class CalculatorController < ApplicationController
|
||||
ingredient = Ingredient.find_by_ingredient_id(ingredient_id)
|
||||
end
|
||||
|
||||
data = {errors: [], output: ''}
|
||||
data = {errors: Hash.new { |h, k| h[k] = [] }, output: ''}
|
||||
|
||||
begin
|
||||
UnitConversion::with_custom_units(ingredient ? ingredient.custom_units : []) do
|
||||
unit = UnitConversion.parse(input)
|
||||
if output_unit.present?
|
||||
unit = unit.convert(output_unit, density)
|
||||
data[:output] = unit.to_s
|
||||
else
|
||||
data[:output] = unit.auto_unit.to_s
|
||||
density_unit = nil
|
||||
begin
|
||||
if density
|
||||
density_unit = UnitConversion.parse(density)
|
||||
unless density_unit.density?
|
||||
data[:errors][:density] << 'not a density unit'
|
||||
density_unit = nil
|
||||
end
|
||||
end
|
||||
rescue UnitConversion::UnparseableUnitError => e
|
||||
data[:errors] << e.message
|
||||
data[:errors][:density] << 'invalid string'
|
||||
end
|
||||
|
||||
begin
|
||||
input_unit = UnitConversion.parse(input)
|
||||
rescue UnitConversion::UnparseableUnitError => e
|
||||
data[:errors][:input] << 'invalid string'
|
||||
end
|
||||
|
||||
if !input_unit.nil?
|
||||
if output_unit.present?
|
||||
begin
|
||||
input_unit = input_unit.convert(output_unit, density_unit)
|
||||
rescue UnitConversion::UnparseableUnitError => e
|
||||
data[:errors][:output_unit] << e.message
|
||||
end
|
||||
else
|
||||
input_unit = input_unit.auto_unit
|
||||
end
|
||||
end
|
||||
|
||||
if data[:errors].empty?
|
||||
data[:output] = input_unit.to_s
|
||||
end
|
||||
end
|
||||
|
||||
render json: data
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
import { mapMutations, mapState } from "vuex";
|
||||
import api from "../lib/Api";
|
||||
import TWEEN from '@tweenjs/tween.js';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@ -44,9 +45,15 @@
|
||||
},
|
||||
|
||||
created() {
|
||||
// Setup global animation loop
|
||||
function animate () {
|
||||
TWEEN.update();
|
||||
requestAnimationFrame(animate);
|
||||
}
|
||||
animate();
|
||||
|
||||
if (this.user === null && this.authChecked === false) {
|
||||
this.checkAuthentication();
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1,55 +1,98 @@
|
||||
<template>
|
||||
<transition
|
||||
name="expand"
|
||||
:duration="500"
|
||||
@enter="enter"
|
||||
@after-enter="afterEnter"
|
||||
@leave="leave">
|
||||
@leave="leave"
|
||||
@enter-cancel="cancel"
|
||||
@leave-cancel="cancel">
|
||||
<slot></slot>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import TWEEN from '@tweenjs/tween.js';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
expandTime: {
|
||||
type: Number,
|
||||
default: 250
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
animation: null
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
cancel () {
|
||||
if (this.animation) {
|
||||
this.animation.stop();
|
||||
this.animation = null;
|
||||
}
|
||||
},
|
||||
|
||||
enter(element, done) {
|
||||
const width = getComputedStyle(element).width;
|
||||
const width = parseInt(getComputedStyle(element).width);
|
||||
const paddingTop = parseInt(getComputedStyle(element).paddingTop);
|
||||
const paddingBottom = parseInt(getComputedStyle(element).paddingBottom);
|
||||
|
||||
element.style.width = width;
|
||||
element.style.position = 'absolute';
|
||||
element.style.visibility = 'hidden';
|
||||
element.style.height = 'auto';
|
||||
|
||||
const height = getComputedStyle(element).height;
|
||||
const height = parseInt(getComputedStyle(element).height);
|
||||
|
||||
element.style.width = null;
|
||||
element.style.position = null;
|
||||
element.style.visibility = null;
|
||||
element.style.overflow = 'hidden';
|
||||
element.style.height = 0;
|
||||
|
||||
// Trigger the animation.
|
||||
// We use `setTimeout` because we need
|
||||
// to make sure the browser has finished
|
||||
// painting after setting the `height`
|
||||
// to `0` in the line above.
|
||||
this.animation = new TWEEN.Tween({height: 0, paddingTop: 0, paddingBottom: 0})
|
||||
.to({height: height, paddingTop: paddingTop, paddingBottom: paddingBottom}, this.expandTime)
|
||||
.onUpdate(obj => {
|
||||
element.style.height = obj.height + "px";
|
||||
element.style.paddingBottom = obj.paddingBottom + "px";
|
||||
element.style.paddingTop = obj.paddingTop + "px";
|
||||
})
|
||||
.onComplete(() => {
|
||||
this.animation = null;
|
||||
element.removeAttribute('style');
|
||||
element.style.opacity = 0.99;
|
||||
setTimeout(() => {
|
||||
element.style.height = height;
|
||||
});
|
||||
},
|
||||
|
||||
afterEnter(element) {
|
||||
element.style.height = 'auto';
|
||||
// Fixes odd drawing bug in Chrome
|
||||
element.style.opacity = 1.0;
|
||||
}, 1000);
|
||||
done();
|
||||
})
|
||||
.start();
|
||||
},
|
||||
|
||||
leave(element, done) {
|
||||
const height = getComputedStyle(element).height;
|
||||
const height = parseInt(getComputedStyle(element).height);
|
||||
const paddingTop = parseInt(getComputedStyle(element).paddingTop);
|
||||
const paddingBottom = parseInt(getComputedStyle(element).paddingBottom);
|
||||
|
||||
element.style.height = height;
|
||||
element.style.overflow = 'hidden';
|
||||
|
||||
setTimeout(() => {
|
||||
element.style.height = 0;
|
||||
});
|
||||
this.animation = new TWEEN.Tween({height: height, paddingTop: paddingTop, paddingBottom: paddingBottom})
|
||||
.to({height: 0, paddingTop: 0, paddingBottom: 0}, this.expandTime)
|
||||
.onUpdate(obj => {
|
||||
element.style.height = obj.height + "px";
|
||||
element.style.paddingBottom = obj.paddingBottom + "px";
|
||||
element.style.paddingTop = obj.paddingTop + "px";
|
||||
})
|
||||
.onComplete(() => {
|
||||
this.animation = null;
|
||||
element.removeAttribute('style');
|
||||
done();
|
||||
})
|
||||
.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,7 @@
|
||||
person: new IconData('person'),
|
||||
star: new IconData('star'),
|
||||
'star-empty': new IconData('star-empty'),
|
||||
warning: new IconData('warning'),
|
||||
x: new IconData('x')
|
||||
};
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
import Pencil from "../iconic/svg/smart/pencil";
|
||||
import Star from "../iconic/svg/smart/star";
|
||||
import StarEmpty from "../iconic/svg/smart/star-empty";
|
||||
import Warning from "../iconic/svg/smart/warning";
|
||||
import X from "../iconic/svg/smart/x";
|
||||
|
||||
const APIS = {};
|
||||
@ -36,6 +37,7 @@
|
||||
person: Person,
|
||||
star: Star,
|
||||
'star-empty': StarEmpty,
|
||||
warning: Warning,
|
||||
x: X
|
||||
};
|
||||
|
||||
|
@ -1,10 +1,14 @@
|
||||
<template>
|
||||
<div class="field">
|
||||
<label v-if="label.length" class="label is-small-mobile">{{ label }}</label>
|
||||
<div class="control">
|
||||
<textarea v-if="isTextarea" class="textarea is-small-mobile" :value="value" @input="input"></textarea>
|
||||
<input v-else :type="type" class="input is-small-mobile" :value="value" @input="input">
|
||||
<div :class="controlClasses">
|
||||
<textarea v-if="isTextarea" :class="inputClasses" :value="value" @input="input" :disabled="disabled"></textarea>
|
||||
<input v-else :type="type" :class="inputClasses" :value="value" @input="input" :disabled="disabled">
|
||||
<app-icon class="is-right" icon="warning" v-if="validationError !== null"></app-icon>
|
||||
</div>
|
||||
<p v-if="helpMessage !== null" :class="helpClasses">
|
||||
{{ helpMessage }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -26,12 +30,54 @@
|
||||
required: false,
|
||||
type: String,
|
||||
default: "text"
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
validationError: {
|
||||
required: false,
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
isTextarea() {
|
||||
return this.type === "textarea";
|
||||
},
|
||||
|
||||
controlClasses() {
|
||||
return [
|
||||
"control",
|
||||
{
|
||||
"has-icons-right": this.validationError !== null
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
inputClasses() {
|
||||
return [
|
||||
"is-small-mobile",
|
||||
{
|
||||
"textarea": this.isTextarea,
|
||||
"input": !this.isTextarea,
|
||||
"is-danger": this.validationError !== null
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
helpMessage() {
|
||||
return this.validationError;
|
||||
},
|
||||
|
||||
helpClasses() {
|
||||
return [
|
||||
"help",
|
||||
{
|
||||
"is-danger": this.validationError !== null
|
||||
}
|
||||
];
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1,6 +1,10 @@
|
||||
<template>
|
||||
<div>
|
||||
<h3 class="title">
|
||||
{{food.name}}
|
||||
</h3>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -1,21 +1,21 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="columns task-item-edit">
|
||||
|
||||
<div class="field">
|
||||
<div class="field column">
|
||||
<label class="label is-small">Name</label>
|
||||
<div class="control">
|
||||
<input class="input is-small" type="text" placeholder="Name" v-model="taskItem.name" @keydown="inputKeydown" ref="nameInput">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="field column">
|
||||
<label class="label is-small">Quantity</label>
|
||||
<div class="control">
|
||||
<input class="input is-small" type="text" placeholder="Qty" v-model="taskItem.quantity" @keydown="inputKeydown">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="field column">
|
||||
<div class="control">
|
||||
<button class="button is-primary" @click="save">Add</button>
|
||||
</div>
|
||||
@ -61,4 +61,8 @@
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.task-item-edit {
|
||||
|
||||
}
|
||||
|
||||
</style>
|
@ -1,43 +1,61 @@
|
||||
<template>
|
||||
<div>
|
||||
|
||||
<app-expand-transition name="fade">
|
||||
<task-item-edit @save="save" :task-item="newItem" v-if="showAddItem" ref="itemEdit"></task-item-edit>
|
||||
<div class="panel">
|
||||
<p class="panel-heading">
|
||||
{{taskList.name}} ({{completedItemCount}} / {{taskList.task_items.length}})
|
||||
</p>
|
||||
|
||||
<div class="panel-block">
|
||||
<button class="button is-fullwidth is-primary" @click="toggleShowAddItem">{{ showAddItem ? 'Done' : 'New Item' }}</button>
|
||||
</div>
|
||||
|
||||
<app-expand-transition>
|
||||
<div class="panel-block" v-if="showAddItem">
|
||||
<task-item-edit @save="save" :task-item="newItem" ref="itemEdit"></task-item-edit>
|
||||
</div>
|
||||
</app-expand-transition>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Name</th>
|
||||
<th>Quantity</th>
|
||||
<th>
|
||||
<button class="button" @click="toggleShowAddItem">{{ showAddItem ? 'Done' : 'New Item' }}</button>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<transition-group tag="tbody" name="list-item-move">
|
||||
<tr v-for="i in taskItems" :key="i.id" @click="toggleItem(i)">
|
||||
<td>
|
||||
<transition-group tag="div" name="list-item-move">
|
||||
<a v-for="i in taskItems" :key="i.id" @click="toggleItem(i)" class="panel-block">
|
||||
<div class="check">
|
||||
<app-icon v-if="i.completed" icon="check"></app-icon>
|
||||
<span class="icon" v-else></span>
|
||||
</div>
|
||||
</td>
|
||||
<td>{{ i.name }}</td>
|
||||
<td>{{ i.quantity }}</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<span>{{ i.quantity }} {{ i.name }}</span>
|
||||
</a>
|
||||
</transition-group>
|
||||
<tbody v-if="taskItems.length === 0">
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
No Items
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<app-expand-transition>
|
||||
<div class="panel-block" v-if="uncompletedItemCount > 0">
|
||||
<button class="button is-fullwidth is-link" @click="completeAllItems">
|
||||
<span class="check">
|
||||
<app-icon icon="check"></app-icon>
|
||||
</span>
|
||||
<span>Check All</span>
|
||||
</button>
|
||||
</div>
|
||||
</app-expand-transition>
|
||||
<app-expand-transition>
|
||||
<div class="panel-block" v-if="completedItemCount > 0">
|
||||
<button class="button is-fullwidth is-link" @click="unCompleteAllItems">
|
||||
<span class="check">
|
||||
<span class="icon"></span>
|
||||
</span>
|
||||
<span>Uncheck All</span>
|
||||
</button>
|
||||
</div>
|
||||
</app-expand-transition>
|
||||
<app-expand-transition>
|
||||
<div class="panel-block" v-if="completedItemCount > 0">
|
||||
<button class="button is-fullwidth is-link" @click="deleteCompletedItems">
|
||||
<app-icon icon="x" class="is-text-danger"></app-icon>
|
||||
<span>Clear Completed</span>
|
||||
</button>
|
||||
</div>
|
||||
</app-expand-transition>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
@ -76,6 +94,13 @@
|
||||
},
|
||||
|
||||
computed: {
|
||||
completedItemCount() {
|
||||
return this.taskList === null ? 0 : this.taskList.task_items.filter(i => i.completed).length;
|
||||
},
|
||||
|
||||
uncompletedItemCount() {
|
||||
return this.taskList === null ? 0 : this.taskList.task_items.filter(i => !i.completed).length;
|
||||
},
|
||||
completedTaskItems() {
|
||||
return (this.taskList ? this.taskList.task_items : []).filter(i => i.completed);
|
||||
},
|
||||
@ -93,6 +118,7 @@
|
||||
...mapActions([
|
||||
'createTaskItem',
|
||||
'updateTaskItem',
|
||||
'deleteTaskItems',
|
||||
'completeTaskItems'
|
||||
]),
|
||||
|
||||
@ -120,7 +146,38 @@
|
||||
toggleShowAddItem() {
|
||||
this.newItem = newItemTemplate(this.taskList.id);
|
||||
this.showAddItem = !this.showAddItem;
|
||||
}
|
||||
},
|
||||
|
||||
completeAllItems() {
|
||||
const toComplete = this.taskList.task_items.filter(i => !i.completed);
|
||||
this.loadResource(
|
||||
this.completeTaskItems({
|
||||
taskList: this.taskList,
|
||||
taskItems: toComplete,
|
||||
completed: true
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
unCompleteAllItems() {
|
||||
const toUnComplete = this.taskList.task_items.filter(i => i.completed);
|
||||
this.loadResource(
|
||||
this.completeTaskItems({
|
||||
taskList: this.taskList,
|
||||
taskItems: toUnComplete,
|
||||
completed: false
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
deleteCompletedItems() {
|
||||
this.loadResource(
|
||||
this.deleteTaskItems({
|
||||
taskList: this.taskList,
|
||||
taskItems: this.taskList.task_items.filter(i => i.completed)
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
@ -147,9 +204,22 @@
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.check {
|
||||
border: 2px solid $link;
|
||||
display: flex;
|
||||
.check {
|
||||
display: inline-flex;
|
||||
margin-right: 1.5rem;
|
||||
|
||||
.icon {
|
||||
position: relative;
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
left: -3px;
|
||||
bottom: -3px;
|
||||
right: -3px;
|
||||
border: 2px solid currentColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
@ -2,23 +2,11 @@
|
||||
<div>
|
||||
<h1 class="title">Calculator</h1>
|
||||
|
||||
<div v-for="err in errors" :key="err" class="notification is-warning">
|
||||
{{err}}
|
||||
</div>
|
||||
<div class="box">
|
||||
|
||||
<div class="columns">
|
||||
<div class="field column">
|
||||
<label class="label">Input</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" placeholder="input" v-model="input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field column">
|
||||
<label class="label">Output Unit</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" placeholder="unit" v-model="outputUnit">
|
||||
</div>
|
||||
</div>
|
||||
<app-text-field label="Input" v-model="input" class="column" :validation-error="inputErrors"></app-text-field>
|
||||
<app-text-field label="Output Unit" v-model="outputUnit" class="column" :validation-error="outputUnitErrors"></app-text-field>
|
||||
|
||||
</div>
|
||||
|
||||
@ -41,20 +29,14 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field column">
|
||||
<label class="label">Density</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" placeholder="8.345 lb/gallon" v-model="density" :disabled="ingredient !== null">
|
||||
</div>
|
||||
</div>
|
||||
<app-text-field label="Density" v-model="density" class="column" :disabled="ingredient !== null" :validation-error="densityErrors"></app-text-field>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="label">Output</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" disabled="disabled" v-model="output">
|
||||
</div>
|
||||
<app-text-field label="Output" v-model="output" disabled></app-text-field>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -72,10 +54,36 @@
|
||||
ingredient: null,
|
||||
density: '',
|
||||
output: '',
|
||||
errors: []
|
||||
errors: {}
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
inputErrors() {
|
||||
if (this.errors.input && this.errors.input.length > 0) {
|
||||
return this.errors.input.join(", ");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
outputUnitErrors() {
|
||||
if (this.errors.output_unit && this.errors.output_unit.length > 0) {
|
||||
return this.errors.output_unit.join(", ");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
densityErrors() {
|
||||
if (this.errors.density && this.errors.density.length > 0) {
|
||||
return this.errors.density.join(", ");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
updateSearchItems(text) {
|
||||
return api.getSearchIngredients(text);
|
||||
@ -88,12 +96,14 @@
|
||||
},
|
||||
|
||||
updateOutput: debounce(function() {
|
||||
if (this.input && this.input.length > 0) {
|
||||
this.loadResource(api.getCalculate(this.input, this.outputUnit, this.ingredient ? this.ingredient.ingredient_id : null, this.density)
|
||||
.then(data => {
|
||||
this.output = data.output;
|
||||
this.errors = data.errors;
|
||||
})
|
||||
);
|
||||
}
|
||||
}, 500)
|
||||
},
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1 class="title is-3">Tasks</h1>
|
||||
|
||||
<h1 class="title is-3">
|
||||
Tasks
|
||||
<app-dropdown button-class="is-primary" :open="showListDropdown" :label="listSelectLabel" @open="showListDropdown = true" @close="showListDropdown = false">
|
||||
|
||||
<task-list-dropdown-item v-for="l in taskLists" :key="l.id" :task-list="l" :active="currentTaskList !== null && currentTaskList.id === l.id" @select="selectList" @delete="deleteList"></task-list-dropdown-item>
|
||||
@ -11,20 +11,12 @@
|
||||
<task-list-mini-form :task-list="newList" :validation-errors="newListValidationErrors" @save="saveNewList"></task-list-mini-form>
|
||||
</div>
|
||||
</app-dropdown>
|
||||
<br><br>
|
||||
</h1>
|
||||
|
||||
<div v-if="currentTaskList !== null">
|
||||
|
||||
<div class="box">
|
||||
<button class="button" @click="deleteCompletedItems" v-if="completedItemCount > 0">Clear Completed</button>
|
||||
<button class="button" @click="completeAllItems" v-if="uncompletedItemCount > 0">Check All</button>
|
||||
<button class="button" @click="unCompleteAllItems" v-if="completedItemCount > 0">Uncheck All</button>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<div class="columns" v-if="currentTaskList !== null">
|
||||
<div class="column is-6-widescreen is-8-desktop is-10-tablet">
|
||||
<task-item-list :task-list="currentTaskList"></task-item-list>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@ -66,14 +58,6 @@
|
||||
} else {
|
||||
return this.currentTaskList.name;
|
||||
}
|
||||
},
|
||||
|
||||
completedItemCount() {
|
||||
return this.currentTaskList === null ? 0 : this.currentTaskList.task_items.filter(i => i.completed).length;
|
||||
},
|
||||
|
||||
uncompletedItemCount() {
|
||||
return this.currentTaskList === null ? 0 : this.currentTaskList.task_items.filter(i => !i.completed).length;
|
||||
}
|
||||
},
|
||||
|
||||
@ -109,36 +93,7 @@
|
||||
);
|
||||
},
|
||||
|
||||
completeAllItems() {
|
||||
const toComplete = this.currentTaskList.task_items.filter(i => !i.completed);
|
||||
this.loadResource(
|
||||
this.completeTaskItems({
|
||||
taskList: this.currentTaskList,
|
||||
taskItems: toComplete,
|
||||
completed: true
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
unCompleteAllItems() {
|
||||
const toUnComplete = this.currentTaskList.task_items.filter(i => i.completed);
|
||||
this.loadResource(
|
||||
this.completeTaskItems({
|
||||
taskList: this.currentTaskList,
|
||||
taskItems: toUnComplete,
|
||||
completed: false
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
deleteCompletedItems() {
|
||||
this.loadResource(
|
||||
this.deleteTaskItems({
|
||||
taskList: this.currentTaskList,
|
||||
taskItems: this.currentTaskList.task_items.filter(i => i.completed)
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
deleteAllItems() {
|
||||
this.loadResource(
|
||||
|
@ -11,8 +11,8 @@
|
||||
|
||||
.expand-enter-active,
|
||||
.expand-leave-active {
|
||||
transition: height .5s ease-in-out;
|
||||
overflow: hidden;
|
||||
// transition: height .5s ease-in-out;
|
||||
// overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
@import "~bulma/sass/components/message";
|
||||
@import "~bulma/sass/components/modal";
|
||||
@import "~bulma/sass/components/pagination";
|
||||
@import "~bulma/sass/components/panel";
|
||||
@import "~bulma/sass/elements/_all";
|
||||
@import "~bulma/sass/grid/columns";
|
||||
@import "~bulma/sass/layout/section";
|
||||
@ -36,6 +37,7 @@ body {
|
||||
.container {
|
||||
padding: 1rem;
|
||||
background-color: $white;
|
||||
min-height: 75vh;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,13 +4,10 @@ class Ingredient < ApplicationRecord
|
||||
class << self
|
||||
|
||||
def find_by_ingredient_id(ingredient_id)
|
||||
puts "looking up |#{ingredient_id}|"
|
||||
case ingredient_id
|
||||
when /^R(\d+)$/
|
||||
puts 'rec'
|
||||
Recipe.find($1)
|
||||
when /^F(\d+)$/
|
||||
puts 'food'
|
||||
Food.find($1)
|
||||
else
|
||||
raise ActiveRecord::RecordNotFound
|
||||
|
@ -24,7 +24,7 @@ module UnitConversion
|
||||
|
||||
def convert(value_unit)
|
||||
|
||||
input = value_unit.unitwise
|
||||
input = value_unit.unitwise * 1.0
|
||||
|
||||
if value_unit.volume? && @target_unit.mass?
|
||||
raise MissingDensityError, "Cannot convert #{value_unit.unit} to #{@target_unit} without density" unless @density
|
||||
@ -36,7 +36,7 @@ module UnitConversion
|
||||
|
||||
begin
|
||||
input = input.convert_to @target_unit.unit
|
||||
rescue Unitwise::ConversionError => err
|
||||
rescue Unitwise::ConversionError, Unitwise::ExpressionError => err
|
||||
raise ConversionError, err.message
|
||||
end
|
||||
|
||||
|
@ -45,7 +45,7 @@ module UnitConversion
|
||||
def compatible?(unit_str)
|
||||
begin
|
||||
unitwise.compatible_with? Unitwise(1, unit_str)
|
||||
rescue UnknownUnitError
|
||||
rescue TypeError, Unitwise::ConversionError, Unitwise::ExpressionError
|
||||
false
|
||||
end
|
||||
end
|
||||
|
@ -19,6 +19,10 @@ module Unitwise
|
||||
|
||||
def self.with_custom_units(unit_list, &block)
|
||||
|
||||
if unit_list.empty?
|
||||
return block.call
|
||||
end
|
||||
|
||||
atoms = []
|
||||
ret_val = nil
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@rails/webpacker": "^3.5.5",
|
||||
"@tweenjs/tween.js": "^17.2.0",
|
||||
"autosize": "^4.0.1",
|
||||
"bulma": "^0.7.1",
|
||||
"caniuse-lite": "^1.0.30000815",
|
||||
|
@ -32,6 +32,10 @@
|
||||
webpack "^3.12.0"
|
||||
webpack-manifest-plugin "^1.3.2"
|
||||
|
||||
"@tweenjs/tween.js@^17.2.0":
|
||||
version "17.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@tweenjs/tween.js/-/tween.js-17.2.0.tgz#21f89b709bafc4b303adae7a83b4f35a0d9e4796"
|
||||
|
||||
"@types/node@*":
|
||||
version "10.9.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.9.4.tgz#0f4cb2dc7c1de6096055357f70179043c33e9897"
|
||||
|
Loading…
Reference in New Issue
Block a user