mirror of
https://github.com/Fabio286/antares.git
synced 2025-06-05 21:59:22 +02:00
Start implementing fields edit
This commit is contained in:
@ -45,7 +45,7 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
updateStatus: 'application/getUpdateStatus',
|
updateStatus: 'application/getUpdateStatus',
|
||||||
downloadPercentage: 'application/getDownloadProgress'// TODO: remove float
|
downloadPercentage: 'application/getDownloadProgress'
|
||||||
}),
|
}),
|
||||||
updateMessage () {
|
updateMessage () {
|
||||||
switch (this.updateStatus) {
|
switch (this.updateStatus) {
|
||||||
|
@ -82,7 +82,6 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions({
|
...mapActions({
|
||||||
addNotification: 'notifications/addNotification',
|
|
||||||
addWorkspace: 'workspaces/addWorkspace',
|
addWorkspace: 'workspaces/addWorkspace',
|
||||||
connectWorkspace: 'workspaces/connectWorkspace',
|
connectWorkspace: 'workspaces/connectWorkspace',
|
||||||
removeConnected: 'workspaces/removeConnected',
|
removeConnected: 'workspaces/removeConnected',
|
||||||
|
@ -45,7 +45,6 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions({
|
...mapActions({
|
||||||
addNotification: 'notifications/addNotification',
|
|
||||||
connectWorkspace: 'workspaces/connectWorkspace'
|
connectWorkspace: 'workspaces/connectWorkspace'
|
||||||
}),
|
}),
|
||||||
async startConnection () {
|
async startConnection () {
|
||||||
|
@ -34,16 +34,14 @@
|
|||||||
:key="row._id"
|
:key="row._id"
|
||||||
class="tr"
|
class="tr"
|
||||||
>
|
>
|
||||||
<div
|
<WorkspaceQueryTableCell
|
||||||
v-for="(col, cKey) in row"
|
v-for="(col, cKey) in row"
|
||||||
:key="cKey"
|
:key="cKey"
|
||||||
class="td"
|
:content="col"
|
||||||
:class="`type-${fieldType(cKey)}${isNull(col)}`"
|
:field="cKey"
|
||||||
:style="{'display': cKey === '_id' ? 'none' : ''}"
|
:type="fieldType(cKey)"
|
||||||
tabindex="0"
|
@updateField="updateField"
|
||||||
>
|
/>
|
||||||
{{ col | typeFormat(fieldType(cKey)) }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -52,48 +50,16 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { uidGen, mimeFromHex, formatBytes } from 'common/libs/utilities';
|
import { uidGen } from 'common/libs/utilities';
|
||||||
import hexToBinary from 'common/libs/hexToBinary';
|
|
||||||
import moment from 'moment';
|
|
||||||
import BaseVirtualScroll from '@/components/BaseVirtualScroll';
|
import BaseVirtualScroll from '@/components/BaseVirtualScroll';
|
||||||
|
import WorkspaceQueryTableCell from '@/components/WorkspaceQueryTableCell';
|
||||||
|
import { mapActions } from 'vuex';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'WorkspaceQueryTable',
|
name: 'WorkspaceQueryTable',
|
||||||
components: {
|
components: {
|
||||||
BaseVirtualScroll
|
BaseVirtualScroll,
|
||||||
},
|
WorkspaceQueryTableCell
|
||||||
filters: {
|
|
||||||
typeFormat (val, type) {
|
|
||||||
if (!val) return val;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case 'char':
|
|
||||||
case 'varchar':
|
|
||||||
case 'text':
|
|
||||||
case 'mediumtext':
|
|
||||||
return val.substring(0, 128);
|
|
||||||
case 'date':
|
|
||||||
return moment(val).format('YYYY-MM-DD');
|
|
||||||
case 'datetime':
|
|
||||||
case 'timestamp':
|
|
||||||
return moment(val).format('YYYY-MM-DD HH:mm:ss.SSS');
|
|
||||||
case 'blob':
|
|
||||||
case 'mediumblob':
|
|
||||||
case 'longblob': {
|
|
||||||
const buff = Buffer.from(val);
|
|
||||||
if (!buff.length) return '';
|
|
||||||
|
|
||||||
const hex = buff.toString('hex').substring(0, 8).toUpperCase();
|
|
||||||
return `${mimeFromHex(hex).mime} (${formatBytes(buff.length)})`;
|
|
||||||
}
|
|
||||||
case 'bit': {
|
|
||||||
const hex = Buffer.from(val).toString('hex');
|
|
||||||
return hexToBinary(hex);
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
results: Object,
|
results: Object,
|
||||||
@ -105,6 +71,11 @@ export default {
|
|||||||
localResults: []
|
localResults: []
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
primaryField () {
|
||||||
|
return this.fields.filter(field => field.key === 'pri')[0] || false;
|
||||||
|
}
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
results () {
|
results () {
|
||||||
this.localResults = this.results.rows ? this.results.rows.map(item => {
|
this.localResults = this.results.rows ? this.results.rows.map(item => {
|
||||||
@ -123,6 +94,9 @@ export default {
|
|||||||
window.removeEventListener('resize', this.resizeResults);
|
window.removeEventListener('resize', this.resizeResults);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
...mapActions({
|
||||||
|
addNotification: 'notifications/addNotification'
|
||||||
|
}),
|
||||||
fieldType (cKey) {
|
fieldType (cKey) {
|
||||||
let type = 'unknown';
|
let type = 'unknown';
|
||||||
const field = this.fields.filter(field => field.name === cKey)[0];
|
const field = this.fields.filter(field => field.name === cKey)[0];
|
||||||
@ -131,9 +105,6 @@ export default {
|
|||||||
|
|
||||||
return type;
|
return type;
|
||||||
},
|
},
|
||||||
isNull (col) {
|
|
||||||
return col === null ? ' is-null' : '';
|
|
||||||
},
|
|
||||||
keyName (key) {
|
keyName (key) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'pri':
|
case 'pri':
|
||||||
@ -156,6 +127,11 @@ export default {
|
|||||||
this.resultsSize = size;
|
this.resultsSize = size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
updateField (payload) {
|
||||||
|
if (!this.primaryField)
|
||||||
|
this.addNotification({ status: 'warning', message: this.$t('message.unableEditFieldWithoutPrimary') });
|
||||||
|
console.log(payload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
147
src/renderer/components/WorkspaceQueryTableCell.vue
Normal file
147
src/renderer/components/WorkspaceQueryTableCell.vue
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-if="field !== '_id'"
|
||||||
|
ref="cell"
|
||||||
|
class="td"
|
||||||
|
:class="`type-${type} p-0`"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
v-if="!isEditing"
|
||||||
|
class="cell-content px-2"
|
||||||
|
:class="isNull(content)"
|
||||||
|
@dblclick="editON"
|
||||||
|
>{{ content | typeFormat(type) }}</span>
|
||||||
|
<input
|
||||||
|
v-else
|
||||||
|
ref="editField"
|
||||||
|
v-model="localContent"
|
||||||
|
:type="inputType"
|
||||||
|
autofocus
|
||||||
|
class="editable-field px-2"
|
||||||
|
@blur="editOFF"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import moment from 'moment';
|
||||||
|
import { mimeFromHex, formatBytes } from 'common/libs/utilities';
|
||||||
|
import hexToBinary from 'common/libs/hexToBinary';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'WorkspaceQueryTableCell',
|
||||||
|
filters: {
|
||||||
|
typeFormat (val, type) {
|
||||||
|
if (!val) return val;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'char':
|
||||||
|
case 'varchar':
|
||||||
|
case 'text':
|
||||||
|
case 'mediumtext':
|
||||||
|
return val.substring(0, 128);
|
||||||
|
case 'date':
|
||||||
|
return moment(val).format('YYYY-MM-DD');
|
||||||
|
case 'datetime':
|
||||||
|
case 'timestamp':
|
||||||
|
return moment(val).format('YYYY-MM-DD HH:mm:ss.SSS');
|
||||||
|
case 'blob':
|
||||||
|
case 'mediumblob':
|
||||||
|
case 'longblob': {
|
||||||
|
const buff = Buffer.from(val);
|
||||||
|
if (!buff.length) return '';
|
||||||
|
|
||||||
|
const hex = buff.toString('hex').substring(0, 8).toUpperCase();
|
||||||
|
return `${mimeFromHex(hex).mime} (${formatBytes(buff.length)})`;
|
||||||
|
}
|
||||||
|
case 'bit': {
|
||||||
|
const hex = Buffer.from(val).toString('hex');
|
||||||
|
return hexToBinary(hex);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
type: String,
|
||||||
|
field: String,
|
||||||
|
content: [String, Number, Object, Date, Uint8Array]
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
isEditing: false,
|
||||||
|
localContent: ''
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
inputType () {
|
||||||
|
switch (this.type) {
|
||||||
|
case 'char':
|
||||||
|
case 'varchar':
|
||||||
|
case 'text':
|
||||||
|
case 'mediumtext':
|
||||||
|
return 'text';
|
||||||
|
case 'int':
|
||||||
|
case 'tinyint':
|
||||||
|
case 'smallint':
|
||||||
|
case 'mediumint':
|
||||||
|
return 'number';
|
||||||
|
case 'date':
|
||||||
|
return 'date';
|
||||||
|
case 'datetime':
|
||||||
|
case 'timestamp':
|
||||||
|
return 'datetime-local';
|
||||||
|
// TODO: file uploader/viewer or bit field
|
||||||
|
case 'blob':
|
||||||
|
case 'mediumblob':
|
||||||
|
case 'longblob':
|
||||||
|
case 'bit':
|
||||||
|
default:
|
||||||
|
return 'text';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
isNull (value) {
|
||||||
|
return value === null ? ' is-null' : '';
|
||||||
|
},
|
||||||
|
editON () {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.cell.blur();
|
||||||
|
|
||||||
|
this.$nextTick(() => this.$refs.editField.focus());
|
||||||
|
});
|
||||||
|
this.localContent = this.$options.filters.typeFormat(this.content, this.type);
|
||||||
|
this.isEditing = true;
|
||||||
|
},
|
||||||
|
editOFF () {
|
||||||
|
this.isEditing = false;
|
||||||
|
if (this.localContent === this.content) return;
|
||||||
|
|
||||||
|
const { field, localContent: content } = this;
|
||||||
|
this.$emit('updateField', { field, content });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.editable-field{
|
||||||
|
margin: 0;
|
||||||
|
border: none;
|
||||||
|
line-height: 1;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell-content{
|
||||||
|
display: block;
|
||||||
|
min-height: .8rem;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
max-width: 200px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
</style>
|
@ -51,7 +51,8 @@ module.exports = {
|
|||||||
updateAvailable: 'Update available',
|
updateAvailable: 'Update available',
|
||||||
downloadingUpdate: 'Downloading update',
|
downloadingUpdate: 'Downloading update',
|
||||||
updateDownloaded: 'Update downloaded',
|
updateDownloaded: 'Update downloaded',
|
||||||
restartToInstall: 'Restart Antares to install'
|
restartToInstall: 'Restart Antares to install',
|
||||||
|
unableEditFieldWithoutPrimary: 'Unable to edit a field without a primary key in resultset'
|
||||||
},
|
},
|
||||||
// Date and Time
|
// Date and Time
|
||||||
short: {
|
short: {
|
||||||
|
@ -7,6 +7,7 @@ $bg-color-gray: #272727;
|
|||||||
$primary-color: #e36929;
|
$primary-color: #e36929;
|
||||||
$success-color: #32b643;
|
$success-color: #32b643;
|
||||||
$error-color: #de3b28;
|
$error-color: #de3b28;
|
||||||
|
$warning-color: #e0a40c;
|
||||||
|
|
||||||
/*Sizes*/
|
/*Sizes*/
|
||||||
$titlebar-height: 1.5rem;
|
$titlebar-height: 1.5rem;
|
||||||
|
@ -24,7 +24,7 @@ export default {
|
|||||||
isSettingModal: state => state.is_setting_modal,
|
isSettingModal: state => state.is_setting_modal,
|
||||||
selectedSettingTab: state => state.selected_setting_tab,
|
selectedSettingTab: state => state.selected_setting_tab,
|
||||||
getUpdateStatus: state => state.update_status,
|
getUpdateStatus: state => state.update_status,
|
||||||
getDownloadProgress: state => state.download_progress
|
getDownloadProgress: state => Number(state.download_progress.toFixed(1))
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
SET_LOADING_STATUS (state, payload) {
|
SET_LOADING_STATUS (state, payload) {
|
||||||
|
Reference in New Issue
Block a user