Skip to content

Commit

Permalink
Merge pull request #3 from agritheory/key-nav
Browse files Browse the repository at this point in the history
Key nav
  • Loading branch information
agritheory authored Jul 19, 2022
2 parents 8d740bd + 46598c1 commit 0823fc5
Show file tree
Hide file tree
Showing 4 changed files with 248 additions and 20 deletions.
1 change: 1 addition & 0 deletions check_run/check_run/doctype/check_run/check_run.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ frappe.ui.form.on("Check Run", {
})
}
frm.doc.transactions = JSON.stringify(frm.check_run_state.transactions)
frm.doc.amount_check_run = frm.check_run_state.check_run_total()
},
refresh: frm => {
frm.layout.show_message('')
Expand Down
174 changes: 174 additions & 0 deletions check_run/public/js/check_run/ADropdown.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
<template>
<div class="autocomplete" :class="{ 'isOpen': isOpen }">
<input
type="text"
:id="`mop-input-${transactionIndex}`"
@input="onChange"
@focus="onChange"
v-model="search"
@keydown.down="onArrowDown"
@keydown.up="onArrowUp"
@keydown.enter="onEnter"
class="form-control"
/>
<ul
id="autocomplete-results"
v-show="isOpen"
class="autocomplete-results"
>
<li
class="loading"
v-if="isLoading"
>
Loading results...
</li>
<li
v-else
v-for="(result, i) in results"
:key="i"
@click="setResult(result)"
class="autocomplete-result"
:class="{ 'is-active': i === arrowCounter }"
>
{{ result }}
</li>
</ul>
</div>
</template>

<script>
export default {
name: 'ADropdown',
props: {
value: String,
isOpen: Boolean,
items: {
type: Array,
required: false,
default: () => [],
},
isAsync: {
type: Boolean,
required: false,
default: false,
},
transactionIndex: Number
},
data() {
return {
results: [],
search: this.value,
isLoading: false,
arrowCounter: 0,
};
},
watch: {
items: function (value, oldValue) {
if (value.length !== oldValue.length) {
this.results = value;
this.isLoading = false;
}
},
value: function (value, oldValue) {
if (value !== oldValue) {
this.setResult(value)
}
}
},
mounted() {
document.addEventListener('click', this.handleClickOutside)
this.filterResults()
},
destroyed() {
document.removeEventListener('click', this.handleClickOutside)
},
methods: {
setResult(result) {
this.search = result;
this.closeResults()
},
filterResults() {
this.results = this.items.filter((item) => {
return item.toLowerCase().indexOf(this.search.toLowerCase()) > -1;
});
},
onChange() {
if (this.isAsync) {
this.isLoading = true;
} else {
this.filterResults();
this.isOpen = true
this.$emit('isOpenChanged', this.isOpen)
}
},
handleClickOutside(event) {
if (!this.$el.contains(event.target)) {
this.closeResults()
this.arrowCounter = 0;
}
},
closeResults() {
this.isOpen = false
this.$emit('isOpenChanged', this.isOpen)
if(!this.items.includes(this.search)) {
this.search = ''
}
if(this.value != this.search) {
cur_frm.dirty();
}
this.value = this.search
this.$emit('input', this.value)
},
onArrowDown() {
if (this.arrowCounter < this.results.length) {
this.arrowCounter = this.arrowCounter + 1;
}
},
onArrowUp() {
if (this.arrowCounter > 0) {
this.arrowCounter = this.arrowCounter - 1;
}
},
onEnter() {
this.search = this.results[this.arrowCounter];
this.closeResults()
this.arrowCounter = 0;
},
},
};
</script>

<style>
.autocomplete {
position: relative;
}
.autocomplete-results {
padding: 0;
margin: 0;
border: 1px solid #eeeeee;
background-color: #f4f5f6;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
}
.autocomplete-result {
list-style: none;
text-align: left;
padding: 4px 6px;
cursor: pointer;
}
.autocomplete-result.is-active,
.autocomplete-result:hover {
background-color: #4590e8;
color: white;
}
</style>
43 changes: 24 additions & 19 deletions check_run/public/js/check_run/CheckRun.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@
v-if="partyIsInFilter(transactions[i].party)"
:key=i
class="checkrun-row-container"
:class="{ selectedRow: state.selectedRow == i }"
tabindex="1"
@click="state.selectedRow = i"
>
<td style="text-align: left">{{ transactions[i].party }}</td>
<td>
Expand All @@ -60,23 +62,9 @@
class="mop-onclick"
:data-mop-index="i"
>
<select
v-if="state.docstatus < 1"
class="mop-input form-control"
:data-mop="transactions[i].mode_of_payment"
v-model="transactions[i].mode_of_payment"
@change="markDirty()"
>
<option></option>
<template v-for="(mop, j) in modes_of_payment">
<option
:value="modes_of_payment[j].name"
:key="j"
>
{{modes_of_payment[j].name}}
</option>
</template>
</select>

<ADropdown v-model="state.transactions[i].mode_of_payment" :items="modeOfPaymentNames" v-if="state.docstatus < 1" :transactionIndex="i" :isOpen="state.transactions[i].mopIsOpen" @isOpenChanged="val => state.transactions[i].mopIsOpen = val"/>

<span v-else>{{ transactions[i].mode_of_payment }}</span>
</td>
<td>{{ format_currency(transactions[i].amount, "USD", 2) }}</td>
Expand All @@ -86,7 +74,7 @@
type="checkbox"
class="input-with-feedback checkrun-check-box"
data-fieldtype="Check"
@change="markDirty()"
@change="onPayChange()"
:data-checkbox-index="i"
v-model="transactions[i].pay"
:id="transactions[i].id" />Pay
Expand All @@ -102,8 +90,13 @@
</template>
<script>
import ADropdown from "./ADropdown.vue";
export default {
name: 'CheckRun',
components: {
ADropdown
},
props: ['transactions', 'modes_of_payment', 'docstatus', 'state'],
data(){
return {
Expand All @@ -113,12 +106,15 @@ export default {
mode_of_payment: 1,
amount: 1,
due_date: 1
}
},
modeOfPaymentNames: this.modes_of_payment.map(mop => mop.name)
}
},
watch: {
selectAll: (val, oldVal) => {
cur_frm.check_run_state.transactions.forEach(row => { row.pay = val })
cur_frm.doc.amount_check_run = cur_frm.check_run_state.check_run_total()
cur_frm.refresh_field("amount_check_run")
cur_frm.dirty();
}
},
Expand Down Expand Up @@ -148,6 +144,11 @@ export default {
},
markDirty() {
cur_frm.dirty()
},
onPayChange() {
cur_frm.doc.amount_check_run = cur_frm.check_run_state.check_run_total()
cur_frm.refresh_field("amount_check_run")
this.markDirty()
}
},
beforeMount() {
Expand All @@ -163,4 +164,8 @@ export default {
.table thead th {
vertical-align: top;
}
.table tr.selectedRow {
background-color: #ececec;
}
</style>
50 changes: 49 additions & 1 deletion check_run/public/js/check_run/check_run.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
import CheckRun from './CheckRun.vue'
import ADropdown from './ADropdown.vue'

frappe.provide('check_run')

check_run.mount_table = frm => {
check_run.frm = frm
frm.transactions.forEach(val => {
val.mopIsOpen = false
})
frm.check_run_state = Vue.observable({
transactions: frm.transactions,
party_filter: "",
docstatus: frm.doc.docstatus,
modes_of_payment: frm.modes_of_payment,
show_party_filter: false
show_party_filter: false,
check_run_total: function() {
return this.transactions.reduce((partialSum, t) => {
return t.pay ? partialSum + t.amount : partialSum;
}, 0);
},
selectedRow: 0,
mopsOpen: 0
})
if (frm.$check_run instanceof Vue) {
frm.$check_run.$destroy();
Expand All @@ -28,5 +40,41 @@ check_run.mount_table = frm => {
})
})

}

