Complete upload framework
Signed-off-by: Justin Georgi <justin.georgi@gmail.com>
This commit is contained in:
@@ -6,6 +6,8 @@
|
|||||||
<path v-else-if="icon == 'photo_library'" d="M360-400h400L622-580l-92 120-62-80-108 140Zm-40 160q-33 0-56.5-23.5T240-320v-480q0-33 23.5-56.5T320-880h480q33 0 56.5 23.5T880-800v480q0 33-23.5 56.5T800-240H320Zm0-80h480v-480H320v480ZM160-80q-33 0-56.5-23.5T80-160v-560h80v560h560v80H160Zm160-720v480-480Z"/>
|
<path v-else-if="icon == 'photo_library'" d="M360-400h400L622-580l-92 120-62-80-108 140Zm-40 160q-33 0-56.5-23.5T240-320v-480q0-33 23.5-56.5T320-880h480q33 0 56.5 23.5T880-800v480q0 33-23.5 56.5T800-240H320Zm0-80h480v-480H320v480ZM160-80q-33 0-56.5-23.5T80-160v-560h80v560h560v80H160Zm160-720v480-480Z"/>
|
||||||
<path v-else-if="icon == 'no_photography'" d="m880-195-80-80v-405H638l-73-80H395l-38 42-57-57 60-65h240l74 80h126q33 0 56.5 23.5T880-680v485Zm-720 75q-33 0-56.5-23.5T80-200v-480q0-33 23.5-56.5T160-760h41l80 80H160v480h601l80 80H160Zm466-215q-25 34-62.5 54.5T480-260q-75 0-127.5-52.5T300-440q0-46 20.5-83.5T375-586l58 58q-24 13-38.5 36T380-440q0 42 29 71t71 29q29 0 52-14.5t36-38.5l58 58Zm-18-233q25 24 38.5 57t13.5 71v12q0 6-1 12L456-619q6-1 12-1h12q38 0 71 13.5t57 38.5ZM819-28 27-820l57-57L876-85l-57 57ZM407-440Zm171-57Z"/>
|
<path v-else-if="icon == 'no_photography'" d="m880-195-80-80v-405H638l-73-80H395l-38 42-57-57 60-65h240l74 80h126q33 0 56.5 23.5T880-680v485Zm-720 75q-33 0-56.5-23.5T80-200v-480q0-33 23.5-56.5T160-760h41l80 80H160v480h601l80 80H160Zm466-215q-25 34-62.5 54.5T480-260q-75 0-127.5-52.5T300-440q0-46 20.5-83.5T375-586l58 58q-24 13-38.5 36T380-440q0 42 29 71t71 29q29 0 52-14.5t36-38.5l58 58Zm-18-233q25 24 38.5 57t13.5 71v12q0 6-1 12L456-619q6-1 12-1h12q38 0 71 13.5t57 38.5ZM819-28 27-820l57-57L876-85l-57 57ZM407-440Zm171-57Z"/>
|
||||||
<path v-else-if="icon == 'photo_camera'" d="M480-260q75 0 127.5-52.5T660-440q0-75-52.5-127.5T480-620q-75 0-127.5 52.5T300-440q0 75 52.5 127.5T480-260Zm0-80q-42 0-71-29t-29-71q0-42 29-71t71-29q42 0 71 29t29 71q0 42-29 71t-71 29ZM160-120q-33 0-56.5-23.5T80-200v-480q0-33 23.5-56.5T160-760h126l74-80h240l74 80h126q33 0 56.5 23.5T880-680v480q0 33-23.5 56.5T800-120H160Zm0-80h640v-480H638l-73-80H395l-73 80H160v480Zm320-240Z"/>
|
<path v-else-if="icon == 'photo_camera'" d="M480-260q75 0 127.5-52.5T660-440q0-75-52.5-127.5T480-620q-75 0-127.5 52.5T300-440q0 75 52.5 127.5T480-260Zm0-80q-42 0-71-29t-29-71q0-42 29-71t71-29q42 0 71 29t29 71q0 42-29 71t-71 29ZM160-120q-33 0-56.5-23.5T80-200v-480q0-33 23.5-56.5T160-760h126l74-80h240l74 80h126q33 0 56.5 23.5T880-680v480q0 33-23.5 56.5T800-120H160Zm0-80h640v-480H638l-73-80H395l-73 80H160v480Zm320-240Z"/>
|
||||||
|
<path v-else-if="icon == 'cloud_upload'" d="M260-160q-91 0-155.5-63T40-377q0-78 47-139t123-78q25-92 100-149t170-57q117 0 198.5 81.5T760-520q69 8 114.5 59.5T920-340q0 75-52.5 127.5T740-160H520q-33 0-56.5-23.5T440-240v-206l-64 62-56-56 160-160 160 160-56 56-64-62v206h220q42 0 71-29t29-71q0-42-29-71t-71-29h-60v-80q0-83-58.5-141.5T480-720q-83 0-141.5 58.5T280-520h-20q-58 0-99 41t-41 99q0 58 41 99t99 41h100v80H260Zm220-280Z"/>
|
||||||
|
<path v-else-if="icon == 'cloud_done'" d="m414-280 226-226-58-58-169 169-84-84-57 57 142 142ZM260-160q-91 0-155.5-63T40-377q0-78 47-139t123-78q25-92 100-149t170-57q117 0 198.5 81.5T760-520q69 8 114.5 59.5T920-340q0 75-52.5 127.5T740-160H260Zm0-80h480q42 0 71-29t29-71q0-42-29-71t-71-29h-60v-80q0-83-58.5-141.5T480-720q-83 0-141.5 58.5T280-520h-20q-58 0-99 41t-41 99q0 58 41 99t99 41Zm220-240Z"/>
|
||||||
</svg>
|
</svg>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -16,7 +18,17 @@
|
|||||||
icon: {
|
icon: {
|
||||||
type: String,
|
type: String,
|
||||||
validator(value) {
|
validator(value) {
|
||||||
return ['image','videocam','visibility','photo_library','no_photography','photo_camera'].includes(value)
|
const iconList = [
|
||||||
|
'image',
|
||||||
|
'videocam',
|
||||||
|
'visibility',
|
||||||
|
'photo_library',
|
||||||
|
'no_photography',
|
||||||
|
'photo_camera',
|
||||||
|
'cloud_upload',
|
||||||
|
'cloud_done'
|
||||||
|
]
|
||||||
|
return iconList.includes(value)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fillColor: {
|
fillColor: {
|
||||||
|
|||||||
@@ -24,20 +24,20 @@
|
|||||||
@delete="deleteChip(result.resultIndex)"
|
@delete="deleteChip(result.resultIndex)"
|
||||||
:style="chipGradient(result.confidence)"
|
:style="chipGradient(result.confidence)"
|
||||||
/>
|
/>
|
||||||
<span v-if="showResults.filter( r => { return r.aboveThreshold && r.isSearched && !r.isDeleted }).length == 0" style="height: var(--f7-chip-height); font-size: calc(var(--f7-chip-height) - 4px); font-weight: bolder; margin: 2px;">No results.</span>
|
<span v-if="numResults == 0" style="height: var(--f7-chip-height); font-size: calc(var(--f7-chip-height) - 4px); font-weight: bolder; margin: 2px;">No results.</span>
|
||||||
</div>
|
</div>
|
||||||
<f7-segmented class="image-menu" raised>
|
<f7-segmented class="image-menu" raised>
|
||||||
<f7-button popover-open="#region-popover">
|
<f7-button popover-open="#region-popover">
|
||||||
<RegionIcon :region="activeRegion" />
|
<RegionIcon :region="activeRegion" />
|
||||||
</f7-button>
|
</f7-button>
|
||||||
<f7-button popover-open="#capture-popover">
|
<f7-button popover-open="#capture-popover">
|
||||||
<SvgIcon icon="image" fill-color="var(--avn-theme-color)"/>
|
<SvgIcon icon="image"/>
|
||||||
</f7-button>
|
</f7-button>
|
||||||
<f7-button @click="setData" :class="(imageLoaded) ? '' : 'disabled'">
|
<f7-button @click="setData" :class="(imageLoaded) ? '' : 'disabled'">
|
||||||
<SvgIcon icon="visibility" fill-color="var(--avn-theme-color)"/>
|
<SvgIcon icon="visibility"/>
|
||||||
</f7-button>
|
</f7-button>
|
||||||
<f7-button class="disabled" @click="setData">
|
<f7-button :class="(numResults && uploadDirty && viewedAll) ? '' : 'disabled'" @click="submitData">
|
||||||
<SvgIcon icon="videocam" fill-color="var(--avn-theme-color)"/>
|
<SvgIcon :icon="(uploadUid) ? 'cloud_done' : 'cloud_upload'"/>
|
||||||
</f7-button>
|
</f7-button>
|
||||||
</f7-segmented>
|
</f7-segmented>
|
||||||
<input type="file" ref="image_chooser" @change="getImage()" accept="image/*" capture="environment" style="display: none;"/>
|
<input type="file" ref="image_chooser" @change="getImage()" accept="image/*" capture="environment" style="display: none;"/>
|
||||||
@@ -56,7 +56,6 @@
|
|||||||
</f7-list>
|
</f7-list>
|
||||||
</f7-accordion-content>
|
</f7-accordion-content>
|
||||||
</f7-list-item>
|
</f7-list-item>
|
||||||
<f7-list-button title="Submit image" @click="submitData"/>
|
|
||||||
<f7-list-item title="Turn on debugging">
|
<f7-list-item title="Turn on debugging">
|
||||||
<f7-toggle v-model:checked="debugOn" style="margin-right: 16px;" />
|
<f7-toggle v-model:checked="debugOn" style="margin-right: 16px;" />
|
||||||
</f7-list-item>
|
</f7-list-item>
|
||||||
@@ -84,6 +83,9 @@
|
|||||||
|
|
||||||
<f7-popover id="capture-popover">
|
<f7-popover id="capture-popover">
|
||||||
<f7-segmented raised style="flex-wrap: wrap; flex-direction: column;">
|
<f7-segmented raised style="flex-wrap: wrap; flex-direction: column;">
|
||||||
|
<f7-button style="height: auto; width: auto;" popover-close="#capture-popover" class="disabled" @click="videoStream">
|
||||||
|
<SvgIcon icon="videocam"/>
|
||||||
|
</f7-button>
|
||||||
<f7-button style="height: auto; width: auto;" popover-close="#capture-popover" @click="selectImage('camera')">
|
<f7-button style="height: auto; width: auto;" popover-close="#capture-popover" @click="selectImage('camera')">
|
||||||
<SvgIcon icon="photo_camera" />
|
<SvgIcon icon="photo_camera" />
|
||||||
</f7-button>
|
</f7-button>
|
||||||
@@ -248,7 +250,9 @@
|
|||||||
serverSettings: {},
|
serverSettings: {},
|
||||||
debugOn: false,
|
debugOn: false,
|
||||||
debugText: ['Variables loaded'],
|
debugText: ['Variables loaded'],
|
||||||
isCordova: !!window.cordova
|
isCordova: !!window.cordova,
|
||||||
|
uploadUid: null,
|
||||||
|
uploadDirty: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
@@ -304,6 +308,7 @@
|
|||||||
},
|
},
|
||||||
showResults () {
|
showResults () {
|
||||||
var filteredResults = this.resultData.detections
|
var filteredResults = this.resultData.detections
|
||||||
|
if (!filteredResults) return []
|
||||||
var allSelect = this.detectorLabels.every( s => { return s.detect } )
|
var allSelect = this.detectorLabels.every( s => { return s.detect } )
|
||||||
var selectedLabels = this.detectorLabels
|
var selectedLabels = this.detectorLabels
|
||||||
.filter( l => { return l.detect })
|
.filter( l => { return l.detect })
|
||||||
@@ -314,6 +319,14 @@
|
|||||||
filteredResults[i].isSearched = allSelect || selectedLabels.includes(d.label)
|
filteredResults[i].isSearched = allSelect || selectedLabels.includes(d.label)
|
||||||
})
|
})
|
||||||
return filteredResults
|
return filteredResults
|
||||||
|
},
|
||||||
|
numResults () {
|
||||||
|
return this.showResults.filter( r => { return r.aboveThreshold && r.isSearched && !r.isDeleted }).length
|
||||||
|
},
|
||||||
|
viewedAll () {
|
||||||
|
return this.resultData.detections
|
||||||
|
.filter( s => { return s.confidence >= this.detectorLevel})
|
||||||
|
.every( s => { return s.beenViewed })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -337,6 +350,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.resultData = JSON.parse(xhr.response)
|
self.resultData = JSON.parse(xhr.response)
|
||||||
|
self.uploadDirty = true
|
||||||
}
|
}
|
||||||
|
|
||||||
var doodsData = {
|
var doodsData = {
|
||||||
@@ -402,11 +416,13 @@
|
|||||||
box.style.top = `${(img.offsetHeight - imgHeight) / 2 + this.resultData.detections[iChip].top * imgHeight}px`
|
box.style.top = `${(img.offsetHeight - imgHeight) / 2 + this.resultData.detections[iChip].top * imgHeight}px`
|
||||||
box.style.width = `${(Math.min(this.resultData.detections[iChip].right, 1) - Math.max(this.resultData.detections[iChip].left, 0)) * imgWidth}px`
|
box.style.width = `${(Math.min(this.resultData.detections[iChip].right, 1) - Math.max(this.resultData.detections[iChip].left, 0)) * imgWidth}px`
|
||||||
box.style.height = `${(Math.min(this.resultData.detections[iChip].bottom, 1) - Math.max(this.resultData.detections[iChip].top, 0)) * imgHeight}px`
|
box.style.height = `${(Math.min(this.resultData.detections[iChip].bottom, 1) - Math.max(this.resultData.detections[iChip].top, 0)) * imgHeight}px`
|
||||||
|
this.resultData.detections[iChip].beenViewed = true
|
||||||
},
|
},
|
||||||
deleteChip ( iChip ) {
|
deleteChip ( iChip ) {
|
||||||
f7.dialog.confirm(`${this.resultData.detections[iChip].label} is identified with ${this.resultData.detections[iChip].confidence.toFixed(1)}% confidence. Are you sure you want to delete it?`, () => {
|
f7.dialog.confirm(`${this.resultData.detections[iChip].label} is identified with ${this.resultData.detections[iChip].confidence.toFixed(1)}% confidence. Are you sure you want to delete it?`, () => {
|
||||||
this.resultData.detections.splice(iChip, 1)
|
this.resultData.detections.splice(iChip, 1)
|
||||||
this.resetView()
|
this.resetView()
|
||||||
|
this.uploadDirty = true
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
getImage (searchImage) {
|
getImage (searchImage) {
|
||||||
@@ -436,8 +452,16 @@
|
|||||||
const box = this.$refs.structure_box
|
const box = this.$refs.structure_box
|
||||||
box.style.display = 'none'
|
box.style.display = 'none'
|
||||||
},
|
},
|
||||||
submitData () {
|
videoStream() {
|
||||||
this.uploadData(this.imageView.split(',')[1],this.resultData.detections)
|
//TODO
|
||||||
|
return null
|
||||||
|
},
|
||||||
|
async submitData () {
|
||||||
|
var uploadData = this.showResults
|
||||||
|
.filter( d => { return d.aboveThreshold && d.isSearched && !d.isDeleted })
|
||||||
|
.map( r => { return {"top": r.top, "left": r.left, "bottom": r.bottom, "right": r.right, "label": r.label}})
|
||||||
|
this.uploadUid = await this.uploadData(this.imageView.split(',')[1],uploadData,this.uploadUid)
|
||||||
|
if (this.uploadUid) { this.uploadDirty = false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ export default {
|
|||||||
}
|
}
|
||||||
return uid.join('')
|
return uid.join('')
|
||||||
},
|
},
|
||||||
uploadData (imagePayload, classPayload) {
|
uploadData (imagePayload, classPayload, prevUid) {
|
||||||
let uploadImage =new Promise(resolve => {
|
let uploadImage = new Promise (resolve => {
|
||||||
const dataUid = this.newUid(16)
|
const dataUid = prevUid || this.newUid(16)
|
||||||
var byteChars = window.atob(imagePayload)
|
var byteChars = window.atob(imagePayload)
|
||||||
var byteArrays = []
|
var byteArrays = []
|
||||||
var len = byteChars.length
|
var len = byteChars.length
|
||||||
@@ -34,6 +34,7 @@ export default {
|
|||||||
var uploadUrl = `https://nextcloud.azgeorgis.net/public.php/webdav/${dataUid}.jpeg`
|
var uploadUrl = `https://nextcloud.azgeorgis.net/public.php/webdav/${dataUid}.jpeg`
|
||||||
xhrJpg.open("PUT", uploadUrl)
|
xhrJpg.open("PUT", uploadUrl)
|
||||||
xhrJpg.setRequestHeader('Content-Type', 'image/jpeg')
|
xhrJpg.setRequestHeader('Content-Type', 'image/jpeg')
|
||||||
|
xhrJpg.setRequestHeader('X-Method-Override', 'PUT')
|
||||||
xhrJpg.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
|
xhrJpg.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
|
||||||
xhrJpg.setRequestHeader("Authorization", "Basic " + btoa("LKBm3H6JdSaywyg:"))
|
xhrJpg.setRequestHeader("Authorization", "Basic " + btoa("LKBm3H6JdSaywyg:"))
|
||||||
xhrJpg.send(imageBlob)
|
xhrJpg.send(imageBlob)
|
||||||
@@ -42,21 +43,24 @@ export default {
|
|||||||
var uploadUrl = `https://nextcloud.azgeorgis.net/public.php/webdav/${dataUid}.txt`
|
var uploadUrl = `https://nextcloud.azgeorgis.net/public.php/webdav/${dataUid}.txt`
|
||||||
xhrTxt.open("PUT", uploadUrl)
|
xhrTxt.open("PUT", uploadUrl)
|
||||||
xhrTxt.setRequestHeader('Content-Type', 'text/plain')
|
xhrTxt.setRequestHeader('Content-Type', 'text/plain')
|
||||||
|
xhrTxt.setRequestHeader('X-Method-Override', 'PUT')
|
||||||
xhrTxt.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
|
xhrTxt.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
|
||||||
xhrTxt.setRequestHeader("Authorization", "Basic " + btoa("LKBm3H6JdSaywyg:"))
|
xhrTxt.setRequestHeader("Authorization", "Basic " + btoa("LKBm3H6JdSaywyg:"))
|
||||||
xhrTxt.send(JSON.stringify(classPayload))
|
xhrTxt.send(JSON.stringify(classPayload))
|
||||||
|
|
||||||
resolve()
|
resolve(dataUid)
|
||||||
})
|
})
|
||||||
uploadImage.then(() => {
|
return uploadImage.then((newUid) => {
|
||||||
var toast = f7.toast.create({
|
var toast = f7.toast.create({
|
||||||
text: 'Detections Uploaded: thank you.',
|
text: 'Detections Uploaded: thank you.',
|
||||||
closeTimeout: 2000
|
closeTimeout: 2000
|
||||||
})
|
})
|
||||||
toast.open()
|
toast.open()
|
||||||
|
return newUid
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
console.log(e.message)
|
console.log(e.message)
|
||||||
f7.dialog.alert(`Error uploading image: ${e.message}`)
|
f7.dialog.alert(`Error uploading image: ${e.message}`)
|
||||||
|
return null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user