Skip to content

Commit

Permalink
Merge pull request #25 from Rena-Yuan/feature/upload-attachments-support
Browse files Browse the repository at this point in the history
Support upload attachments
  • Loading branch information
Rena-Yuan authored Mar 23, 2022
2 parents 66d0957 + d5ddc44 commit 2d0cb8f
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 38 deletions.
8 changes: 5 additions & 3 deletions frontend/src/components/form/AttachmentItem.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<template>
<FormItem>
<Tooltip content="Click to preview" placement="top">
<a style="padding-right:10px;color:#515a6e" @click="displayAttach(data)">{{data.name}}</a>
<a style="padding-right:10px;color:#515a6e" @click="displayAttach(data)">
<Icon type="md-attach" /> {{data.name}}
</a>
</Tooltip>
<Tooltip content="Delete this attachment" placement="top">
<a @click="deleteAttach(data)">delete</a>
Expand All @@ -13,10 +15,10 @@
export default {
props: ['data', 'index'],
methods: {
deleteAttach(data) {
deleteAttach (data) {
this.$store.dispatch('removeAttachment', { id: data.id, index: this.index })
},
displayAttach(data) {
displayAttach (data) {
this.$bus.$emit('displayAttach', data)
}
}
Expand Down
19 changes: 9 additions & 10 deletions frontend/src/components/form/AttachmentModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,16 @@ import ImageEditor from '@/components/form/ImageEditor.vue'
import FileViewer from '@/components/form/FileViewer.vue'
import CodeEditor from '@/components/event/CodeEditor.vue'
export default {
components: {
ImageEditor,
FileViewer,
CodeEditor
},
created() {
created () {
this.$bus.$on('displayAttach', this.displayAttach)
},
data() {
data () {
return {
isDisplayFile: false,
attachmentName: null,
Expand All @@ -55,34 +54,34 @@ export default {
}
},
computed: {
isImageFile() {
isImageFile () {
if (!this.attachmentName) {
return false
}
const imageFileSuffix = ['png', 'jpg', 'jpeg', 'webp']
const imageFileSuffix = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'wbmp', 'webp', 'tif', 'psd']
let nameSplit = this.attachmentName.split('.')
let nameSuffix = nameSplit[nameSplit.length - 1]
return imageFileSuffix.indexOf(nameSuffix) > -1
},
isSnapshot() {
isSnapshot () {
if (this.attachmentContent) {
this.attachmentContent = JSON.stringify(this.attachmentContent, null, 2)
return true
}else {
return true
} else {
return false
}
}
},
methods: {
displayAttach(data) {
displayAttach (data) {
this.isDisplayFile = true
this.attachmentName = data.name
this.attachmentId = data.id
this.attachmentContent = data.eventObj
},
saveImage() {
saveImage () {
this.$bus.$emit('saveImage')
this.isDisplayFile = false
}
Expand Down
32 changes: 22 additions & 10 deletions frontend/src/components/form/AttachmentsList.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<FormItem label="attachments">
<FormItem label="Attachments">
<div v-if="attachments.length">
<p v-for="(attachment, index) in attachments" :key="index">
<AttachmentItem :data="attachment" :index="index"/>
Expand All @@ -10,9 +10,21 @@
<SnapshotItem :data="snapshot" :index="index"/>
</p>
</div>
<div v-else-if="!attachments.length">
<p style="color:#c5c8ce">No attachment</p>
</div>
<Upload
multiple
action="/plugins/bugit/api/attachments"
:format="['jpg','jpeg','png','gif','bmp','wbmp','webp','tif','psd']"
accept=".jpg,.jpeg,.png,.gif,.bmp,.wbmp,.webp,.tif,.psd"
:show-upload-list="false"
>
<Tooltip
placement="right"
content="Support .jpg/.jpeg/.png/.gif/.bmp/.wbmp/.webp/.tif/.psd files"
max-width="450"
>
<a><Icon type="md-add" /> Add attachments</a>
</Tooltip>
</Upload>
</FormItem>
</template>

Expand All @@ -25,27 +37,27 @@ export default {
AttachmentItem,
SnapshotItem
},
created() {
created () {
this.$io.on('attachments', this.addAttachment)
this.$bus.$on('addAttachments', this.addAttachment)
this.$bus.$on('addSnapshot', this.addSnapshot)
this.$store.dispatch('loadAttachment')
},
computed: {
attachments() {
attachments () {
return this.$store.state.form.attachmentsList
},
snapshots() {
snapshots () {
return this.$store.state.form.snapshotList
}
},
methods: {
addAttachment() {
addAttachment () {
this.$store.dispatch('loadAttachment')
},
addSnapshot(snapshot) {
addSnapshot (snapshot) {
this.$store.commit('addSnapshot', snapshot)
}
}
};
}
</script>
10 changes: 5 additions & 5 deletions frontend/src/components/form/MovableDescription.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@
export default {
props: ["data", "index"],
methods: {
deleteDesc(index) {
this.$parent.$parent.deleteDesc(index);
deleteDesc (index) {
this.$parent.$parent.deleteDesc(index)
},
sortDesc(index) {
this.$parent.$parent.sortDesc(index);
sortDesc (index) {
this.$parent.$parent.sortDesc(index)
}
}
};
}
</script>
4 changes: 3 additions & 1 deletion frontend/src/components/form/SnapshotItem.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<template>
<FormItem>
<Tooltip content="Click to preview" placement="top">
<a style="padding-right:10px;color:#515a6e" @click="displayAttach(data)">{{data.name}}</a>
<a style="padding-right:10px;color:#515a6e" @click="displayAttach(data)">
<Icon type="md-attach" /> {{data.name}}
</a>
</Tooltip>
<Tooltip content="Delete this snapshot" placement="top">
<a @click="deleteAttach(data)">delete</a>
Expand Down
30 changes: 23 additions & 7 deletions lyrebird_bugit/apis.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import imp
import json
import base64
import codecs
import inspect
Expand All @@ -12,12 +10,14 @@
from . import event_handler
from . import template_loader
from . import cache
from . import upload
from . import attachment
import traceback


logger = log.get_logger()


def template():
if request.method == 'GET':
'''
Expand Down Expand Up @@ -153,11 +153,15 @@ def _update_device_info(device_info, platform="Android"):
def attachments(attachment_id=None):
if request.method == 'GET':
if not attachment_id:
return jsonify(list(event_handler.attachments.values()))
attachment_list = list(event_handler.attachments.values())
if not attachment_list:
upload.reset_dir()
attachment.remove_attach()
return jsonify(attachment_list)
else:
attachment = event_handler.attachments.get(attachment_id)
if attachment:
return send_file(attachment['path'])
attachment_item = event_handler.attachments.get(attachment_id)
if attachment_item:
return send_file(attachment_item['path'])
else:
return make_fail_response('Not found attachment')

Expand All @@ -174,9 +178,21 @@ def attachments(attachment_id=None):
return make_ok_response(message=f'Edited picture {name} has been saved')

elif request.method == 'DELETE':
event_handler.attachments.pop(attachment_id)
attachment_item = event_handler.attachments.pop(attachment_id)
upload.delete(attachment_item.get('path'))
return make_ok_response()

# Upload attachment files
elif request.method == 'POST':
if request.files:
stream = request.files['file']
if not stream:
return application.make_fail_response('Missing file data')

upload.add(stream)
return application.make_ok_response()
return application.make_fail_response('No upload file found')


def ui_cache(template_key):
if request.method == 'GET':
Expand Down
11 changes: 11 additions & 0 deletions lyrebird_bugit/event_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,14 @@ def on_ios_screenshot(msg):
'name': item['screenshot']['name'],
'path': item['screenshot']['path']}
lyrebird.emit('attachments')


def on_upload_files(msg):
if len(msg) == 0:
return
for item in msg:
attachment_id = str(uuid4())
attachments[attachment_id] = {'id': attachment_id,
'name': item['upload_file']['name'],
'path': item['upload_file']['path']}
lyrebird.emit('attachments')
5 changes: 3 additions & 2 deletions lyrebird_bugit/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
('/api/device', apis.device, ['GET']),
('/api/issue', apis.issue, ['GET', 'POST']),
('/api/take_screenshot/<string:platform>/<string:device_id>', apis.take_screenshot, ['GET']),
('/api/attachments', apis.attachments, ['GET']),
('/api/attachments', apis.attachments, ['GET', 'POST']),
('/api/attachments/<string:attachment_id>', apis.attachments, ['GET', 'PUT', 'DELETE']),
('/api/cache/<string:template_key>', apis.ui_cache, ['GET', 'POST', 'DELETE'])
],
event=[
('android.device', event_handler.on_android_device),
('ios.device', event_handler.on_ios_device),
('android.screenshot', event_handler.on_android_screenshot),
('ios.screenshot', event_handler.on_ios_screenshot)
('ios.screenshot', event_handler.on_ios_screenshot),
('upload_files', event_handler.on_upload_files)
]
)
71 changes: 71 additions & 0 deletions lyrebird_bugit/upload.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import os
import time
import codecs
import shutil
import uuid
import lyrebird
from pathlib import Path
from lyrebird import publish


logger = lyrebird.log.get_logger()

BUGIT_STORAGE = lyrebird.get_plugin_storage()
UPLOAD_ROOT = Path(BUGIT_STORAGE)/'upload'


def get(file_name):
_check_dir()
file_path = Path(UPLOAD_ROOT).joinpath(file_name)
if not file_path.exists():
return None
try:
with codecs.open(str(file_path), 'rb') as f:
return f.read()
except Exception:
return None


def _build_file_name(stream):
if not stream.filename:
return str(uuid.uuid4())
file_name_base, file_name_ext = os.path.splitext(stream.filename)
file_name = f'{file_name_base}_{int(time.time())}{file_name_ext}'
return file_name


def add(stream):
_check_dir()
file_name = _build_file_name(stream)
file_path = Path(UPLOAD_ROOT).joinpath(file_name)
stream.save(str(file_path))
upload_files = []
upload_files.append(
{
'id': file_name,
'upload_file': {
'name': file_name,
'path': str(file_path)
}
}
)
publish('upload_files', upload_files)


def delete(file_path):
file_path = Path(file_path)
if file_path.parent != UPLOAD_ROOT:
return
if file_path.exists() and file_path.is_file():
file_path.unlink()


def _check_dir():
if not UPLOAD_ROOT.exists():
UPLOAD_ROOT.mkdir(parents=True, exist_ok=True)


def reset_dir():
logger.debug('Upload files reset')
if UPLOAD_ROOT.exists():
shutil.rmtree(UPLOAD_ROOT)

0 comments on commit 2d0cb8f

Please sign in to comment.