Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Actions for current item #64

Merged
merged 21 commits into from
Jul 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
6b5bf74
Rename un/archive actions to un/archiveSelected
kungpaogao Jun 16, 2020
6b349f2
Update edit card dialog behavior
kungpaogao Jun 17, 2020
4768145
Add events for export and archive from edit card
kungpaogao Jun 17, 2020
7b798fb
Implement module actions for archiving current
kungpaogao Jun 18, 2020
f1fc6fc
Rename category to collection in XLSX function
kungpaogao Jun 18, 2020
e4f9424
Add exports for other Firebase services
kungpaogao Jun 18, 2020
4e592e6
Add exportItems to FirestoreService
kungpaogao Jun 18, 2020
2fd18e8
Rename db to firebase
kungpaogao Jun 18, 2020
021b06c
Implement actions for export current and selected
kungpaogao Jun 18, 2020
6c02b01
Update inventory to use new export actions
kungpaogao Jun 18, 2020
b18852b
Remove collection parameter from commitUpdates
kungpaogao Jun 19, 2020
f7adaf1
Move all dialog logic into FurnitureCardDialog
kungpaogao Jun 19, 2020
d11628b
Add dialogs back to Archive
kungpaogao Jun 19, 2020
8b4cb88
Add loading to menu actions in ViewActionGroup
kungpaogao Jun 19, 2020
044f5d1
Add menu actions and loading props for EditCard
kungpaogao Jun 19, 2020
a94fb2a
Add unarchive events to EditCard
kungpaogao Jun 19, 2020
32285b5
Implement current actions for Inventory, Archive
kungpaogao Jun 19, 2020
aebf201
Update functions to use Node 10
kungpaogao Jun 25, 2020
2ce13e5
Merge branch 'master' into kungpaogao/current-actions
kungpaogao Jun 25, 2020
9765991
Fix whitespace
kungpaogao Jun 30, 2020
e0531a8
Fix bug that shows unsaved dialog after save
kungpaogao Jun 30, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion functions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"logs": "firebase functions:log"
},
"engines": {
"node": "8"
"node": "10"
},
"main": "lib/index.js",
"dependencies": {
Expand Down
10 changes: 5 additions & 5 deletions functions/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,9 @@ function renameSubheaders(mainHeaders: string[], subheaders: string[]): any {
return newHeaders;
}

async function getData(id: string[], category: string): Promise<string> {
async function getData(id: string[], collection: string): Promise<string> {
const inventory: any = [];
const furniture = admin.firestore().collection(category);
const furniture = admin.firestore().collection(collection);
const wb = XLSX.utils.book_new();

// converting each inventory entry to single-layer JSON object
Expand Down Expand Up @@ -178,14 +178,14 @@ async function getData(id: string[], category: string): Promise<string> {
const date = `${today.getFullYear()}-${
today.getMonth() + 1
}-${today.getDate()}`;
const fileName = category.concat(`${date}.xlsx`);
const fileName = collection.concat(`${date}.xlsx`);
const file = bucket.file(fileName);
await file.save(buffer);
return `/n2n-inventory/${fileName}`;
}

exports.getInventoryXLSX = functions.https.onCall(
(data: { id: string[]; category: string }) => {
return getData(data.id, data.category);
(data: { id: string[]; collection: string }) => {
return getData(data.id, data.collection);
},
);
64 changes: 41 additions & 23 deletions src/components/EditCard.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
<template>
<v-card>
<v-overlay absolute :value="loading" align="center" opacity="0.25">
<v-progress-circular
class="mr-3"
indeterminate
size="32"
></v-progress-circular>
Saving edits...
</v-overlay>

<v-card-title
class="headline ease-transition pb-4"
:class="{
Expand All @@ -17,6 +26,9 @@
v-if="!isEdit"
@close="$emit('close')"
@edit="$emit('edit')"
@export="$emit('export')"
@archive="$emit('archive')"
@unarchive="$emit('unarchive')"
/>
</v-card-title>

Expand All @@ -34,6 +46,7 @@
<h2>Donor Info</h2>

<!-- TODO: make these just normal text when in readonly -->
<!-- :value="donor ? donor.name : ''" -->
<v-text-field
:value="donor.name"
@input="updateDonor('name', $event)"
Expand Down Expand Up @@ -90,7 +103,7 @@

<v-text-field
v-if="!isEdit"
:value="statusOptions[status].text"
:value="statusOptions[status] ? statusOptions[status].text : ''"
label="Furniture Status"
readonly
:prepend-icon="statusIcons[status]"
Expand Down Expand Up @@ -273,6 +286,15 @@ export default class EditCard extends Vue {
@Prop({ default: true })
readonly isStaff!: boolean;

@Prop({ default: [] })
readonly menuActions!: ViewAction[];

@Prop({ default: false })
readonly menuLoading!: boolean;

@Prop({ default: false })
readonly loading!: boolean;

/**
* Sets the offset when user scrolls
*/
Expand All @@ -294,23 +316,19 @@ export default class EditCard extends Vue {
(v: any): boolean | string => /.+@.+/.test(v) || "E-mail must be valid",
];

readonly ACTIONS: ViewAction[] = [
{ icon: "edit", desc: "Edit Item", emit: "edit" },
{
icon: "more_vert",
desc: "More Actions",
emit: "menu",
menu: [
{ icon: "archive", desc: "Archive", emit: "archive" },
{
icon: "cloud_download",
desc: "Export",
emit: "export",
},
],
},
{ icon: "close", desc: "Close", emit: "close" },
];
get ACTIONS(): ViewAction[] {
return [
{ icon: "edit", desc: "Edit Item", emit: "edit" },
{
icon: "more_vert",
desc: "More Actions",
emit: "menu",
menu: this.menuActions,
loading: (): boolean => this.menuLoading,
},
{ icon: "close", desc: "Close", emit: "close" },
];
}

/* Getters and setters for form fields */

Expand All @@ -319,7 +337,7 @@ export default class EditCard extends Vue {
}

get donor(): Donor {
return this.current.donor;
return this.current.donor || new Donor();
}

updateDonor(key: string, value: string): void {
Expand Down Expand Up @@ -353,7 +371,7 @@ export default class EditCard extends Vue {
];

get fclass(): FClass {
return this.current.physical.class;
return this.current.physical ? this.current.physical.class : FClass.Bed;
}

set fclass(value: FClass) {
Expand All @@ -367,7 +385,7 @@ export default class EditCard extends Vue {
readonly classOptions = Object.keys(FClass);

get physical(): Physical {
return this.current.physical;
return this.current.physical || new Physical();
}

set physical(value: Physical) {
Expand All @@ -376,7 +394,7 @@ export default class EditCard extends Vue {
}

get timing(): Timing {
return this.current.timing;
return this.current.timing || new Timing();
}

set timing(value: Timing) {
Expand All @@ -396,7 +414,7 @@ export default class EditCard extends Vue {
}

get attributes(): Attributes {
return this.current.attributes;
return this.current.attributes || new Attributes();
}

set attributes(value: Attributes) {
Expand Down
130 changes: 104 additions & 26 deletions src/components/FurnitureCardDialog.vue
Original file line number Diff line number Diff line change
@@ -1,58 +1,136 @@
<template>
<v-dialog
v-model="dialog"
width="750"
persistent
scrollable
@click:outside="closeDialog()"
@keydown.escape="closeDialog()"
>
<edit-card
:namespace="namespace"
:is-edit="isEdit"
:is-add="isAdd"
@edit="$emit('edit')"
@close="closeDialog()"
@save="saveChanges()"
<div>
<v-dialog
v-model="dialog"
width="750"
persistent
scrollable
@click:outside="closeDialog()"
@keydown.escape="closeDialog()"
>
<edit-card
:namespace="namespace"
:is-edit="isEdit"
:is-add="isAdd"
:menu-actions="menuActions"
:menu-loading="menuLoading"
:loading="updatesLoading"
@edit="toggleEdit()"
@close="closeDialog()"
@save="saveChanges()"
@export="$emit('export')"
@archive="$emit('archive')"
@unarchive="$emit('unarchive')"
/>
</v-dialog>

<unsaved-dialog
:dialog="unsavedDialog"
@cancel="unsavedDialog = false"
@discard="closeDialog(true)"
/>
</v-dialog>
</div>
</template>

<script lang="ts">
import Vue from "vue";
import { Component, Prop } from "vue-property-decorator";
import { mapActions, mapState } from "vuex";
import ViewAction from "@/data/ViewAction";
import collections from "@/network/collections";
import EditCard from "@/components/EditCard.vue";
import UnsavedDialog from "@/components/FurnitureCardUnsavedDialog.vue";

@Component({ components: { EditCard } })
@Component({
components: { EditCard, UnsavedDialog },
computed: mapState({
updatesLength(state, getters) {
return getters[`${this.namespace}/getUpdatesLength`];
},
}),
methods: mapActions({
clearCurrent(dispatch) {
return dispatch(`${this.namespace}/clearCurrent`);
},
clearUpdates(dispatch) {
return dispatch(`${this.namespace}/clearUpdates`);
},
async commitUpdates(dispatch) {
return dispatch(`${this.namespace}/commitUpdates`);
},
}),
})
export default class FurnitureCardDialog extends Vue {
@Prop({ default: false })
readonly dialog!: boolean;

@Prop({ default: false })
readonly isEdit!: boolean;
@Prop({})
readonly collection!: collections;

@Prop({ default: false })
readonly isAdd!: boolean;

@Prop({})
readonly namespace!: string;

@Prop({})
readonly menuActions!: ViewAction[];

@Prop({ default: false })
readonly menuLoading!: boolean;

readonly updatesLength!: number;

readonly clearCurrent!: () => void;

readonly clearUpdates!: () => void;

readonly commitUpdates!: () => Promise<void>;

updatesLoading = false;

unsavedDialog = false;

isEdit = false;

/**
* Emits `close` event
* Exits dialog and clears the current item
*/
closeDialog(): void {
this.$emit("close");
closeDialog(forceClose = false): void {
if (this.updatesLoading) {
return;
}
if (this.updatesLength === 0 || forceClose) {
this.unsavedDialog = false;
this.isEdit = false;
this.clearCurrent();
} else {
this.unsavedDialog = true;
}
}

/**
* Toggles edit state `isEdit` and clears update if setting `isEdit`
* to false
*/
toggleEdit(): void {
if (this.isEdit) {
this.clearUpdates();
}
this.isEdit = !this.isEdit;
}

/**
* Emits `add` when dialog is used to add new items and `save`,
* otherwise
* Commits updates to Firestore
*/
saveChanges(): void {
async saveChanges(): Promise<void> {
if (this.isAdd) {
this.$emit("add");
} else {
this.$emit("save");
this.updatesLoading = true;
await this.commitUpdates();
this.isEdit = false;
this.updatesLoading = false;
}
}
}
Expand Down
11 changes: 9 additions & 2 deletions src/components/ViewActionGroup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,15 @@
<template v-slot:activator="{ on: menu }">
<v-tooltip bottom :disabled="disabled">
<template v-slot:activator="{ on: tooltip }">
<v-btn icon v-on="{ ...tooltip, ...menu }" v-if="action.menu">
<v-icon>{{ action.icon }}</v-icon>
<v-btn
icon
v-on="{ ...tooltip, ...menu }"
v-if="action.menu"
:loading="action.loading && action.loading()"
>
<v-icon>
{{ action.icon }}
</v-icon>
</v-btn>
<v-btn
v-else
Expand Down
2 changes: 1 addition & 1 deletion src/network/archive-service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Furniture } from "@/data/Furniture";
import collections from "./collections";
import FirestoreService from "./firestore-service";
import db from "./db";
import { db } from "./firebase";

class ArchiveService extends FirestoreService {
unarchiveItem = async (id: string): Promise<void> => {
Expand Down
7 changes: 0 additions & 7 deletions src/network/db.ts

This file was deleted.

15 changes: 15 additions & 0 deletions src/network/firebase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import firebase from "firebase/app";
import "firebase/firestore";
import "firebase/functions";
import "firebase/storage";
import config from "./config";

firebase.initializeApp(config);

export const db = firebase.firestore();

export const functions = firebase.functions();

export const storage = firebase.storage();

export default db;
Loading