Skip to content

Commit

Permalink
Merge pull request #269 from ncosd/dev-1.10.0
Browse files Browse the repository at this point in the history
Release v1.10.0
  • Loading branch information
dherbst authored Jan 9, 2024
2 parents 8c2f219 + 5aca5e7 commit f32df7a
Show file tree
Hide file tree
Showing 20 changed files with 184 additions and 55 deletions.
2 changes: 1 addition & 1 deletion web/admin/fixtures/auth_export/accounts.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"kind":"identitytoolkit#DownloadAccountResponse","users":[{"localId":"5WddDr1Teytl9YHQ0Lgf2yP86pft","createdAt":"1681846355208","lastLoginAt":"1681846355208","displayName":"v2","passwordHash":"fakeHash:salt=fakeSaltMaXkJGcoDb58rWtYnrD4:password=password","salt":"fakeSaltMaXkJGcoDb58rWtYnrD4","passwordUpdatedAt":1704077730177,"customAttributes":"{\"volunteer\":true}","providerUserInfo":[{"providerId":"password","email":"[email protected]","federatedId":"[email protected]","rawId":"[email protected]","displayName":"v2"}],"validSince":"1704077730","email":"[email protected]","emailVerified":false,"disabled":false},{"localId":"olN7alG8mHwRg6YYgVjlpR9scwq5","createdAt":"1614344510322","lastLoginAt":"1704077775556","displayName":"VolunteerUser","photoUrl":"","passwordHash":"fakeHash:salt=fakeSaltPdNFgJYXTp3KoHpHPeET:password=password","salt":"fakeSaltPdNFgJYXTp3KoHpHPeET","passwordUpdatedAt":1704077730177,"customAttributes":"{\"admin\": true,\"volunteer\":true}","providerUserInfo":[{"providerId":"password","email":"[email protected]","federatedId":"[email protected]","rawId":"[email protected]","displayName":"VolunteerUser","photoUrl":""}],"validSince":"1704077730","email":"[email protected]","emailVerified":false,"disabled":false,"lastRefreshAt":"2024-01-01T02:56:15.556Z"},{"localId":"woEHhjSLumylkHLkbJKYdV7bTlNF","createdAt":"1681846322321","lastLoginAt":"1684257041600","displayName":"v1","passwordHash":"fakeHash:salt=fakeSaltMmMYfmogc9thU5bAe1wL:password=password","salt":"fakeSaltMmMYfmogc9thU5bAe1wL","passwordUpdatedAt":1704077730177,"customAttributes":"{\"volunteer\":true}","providerUserInfo":[{"providerId":"password","email":"[email protected]","federatedId":"[email protected]","rawId":"[email protected]","displayName":"v1"}],"validSince":"1704077730","email":"[email protected]","emailVerified":false,"disabled":false}]}
{"kind":"identitytoolkit#DownloadAccountResponse","users":[{"localId":"5WddDr1Teytl9YHQ0Lgf2yP86pft","createdAt":"1681846355208","lastLoginAt":"1681846355208","displayName":"v2","passwordHash":"fakeHash:salt=fakeSaltMaXkJGcoDb58rWtYnrD4:password=password","salt":"fakeSaltMaXkJGcoDb58rWtYnrD4","passwordUpdatedAt":1704248415365,"customAttributes":"{\"volunteer\":true}","providerUserInfo":[{"providerId":"password","email":"[email protected]","federatedId":"[email protected]","rawId":"[email protected]","displayName":"v2"}],"validSince":"1704248415","email":"[email protected]","emailVerified":false,"disabled":false},{"localId":"olN7alG8mHwRg6YYgVjlpR9scwq5","createdAt":"1614344510322","lastLoginAt":"1704077775556","displayName":"VolunteerUser","photoUrl":"","passwordHash":"fakeHash:salt=fakeSaltPdNFgJYXTp3KoHpHPeET:password=password","salt":"fakeSaltPdNFgJYXTp3KoHpHPeET","passwordUpdatedAt":1704248415365,"customAttributes":"{\"admin\": true,\"volunteer\":true}","providerUserInfo":[{"providerId":"password","email":"[email protected]","federatedId":"[email protected]","rawId":"[email protected]","displayName":"VolunteerUser","photoUrl":""}],"validSince":"1704248415","email":"[email protected]","emailVerified":false,"disabled":false,"lastRefreshAt":"2024-01-03T02:20:59.137Z"},{"localId":"woEHhjSLumylkHLkbJKYdV7bTlNF","createdAt":"1681846322321","lastLoginAt":"1684257041600","displayName":"v1","passwordHash":"fakeHash:salt=fakeSaltMmMYfmogc9thU5bAe1wL:password=password","salt":"fakeSaltMmMYfmogc9thU5bAe1wL","passwordUpdatedAt":1704248415365,"customAttributes":"{\"volunteer\":true}","providerUserInfo":[{"providerId":"password","email":"[email protected]","federatedId":"[email protected]","rawId":"[email protected]","displayName":"v1"}],"validSince":"1704248415","email":"[email protected]","emailVerified":false,"disabled":false}]}
Binary file not shown.
Binary file not shown.
Binary file not shown.
28 changes: 27 additions & 1 deletion web/admin/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion web/admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"firebase": "^9.22.1",
"pinia": "^2.1.3",
"vue": "^3.3.4",
"vue-router": "^4.2.2"
"vue-router": "^4.2.2",
"vue-signature-pad": "^3.0.2"
},
"devDependencies": {
"@storybook/addon-essentials": "^7.6.6",
Expand Down
89 changes: 72 additions & 17 deletions web/admin/src/components/AgreementForm.vue
Original file line number Diff line number Diff line change
@@ -1,44 +1,99 @@
<script setup>
import { ref } from 'vue'
import dayjs from 'dayjs'
import { VueSignaturePad } from 'vue-signature-pad'
const props = defineProps({
agreementHTML: String,
name: String
})
const emit = defineEmits(['saveSignature'])
const signaturePad = ref(null)
const showSigErr = ref(false)
const showNameErr =ref(false)
const showAgreeErr = ref(false)
const agreeCheckBox = ref(false)
const userName = ref('')
const agreementDate = ref(dayjs().toDate())
const saveForm = ()=>{
showSigErr.value = false
showNameErr.value = false
showAgreeErr.value = false
let hasErr = false
const { isEmpty, data } = signaturePad.value.saveSignature()
//console.log('isEmpty', isEmpty, 'data', data)
if (isEmpty) {
showSigErr.value = true
hasErr = true
}
if (!agreeCheckBox.value) {
showAgreeErr.value = true
hasErr = true
}
console.log('username.value', userName.value)
if (!userName.value || userName.value === '') {
showNameErr.value = true
hasErr = true
}
if (hasErr) {
return
}
console.log('Saving signature')
emit('saveSignature', {
agreementDate: agreementDate.value,
agreementName: props.name,
agreeCheckBox: agreeCheckBox.value,
printedName: userName.value,
signatureData: data
})
}
</script>

<template>
<div class="container">
<div v-html="props.agreementHTML"></div>

<form>
<div>
<input type="checkbox" class="form-check-input me-3" id="agreementCheck">
<label class="form-check-label" for="agreementCheck">By checking this, I agree with all of the above.</label>
<form @submit.prevent="saveForm">
<div class="my-3">
<input type="checkbox" class="form-check-input me-3" id="agreementCheck" v-model="agreeCheckBox">
<label class="form-check-label" for="agreementCheck">By checking this, I have read and I agree with all of the above.</label>
</div>
<div v-if="showAgreeErr" class="text-danger">You must agree to save this form.</div>

<div>
<div class="my-3">
<label class="form-label" for="agreementDate">Date</label>
<input type="text" class="form-control" id="agreementDate" />
<input type="text" class="form-control" id="agreementDate" v-model="agreementDate"/>
</div>

<div>
<div class="my-3">
<label class="form-label" for="agreementSignature">
Signature of Staff Member/Volunteer
</label>
<input type="text" class="form-control" id="agreementSignature" />


<VueSignaturePad id="agreementSignature" class="border" ref="signaturePad"/>
<div id="signatureHelp" class="form-text">Draw your signature in the box above with your mouse or finger</div>
<div v-if="showSigErr" class="text-danger">You must provide a signature.</div>

</div>

<div>
<label class="form-label" for="printedName">
Printed Name
</label>
<input type="text" class="form-control" id="printedName" />
<div class="my-3">
<label class="form-label" for="printedName">Printed Name</label>
<input type="text" class="form-control" id="printedName" v-model="userName"/>
<div v-if="showNameErr" class="text-danger">You must provide your name.</div>
</div>
<div class="mt-3">
<button type="submit" class="btn btn-primary" disabled>Submit</button>
<div class="my-3">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
</template>

<style></style>
2 changes: 0 additions & 2 deletions web/admin/src/components/Confidentiality.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,3 @@ const props = defineProps({
</label>
</form>
</template>

<style></style>
2 changes: 1 addition & 1 deletion web/admin/src/components/SortableTableHeader.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup>
import { computed, defineEmits, defineProps } from "vue"
import { computed } from "vue"
const emit = defineEmits(["sort-list"])
const props = defineProps({
Expand Down
2 changes: 1 addition & 1 deletion web/admin/src/config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export let config = {
version: "1.9.1",
version: "1.10.0",
adminAppNavName: import.meta.env.VITE_ADMIN_APP_NAV_NAME || 'ADMIN_APP_NAV_NAME',
adminAppNavImg: import.meta.env.VITE_ADMIN_APP_NAV_IMG || null,
appNavName: import.meta.env.VITE_APP_NAV_NAME || 'APP_NAV_NAME',
Expand Down
10 changes: 2 additions & 8 deletions web/admin/src/scss/styles.scss
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
// TODO: this is a workaround for the vite-sass issue of loading the woff files in bootstrap-icons.scss using variables
@font-face {
font-display: block;
font-family: "bootstrap-icons";
src: url("~bootstrap-icons/font/fonts/bootstrap-icons.woff2?1fa40e8900654d2863d011707b9fb6f2") format("woff2"),
url("~bootstrap-icons/font/fonts/bootstrap-icons.woff?1fa40e8900654d2863d011707b9fb6f2") format("woff");
}

@import "~bootstrap/scss/_functions.scss";
@import "~bootstrap/scss/_variables.scss";
@import "~bootstrap/scss/_mixins.scss";
Expand Down Expand Up @@ -99,4 +91,6 @@ url("~bootstrap-icons/font/fonts/bootstrap-icons.woff?1fa40e8900654d2863d011707b


@import "~bootstrap/scss/bootstrap.scss";
// NOTE: this is a workaround for the vite-sass issue of loading the woff files in bootstrap-icons.scss using variables
$bootstrap-icons-font-file: "~bootstrap-icons/font/fonts/bootstrap-icons";
@import "~bootstrap-icons/font/bootstrap-icons.scss";
31 changes: 25 additions & 6 deletions web/admin/src/views/AgreementPage.vue
Original file line number Diff line number Diff line change
@@ -1,30 +1,49 @@
<script setup>
import AgreementForm from '@/components/AgreementForm.vue'
import { ref, onBeforeMount } from 'vue'
import { getFirestore, doc, getDoc } from 'firebase/firestore'
import { getFirestore, doc, getDoc, addDoc, collection } from 'firebase/firestore'
import { useAuthUserStore } from '@/stores/authUser'
import { useRouter } from 'vue-router'
const props = defineProps({
name: String,
})
const router = useRouter()
const user = useAuthUserStore()
const db = getFirestore()
const agreementHTML = ref()
const showErr = ref(false)
const showSuccess = ref(false)
onBeforeMount(async()=>{
const db = getFirestore()
const docRef = doc(db, 'agreements', props.name)
console.log('docRef', docRef)
const docSnap = await getDoc(docRef)
if (docSnap.exists()) {
agreementHTML.value = docSnap.data().html
} else {
agreementHTML.value = '<div><strong>Agreement not found.</strong></div>'
agreementHTML.value = '<div><strong>Agreement (' + props.name + ') not found in database.</strong></div>'
}
})
const saveSignatureHandler = async (formData) => {
showSuccess.value = false
showErr.value = false
try {
const savedSigRef = await addDoc(collection(db, 'signedagreements', user.data.uid, props.name),
{ ...formData })
showSuccess.value = true
router.push({name:'Profile-Forms'})
} catch (err) {
showErr.value = true
}
}
</script>

<template>
<AgreementForm :agreementHTML="agreementHTML" :name="props.name"/>
<AgreementForm :agreementHTML="agreementHTML" :name="props.name" @saveSignature="saveSignatureHandler"/>
<div v-if="showErr" class="text-danger">An error occurred, try again later.</div>
<div v-if="showSuccess" class="text-success">Agreement saved</div>
</template>
26 changes: 19 additions & 7 deletions web/admin/src/views/ProfileFormsPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,37 @@ import { ref, onBeforeMount } from 'vue'
import { useAuthUserStore } from '@/stores/authUser'
import { useRouter } from 'vue-router'
import ProfileTabs from '@/components/ProfileTabs.vue'
import { getFirestore, getCountFromServer, doc, getDoc, getDocs, addDoc, collection, query, limit, orderBy } from 'firebase/firestore'
const props = defineProps({
uid: String,
})
const db = getFirestore()
const user = useAuthUserStore()
const router = useRouter()
const userId = ref(props.uid)
const confAgreement = ref(null)
onBeforeMount(async () => {
if (props.uid === '' || props.uid === undefined) {
props.uid = user.data.uid
}
if (props.uid === '' || props.uid === undefined) {
userId.value = user.data.uid
}
// check agreement form
const confQuery = query(collection(db, 'signedagreements', userId.value, 'confidentiality'), orderBy('agreementDate', 'desc'), limit(1))
const confSnap = await getDocs(confQuery)
if (confSnap.size > 0) {
confAgreement.value = confSnap.docs[0].data()
}
console.log('ProfileFormsPage uid=', props.uid)
})
</script>

<template>
<div class="container">

<ProfileTabs activeTab="Forms" :uid="props.uid"></ProfileTabs>
<ProfileTabs activeTab="Forms" :uid="userId"></ProfileTabs>

<h2 class="my-3">Electronic Forms</h2>
<div class="mt-3 row fw-bold">
Expand All @@ -38,10 +48,12 @@ console.log('ProfileFormsPage uid=', props.uid)
<router-link :to="{name:'AgreementForm', params: { name: 'confidentiality'}}">Confidentiality Agreement</router-link>
</div>
<div class="col">
<i class="bi bi-exclamation-diamond-fill text-danger"></i> Unsigned
<div v-if="confAgreement && confAgreement && confAgreement.agreeCheckBox"><i class="bi bi-check-circle text-success"/> Signed</div>
<div v-else><i class="bi bi-exclamation-diamond-fill text-danger"></i> Unsigned</div>
</div>
<div class="col">

<div v-if="confAgreement && confAgreement.agreementDate">{{confAgreement.agreementDate.toDate()}}</div>
<div v-else>-</div>
</div>
</div>

Expand Down
7 changes: 7 additions & 0 deletions web/admin/src/views/ReleaseNotesPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,17 @@
<template>
<div class="container">
<h1>Release Notes</h1>
<h2 id="1.10.0">January 9, 2024 - 1.10.0</h2>
<ul>
<li><a href="https://github.com/ncosd/food-pantry-app/issues/181">#181</a> Adds signable confidentiality agreement page.</li>
<li><a href="https://github.com/ncosd/food-pantry-app/issues/271">#271</a> Adds design page for admin reporting page.</li>
<li>Various macro warning fixes.</li>
</ul>
<h2 id="1.9.1">January 2, 2024 - 1.9.1</h2>
<ul>
<li><a href="https://github.com/ncosd/food-pantry-app/issues/39">#39</a> Add a way for users to verify their email.</li>
<li><a href="https://github.com/ncosd/food-pantry-app/issues/171">#171</a> Add sorting to volunteer list page.</li>
<li><a href="https://github.com/ncosd/food-pantry-app/issues/241">#241</a> Show error messages on volunteer registration page.</li>
</ul>
<h2 id="1.8.0">December 28, 2023 - 1.8.0</h2>
<ul>
Expand Down
2 changes: 1 addition & 1 deletion web/app/src/components/PageFooter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { config } from '@/config'
<li class="list-group-item border border-0"><router-link to="/privacy-policy">Privacy Policy</router-link></li>
<li class="list-group-item border border-0"><router-link to="/contact"><i class="bi bi-telephone-fill"></i> Contact</router-link></li>
<li class="list-group-item border border-0"><a href="https://github.com/ncosd/food-pantry-app"><i class="bi bi-github"></i> Made with Food-Pantry-App</a></li>
<li class="list-group-item border border-0">{{config.version}}</li>
<li class="list-group-item border border-0"><router-link :to='{name:"ReleaseNotes", hash: "#"+config.version}'><i class="bi bi-journal-check"></i> {{config.version}}</router-link></li>
</ul>
</footer>
</template>
2 changes: 1 addition & 1 deletion web/app/src/config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export let config = {
version: "1.0.1",
version: "1.10.0",
appNavName: import.meta.env.VITE_APP_NAV_NAME || 'APP_NAV_NAME',
OrganizationName: import.meta.env.VITE_ORGANIZATION_NAME || 'ORGANIZATION_NAME',
ProjectLongName: import.meta.env.VITE_PROJECT_LONG_NAME || 'PROJECT_LONG_NAME',
Expand Down
5 changes: 5 additions & 0 deletions web/app/src/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ const routes = [
name: 'Contact',
component: () => import('../views/ContactPage.vue'),
meta: config.meta.Contact
},
{
path: '/release-notes/',
name: 'ReleaseNotes',
component: () => import('@/views/ReleaseNotesPage.vue'),
}
]

Expand Down
Loading

0 comments on commit f32df7a

Please sign in to comment.