mirror of
				https://github.com/Fabio286/antares.git
				synced 2025-06-05 21:59:22 +02:00 
			
		
		
		
	feat: fake table data generator
This commit is contained in:
		| @@ -56,6 +56,7 @@ | ||||
|     "electron-log": "^4.3.0", | ||||
|     "electron-store": "^7.0.0", | ||||
|     "electron-updater": "^4.3.5", | ||||
|     "faker": "^5.3.1", | ||||
|     "keytar": "^7.3.0", | ||||
|     "lodash": "^4.17.20", | ||||
|     "moment": "^2.29.1", | ||||
|   | ||||
							
								
								
									
										217
									
								
								src/common/FakerMethods.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								src/common/FakerMethods.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,217 @@ | ||||
| export default class { | ||||
|    static get _methods () { | ||||
|       return [ | ||||
|          { name: 'zipCode', group: 'address', types: ['string'] }, | ||||
|          { name: 'zipCodeByState', group: 'address', types: ['string'] }, | ||||
|          { name: 'city', group: 'address', types: ['string'] }, | ||||
|          { name: 'cityPrefix', group: 'address', types: ['string'] }, | ||||
|          { name: 'citySuffix', group: 'address', types: ['string'] }, | ||||
|          { name: 'streetName', group: 'address', types: ['string'] }, | ||||
|          { name: 'streetAddress', group: 'address', types: ['string'] }, | ||||
|          { name: 'streetSuffix', group: 'address', types: ['string'] }, | ||||
|          { name: 'streetPrefix', group: 'address', types: ['string'] }, | ||||
|          { name: 'secondaryAddress', group: 'address', types: ['string'] }, | ||||
|          { name: 'county', group: 'address', types: ['string'] }, | ||||
|          { name: 'country', group: 'address', types: ['string'] }, | ||||
|          { name: 'countryCode', group: 'address', types: ['string'] }, | ||||
|          { name: 'state', group: 'address', types: ['string'] }, | ||||
|          { name: 'stateAbbr', group: 'address', types: ['string'] }, | ||||
|          { name: 'latitude', group: 'address', types: ['string'] }, | ||||
|          { name: 'longitude', group: 'address', types: ['string'] }, | ||||
|          { name: 'direction', group: 'address', types: ['string'] }, | ||||
|          { name: 'cardinalDirection', group: 'address', types: ['string'] }, | ||||
|          { name: 'ordinalDirection', group: 'address', types: ['string'] }, | ||||
|          // { name: 'nearbyGPSCoordinate', group: 'address', types: ['string'] }, | ||||
|          { name: 'timeZone', group: 'address', types: ['string'] }, | ||||
|  | ||||
|          { name: 'color', group: 'commerce', types: ['string'] }, | ||||
|          { name: 'department', group: 'commerce', types: ['string'] }, | ||||
|          { name: 'productName', group: 'commerce', types: ['string'] }, | ||||
|          { name: 'price', group: 'commerce', types: ['string', 'float'] }, | ||||
|          { name: 'productAdjective', group: 'commerce', types: ['string'] }, | ||||
|          { name: 'productMaterial', group: 'commerce', types: ['string'] }, | ||||
|          { name: 'product', group: 'commerce', types: ['string'] }, | ||||
|          { name: 'productDescription', group: 'commerce', types: ['string'] }, | ||||
|  | ||||
|          { name: 'suffixes', group: 'company', types: ['string'] }, | ||||
|          { name: 'companyName', group: 'company', types: ['string'] }, | ||||
|          { name: 'companySuffix', group: 'company', types: ['string'] }, | ||||
|          { name: 'catchPhrase', group: 'company', types: ['string'] }, | ||||
|          { name: 'bs', group: 'company', types: ['string'] }, | ||||
|          { name: 'catchPhraseAdjective', group: 'company', types: ['string'] }, | ||||
|          { name: 'catchPhraseDescriptor', group: 'company', types: ['string'] }, | ||||
|          { name: 'catchPhraseNoun', group: 'company', types: ['string'] }, | ||||
|          { name: 'bsAdjective', group: 'company', types: ['string'] }, | ||||
|          { name: 'bsBuzz', group: 'company', types: ['string'] }, | ||||
|          { name: 'bsNoun', group: 'company', types: ['string'] }, | ||||
|  | ||||
|          { name: 'column', group: 'database', types: ['string'] }, | ||||
|          { name: 'type', group: 'database', types: ['string'] }, | ||||
|          { name: 'collation', group: 'database', types: ['string'] }, | ||||
|          { name: 'engine', group: 'database', types: ['string'] }, | ||||
|  | ||||
|          { name: 'past', group: 'date', types: ['string', 'datetime'] }, | ||||
|          { name: 'future', group: 'date', types: ['string', 'datetime'] }, | ||||
|          // { name: 'between', group: 'date', types: ['string'] }, | ||||
|          { name: 'recent', group: 'date', types: ['string', 'datetime'] }, | ||||
|          { name: 'soon', group: 'date', types: ['string', 'datetime'] }, | ||||
|          { name: 'month', group: 'date', types: ['string'] }, | ||||
|          { name: 'weekday', group: 'date', types: ['string'] }, | ||||
|  | ||||
|          { name: 'account', group: 'finance', types: ['string', 'number'] }, | ||||
|          { name: 'accountName', group: 'finance', types: ['string'] }, | ||||
|          { name: 'routingNumber', group: 'finance', types: ['string', 'number'] }, | ||||
|          { name: 'mask', group: 'finance', types: ['string', 'number'] }, | ||||
|          { name: 'amount', group: 'finance', types: ['string', 'float'] }, | ||||
|          { name: 'transactionType', group: 'finance', types: ['string'] }, | ||||
|          { name: 'currencyCode', group: 'finance', types: ['string'] }, | ||||
|          { name: 'currencyName', group: 'finance', types: ['string'] }, | ||||
|          { name: 'currencySymbol', group: 'finance', types: ['string'] }, | ||||
|          { name: 'bitcoinAddress', group: 'finance', types: ['string'] }, | ||||
|          { name: 'litecoinAddress', group: 'finance', types: ['string'] }, | ||||
|          { name: 'creditCardNumber', group: 'finance', types: ['string'] }, | ||||
|          { name: 'creditCardCVV', group: 'finance', types: ['string', 'number'] }, | ||||
|          { name: 'ethereumAddress', group: 'finance', types: ['string'] }, | ||||
|          { name: 'iban', group: 'finance', types: ['string'] }, | ||||
|          { name: 'bic', group: 'finance', types: ['string'] }, | ||||
|          { name: 'transactionDescription', group: 'finance', types: ['string'] }, | ||||
|  | ||||
|          { name: 'branch', group: 'git', types: ['string'] }, | ||||
|          { name: 'commitEntry', group: 'git', types: ['string'] }, | ||||
|          { name: 'commitMessage', group: 'git', types: ['string'] }, | ||||
|          { name: 'commitSha', group: 'git', types: ['string'] }, | ||||
|          { name: 'shortSha', group: 'git', types: ['string'] }, | ||||
|  | ||||
|          { name: 'abbreviation', group: 'hacker', types: ['string'] }, | ||||
|          { name: 'adjective', group: 'hacker', types: ['string'] }, | ||||
|          { name: 'noun', group: 'hacker', types: ['string'] }, | ||||
|          { name: 'verb', group: 'hacker', types: ['string'] }, | ||||
|          { name: 'ingverb', group: 'hacker', types: ['string'] }, | ||||
|          { name: 'phrase', group: 'hacker', types: ['string'] }, | ||||
|  | ||||
|          // { name: 'avatar', group: 'internet', types: ['string'] }, | ||||
|          { name: 'email', group: 'internet', types: ['string'] }, | ||||
|          { name: 'exampleEmail', group: 'internet', types: ['string'] }, | ||||
|          { name: 'userName', group: 'internet', types: ['string'] }, | ||||
|          { name: 'protocol', group: 'internet', types: ['string'] }, | ||||
|          { name: 'url', group: 'internet', types: ['string'] }, | ||||
|          { name: 'domainName', group: 'internet', types: ['string'] }, | ||||
|          { name: 'domainSuffix', group: 'internet', types: ['string'] }, | ||||
|          { name: 'domainWord', group: 'internet', types: ['string'] }, | ||||
|          { name: 'ip', group: 'internet', types: ['string'] }, | ||||
|          { name: 'ipv6', group: 'internet', types: ['string'] }, | ||||
|          { name: 'userAgent', group: 'internet', types: ['string'] }, | ||||
|          { name: 'color', group: 'internet', types: ['string'] }, | ||||
|          { name: 'mac', group: 'internet', types: ['string'] }, | ||||
|          { name: 'password', group: 'internet', types: ['string'] }, | ||||
|  | ||||
|          { name: 'word', group: 'lorem', types: ['string'] }, | ||||
|          { name: 'words', group: 'lorem', types: ['string'] }, | ||||
|          { name: 'sentence', group: 'lorem', types: ['string'] }, | ||||
|          { name: 'slug', group: 'lorem', types: ['string'] }, | ||||
|          { name: 'sentences', group: 'lorem', types: ['string'] }, | ||||
|          { name: 'paragraph', group: 'lorem', types: ['string'] }, | ||||
|          { name: 'paragraphs', group: 'lorem', types: ['string'] }, | ||||
|          { name: 'text', group: 'lorem', types: ['string'] }, | ||||
|          { name: 'lines', group: 'lorem', types: ['string'] }, | ||||
|  | ||||
|          { name: 'genre', group: 'music', types: ['string'] }, | ||||
|  | ||||
|          { name: 'firstName', group: 'name', types: ['string'] }, | ||||
|          { name: 'lastName', group: 'name', types: ['string'] }, | ||||
|          { name: 'middleName', group: 'name', types: ['string'] }, | ||||
|          { name: 'findName', group: 'name', types: ['string'] }, | ||||
|          { name: 'jobTitle', group: 'name', types: ['string'] }, | ||||
|          { name: 'gender', group: 'name', types: ['string'] }, | ||||
|          { name: 'prefix', group: 'name', types: ['string'] }, | ||||
|          { name: 'suffix', group: 'name', types: ['string'] }, | ||||
|          { name: 'title', group: 'name', types: ['string'] }, | ||||
|          { name: 'jobDescriptor', group: 'name', types: ['string'] }, | ||||
|          { name: 'jobArea', group: 'name', types: ['string'] }, | ||||
|          { name: 'jobType', group: 'name', types: ['string'] }, | ||||
|  | ||||
|          { name: 'phoneNumber', group: 'phone', types: ['string'] }, | ||||
|          { name: 'phoneNumberFormat', group: 'phone', types: ['string'] }, | ||||
|          { name: 'phoneFormats', group: 'phone', types: ['string'] }, | ||||
|  | ||||
|          { name: 'number', group: 'random', types: ['string', 'number'] }, | ||||
|          { name: 'float', group: 'random', types: ['string', 'float'] }, | ||||
|          { name: 'arrayElement', group: 'random', types: ['string'] }, | ||||
|          { name: 'arrayElements', group: 'random', types: ['string'] }, | ||||
|          { name: 'objectElement', group: 'random', types: ['string'] }, | ||||
|          { name: 'uuid', group: 'random', types: ['string'] }, | ||||
|          { name: 'boolean', group: 'random', types: ['string'] }, | ||||
|          { name: 'word', group: 'random', types: ['string'] }, | ||||
|          { name: 'words', group: 'random', types: ['string'] }, | ||||
|          // { name: 'image', group: 'random', types: ['string'] }, | ||||
|          { name: 'locale', group: 'random', types: ['string'] }, | ||||
|          { name: 'alpha', group: 'random', types: ['string'] }, | ||||
|          { name: 'alphaNumeric', group: 'random', types: ['string'] }, | ||||
|          { name: 'hexaDecimal', group: 'random', types: ['string'] }, | ||||
|  | ||||
|          { name: 'fileName', group: 'system', types: ['string'] }, | ||||
|          { name: 'commonFileName', group: 'system', types: ['string'] }, | ||||
|          { name: 'mimeType', group: 'system', types: ['string'] }, | ||||
|          { name: 'commonFileType', group: 'system', types: ['string'] }, | ||||
|          { name: 'commonFileExt', group: 'system', types: ['string'] }, | ||||
|          { name: 'fileType', group: 'system', types: ['string'] }, | ||||
|          { name: 'fileExt', group: 'system', types: ['string'] }, | ||||
|          { name: 'directoryPath', group: 'system', types: ['string'] }, | ||||
|          { name: 'filePath', group: 'system', types: ['string'] }, | ||||
|          { name: 'semver', group: 'system', types: ['string'] }, | ||||
|  | ||||
|          { name: 'recent', group: 'time', types: ['string', 'time'] }, | ||||
|  | ||||
|          { name: 'vehicle', group: 'vehicle', types: ['string'] }, | ||||
|          { name: 'manufacturer', group: 'vehicle', types: ['string'] }, | ||||
|          { name: 'model', group: 'vehicle', types: ['string'] }, | ||||
|          { name: 'type', group: 'vehicle', types: ['string'] }, | ||||
|          { name: 'fuel', group: 'vehicle', types: ['string'] }, | ||||
|          { name: 'vin', group: 'vehicle', types: ['string'] }, | ||||
|          { name: 'color', group: 'vehicle', types: ['string'] } | ||||
|       ]; | ||||
|    } | ||||
|  | ||||
|    static getGroups () { | ||||
|       const groupsObj = this._methods.reduce((acc, curr) => { | ||||
|          if (curr.group in acc) | ||||
|             curr.types.forEach(type => acc[curr.group].add(type)); | ||||
|          else | ||||
|             acc[curr.group] = new Set(curr.types); | ||||
|  | ||||
|          return acc; | ||||
|       }, {}); | ||||
|  | ||||
|       const groupsArr = []; | ||||
|  | ||||
|       for (const key in groupsObj) | ||||
|          groupsArr.push({ name: key, types: [...groupsObj[key]] }); | ||||
|  | ||||
|       return groupsArr.sort((a, b) => { | ||||
|          if (a.name < b.name) | ||||
|             return -1; | ||||
|  | ||||
|          if (b.name > a.name) | ||||
|             return 1; | ||||
|  | ||||
|          return 0; | ||||
|       }); ; | ||||
|    } | ||||
|  | ||||
|    static getGroupsByType (type) { | ||||
|       if (!type) return []; | ||||
|       return this.getGroups().filter(group => group.types.includes(type)); | ||||
|    } | ||||
|  | ||||
|    static getMethods ({ type, group }) { | ||||
|       return this._methods.filter(method => method.group === group && method.types.includes(type)).sort((a, b) => { | ||||
|          if (a.name < b.name) | ||||
|             return -1; | ||||
|  | ||||
|          if (b.name > a.name) | ||||
|             return 1; | ||||
|  | ||||
|          return 0; | ||||
|       }); | ||||
|    } | ||||
| } | ||||
| @@ -1,6 +1,8 @@ | ||||
| import { ipcMain } from 'electron'; | ||||
| import faker from 'faker'; | ||||
| import moment from 'moment'; | ||||
| import { sqlEscaper } from 'common/libs/sqlEscaper'; | ||||
| import { TEXT, LONG_TEXT, NUMBER, FLOAT, BLOB, BIT } from 'common/fieldTypes'; | ||||
| import { TEXT, LONG_TEXT, NUMBER, FLOAT, BLOB, BIT, DATE, DATETIME } from 'common/fieldTypes'; | ||||
| import fs from 'fs'; | ||||
|  | ||||
| export default (connections) => { | ||||
| @@ -204,6 +206,65 @@ export default (connections) => { | ||||
|       } | ||||
|    }); | ||||
|  | ||||
|    ipcMain.handle('insert-table-fake-rows', async (event, params) => { | ||||
|       try { | ||||
|          const rows = []; | ||||
|  | ||||
|          for (let i = 0; i < +params.repeat; i++) { | ||||
|             const insertObj = {}; | ||||
|  | ||||
|             for (const key in params.row) { | ||||
|                const type = params.fields[key]; | ||||
|                let escapedParam; | ||||
|  | ||||
|                if (!('group' in params.row[key]) || params.row[key].group === 'manual') { // Manual value | ||||
|                   if (params.row[key].value === null) | ||||
|                      escapedParam = 'NULL'; | ||||
|                   else if ([...NUMBER, ...FLOAT].includes(type)) | ||||
|                      escapedParam = params.row[key].value; | ||||
|                   else if ([...TEXT, ...LONG_TEXT].includes(type)) | ||||
|                      escapedParam = `"${sqlEscaper(params.row[key].value)}"`; | ||||
|                   else if (BLOB.includes(type)) { | ||||
|                      if (params.row[key].value) { | ||||
|                         const fileBlob = fs.readFileSync(params.row[key].value); | ||||
|                         escapedParam = `0x${fileBlob.toString('hex')}`; | ||||
|                      } | ||||
|                      else | ||||
|                         escapedParam = '""'; | ||||
|                   } | ||||
|                   else | ||||
|                      escapedParam = `"${sqlEscaper(params.row[key].value)}"`; | ||||
|  | ||||
|                   insertObj[key] = escapedParam; | ||||
|                } | ||||
|                else { // Faker value | ||||
|                   let fakeValue = faker[params.row[key].group][params.row[key].method](); | ||||
|  | ||||
|                   if ([...TEXT, ...LONG_TEXT].includes(type)) | ||||
|                      fakeValue = `"${sqlEscaper(fakeValue)}"`; | ||||
|                   else if ([...DATE, ...DATETIME].includes(type)) | ||||
|                      fakeValue = `"${moment(fakeValue).format('YYYY-MM-DD HH:mm:ss.SSSSSS')}"`; | ||||
|  | ||||
|                   insertObj[key] = fakeValue; | ||||
|                } | ||||
|             } | ||||
|  | ||||
|             rows.push(insertObj); | ||||
|          } | ||||
|  | ||||
|          await connections[params.uid] | ||||
|             .schema(params.schema) | ||||
|             .into(params.table) | ||||
|             .insert(rows) | ||||
|             .run(); | ||||
|  | ||||
|          return { status: 'success' }; | ||||
|       } | ||||
|       catch (err) { | ||||
|          return { status: 'error', response: err.toString() }; | ||||
|       } | ||||
|    }); | ||||
|  | ||||
|    ipcMain.handle('get-foreign-list', async (event, { uid, schema, table, column, description }) => { | ||||
|       try { | ||||
|          const query = connections[uid] | ||||
|   | ||||
							
								
								
									
										205
									
								
								src/renderer/components/FakerSelect.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										205
									
								
								src/renderer/components/FakerSelect.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,205 @@ | ||||
| <template> | ||||
|    <fieldset class="input-group mb-0" :disabled="!fakerGroups.length"> | ||||
|       <select | ||||
|          v-model="selectedGroup" | ||||
|          class="form-select" | ||||
|          :disabled="!isChecked" | ||||
|          style="flex-grow: 0;" | ||||
|          @change="onChange" | ||||
|       > | ||||
|          <option value="manual"> | ||||
|             {{ $t('message.manualValue') }} | ||||
|          </option> | ||||
|          <option | ||||
|             v-for="group in fakerGroups" | ||||
|             :key="group.name" | ||||
|             :value="group.name" | ||||
|          > | ||||
|             {{ $t(`faker.${group.name}`) }} | ||||
|          </option> | ||||
|       </select> | ||||
|       <select | ||||
|          v-if="selectedGroup !== 'manual'" | ||||
|          v-model="selectedMethod" | ||||
|          class="form-select" | ||||
|          :disabled="!isChecked" | ||||
|          @change="onChange" | ||||
|       > | ||||
|          <option | ||||
|             v-for="method in fakerMethods" | ||||
|             :key="method.name" | ||||
|             :value="method.name" | ||||
|          > | ||||
|             {{ $t(`faker.${method.name}`) }} | ||||
|          </option> | ||||
|       </select> | ||||
|       <ForeignKeySelect | ||||
|          v-else-if="foreignKeys.includes(field.name)" | ||||
|          ref="formInput" | ||||
|          class="form-select" | ||||
|          :value.sync="selectedValue" | ||||
|          :key-usage="getKeyUsage(field.name)" | ||||
|          :disabled="!isChecked" | ||||
|       /> | ||||
|       <input | ||||
|          v-else-if="inputProps().mask" | ||||
|          ref="formInput" | ||||
|          v-model="selectedValue" | ||||
|          v-mask="inputProps().mask" | ||||
|          class="form-input" | ||||
|          :type="inputProps().type" | ||||
|          :disabled="!isChecked" | ||||
|       > | ||||
|       <input | ||||
|          v-else-if="inputProps().type === 'file'" | ||||
|          ref="formInput" | ||||
|          class="form-input" | ||||
|          type="file" | ||||
|          :disabled="!isChecked" | ||||
|       > | ||||
|       <input | ||||
|          v-else-if="inputProps().type === 'number'" | ||||
|          ref="formInput" | ||||
|          v-model="selectedValue" | ||||
|          class="form-input" | ||||
|          step="any" | ||||
|          :type="inputProps().type" | ||||
|          :disabled="!isChecked" | ||||
|       > | ||||
|       <input | ||||
|          v-else | ||||
|          ref="formInput" | ||||
|          v-model="selectedValue" | ||||
|          class="form-input" | ||||
|          :type="inputProps().type" | ||||
|          :disabled="!isChecked" | ||||
|       > | ||||
|       <slot /> | ||||
|    </fieldset> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { mask } from 'vue-the-mask'; | ||||
| import { TEXT, LONG_TEXT, NUMBER, FLOAT, DATE, TIME, DATETIME, BLOB, BIT } from 'common/fieldTypes'; | ||||
| import ForeignKeySelect from '@/components/ForeignKeySelect'; | ||||
| import FakerMethods from 'common/FakerMethods'; | ||||
|  | ||||
| export default { | ||||
|    name: 'FakerSelect', | ||||
|    components: { | ||||
|       ForeignKeySelect | ||||
|    }, | ||||
|    directives: { | ||||
|       mask | ||||
|    }, | ||||
|    props: { | ||||
|       type: String, | ||||
|       field: Object, | ||||
|       isChecked: Boolean, | ||||
|       foreignKeys: Array, | ||||
|       keyUsage: Array, | ||||
|       fieldLength: Number, | ||||
|       fieldObj: Object | ||||
|    }, | ||||
|    data () { | ||||
|       return { | ||||
|          localType: null, | ||||
|          selectedGroup: 'manual', | ||||
|          selectedMethod: '', | ||||
|          selectedValue: '', | ||||
|          debounceTimeout: null | ||||
|       }; | ||||
|    }, | ||||
|    computed: { | ||||
|       fakerGroups () { | ||||
|          if ([...TEXT, ...LONG_TEXT].includes(this.type)) | ||||
|             this.localType = 'string'; | ||||
|          else if (NUMBER.includes(this.type)) | ||||
|             this.localType = 'number'; | ||||
|          else if (FLOAT.includes(this.type)) | ||||
|             this.localType = 'float'; | ||||
|          else if ([...DATE, ...DATETIME].includes(this.type)) | ||||
|             this.localType = 'datetime'; | ||||
|          else if (TIME.includes(this.type)) | ||||
|             this.localType = 'time'; | ||||
|  | ||||
|          return FakerMethods.getGroupsByType(this.localType); | ||||
|       }, | ||||
|       fakerMethods () { | ||||
|          return FakerMethods.getMethods({ type: this.localType, group: this.selectedGroup }); | ||||
|       } | ||||
|    }, | ||||
|    watch: { | ||||
|       fieldObj () { | ||||
|          if (this.fieldObj) | ||||
|             this.selectedValue = this.fieldObj.value; | ||||
|       }, | ||||
|       selectedGroup () { | ||||
|          if (this.fakerMethods.length) | ||||
|             this.selectedMethod = this.fakerMethods[0].name; | ||||
|          else | ||||
|             this.selectedMethod = ''; | ||||
|       }, | ||||
|       selectedMethod () { | ||||
|          this.onChange(); | ||||
|       }, | ||||
|       selectedValue () { | ||||
|          clearTimeout(this.debounceTimeout); | ||||
|          this.debounceTimeout = null; | ||||
|          this.debounceTimeout = setTimeout(() => { | ||||
|             this.onChange(); | ||||
|          }, 200); | ||||
|       } | ||||
|    }, | ||||
|    methods: { | ||||
|       inputProps () { | ||||
|          if ([...TEXT, ...LONG_TEXT].includes(this.type)) | ||||
|             return { type: 'text', mask: false }; | ||||
|  | ||||
|          if ([...NUMBER, ...FLOAT].includes(this.type)) | ||||
|             return { type: 'number', mask: false }; | ||||
|  | ||||
|          if (TIME.includes(this.type)) { | ||||
|             let timeMask = '##:##:##'; | ||||
|             const precision = this.fieldLength; | ||||
|  | ||||
|             for (let i = 0; i < precision; i++) | ||||
|                timeMask += i === 0 ? '.#' : '#'; | ||||
|  | ||||
|             return { type: 'text', mask: timeMask }; | ||||
|          } | ||||
|  | ||||
|          if (DATE.includes(this.type)) | ||||
|             return { type: 'text', mask: '####-##-##' }; | ||||
|  | ||||
|          if (DATETIME.includes(this.type)) { | ||||
|             let datetimeMask = '####-##-## ##:##:##'; | ||||
|             const precision = this.fieldLength; | ||||
|  | ||||
|             for (let i = 0; i < precision; i++) | ||||
|                datetimeMask += i === 0 ? '.#' : '#'; | ||||
|  | ||||
|             return { type: 'text', mask: datetimeMask }; | ||||
|          } | ||||
|  | ||||
|          if (BLOB.includes(this.type)) | ||||
|             return { type: 'file', mask: false }; | ||||
|  | ||||
|          if (BIT.includes(this.type)) | ||||
|             return { type: 'text', mask: false }; | ||||
|  | ||||
|          return { type: 'text', mask: false }; | ||||
|       }, | ||||
|       getKeyUsage (keyName) { | ||||
|          return this.keyUsage.find(key => key.field === keyName); | ||||
|       }, | ||||
|       onChange () { | ||||
|          this.$emit('update:value', { | ||||
|             group: this.selectedGroup, | ||||
|             method: this.selectedMethod, | ||||
|             value: this.selectedValue | ||||
|          }); | ||||
|       } | ||||
|    } | ||||
| }; | ||||
| </script> | ||||
							
								
								
									
										278
									
								
								src/renderer/components/ModalFakerRows.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										278
									
								
								src/renderer/components/ModalFakerRows.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,278 @@ | ||||
| <template> | ||||
|    <div class="modal active"> | ||||
|       <a class="modal-overlay" @click.stop="closeModal" /> | ||||
|       <div class="modal-container p-0"> | ||||
|          <div class="modal-header pl-2"> | ||||
|             <div class="modal-title h6"> | ||||
|                <div class="d-flex"> | ||||
|                   <i class="mdi mdi-24px mdi-drama-masks mr-1" /> {{ $t('message.addFakeData') }} | ||||
|                </div> | ||||
|             </div> | ||||
|             <a class="btn btn-clear c-hand" @click.stop="closeModal" /> | ||||
|          </div> | ||||
|          <div class="modal-body pb-0"> | ||||
|             <div class="content"> | ||||
|                <form class="form-horizontal"> | ||||
|                   <fieldset :disabled="isInserting"> | ||||
|                      <div | ||||
|                         v-for="field in fields" | ||||
|                         :key="field.name" | ||||
|                         class="form-group" | ||||
|                      > | ||||
|                         <div class="col-3 col-sm-12"> | ||||
|                            <label class="form-label" :title="field.name">{{ field.name }}</label> | ||||
|                         </div> | ||||
|                         <div class="column columns col-sm-12"> | ||||
|                            <FakerSelect | ||||
|                               :type="field.type" | ||||
|                               class="column columns pr-0" | ||||
|                               :is-checked="!fieldsToExclude.includes(field.name)" | ||||
|                               :foreign-keys="foreignKeys" | ||||
|                               :key-usage="keyUsage" | ||||
|                               :field="field" | ||||
|                               :field-length="fieldLength(field)" | ||||
|                               :field-obj="localRow[field.name]" | ||||
|                               :value.sync="localRow[field.name]" | ||||
|                            > | ||||
|                               <span class="input-group-addon text-small" :class="`type-${field.type.toLowerCase()}`"> | ||||
|                                  {{ field.type }} {{ fieldLength(field) | wrapNumber }} | ||||
|                               </span> | ||||
|                               <label class="form-checkbox ml-3" :title="$t('word.insert')"> | ||||
|                                  <input | ||||
|                                     type="checkbox" | ||||
|                                     :checked="!field.autoIncrement" | ||||
|                                     @change.prevent="toggleFields($event, field)" | ||||
|                                  ><i class="form-icon" /> | ||||
|                               </label> | ||||
|                            </FakerSelect> | ||||
|                         </div> | ||||
|                      </div> | ||||
|                   </fieldset> | ||||
|                </form> | ||||
|             </div> | ||||
|          </div> | ||||
|          <div class="modal-footer text-light"> | ||||
|             <div class="input-group col-2 tooltip tooltip-right" :data-tooltip="$t('message.numberOfInserts')"> | ||||
|                <input | ||||
|                   v-model="nInserts" | ||||
|                   type="number" | ||||
|                   class="form-input" | ||||
|                   min="1" | ||||
|                   :disabled="isInserting" | ||||
|                > | ||||
|                <span class="input-group-addon"> | ||||
|                   <i class="mdi mdi-24px mdi-repeat" /> | ||||
|                </span> | ||||
|             </div> | ||||
|             <div class="column col-auto"> | ||||
|                <button | ||||
|                   class="btn btn-primary mr-2" | ||||
|                   :class="{'loading': isInserting}" | ||||
|                   @click.stop="insertRows" | ||||
|                > | ||||
|                   {{ $t('word.insert') }} | ||||
|                </button> | ||||
|                <button class="btn btn-link" @click.stop="closeModal"> | ||||
|                   {{ $t('word.close') }} | ||||
|                </button> | ||||
|             </div> | ||||
|          </div> | ||||
|       </div> | ||||
|    </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import moment from 'moment'; | ||||
| import { TEXT, LONG_TEXT, NUMBER, FLOAT, DATE, TIME, DATETIME, BLOB } from 'common/fieldTypes'; | ||||
| import { mask } from 'vue-the-mask'; | ||||
| import { mapGetters, mapActions } from 'vuex'; | ||||
| import Tables from '@/ipc-api/Tables'; | ||||
| import FakerSelect from '@/components/FakerSelect'; | ||||
|  | ||||
| export default { | ||||
|    name: 'ModalFakerRows', | ||||
|    components: { | ||||
|       FakerSelect | ||||
|    }, | ||||
|    directives: { | ||||
|       mask | ||||
|    }, | ||||
|    filters: { | ||||
|       wrapNumber (num) { | ||||
|          if (!num) return ''; | ||||
|          return `(${num})`; | ||||
|       } | ||||
|    }, | ||||
|    props: { | ||||
|       tabUid: [String, Number], | ||||
|       fields: Array, | ||||
|       keyUsage: Array | ||||
|    }, | ||||
|    data () { | ||||
|       return { | ||||
|          localRow: {}, | ||||
|          fieldsToExclude: [], | ||||
|          nInserts: 1, | ||||
|          isInserting: false | ||||
|       }; | ||||
|    }, | ||||
|    computed: { | ||||
|       ...mapGetters({ | ||||
|          selectedWorkspace: 'workspaces/getSelected', | ||||
|          getWorkspace: 'workspaces/getWorkspace', | ||||
|          getWorkspaceTab: 'workspaces/getWorkspaceTab' | ||||
|       }), | ||||
|       workspace () { | ||||
|          return this.getWorkspace(this.selectedWorkspace); | ||||
|       }, | ||||
|       foreignKeys () { | ||||
|          return this.keyUsage.map(key => key.field); | ||||
|       } | ||||
|    }, | ||||
|    watch: { | ||||
|       nInserts (val) { | ||||
|          if (!val || val < 1) | ||||
|             this.nInserts = 1; | ||||
|          else if (val > 1000) | ||||
|             this.nInserts = 1000; | ||||
|       } | ||||
|    }, | ||||
|    created () { | ||||
|       window.addEventListener('keydown', this.onKey); | ||||
|    }, | ||||
|    mounted () { | ||||
|       const rowObj = {}; | ||||
|  | ||||
|       for (const field of this.fields) { | ||||
|          let fieldDefault; | ||||
|  | ||||
|          if (field.default === 'NULL') fieldDefault = null; | ||||
|          else { | ||||
|             if ([...NUMBER, ...FLOAT].includes(field.type)) | ||||
|                fieldDefault = +field.default; | ||||
|  | ||||
|             if ([...TEXT, ...LONG_TEXT].includes(field.type)) | ||||
|                fieldDefault = field.default ? field.default.substring(1, field.default.length - 1) : ''; | ||||
|  | ||||
|             if ([...TIME, ...DATE].includes(field.type)) | ||||
|                fieldDefault = field.default; | ||||
|  | ||||
|             if (DATETIME.includes(field.type)) { | ||||
|                if (field.default && field.default.toLowerCase().includes('current_timestamp')) { | ||||
|                   let datePrecision = ''; | ||||
|                   for (let i = 0; i < field.datePrecision; i++) | ||||
|                      datePrecision += i === 0 ? '.S' : 'S'; | ||||
|                   fieldDefault = moment().format(`YYYY-MM-DD HH:mm:ss${datePrecision}`); | ||||
|                } | ||||
|             } | ||||
|          } | ||||
|  | ||||
|          rowObj[field.name] = { value: fieldDefault }; | ||||
|  | ||||
|          if (field.autoIncrement)// Disable by default auto increment fields | ||||
|             this.fieldsToExclude = [...this.fieldsToExclude, field.name]; | ||||
|       } | ||||
|  | ||||
|       this.localRow = { ...rowObj }; | ||||
|    }, | ||||
|    beforeDestroy () { | ||||
|       window.removeEventListener('keydown', this.onKey); | ||||
|    }, | ||||
|    methods: { | ||||
|       ...mapActions({ | ||||
|          addNotification: 'notifications/addNotification' | ||||
|       }), | ||||
|       async insertRows () { | ||||
|          this.isInserting = true; | ||||
|          const rowToInsert = this.localRow; | ||||
|  | ||||
|          Object.keys(rowToInsert).forEach(key => { | ||||
|             if (this.fieldsToExclude.includes(key)) | ||||
|                delete rowToInsert[key]; | ||||
|  | ||||
|             if (typeof rowToInsert[key] === 'undefined') | ||||
|                delete rowToInsert[key]; | ||||
|          }); | ||||
|  | ||||
|          const fieldTypes = {}; | ||||
|          this.fields.forEach(field => { | ||||
|             fieldTypes[field.name] = field.type; | ||||
|          }); | ||||
|  | ||||
|          try { | ||||
|             const { status, response } = await Tables.insertTableFakeRows({ | ||||
|                uid: this.selectedWorkspace, | ||||
|                schema: this.workspace.breadcrumbs.schema, | ||||
|                table: this.workspace.breadcrumbs.table, | ||||
|                row: rowToInsert, | ||||
|                repeat: this.nInserts, | ||||
|                fields: fieldTypes | ||||
|             }); | ||||
|  | ||||
|             if (status === 'success') { | ||||
|                this.closeModal(); | ||||
|                this.$emit('reload'); | ||||
|             } | ||||
|             else | ||||
|                this.addNotification({ status: 'error', message: response }); | ||||
|          } | ||||
|          catch (err) { | ||||
|             this.addNotification({ status: 'error', message: err.stack }); | ||||
|          } | ||||
|  | ||||
|          this.isInserting = false; | ||||
|       }, | ||||
|       closeModal () { | ||||
|          this.$emit('hide'); | ||||
|       }, | ||||
|       fieldLength (field) { | ||||
|          if ([...BLOB, ...LONG_TEXT].includes(field.type)) return null; | ||||
|          else if (TEXT.includes(field.type)) return field.charLength; | ||||
|          return field.length; | ||||
|       }, | ||||
|       toggleFields (event, field) { | ||||
|          if (event.target.checked) | ||||
|             this.fieldsToExclude = this.fieldsToExclude.filter(f => f !== field.name); | ||||
|          else | ||||
|             this.fieldsToExclude = [...this.fieldsToExclude, field.name]; | ||||
|       }, | ||||
|       filesChange (event, field) { | ||||
|          const { files } = event.target; | ||||
|          if (!files.length) return; | ||||
|  | ||||
|          this.localRow[field] = files[0].path; | ||||
|       }, | ||||
|       getKeyUsage (keyName) { | ||||
|          return this.keyUsage.find(key => key.field === keyName); | ||||
|       }, | ||||
|       onKey (e) { | ||||
|          e.stopPropagation(); | ||||
|          if (e.key === 'Escape') | ||||
|             this.closeModal(); | ||||
|       } | ||||
|    } | ||||
| }; | ||||
| </script> | ||||
|  | ||||
| <style scoped> | ||||
|   .modal-container { | ||||
|     max-width: 700px; | ||||
|   } | ||||
|  | ||||
|   .form-label { | ||||
|     overflow: hidden; | ||||
|     white-space: normal; | ||||
|     text-overflow: ellipsis; | ||||
|   } | ||||
|  | ||||
|   .input-group-addon { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|   } | ||||
|  | ||||
|   .modal-footer { | ||||
|     display: flex; | ||||
|     justify-content: space-between; | ||||
|     align-items: center; | ||||
|   } | ||||
| </style> | ||||
| @@ -50,6 +50,16 @@ | ||||
|                               :tabindex="key+1" | ||||
|                               @change="filesChange($event,field.name)" | ||||
|                            > | ||||
|                            <input | ||||
|                               v-else-if="inputProps(field).type === 'number'" | ||||
|                               ref="formInput" | ||||
|                               v-model="localRow[field.name]" | ||||
|                               class="form-input" | ||||
|                               step="any" | ||||
|                               :type="inputProps(field).type" | ||||
|                               :disabled="fieldsToExclude.includes(field.name)" | ||||
|                               :tabindex="key+1" | ||||
|                            > | ||||
|                            <input | ||||
|                               v-else | ||||
|                               ref="formInput" | ||||
| @@ -255,6 +265,7 @@ export default { | ||||
|       }, | ||||
|       fieldLength (field) { | ||||
|          if ([...BLOB, ...LONG_TEXT].includes(field.type)) return null; | ||||
|          else if (TEXT.includes(field.type)) return field.charLength; | ||||
|          return field.length; | ||||
|       }, | ||||
|       inputProps (field) { | ||||
|   | ||||
| @@ -437,7 +437,7 @@ export default { | ||||
|             schema: this.schema, | ||||
|             table: this.table, | ||||
|             numPrecision: null, | ||||
|             numLength: null, | ||||
|             numLength: 11, | ||||
|             datePrecision: null, | ||||
|             charLength: null, | ||||
|             nullable: false, | ||||
|   | ||||
| @@ -37,7 +37,13 @@ | ||||
|                   <span>{{ $t('word.add') }}</span> | ||||
|                   <i class="mdi mdi-24px mdi-playlist-plus ml-1" /> | ||||
|                </button> | ||||
|                <div class="dropdown export-dropdown"> | ||||
|  | ||||
|                <button class="btn btn-dark btn-sm" @click="showFakerModal"> | ||||
|                   <span>{{ $t('word.faker') }}</span> | ||||
|                   <i class="mdi mdi-24px mdi-drama-masks ml-1" /> | ||||
|                </button> | ||||
|  | ||||
|                <div class="dropdown export-dropdown pr-2"> | ||||
|                   <button | ||||
|                      :disabled="isQuering" | ||||
|                      class="btn btn-dark btn-sm dropdown-toggle mr-0 pr-0" | ||||
| @@ -91,6 +97,14 @@ | ||||
|          @hide="hideAddModal" | ||||
|          @reload="reloadTable" | ||||
|       /> | ||||
|       <ModalFakerRows | ||||
|          v-if="isFakerModal" | ||||
|          :fields="fields" | ||||
|          :key-usage="keyUsage" | ||||
|          :tab-uid="tabUid" | ||||
|          @hide="hideFakerModal" | ||||
|          @reload="reloadTable" | ||||
|       /> | ||||
|    </div> | ||||
| </template> | ||||
|  | ||||
| @@ -98,6 +112,7 @@ | ||||
| import Tables from '@/ipc-api/Tables'; | ||||
| import WorkspaceQueryTable from '@/components/WorkspaceQueryTable'; | ||||
| import ModalNewTableRow from '@/components/ModalNewTableRow'; | ||||
| import ModalFakerRows from '@/components/ModalFakerRows'; | ||||
| import { mapGetters, mapActions } from 'vuex'; | ||||
| import tableTabs from '@/mixins/tableTabs'; | ||||
|  | ||||
| @@ -105,7 +120,8 @@ export default { | ||||
|    name: 'WorkspaceTableTab', | ||||
|    components: { | ||||
|       WorkspaceQueryTable, | ||||
|       ModalNewTableRow | ||||
|       ModalNewTableRow, | ||||
|       ModalFakerRows | ||||
|    }, | ||||
|    mixins: [tableTabs], | ||||
|    props: { | ||||
| @@ -119,6 +135,7 @@ export default { | ||||
|          results: [], | ||||
|          lastTable: null, | ||||
|          isAddModal: false, | ||||
|          isFakerModal: false, | ||||
|          autorefreshTimer: 0, | ||||
|          refreshInterval: null, | ||||
|          sortParams: {} | ||||
| @@ -222,6 +239,12 @@ export default { | ||||
|       hideAddModal () { | ||||
|          this.isAddModal = false; | ||||
|       }, | ||||
|       showFakerModal () { | ||||
|          this.isFakerModal = true; | ||||
|       }, | ||||
|       hideFakerModal () { | ||||
|          this.isFakerModal = false; | ||||
|       }, | ||||
|       onKey (e) { | ||||
|          if (this.isSelected) { | ||||
|             e.stopPropagation(); | ||||
|   | ||||
| @@ -92,7 +92,8 @@ module.exports = { | ||||
|       caCertificate: 'CA certificate', | ||||
|       ciphers: 'Ciphers', | ||||
|       upload: 'Upload', | ||||
|       browse: 'Browse' | ||||
|       browse: 'Browse', | ||||
|       faker: 'Faker' | ||||
|    }, | ||||
|    message: { | ||||
|       appWelcome: 'Welcome to Antares SQL Client!', | ||||
| @@ -180,7 +181,173 @@ module.exports = { | ||||
|       createNewScheduler: 'Create new scheduler', | ||||
|       deleteScheduler: 'Delete scheduler', | ||||
|       preserveOnCompletion: 'Preserve on completion', | ||||
|       enableSsl: 'Enable SSL' | ||||
|       enableSsl: 'Enable SSL', | ||||
|       addFakeData: 'Add fake data', | ||||
|       manualValue: 'Manual value' | ||||
|    }, | ||||
|    faker: { | ||||
|       address: 'Address', | ||||
|       commerce: 'Commerce', | ||||
|       company: 'Company', | ||||
|       database: 'Database', | ||||
|       date: 'Date', | ||||
|       finance: 'Finance', | ||||
|       git: 'Git', | ||||
|       hacker: 'Hacker', | ||||
|       internet: 'Internet', | ||||
|       lorem: 'Lorem', | ||||
|       name: 'Name', | ||||
|       music: 'Music', | ||||
|       phone: 'Phone', | ||||
|       random: 'Random', | ||||
|       system: 'System', | ||||
|       time: 'Time', | ||||
|       vehicle: 'Vehicle', | ||||
|       zipCode: 'Zip code', | ||||
|       zipCodeByState: 'Zip code by state', | ||||
|       city: 'City', | ||||
|       cityPrefix: 'City prefix', | ||||
|       citySuffix: 'City suffix', | ||||
|       streetName: 'Street name', | ||||
|       streetAddress: 'Street address', | ||||
|       streetSuffix: 'Street suffix', | ||||
|       streetPrefix: 'Street prefix', | ||||
|       secondaryAddress: 'Secondary address', | ||||
|       county: 'County', | ||||
|       country: 'Country', | ||||
|       countryCode: 'Country code', | ||||
|       state: 'State', | ||||
|       stateAbbr: 'State abbreviation', | ||||
|       latitude: 'Latitude', | ||||
|       longitude: 'Longitude', | ||||
|       direction: 'Direction', | ||||
|       cardinalDirection: 'Cardinal direction', | ||||
|       ordinalDirection: 'Ordinal direction', | ||||
|       nearbyGPSCoordinate: 'Nearby GPS coordinate', | ||||
|       timeZone: 'Time zone', | ||||
|       color: 'Color', | ||||
|       department: 'Department', | ||||
|       productName: 'Product name', | ||||
|       price: 'Price', | ||||
|       productAdjective: 'Product adjective', | ||||
|       productMaterial: 'Product material', | ||||
|       product: 'Product', | ||||
|       productDescription: 'Product description', | ||||
|       suffixes: 'Suffixes', | ||||
|       companyName: 'Company name', | ||||
|       companySuffix: 'Company suffix', | ||||
|       catchPhrase: 'Catch phrase', | ||||
|       bs: 'BS', | ||||
|       catchPhraseAdjective: 'Catch phrase adjective', | ||||
|       catchPhraseDescriptor: 'Catch phrase descriptor', | ||||
|       catchPhraseNoun: 'Catch phrase noun', | ||||
|       bsAdjective: 'BS adjective', | ||||
|       bsBuzz: 'BS buzz', | ||||
|       bsNoun: 'BS noun', | ||||
|       column: 'Column', | ||||
|       type: 'Type', | ||||
|       collation: 'Collation', | ||||
|       engine: 'Engine', | ||||
|       past: 'Past', | ||||
|       future: 'Future', | ||||
|       between: 'Between', | ||||
|       recent: 'Recent', | ||||
|       soon: 'Soon', | ||||
|       month: 'Month', | ||||
|       weekday: 'Weekday', | ||||
|       account: 'Account', | ||||
|       accountName: 'Account name', | ||||
|       routingNumber: 'Routing number', | ||||
|       mask: 'Mask', | ||||
|       amount: 'Amount', | ||||
|       transactionType: 'Transaction type', | ||||
|       currencyCode: 'Currency code', | ||||
|       currencyName: 'Currency name', | ||||
|       currencySymbol: 'Currency symbol', | ||||
|       bitcoinAddress: 'Bitcoin address', | ||||
|       litecoinAddress: 'Litecoin address', | ||||
|       creditCardNumber: 'Credit card number', | ||||
|       creditCardCVV: 'Credit card CVV', | ||||
|       ethereumAddress: 'Ethereum address', | ||||
|       iban: 'Iban', | ||||
|       bic: 'Bic', | ||||
|       transactionDescription: 'Transaction description', | ||||
|       branch: 'Branch', | ||||
|       commitEntry: 'Commit entry', | ||||
|       commitMessage: 'Commit message', | ||||
|       commitSha: 'Commit SHA', | ||||
|       shortSha: 'Short SHA', | ||||
|       abbreviation: 'Abbreviation', | ||||
|       adjective: 'Adjective', | ||||
|       noun: 'Noun', | ||||
|       verb: 'Verb', | ||||
|       ingverb: 'Ingverb', | ||||
|       phrase: 'Phrase', | ||||
|       avatar: 'Avatar', | ||||
|       email: 'Email', | ||||
|       exampleEmail: 'Example email', | ||||
|       userName: 'Username', | ||||
|       protocol: 'Protocol', | ||||
|       url: 'Url', | ||||
|       domainName: 'Domin name', | ||||
|       domainSuffix: 'Domain suffix', | ||||
|       domainWord: 'Domain word', | ||||
|       ip: 'Ip', | ||||
|       ipv6: 'Ipv6', | ||||
|       userAgent: 'User agent', | ||||
|       mac: 'Mac', | ||||
|       password: 'Password', | ||||
|       word: 'Word', | ||||
|       words: 'Words', | ||||
|       sentence: 'Sentence', | ||||
|       slug: 'Slug', | ||||
|       sentences: 'Sentences', | ||||
|       paragraph: 'Paragraph', | ||||
|       paragraphs: 'Paragraphs', | ||||
|       text: 'Text', | ||||
|       lines: 'Lines', | ||||
|       genre: 'Genre', | ||||
|       firstName: 'First name', | ||||
|       lastName: 'Last name', | ||||
|       middleName: 'Middle name', | ||||
|       findName: 'Full name', | ||||
|       jobTitle: 'Job title', | ||||
|       gender: 'Gender', | ||||
|       prefix: 'Prefix', | ||||
|       suffix: 'Suffix', | ||||
|       title: 'Title', | ||||
|       jobDescriptor: 'Job descriptor', | ||||
|       jobArea: 'Job area', | ||||
|       jobType: 'Job type', | ||||
|       phoneNumber: 'Phone number', | ||||
|       phoneNumberFormat: 'Phone number format', | ||||
|       phoneFormats: 'Phone formats', | ||||
|       number: 'Number', | ||||
|       float: 'Float', | ||||
|       arrayElement: 'Array element', | ||||
|       arrayElements: 'Array elements', | ||||
|       objectElement: 'Object element', | ||||
|       uuid: 'Uuid', | ||||
|       boolean: 'Boolean', | ||||
|       image: 'Image', | ||||
|       locale: 'Locale', | ||||
|       alpha: 'Alpha', | ||||
|       alphaNumeric: 'Alphanumeric', | ||||
|       hexaDecimal: 'Hexadecimal', | ||||
|       fileName: 'File name', | ||||
|       commonFileName: 'Common file name', | ||||
|       mimeType: 'Mime type', | ||||
|       commonFileType: 'Common file type', | ||||
|       commonFileExt: 'Common file extension', | ||||
|       fileType: 'File type', | ||||
|       fileExt: 'File extension', | ||||
|       directoryPath: 'Directory path', | ||||
|       filePath: 'File path', | ||||
|       semver: 'Semver', | ||||
|       manufacturer: 'Manufacturer', | ||||
|       model: 'Model', | ||||
|       fuel: 'Fuel', | ||||
|       vin: 'Vin' | ||||
|    }, | ||||
|    // Date and Time | ||||
|    short: { | ||||
|   | ||||
| @@ -30,6 +30,10 @@ export default class { | ||||
|       return ipcRenderer.invoke('insert-table-rows', params); | ||||
|    } | ||||
|  | ||||
|    static insertTableFakeRows (params) { | ||||
|       return ipcRenderer.invoke('insert-table-fake-rows', params); | ||||
|    } | ||||
|  | ||||
|    static getForeignList (params) { | ||||
|       return ipcRenderer.invoke('get-foreign-list', params); | ||||
|    } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user