mirror of https://github.com/Fabio286/antares.git
refactor: improvements to blob editor and code cleanup
This commit is contained in:
parent
712fe9f00d
commit
4fd72ec9e7
|
@ -0,0 +1,12 @@
|
||||||
|
export const TEXT = ['char', 'varchar'];
|
||||||
|
export const LONG_TEXT = ['text', 'mediumtext', 'longtext'];
|
||||||
|
|
||||||
|
export const NUMBER = ['int', 'tinyint', 'smallint', 'mediumint', 'bigint'];
|
||||||
|
|
||||||
|
export const DATE = ['date'];
|
||||||
|
export const TIME = ['time'];
|
||||||
|
export const DATETIME = ['datetime', 'timestamp'];
|
||||||
|
|
||||||
|
export const BLOB = ['blob', 'mediumblob', 'longblob'];
|
||||||
|
|
||||||
|
export const BIT = ['bit'];
|
|
@ -0,0 +1,7 @@
|
||||||
|
'use strict';
|
||||||
|
export function bufferToBase64 (buf) {
|
||||||
|
const binstr = Array.prototype.map.call(buf, ch => {
|
||||||
|
return String.fromCharCode(ch);
|
||||||
|
}).join('');
|
||||||
|
return btoa(binstr);
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
'use strict';
|
||||||
|
export function formatBytes (bytes, decimals = 2) {
|
||||||
|
if (bytes === 0) return '0 Bytes';
|
||||||
|
|
||||||
|
const k = 1024;
|
||||||
|
const dm = decimals < 0 ? 0 : decimals;
|
||||||
|
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||||
|
|
||||||
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
|
||||||
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
||||||
|
}
|
|
@ -1,7 +1,4 @@
|
||||||
export function uidGen () {
|
'use strict';
|
||||||
return Math.random().toString(36).substr(2, 9).toUpperCase();
|
|
||||||
};
|
|
||||||
|
|
||||||
export function mimeFromHex (hex) {
|
export function mimeFromHex (hex) {
|
||||||
switch (hex.substring(0, 4)) { // 2 bytes
|
switch (hex.substring(0, 4)) { // 2 bytes
|
||||||
case '424D':
|
case '424D':
|
||||||
|
@ -39,28 +36,11 @@ export function mimeFromHex (hex) {
|
||||||
return { ext: 'bpg', mime: 'image/bpg' };
|
return { ext: 'bpg', mime: 'image/bpg' };
|
||||||
case '4D4D002A':
|
case '4D4D002A':
|
||||||
return { ext: 'tif', mime: 'image/tiff' };
|
return { ext: 'tif', mime: 'image/tiff' };
|
||||||
|
case '00000100':
|
||||||
|
return { ext: 'ico', mime: 'image/x-icon' };
|
||||||
default:
|
default:
|
||||||
return { ext: '', mime: 'unknown ' + hex };
|
return { ext: '', mime: 'unknown ' + hex };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export function formatBytes (bytes, decimals = 2) {
|
|
||||||
if (bytes === 0) return '0 Bytes';
|
|
||||||
|
|
||||||
const k = 1024;
|
|
||||||
const dm = decimals < 0 ? 0 : decimals;
|
|
||||||
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
|
||||||
|
|
||||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
||||||
|
|
||||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function bufferToBase64 (buf) {
|
|
||||||
const binstr = Array.prototype.map.call(buf, ch => {
|
|
||||||
return String.fromCharCode(ch);
|
|
||||||
}).join('');
|
|
||||||
return btoa(binstr);
|
|
||||||
}
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
'use strict';
|
||||||
|
export function uidGen () {
|
||||||
|
return Math.random().toString(36).substr(2, 9).toUpperCase();
|
||||||
|
};
|
|
@ -248,7 +248,7 @@ export class AntaresConnector {
|
||||||
* @memberof AntaresConnector
|
* @memberof AntaresConnector
|
||||||
*/
|
*/
|
||||||
async raw (sql) {
|
async raw (sql) {
|
||||||
if (process.env.NODE_ENV === 'development') this._logger(sql);
|
if (process.env.NODE_ENV === 'development') this._logger(sql);// TODO: replace BLOB content with a placeholder
|
||||||
|
|
||||||
switch (this._client) { // TODO: uniform fields with every client type, needed table name and fields array
|
switch (this._client) { // TODO: uniform fields with every client type, needed table name and fields array
|
||||||
case 'maria':
|
case 'maria':
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
import { sqlEscaper } from 'common/libs/sqlEscaper';
|
import { sqlEscaper } from 'common/libs/sqlEscaper';
|
||||||
|
import { TEXT, LONG_TEXT, NUMBER, BLOB } from 'common/fieldTypes';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
|
||||||
export default class {
|
export default class {
|
||||||
|
@ -14,38 +15,32 @@ export default class {
|
||||||
|
|
||||||
static async updateTableCell (connection, params) {
|
static async updateTableCell (connection, params) {
|
||||||
let escapedParam;
|
let escapedParam;
|
||||||
switch (params.type) {
|
let reload = false;
|
||||||
case 'int':
|
|
||||||
case 'tinyint':
|
if (NUMBER.includes(params.type))
|
||||||
case 'smallint':
|
|
||||||
case 'mediumint':
|
|
||||||
case 'bigint':
|
|
||||||
escapedParam = params.content;
|
escapedParam = params.content;
|
||||||
break;
|
else if ([...TEXT, ...LONG_TEXT].includes(params.type))
|
||||||
case 'char':
|
|
||||||
case 'varchar':
|
|
||||||
case 'text':
|
|
||||||
case 'mediumtext':
|
|
||||||
case 'longtext':
|
|
||||||
escapedParam = `"${sqlEscaper(params.content)}"`;
|
escapedParam = `"${sqlEscaper(params.content)}"`;
|
||||||
break;
|
else if (BLOB.includes(params.type)) {
|
||||||
case 'blob':
|
if (params.content) {
|
||||||
case 'mediumblob':
|
|
||||||
case 'longblob': {
|
|
||||||
const fileBlob = fs.readFileSync(params.content);
|
const fileBlob = fs.readFileSync(params.content);
|
||||||
escapedParam = `0x${fileBlob.toString('hex')}`;
|
escapedParam = `0x${fileBlob.toString('hex')}`;
|
||||||
|
reload = true;
|
||||||
}
|
}
|
||||||
break;
|
else
|
||||||
default:
|
escapedParam = '""';
|
||||||
|
}
|
||||||
|
else
|
||||||
escapedParam = `"${sqlEscaper(params.content)}"`;
|
escapedParam = `"${sqlEscaper(params.content)}"`;
|
||||||
break;
|
|
||||||
}
|
await connection
|
||||||
return connection
|
|
||||||
.update({ [params.field]: `= ${escapedParam}` })
|
.update({ [params.field]: `= ${escapedParam}` })
|
||||||
.schema(params.schema)
|
.schema(params.schema)
|
||||||
.from(params.table)
|
.from(params.table)
|
||||||
.where({ [params.primary]: `= ${params.id}` })
|
.where({ [params.primary]: `= ${params.id}` })
|
||||||
.run();
|
.run();
|
||||||
|
|
||||||
|
return { reload };
|
||||||
}
|
}
|
||||||
|
|
||||||
static async deleteTableRows (connection, params) {
|
static async deleteTableRows (connection, params) {
|
||||||
|
|
|
@ -29,13 +29,13 @@
|
||||||
class="btn btn-primary mr-2"
|
class="btn btn-primary mr-2"
|
||||||
@click="confirmModal"
|
@click="confirmModal"
|
||||||
>
|
>
|
||||||
{{ $t('word.confirm') }}
|
{{ confirmText || $t('word.confirm') }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="btn btn-link"
|
class="btn btn-link"
|
||||||
@click="hideModal"
|
@click="hideModal"
|
||||||
>
|
>
|
||||||
{{ $t('word.cancel') }}
|
{{ cancelText || $t('word.cancel') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -48,8 +48,11 @@ export default {
|
||||||
props: {
|
props: {
|
||||||
size: {
|
size: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'small' // small, medium, large
|
validator: prop => ['small', 'medium', 'large'].includes(prop),
|
||||||
}
|
default: 'small'
|
||||||
|
},
|
||||||
|
confirmText: String,
|
||||||
|
cancelText: String
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
hasHeader () {
|
hasHeader () {
|
||||||
|
|
|
@ -148,7 +148,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { mapActions } from 'vuex';
|
import { mapActions } from 'vuex';
|
||||||
import Connection from '@/ipc-api/Connection';
|
import Connection from '@/ipc-api/Connection';
|
||||||
import { uidGen } from 'common/libs/utilities';
|
import { uidGen } from 'common/libs/uidGen';
|
||||||
import ModalAskCredentials from '@/components/ModalAskCredentials';
|
import ModalAskCredentials from '@/components/ModalAskCredentials';
|
||||||
import BaseToast from '@/components/BaseToast';
|
import BaseToast from '@/components/BaseToast';
|
||||||
|
|
||||||
|
|
|
@ -143,6 +143,9 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isQuering = false;
|
this.isQuering = false;
|
||||||
|
},
|
||||||
|
reloadTable () {
|
||||||
|
this.runQuery();// TODO: run last executed query
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -66,7 +66,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { uidGen } from 'common/libs/utilities';
|
import { uidGen } from 'common/libs/uidGen';
|
||||||
import BaseVirtualScroll from '@/components/BaseVirtualScroll';
|
import BaseVirtualScroll from '@/components/BaseVirtualScroll';
|
||||||
import WorkspaceQueryTableCell from '@/components/WorkspaceQueryTableCell';
|
import WorkspaceQueryTableCell from '@/components/WorkspaceQueryTableCell';
|
||||||
import TableContext from '@/components/WorkspaceQueryTableContext';
|
import TableContext from '@/components/WorkspaceQueryTableContext';
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
</template>
|
</template>
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
v-if="isTextareaEditor"
|
v-if="isTextareaEditor"
|
||||||
|
:confirm-text="$t('word.update')"
|
||||||
size="medium"
|
size="medium"
|
||||||
@confirm="editOFF"
|
@confirm="editOFF"
|
||||||
@hide="hideEditorModal"
|
@hide="hideEditorModal"
|
||||||
|
@ -59,6 +60,7 @@
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
v-if="isBlobEditor"
|
v-if="isBlobEditor"
|
||||||
|
:confirm-text="$t('word.update')"
|
||||||
@confirm="editOFF"
|
@confirm="editOFF"
|
||||||
@hide="hideEditorModal"
|
@hide="hideEditorModal"
|
||||||
>
|
>
|
||||||
|
@ -67,19 +69,28 @@
|
||||||
</template>
|
</template>
|
||||||
<div :slot="'body'">
|
<div :slot="'body'">
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<div>
|
<transition name="jump-down">
|
||||||
|
<div v-if="contentInfo.size">
|
||||||
<img
|
<img
|
||||||
v-if="isImage"
|
v-if="isImage"
|
||||||
:src="`data:${contentInfo.mime};base64, ${bufferToBase64(localContent)}`"
|
:src="`data:${contentInfo.mime};base64, ${bufferToBase64(localContent)}`"
|
||||||
class="img-responsive p-centered"
|
class="img-responsive p-centered bg-checkered"
|
||||||
>
|
>
|
||||||
<div v-if="contentInfo.size" class="editor-buttons mt-2">
|
<div v-else class="text-center">
|
||||||
|
<i class="material-icons md-36">insert_drive_file</i>
|
||||||
|
</div>
|
||||||
|
<div class="editor-buttons mt-2">
|
||||||
<button class="btn btn-link btn-sm" @click="downloadFile">
|
<button class="btn btn-link btn-sm" @click="downloadFile">
|
||||||
<span>{{ $t('word.download') }}</span>
|
<span>{{ $t('word.download') }}</span>
|
||||||
<i class="material-icons ml-1">file_download</i>
|
<i class="material-icons ml-1">file_download</i>
|
||||||
</button>
|
</button>
|
||||||
|
<button class="btn btn-link btn-sm" @click="prepareToDelete">
|
||||||
|
<span>{{ $t('word.delete') }}</span>
|
||||||
|
<i class="material-icons ml-1">delete_forever</i>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</transition>
|
||||||
<div class="editor-field-info">
|
<div class="editor-field-info">
|
||||||
<div>
|
<div>
|
||||||
<b>{{ $t('word.size') }}</b>: {{ localContent.length | formatBytes }}<br>
|
<b>{{ $t('word.size') }}</b>: {{ localContent.length | formatBytes }}<br>
|
||||||
|
@ -103,8 +114,11 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { mimeFromHex, formatBytes, bufferToBase64 } from 'common/libs/utilities';
|
import { mimeFromHex } from 'common/libs/mimeFromHex';
|
||||||
|
import { formatBytes } from 'common/libs/formatBytes';
|
||||||
|
import { bufferToBase64 } from 'common/libs/bufferToBase64';
|
||||||
import hexToBinary from 'common/libs/hexToBinary';
|
import hexToBinary from 'common/libs/hexToBinary';
|
||||||
|
import { TEXT, LONG_TEXT, NUMBER, DATE, TIME, DATETIME, BLOB, BIT } from 'common/fieldTypes';
|
||||||
import { mask } from 'vue-the-mask';
|
import { mask } from 'vue-the-mask';
|
||||||
import ConfirmModal from '@/components/BaseConfirmModal';
|
import ConfirmModal from '@/components/BaseConfirmModal';
|
||||||
|
|
||||||
|
@ -122,40 +136,32 @@ export default {
|
||||||
typeFormat (val, type, precision) {
|
typeFormat (val, type, precision) {
|
||||||
if (!val) return val;
|
if (!val) return val;
|
||||||
|
|
||||||
switch (type) {
|
if (DATE.includes(type))
|
||||||
case 'char':
|
|
||||||
case 'varchar':
|
|
||||||
case 'text':
|
|
||||||
case 'mediumtext':
|
|
||||||
return val;
|
|
||||||
case 'date': {
|
|
||||||
return moment(val).isValid() ? moment(val).format('YYYY-MM-DD') : val;
|
return moment(val).isValid() ? moment(val).format('YYYY-MM-DD') : val;
|
||||||
}
|
|
||||||
case 'datetime':
|
if (DATETIME.includes(type)) {
|
||||||
case 'timestamp': {
|
|
||||||
let datePrecision = '';
|
let datePrecision = '';
|
||||||
for (let i = 0; i < precision; i++)
|
for (let i = 0; i < precision; i++)
|
||||||
datePrecision += i === 0 ? '.S' : 'S';
|
datePrecision += i === 0 ? '.S' : 'S';
|
||||||
|
|
||||||
return moment(val).isValid() ? moment(val).format(`YYYY-MM-DD HH:mm:ss${datePrecision}`) : val;
|
return moment(val).isValid() ? moment(val).format(`YYYY-MM-DD HH:mm:ss${datePrecision}`) : val;
|
||||||
}
|
}
|
||||||
case 'blob':
|
|
||||||
case 'mediumblob':
|
if (BLOB.includes(type)) {
|
||||||
case 'longblob': {
|
|
||||||
const buff = Buffer.from(val);
|
const buff = Buffer.from(val);
|
||||||
if (!buff.length) return '';
|
if (!buff.length) return '';
|
||||||
|
|
||||||
const hex = buff.toString('hex').substring(0, 8).toUpperCase();
|
const hex = buff.toString('hex').substring(0, 8).toUpperCase();
|
||||||
return `${mimeFromHex(hex).mime} (${formatBytes(buff.length)})`;
|
return `${mimeFromHex(hex).mime} (${formatBytes(buff.length)})`;
|
||||||
}
|
}
|
||||||
case 'bit': {
|
|
||||||
|
if (BIT.includes(type)) {
|
||||||
const hex = Buffer.from(val).toString('hex');
|
const hex = Buffer.from(val).toString('hex');
|
||||||
return hexToBinary(hex);
|
return hexToBinary(hex);
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
directives: {
|
directives: {
|
||||||
mask
|
mask
|
||||||
|
@ -171,6 +177,7 @@ export default {
|
||||||
isInlineEditor: false,
|
isInlineEditor: false,
|
||||||
isTextareaEditor: false,
|
isTextareaEditor: false,
|
||||||
isBlobEditor: false,
|
isBlobEditor: false,
|
||||||
|
willBeDeleted: false,
|
||||||
localContent: null,
|
localContent: null,
|
||||||
contentInfo: {
|
contentInfo: {
|
||||||
ext: '',
|
ext: '',
|
||||||
|
@ -182,39 +189,35 @@ export default {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
inputProps () {
|
inputProps () {
|
||||||
switch (this.type) {
|
if ([...TEXT, ...LONG_TEXT].includes(this.type))
|
||||||
case 'char':
|
|
||||||
case 'varchar':
|
|
||||||
case 'text':
|
|
||||||
case 'mediumtext':
|
|
||||||
case 'longtext':
|
|
||||||
return { type: 'text', mask: false };
|
return { type: 'text', mask: false };
|
||||||
case 'int':
|
|
||||||
case 'tinyint':
|
if (NUMBER.includes(this.type))
|
||||||
case 'smallint':
|
|
||||||
case 'mediumint':
|
|
||||||
case 'bigint':
|
|
||||||
return { type: 'number', mask: false };
|
return { type: 'number', mask: false };
|
||||||
case 'date':
|
|
||||||
|
if (TIME.includes(this.type))
|
||||||
|
return { type: 'number', mask: false };
|
||||||
|
|
||||||
|
if (DATE.includes(this.type))
|
||||||
return { type: 'text', mask: '####-##-##' };
|
return { type: 'text', mask: '####-##-##' };
|
||||||
case 'datetime':
|
|
||||||
case 'timestamp': {
|
if (DATETIME.includes(this.type)) {
|
||||||
let datetimeMask = '####-##-## ##:##:##';
|
let datetimeMask = '####-##-## ##:##:##';
|
||||||
for (let i = 0; i < this.precision; i++)
|
for (let i = 0; i < this.precision; i++)
|
||||||
datetimeMask += i === 0 ? '.#' : '#';
|
datetimeMask += i === 0 ? '.#' : '#';
|
||||||
return { type: 'text', mask: datetimeMask };
|
return { type: 'text', mask: datetimeMask };
|
||||||
}
|
}
|
||||||
case 'blob':
|
|
||||||
case 'mediumblob':
|
if (BLOB.includes(this.type))
|
||||||
case 'longblob':
|
|
||||||
case 'bit':
|
|
||||||
return { type: 'file', mask: false };
|
return { type: 'file', mask: false };
|
||||||
default:
|
|
||||||
return 'hidden';
|
if (BIT.includes(this.type))
|
||||||
}
|
return { type: 'text', mask: false };
|
||||||
|
|
||||||
|
return { type: 'text', mask: false };
|
||||||
},
|
},
|
||||||
isImage () {
|
isImage () {
|
||||||
return ['gif', 'jpg', 'png'].includes(this.contentInfo.ext);
|
return ['gif', 'jpg', 'png', 'bmp', 'ico', 'tif'].includes(this.contentInfo.ext);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -225,21 +228,17 @@ export default {
|
||||||
return bufferToBase64(val);
|
return bufferToBase64(val);
|
||||||
},
|
},
|
||||||
editON () {
|
editON () {
|
||||||
switch (this.type) {
|
if (LONG_TEXT.includes(this.type)) {
|
||||||
// Large text editor
|
|
||||||
case 'text':
|
|
||||||
case 'mediumtext':
|
|
||||||
case 'longtext':
|
|
||||||
this.isTextareaEditor = true;
|
this.isTextareaEditor = true;
|
||||||
this.localContent = this.$options.filters.typeFormat(this.content, this.type);
|
this.localContent = this.$options.filters.typeFormat(this.content, this.type);
|
||||||
break;
|
return;
|
||||||
// File fields editor
|
}
|
||||||
case 'blob':
|
|
||||||
case 'mediumblob':
|
if (BLOB.includes(this.type)) {
|
||||||
case 'longblob':
|
|
||||||
this.isBlobEditor = true;
|
this.isBlobEditor = true;
|
||||||
this.localContent = this.content ? this.content : '';
|
this.localContent = this.content ? this.content : '';
|
||||||
this.fileToUpload = null;
|
this.fileToUpload = null;
|
||||||
|
this.willBeDeleted = false;
|
||||||
|
|
||||||
if (this.content !== null) {
|
if (this.content !== null) {
|
||||||
const buff = Buffer.from(this.localContent);
|
const buff = Buffer.from(this.localContent);
|
||||||
|
@ -253,10 +252,10 @@ export default {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
// Inline editable fields
|
// Inline editable fields
|
||||||
default:
|
|
||||||
this.localContent = this.$options.filters.typeFormat(this.content, this.type);
|
this.localContent = this.$options.filters.typeFormat(this.content, this.type);
|
||||||
this.$nextTick(() => { // Focus on input
|
this.$nextTick(() => { // Focus on input
|
||||||
this.$refs.cell.blur();
|
this.$refs.cell.blur();
|
||||||
|
@ -264,8 +263,6 @@ export default {
|
||||||
this.$nextTick(() => this.$refs.editField.focus());
|
this.$nextTick(() => this.$refs.editField.focus());
|
||||||
});
|
});
|
||||||
this.isInlineEditor = true;
|
this.isInlineEditor = true;
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
editOFF () {
|
editOFF () {
|
||||||
this.isInlineEditor = false;
|
this.isInlineEditor = false;
|
||||||
|
@ -275,9 +272,15 @@ export default {
|
||||||
content = this.localContent;
|
content = this.localContent;
|
||||||
}
|
}
|
||||||
else { // Handle file upload
|
else { // Handle file upload
|
||||||
|
if (this.willBeDeleted) {
|
||||||
|
content = '';
|
||||||
|
this.willBeDeleted = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
if (!this.fileToUpload) return;
|
if (!this.fileToUpload) return;
|
||||||
content = this.fileToUpload.file.path;
|
content = this.fileToUpload.file.path;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.$emit('updateField', {
|
this.$emit('updateField', {
|
||||||
field: this.field,
|
field: this.field,
|
||||||
|
@ -304,6 +307,16 @@ export default {
|
||||||
if (!files.length) return;
|
if (!files.length) return;
|
||||||
|
|
||||||
this.fileToUpload = { name: files[0].name, file: files[0] };
|
this.fileToUpload = { name: files[0].name, file: files[0] };
|
||||||
|
this.willBeDeleted = false;
|
||||||
|
},
|
||||||
|
prepareToDelete () {
|
||||||
|
this.localContent = '';
|
||||||
|
this.contentInfo = {
|
||||||
|
ext: '',
|
||||||
|
mime: '',
|
||||||
|
size: null
|
||||||
|
};
|
||||||
|
this.willBeDeleted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -338,7 +351,7 @@ export default {
|
||||||
|
|
||||||
.editor-buttons {
|
.editor-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: space-evenly;
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<button
|
<button
|
||||||
class="btn btn-link btn-sm"
|
class="btn btn-link btn-sm"
|
||||||
:class="{'loading':isQuering}"
|
:class="{'loading':isQuering}"
|
||||||
@click="getTableData"
|
@click="reloadTable"
|
||||||
>
|
>
|
||||||
<span>{{ $t('word.refresh') }}</span>
|
<span>{{ $t('word.refresh') }}</span>
|
||||||
<i class="material-icons ml-1">refresh</i>
|
<i class="material-icons ml-1">refresh</i>
|
||||||
|
@ -140,6 +140,9 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isQuering = false;
|
this.isQuering = false;
|
||||||
|
},
|
||||||
|
reloadTable () {
|
||||||
|
this.getTableData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,8 @@ import Tables from '@/ipc-api/Tables';
|
||||||
export default {
|
export default {
|
||||||
methods: {
|
methods: {
|
||||||
async updateField (payload) {
|
async updateField (payload) {
|
||||||
|
this.isQuering = true;
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
uid: this.connection.uid,
|
uid: this.connection.uid,
|
||||||
schema: this.workspace.breadcrumbs.schema,
|
schema: this.workspace.breadcrumbs.schema,
|
||||||
|
@ -12,16 +14,24 @@ export default {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { status, response } = await Tables.updateTableCell(params);
|
const { status, response } = await Tables.updateTableCell(params);
|
||||||
if (status === 'success')
|
if (status === 'success') {
|
||||||
|
if (response.reload)// Needed for blob fields
|
||||||
|
this.reloadTable();
|
||||||
|
else
|
||||||
this.$refs.queryTable.applyUpdate(payload);
|
this.$refs.queryTable.applyUpdate(payload);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
this.addNotification({ status: 'error', message: response });
|
this.addNotification({ status: 'error', message: response });
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
this.addNotification({ status: 'error', message: err.stack });
|
this.addNotification({ status: 'error', message: err.stack });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.isQuering = false;
|
||||||
},
|
},
|
||||||
async deleteSelected (payload) {
|
async deleteSelected (payload) {
|
||||||
|
this.isQuering = true;
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
uid: this.connection.uid,
|
uid: this.connection.uid,
|
||||||
schema: this.workspace.breadcrumbs.schema,
|
schema: this.workspace.breadcrumbs.schema,
|
||||||
|
@ -42,6 +52,8 @@ export default {
|
||||||
catch (err) {
|
catch (err) {
|
||||||
this.addNotification({ status: 'error', message: err.stack });
|
this.addNotification({ status: 'error', message: err.stack });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.isQuering = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,3 +11,31 @@
|
||||||
transform: translateX(10px);
|
transform: translateX(10px);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fade-enter-active,
|
||||||
|
.fade-leave-active {
|
||||||
|
transition: opacity 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter,
|
||||||
|
.fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jump-down-enter-active {
|
||||||
|
animation: jump-down-in 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jump-down-leave-active {
|
||||||
|
animation: jump-down-in 0.2s reverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes jump-down-in {
|
||||||
|
0% {
|
||||||
|
transform: scale(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -36,6 +36,15 @@ body {
|
||||||
cursor: help;
|
cursor: help;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bg-checkered {
|
||||||
|
background-image:
|
||||||
|
linear-gradient(to right, rgba(192, 192, 192, 0.75), rgba(192, 192, 192, 0.75)),
|
||||||
|
linear-gradient(to right, black 50%, white 50%),
|
||||||
|
linear-gradient(to bottom, black 50%, white 50%);
|
||||||
|
background-blend-mode: normal, difference, normal;
|
||||||
|
background-size: 2em 2em;
|
||||||
|
}
|
||||||
|
|
||||||
// Scrollbars
|
// Scrollbars
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 10px;
|
width: 10px;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
import { uidGen } from 'common/libs/utilities';
|
import { uidGen } from 'common/libs/uidGen';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
namespaced: true,
|
namespaced: true,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
import Connection from '@/ipc-api/Connection';
|
import Connection from '@/ipc-api/Connection';
|
||||||
import { uidGen } from 'common/libs/utilities';
|
import { uidGen } from 'common/libs/uidGen';
|
||||||
|
|
||||||
function remapStructure (structure) {
|
function remapStructure (structure) {
|
||||||
const databases = structure.map(table => table.TABLE_SCHEMA)
|
const databases = structure.map(table => table.TABLE_SCHEMA)
|
||||||
|
|
Loading…
Reference in New Issue