check_run.keyDownHandler = e => {
if(!check_run.frm) {
return
}

if(e.keyCode == 40 && check_run.frm.check_run_state.selectedRow < (check_run.frm.check_run_state.transactions.length - 1)){
console.log("state", check_run.frm.check_run_state)
for(let j=0;j<check_run.frm.check_run_state.transactions.length;j++) {
if(check_run.frm.check_run_state.transactions[j].mopIsOpen) {
return
}
}
document.getElementById(`mop-input-${check_run.frm.check_run_state.selectedRow}`).blur()
check_run.frm.check_run_state.selectedRow += 1
}

if(e.keyCode == 38 && check_run.frm.check_run_state.selectedRow > 0){
for(let j=0;j<check_run.frm.check_run_state.transactions.length;j++) {
if(check_run.frm.check_run_state.transactions[j].mopIsOpen) {
return
}
}
document.getElementById(`mop-input-${check_run.frm.check_run_state.selectedRow}`).blur()
check_run.frm.check_run_state.selectedRow -= 1
}

if(e.keyCode == 32 && check_run.frm.check_run_state.selectedRow != null && check_run.frm.check_run_state.transactions.length){
e.preventDefault()
document.getElementById(`mop-input-${check_run.frm.check_run_state.selectedRow}`).focus()

}

}

window.removeEventListener('keydown', check_run.keyDownHandler);
window.addEventListener('keydown', check_run.keyDownHandler);

0 comments on commit 0823fc5

Please sign in to comment.