notes work

This commit is contained in:
Dan Elbert 2018-04-07 10:54:56 -05:00
parent 63a566d697
commit 2da16e334e
8 changed files with 190 additions and 9 deletions

View File

@ -77,6 +77,6 @@ class NotesController < ApplicationController
# Never trust parameters from the scary internet, only allow the white list through.
def note_params
params.require(:note).permit(:user_id, :content)
params.require(:note).permit(:content)
end
end

View File

@ -0,0 +1,57 @@
<template>
<div>
<div class="field">
<label class="label">Note</label>
<div class="control">
<textarea class="textarea" v-model="note.content"></textarea>
</div>
</div>
<div class="buttons">
<button type="button" class="button is-primary" :disabled="!canSave" @click="save">
Save
</button>
<button type="button" class="button is-secondary" @click="cancel">
Cancel
</button>
</div>
</div>
</template>
<script>
export default {
props: {
note: {
required: true,
type: Object
}
},
data() {
return {
};
},
computed: {
canSave() {
return this.note && this.note.content && this.note.content.length;
}
},
methods: {
save() {
this.$emit("save", this.note);
},
cancel() {
this.$emit("cancel");
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -2,11 +2,13 @@
<div>
<h1 class="title">Ingredients</h1>
<div class="buttons">
<router-link v-if="isLoggedIn" :to="{name: 'new_ingredient'}" class="button is-primary">Create Ingredient</router-link>
</div>
<app-pager :current-page="currentPage" :total-pages="totalPages" paged-item-name="ingredient" @changePage="changePage"></app-pager>
<table class="table">
<table class="table is-fullwidth is-narrow">
<thead>
<tr>
<th>Name</th>
@ -46,6 +48,10 @@
<app-pager :current-page="currentPage" :total-pages="totalPages" paged-item-name="ingredient" @changePage="changePage"></app-pager>
<div class="buttons">
<router-link v-if="isLoggedIn" :to="{name: 'new_ingredient'}" class="button is-primary">Create Ingredient</router-link>
</div>
</div>
</template>

View File

@ -1,11 +1,95 @@
<template>
<div>
<div class="buttons">
<button type="button" class="button is-primary" @click="addNote">Add Note</button>
</div>
<app-modal title="Add Note" :open="editNote !== null" @dismiss="cancelNote">
<note-edit v-if="editNote !== null" :note="editNote" @save="saveNote" @cancel="cancelNote"></note-edit>
</app-modal>
<table class="table">
<tr>
<th>Note</th>
<th>Date</th>
<th></th>
</tr>
<tr v-for="n in notes" :key="n.id">
<td>
{{ n.content }}
</td>
<td>
<app-date-time :date-time="n.created_at"></app-date-time>
</td>
<td>
<button type="button" class="button is-danger" @click="deleteNote(n)">
<app-icon icon="x"></app-icon>
</button>
</td>
</tr>
</table>
</div>
</template>
<script>
export default {
import api from "../lib/Api";
import NoteEdit from "./NoteEdit";
export default {
data() {
return {
notes: [],
editNote: null
};
},
methods: {
refreshList() {
this.loadResource(
api.getNoteList()
.then(data => this.notes = data)
);
},
addNote() {
this.editNote = { id: null, content: "" };
},
saveNote() {
this.loadResource(
api.postNote(this.editNote)
.then(() => {
this.editNote = null;
return this.refreshList();
})
);
},
cancelNote() {
this.editNote = null;
},
deleteNote(n) {
this.loadResource(
api.deleteNote(n)
.then(() => {
return this.refreshList();
})
);
}
},
created() {
this.refreshList();
},
components: {
NoteEdit
}
}
</script>

View File

@ -12,8 +12,10 @@ class Api {
}
checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
return response;
if (response.status == 204) {
return null;
} else if (response.ok) {
return response.json();
} else if (response.status === 404) {
throw new Errors.ApiNotFoundError(response.statusText, response);
} else if (response.status === 422) {
@ -32,6 +34,7 @@ class Api {
const headers = new Headers();
headers.append('Accept', 'application/json');
headers.append('Content-Type', 'application/json');
const opts = {
headers,
@ -40,11 +43,10 @@ class Api {
};
if (hasBody) {
headers.append('Content-Type', 'application/json');
opts.body = JSON.stringify(params);
}
return fetch(url, opts).then(this.checkStatus).then(this.parseJSON);
return fetch(url, opts).then(this.checkStatus);
}
objectToUrlParams(obj, queryParams = [], prefixes = []) {
@ -84,6 +86,10 @@ class Api {
return this.performRequest(url, "PATCH", params);
}
del(url, params = {}) {
return this.performRequest(url, "DELETE", params);
}
getRecipeList(page, per, sortColumn, sortDirection, name, tags) {
const params = {
criteria: {
@ -251,6 +257,22 @@ class Api {
return this.get("/ingredients/usda_food_search", {query: query});
}
getNoteList() {
return this.get("/notes/");
}
postNote(note) {
const params = {
content: note.content
};
return this.post("/notes/", params);
}
deleteNote(note) {
return this.del("/notes/" + note.id);
}
postLogin(username, password) {
const params = {
username: username,

View File

@ -43,6 +43,7 @@ export default new Vuex.Store({
},
setError(state, value) {
console.log(value);
state.error = value;
},

View File

@ -7,6 +7,8 @@ $coolors-green: rgba(121, 167, 54, 1);
$coolors-red: #ab4c34;
$coolors-yellow: rgba(240, 162, 2, 1);
$family-serif: Georgia, "Times New Roman", Times, serif;
// Bluma default overrides
//$green: #79A736;
//$red: #d4424e;
@ -19,6 +21,7 @@ $yellow: $coolors-yellow;
$dark: $coolors-dark;
$primary: $green;
$family-primary: $family-serif;
$modal-content-width: 750px;

View File

@ -34,3 +34,11 @@ body {
background-color: $white;
}
}
.title, .subtitle, .navbar, .button, .pagination, .modal-card-title, th {
font-family: $family-sans-serif;
}
.pagination:not(:last-child) {
margin-bottom: 1em;
}