Init config #68

Merged
jsegarra merged 6 commits from wbuezas/hedera-web-mindshore:feature/InitConfig into 4922-vueMigration 2024-07-19 11:13:56 +00:00
42 changed files with 2564 additions and 2249 deletions
Showing only changes of commit 47c6fe02ec - Show all commits

View File

@ -7,15 +7,14 @@ module.exports = {
parserOptions: {
parser: '@babel/eslint-parser',
ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
sourceType: 'module' // Allows for the use of imports
sourceType: 'module', // Allows for the use of imports
},
env: {
browser: true,
'vue/setup-compiler-macros': true
'vue/setup-compiler-macros': true,
},
// Rules order is important, please avoid shuffling them
extends: [
// Base ESLint recommended rules
// 'eslint:recommended',
@ -31,12 +30,9 @@ module.exports = {
],
plugins: [
// https://eslint.vuejs.org/user-guide/#why-doesn-t-it-work-on-vue-files
// required to lint *.vue files
'vue',
],
plugins: ['vue', 'prettier'],
globals: {
ga: 'readonly', // Google Analytics
@ -48,12 +44,11 @@ module.exports = {
__QUASAR_SSR_PWA__: 'readonly',
process: 'readonly',
Capacitor: 'readonly',
chrome: 'readonly'
chrome: 'readonly',
},
// add your custom rules here
rules: {
// allow async-await
'generator-star-spacing': 'off',
// allow paren-less arrow functions
@ -72,8 +67,20 @@ module.exports = {
'import/no-extraneous-dependencies': 'off',
'prefer-promise-reject-errors': 'off',
semi: 'off',
// allow debugger during development only
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
}
}
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
},
overrides: [
{
extends: [
'plugin:vue/vue3-essential',
],
files: ['src/**/*.{js,vue,scss}'], // Aplica ESLint solo a archivos .js y .vue dentro de src
rules: {
semi: 'off',
indent: ['error', 4, { SwitchCase: 1 }],
},
},
],
};

9
.prettierrc.js Normal file
View File

@ -0,0 +1,9 @@
module.exports = {
printWidth: 80,
tabWidth: 4,
useTabs: false,
singleQuote: true,
trailingComma: 'all',
bracketSpacing: true,
arrowParens: 'avoid',
};

589
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -17,12 +17,14 @@
"assets-webpack-plugin": "^7.1.1",
"babel-loader": "^9.1.0",
"bundle-loader": "^0.5.6",
"eslint": "^8.10.0",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-standard": "^17.0.0",
"eslint-plugin-import": "^2.19.1",
"eslint-plugin-n": "^15.0.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-vue": "^9.0.0",
"eslint-plugin-vue": "^9.27.0",
"eslint-webpack-plugin": "^3.1.1",
"file-loader": "^6.2.0",
"fs-extra": "^10.1.0",

View File

@ -1,4 +1,3 @@
export default async ({ app }) => {
/*
window.addEventListener('error',

View File

@ -28,7 +28,7 @@ a.link {
}
.q-card {
border-radius: 7px;
box-shadow: 0 0 3px rgba(0, 0, 0, .1);
box-shadow: 0 0 3px rgba(0, 0, 0, 0.1);
}
.q-page-sticky.fixed-bottom-right {
margin: 18px;

View File

@ -12,17 +12,17 @@
// to match your app's branding.
// Tip: Use the "Theme Builder" on Quasar's documentation website.
$primary : #1A1A1A;
$secondary : #26A69A;
$primary: #1a1a1a;
$secondary: #26a69a;
$accent: #8cc63f;
$dark : #1D1D1D;
$dark: #1d1d1d;
$dark-page: #121212;
$positive : #21BA45;
$negative : #C10015;
$info : #31CCEC;
$warning : #F2C037;
$positive: #21ba45;
$negative: #c10015;
$info: #31ccec;
$warning: #f2c037;
// Width

View File

@ -1,4 +1,3 @@
%margin-auto {
margin-left: auto;
margin-right: auto;

View File

@ -22,15 +22,7 @@ export default {
'Friday',
'Saturday'
],
daysShort: [
'Sun',
'Mon',
'Tue',
'Wed',
'Thu',
'Fri',
'Sat'
],
daysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
months: [
'January',
'February',

View File

@ -22,15 +22,7 @@ export default {
'Viernes',
'Sábado'
],
daysShort: [
'Do',
'Lu',
'Mi',
'Mi',
'Ju',
'Vi',
'Sa'
],
daysShort: ['Do', 'Lu', 'Mi', 'Mi', 'Ju', 'Vi', 'Sa'],
months: [
'Enero',
'Febrero',

View File

@ -57,8 +57,10 @@ export class Connection extends JsonConnection {
})
for (let j = 0; j < rows.length; j++) {
const row = data[j] = {}
for (let k = 0; k < columns.length; k++) { row[columns[k].name] = rows[j][k] }
const row = (data[j] = {})
for (let k = 0; k < columns.length; k++) {
row[columns[k].name] = rows[j][k]
}
}
for (let j = 0; j < columns.length; j++) {
@ -74,14 +76,20 @@ export class Connection extends JsonConnection {
}
if (castFunc !== null) {
if (col.def != null) { col.def = castFunc(col.def) }
if (col.def != null) {
col.def = castFunc(col.def)
}
for (let k = 0; k < data.length; k++) {
if (data[k][col.name] != null) { data[k][col.name] = castFunc(data[k][col.name]) }
if (data[k][col.name] != null) {
data[k][col.name] = castFunc(data[k][col.name])
}
}
}
} else { results.push(json[i]) }
}
} else {
results.push(json[i])
}
}
}
} catch (e) {
@ -100,7 +108,7 @@ export class Connection extends JsonConnection {
* @return {ResultSet} The result
*/
async execQuery (query, params) {
const sql = query.replace(/#\w+/g, key => {
const sql = query.replace(/#\w+/g, (key) => {
const value = params[key.substring(1)]
return value ? this.renderValue(value) : key
})
@ -128,7 +136,7 @@ export class Connection extends JsonConnection {
case 'number':
return v
case 'boolean':
return (v) ? 'TRUE' : 'FALSE'
return v ? 'TRUE' : 'FALSE'
case 'string':
return "'" + v.replace(this.regexp, this.replaceFunc) + "'"
default:
@ -136,8 +144,12 @@ export class Connection extends JsonConnection {
if (!isNaN(v.getTime())) {
const unixTime = parseInt(fixTz(v).getTime() / 1000)
return 'DATE(FROM_UNIXTIME(' + unixTime + '))'
} else { return '0000-00-00' }
} else { return 'NULL' }
} else {
return '0000-00-00'
}
} else {
return 'NULL'
}
}
}
@ -151,16 +163,14 @@ export class Connection extends JsonConnection {
// TODO: Read time zone from db configuration
const tz = { timeZone: 'Europe/Madrid' }
const isLocal = Intl
.DateTimeFormat()
.resolvedOptions()
.timeZone === tz.timeZone
const isLocal = Intl.DateTimeFormat().resolvedOptions().timeZone === tz.timeZone
function fixTz (date) {
if (isLocal) return date
const localDate = new Date(date.toLocaleString('en-US', tz))
const hasTime = localDate.getHours() ||
const hasTime =
localDate.getHours() ||
localDate.getMinutes() ||
localDate.getSeconds() ||
localDate.getMilliseconds()

View File

@ -1,4 +1,3 @@
import { Result } from './result'
/**
@ -26,10 +25,13 @@ export class ResultSet {
}
fetch () {
if (this.error) { throw this.error }
if (this.error) {
throw this.error
}
if (this.results !== null &&
this.results.length > 0) { return this.results.shift() }
if (this.results !== null && this.results.length > 0) {
return this.results.shift()
}
return null
}
@ -61,9 +63,13 @@ export class ResultSet {
fetchObject () {
const result = this.fetch()
if (result !== null &&
if (
result !== null &&
result.data instanceof Array &&
result.data.length > 0) { return result.data[0] }
result.data.length > 0
) {
return result.data[0]
}
return null
}
@ -76,8 +82,7 @@ export class ResultSet {
fetchData () {
const result = this.fetch()
if (result !== null &&
result.data instanceof Array) {
if (result !== null && result.data instanceof Array) {
return result.data
}
@ -92,7 +97,9 @@ export class ResultSet {
fetchValue () {
const row = this.fetchRow()
if (row instanceof Array && row.length > 0) { return row[0] }
if (row instanceof Array && row.length > 0) {
return row[0]
}
return null
}
@ -105,9 +112,11 @@ export class ResultSet {
fetchRow () {
const result = this.fetch()
if (result !== null &&
if (
result !== null &&
result.data instanceof Array &&
result.data.length > 0) {
result.data.length > 0
) {
const object = result.data[0]
const row = new Array(result.columns.length)
for (let i = 0; i < row.length; i++) {

View File

@ -19,7 +19,9 @@ export class Result {
col.index = i
this.columnMap[col.name] = col
}
} else { this.columnMap = null }
} else {
this.columnMap = null
}
}
/**
@ -54,7 +56,9 @@ export class Result {
next () {
this.row++
if (this.row >= this.data.length) { return false }
if (this.row >= this.data.length) {
return false
}
return true
}

View File

@ -1,4 +1,3 @@
import { VnObject } from './object'
import { JsonException } from './json-exception'
@ -34,7 +33,9 @@ export class JsonConnection extends VnObject {
const elements = form.elements
for (let i = 0; i < elements.length; i++) {
if (elements[i].name) { params[elements[i].name] = elements[i].value }
if (elements[i].name) {
params[elements[i].name] = elements[i].value
}
}
return this.sendWithUrl('POST', form.action, params)
@ -93,32 +94,39 @@ export class JsonConnection extends VnObject {
}
const promise = new Promise((resolve, reject) => {
request.onreadystatechange =
() => this._onStateChange(request, resolve, reject)
request.onreadystatechange = () =>
this._onStateChange(request, resolve, reject)
})
request.send(config.data)
this._requestsCount++
if (this._requestsCount === 1) { this.emit('loading-changed', true) }
if (this._requestsCount === 1) {
this.emit('loading-changed', true)
}
return promise
}
_onStateChange (request, resolve, reject) {
if (request.readyState !== 4) { return }
if (request.readyState !== 4) {
return
}
this._requestsCount--
if (this._requestsCount === 0) { this.emit('loading-changed', false) }
if (this._requestsCount === 0) {
this.emit('loading-changed', false)
}
let data = null
let error = null
try {
if (request.status === 0) {
const err = new JsonException()
err.message = 'The server does not respond, please check your Internet connection'
err.message =
'The server does not respond, please check your Internet connection'
err.statusCode = request.status
throw err
}
@ -144,8 +152,12 @@ export class JsonConnection extends VnObject {
let json
let jsData
if (request.responseText) { json = JSON.parse(request.responseText) }
if (json) { jsData = json.data || json }
if (request.responseText) {
json = JSON.parse(request.responseText)
}
if (json) {
jsData = json.data || json
}
if (request.status >= 200 && request.status < 300) {
data = jsData
@ -181,6 +193,8 @@ export class JsonConnection extends VnObject {
if (error) {
this.emit('error', error)
reject(error)
} else { resolve(data) }
} else {
resolve(data)
}
}
}

View File

@ -1,4 +1,3 @@
/**
* The main base class. Manages the signal system. Objects based on this class
* can be instantiated declaratively using XML.
@ -45,7 +44,9 @@ export class VnObject {
* @param {Object} props Properties
*/
setProperties (props) {
for (const prop in props) { this[prop] = props[prop] }
for (const prop in props) {
this[prop] = props[prop]
}
}
/**
@ -62,7 +63,9 @@ export class VnObject {
unref () {
this._refCount--
if (this._refCount === 0) { this._destroy() }
if (this._refCount === 0) {
this._destroy()
}
}
/**
@ -91,14 +94,16 @@ export class VnObject {
*/
on (id, callback, instance) {
if (!(callback instanceof Function)) {
console.warn('Vn.Object: Invalid callback for signal \'%s\'', id)
console.warn("Vn.Object: Invalid callback for signal '%s'", id)
return
}
this._signalInit()
let callbacks = this._thisArg.signals[id]
if (!callbacks) { callbacks = this._thisArg.signals[id] = [] }
if (!callbacks) {
callbacks = this._thisArg.signals[id] = []
}
callbacks.push({
blocked: false,
@ -115,15 +120,23 @@ export class VnObject {
* @param {boolean} block %true for lock the signal, %false for unlock
*/
blockSignal (id, callback, block, instance) {
if (!this._thisArg) { return }
if (!this._thisArg) {
return
}
const callbacks = this._thisArg.signals[id]
if (!callbacks) { return }
if (!callbacks) {
return
}
for (let i = 0; i < callbacks.length; i++) {
if (callbacks[i].callback === callback &&
callbacks[i].instance === instance) { callbacks[i].blocked = block }
if (
callbacks[i].callback === callback &&
callbacks[i].instance === instance
) {
callbacks[i].blocked = block
}
}
}
@ -133,19 +146,27 @@ export class VnObject {
* @param {string} id The signal identifier
*/
emit (id) {
if (!this._thisArg) { return }
if (!this._thisArg) {
return
}
const callbacks = this._thisArg.signals[id]
if (!callbacks) { return }
if (!callbacks) {
return
}
const callbackArgs = []
callbackArgs.push(this)
for (let i = 1; i < arguments.length; i++) { callbackArgs.push(arguments[i]) }
for (let i = 1; i < arguments.length; i++) {
callbackArgs.push(arguments[i])
}
for (let i = 0; i < callbacks.length; i++) {
if (!callbacks[i].blocked) { callbacks[i].callback.apply(callbacks[i].instance, callbackArgs) }
if (!callbacks[i].blocked) {
callbacks[i].callback.apply(callbacks[i].instance, callbackArgs)
}
}
}
@ -157,14 +178,20 @@ export class VnObject {
* @param {Object} instance The instance
*/
disconnect (id, callback, instance) {
if (!this._thisArg) { return }
if (!this._thisArg) {
return
}
const callbacks = this._thisArg.signals[id]
if (callbacks) {
for (let i = callbacks.length; i--;) {
if (callbacks[i].callback === callback &&
callbacks[i].instance === instance) { callbacks.splice(i, 1) }
if (
callbacks[i].callback === callback &&
callbacks[i].instance === instance
) {
callbacks.splice(i, 1)
}
}
}
}
@ -175,7 +202,9 @@ export class VnObject {
* @param {Object} instance The instance
*/
disconnectByInstance (instance) {
if (!this._thisArg) { return }
if (!this._thisArg) {
return
}
const signals = this._thisArg.signals
@ -184,7 +213,9 @@ export class VnObject {
if (callbacks) {
for (let i = callbacks.length; i--;) {
if (callbacks[i].instance === instance) { callbacks.splice(i, 1) }
if (callbacks[i].instance === instance) {
callbacks.splice(i, 1)
}
}
}
}
@ -196,11 +227,15 @@ export class VnObject {
* but should always call the parent method.
*/
_destroy () {
if (!this._thisArg) { return }
if (!this._thisArg) {
return
}
const links = this._thisArg.links
for (const key in links) { this._unlink(links[key]) }
for (const key in links) {
this._unlink(links[key])
}
this._thisArg = null
}
@ -219,15 +254,21 @@ export class VnObject {
const newObject = prop[key]
const oldObject = this[key]
if (oldObject) { this._unlink(oldObject) }
if (oldObject) {
this._unlink(oldObject)
}
this[key] = newObject
if (newObject) {
links[key] = newObject.ref()
for (const signal in handlers) { newObject.on(signal, handlers[signal], this) }
} else if (oldObject) { links[key] = undefined }
for (const signal in handlers) {
newObject.on(signal, handlers[signal], this)
}
} else if (oldObject) {
links[key] = undefined
}
}
}

View File

@ -1,5 +1,8 @@
<template>
<q-layout id="bg" class="fullscreen row justify-center items-center layout-view scroll">
<q-layout
id="bg"
class="fullscreen row justify-center items-center layout-view scroll"
>
<div class="column q-pa-md row items-center justify-center">
<router-view v-slot="{ Component }">
<transition>

View File

@ -8,38 +8,34 @@
round
icon="menu"
aria-label="Menu"
@click="toggleLeftDrawer"/>
@click="toggleLeftDrawer"
/>
<q-toolbar-title>
{{ $app.title }}
<div
v-if="$app.subtitle"
class="subtitle text-caption">
<div v-if="$app.subtitle" class="subtitle text-caption">
{{ $app.subtitle }}
</div>
</q-toolbar-title>
<div id="actions" ref="actions">
</div>
<div id="actions" ref="actions"></div>
<q-btn
v-if="$app.useRightDrawer"
@click="$app.rightDrawerOpen = !$app.rightDrawerOpen"
aria-label="Menu"
flat
dense
round>
round
>
<q-icon name="menu" />
</q-btn>
</q-toolbar>
</q-header>
<q-drawer
v-model="leftDrawerOpen"
:width="250"
show-if-above>
<q-drawer v-model="leftDrawerOpen" :width="250" show-if-above>
<q-toolbar class="logo">
<img src="statics/logo-dark.svg">
<img src="statics/logo-dark.svg" />
</q-toolbar>
<div class="user-info">
<div>
<span id="user-name">{{(user.nickname)}}</span>
<span id="user-name">{{ user.nickname }}</span>
<q-btn flat icon="logout" alt="_Exit" @click="logout()" />
</div>
<div id="supplant" class="supplant">
@ -47,12 +43,8 @@
<q-btn flat icon="logout" alt="_Exit" />
</div>
</div>
<q-list
v-for="item in essentialLinks"
:key="item.id">
<q-item
v-if="!item.childs"
:to="`/${item.path}`">
<q-list v-for="item in essentialLinks" :key="item.id">
<q-item v-if="!item.childs" :to="`/${item.path}`">
<q-item-section>
<q-item-label>{{ item.description }}</q-item-label>
</q-item-section>
@ -60,13 +52,15 @@
<q-expansion-item
v-if="item.childs"
:label="item.description"
expand-separator>
expand-separator
>
<q-list>
<q-item
v-for="subitem in item.childs"
:key="subitem.id"
:to="`/${subitem.path}`"
class="q-pl-lg">
class="q-pl-lg"
>
<q-item-section>
<q-item-label>{{ subitem.description }}</q-item-label>
</q-item-section>
@ -134,7 +128,7 @@
</style>
<style lang="scss">
@import "src/css/responsive";
@import 'src/css/responsive';
.q-drawer {
.q-item {
@ -215,7 +209,9 @@ export default defineComponent({
const parentSection = sectionMap.get(parent)
if (!parentSection) continue
let childs = parentSection.childs
if (!childs) { childs = parentSection.childs = [] }
if (!childs) {
childs = parentSection.childs = []
}
childs.push(section)
} else {
sectionTree.push(section)

View File

@ -1,4 +1,3 @@
import { date as qdate, format } from 'quasar'
const { pad } = format
@ -61,7 +60,7 @@ export function elapsedTime (val) {
if (!(val instanceof Date)) {
val = new Date(val)
}
const now = (new Date()).getTime()
const now = new Date().getTime()
val = Math.floor((now - val.getTime()) / 1000)
const hours = Math.floor(val / 3600)

View File

@ -1,13 +1,9 @@
<template>
<div style="padding: 0;">
<div style="padding: 0">
<div class="q-pa-sm row items-start">
<div
class="new-card q-pa-sm"
v-for="myNew in news"
:key="myNew.id">
<div class="new-card q-pa-sm" v-for="myNew in news" :key="myNew.id">
<q-card>
<q-img :src="`${$app.imageUrl}/news/full/${myNew.image}`">
</q-img>
<q-img :src="`${$app.imageUrl}/news/full/${myNew.image}`"> </q-img>
<q-card-section>
<div class="text-h5">{{ myNew.title }}</div>
</q-card-section>

View File

@ -8,12 +8,10 @@
rounded
dark
dense
standout>
standout
>
<template v-slot:prepend>
<q-icon
v-if="search === ''"
name="search"
/>
<q-icon v-if="search === ''" name="search" />
<q-icon
v-else
name="clear"
@ -27,13 +25,11 @@
:label="$t(viewMode == 'list' ? 'listView' : 'gridView')"
@click="onViewModeClick()"
rounded
no-caps/>
no-caps
/>
</Teleport>
<div style="padding-bottom: 5em;">
<q-drawer
v-model="$app.rightDrawerOpen"
side="right"
:width="250">
<div style="padding-bottom: 5em">
<q-drawer v-model="$app.rightDrawerOpen" side="right" :width="250">
<div class="q-pa-md">
<div class="basket-info">
<p>{{ date(new Date()) }}</p>
@ -41,10 +37,7 @@
{{ $t('warehouse') }}
{{ 'Algemesi' }}
</p>
<q-btn
flat
rounded
no-caps>
<q-btn flat rounded no-caps>
{{ $t('modify') }}
</q-btn>
</div>
@ -53,7 +46,7 @@
{{ $t('category') }}
<q-icon
v-if="category"
style="font-size: 1.3em;"
style="font-size: 1.3em"
name="cancel"
class="cursor-pointer"
:title="$t('deleteFilter')"
@ -69,13 +62,13 @@
:class="{ active: category == cat.id }"
:key="cat.id"
:title="cat.name"
:to="{params: {category: cat.id, type: null}}">
<img :src="`statics/category/${cat.code}.svg`">
:to="{ params: { category: cat.id, type: null } }"
>
<img :src="`statics/category/${cat.code}.svg`" />
</q-btn>
</div>
</div>
<div class="q-mt-md"
v-if="category || search">
<div class="q-mt-md" v-if="category || search">
<div class="q-mb-xs text-grey-7">
{{ $t('filterBy') }}
</div>
@ -98,16 +91,13 @@
/>
</div>
</div>
<div class="q-pa-md"
v-if="typeId || search">
<div class="q-mb-md"
v-for="tag in tags"
:key="tag.uid">
<div class="q-pa-md" v-if="typeId || search">
<div class="q-mb-md" v-for="tag in tags" :key="tag.uid">
<div class="q-mb-xs text-caption text-grey-7">
{{ tag.name }}
<q-icon
v-if="tag.hasFilter"
style="font-size: 1.3em;"
style="font-size: 1.3em"
name="cancel"
:title="$t('deleteFilter')"
class="cursor-pointer"
@ -117,7 +107,8 @@
<div v-if="!tag.useRange">
<div
v-for="value in tag.values.slice(0, tag.showCount)"
:key="value">
:key="value"
>
<q-checkbox
v-model="tag.filter"
:dense="true"
@ -129,7 +120,8 @@
<div v-if="tag.values.length > tag.showCount">
<span
class="cursor-pointer text-blue"
@click="tag.showCount = Infinity">
@click="tag.showCount = Infinity"
>
<q-icon name="keyboard_arrow_down" />
{{ $t('viewMore') }}
</span>
@ -137,7 +129,8 @@
<div v-if="tag.showCount == Infinity">
<span
class="cursor-pointer text-blue"
@click="tag.showCount = tag.initialCount">
@click="tag.showCount = tag.initialCount"
>
<q-icon name="keyboard_arrow_up" />
{{ $t('viewLess') }}
</span>
@ -166,44 +159,45 @@
@load="onLoad"
scroll-taget="html"
:offset="800"
:disable="disableScroll">
:disable="disableScroll"
>
<div class="q-pa-md row justify-center q-gutter-md">
<q-spinner
v-if="isLoading"
color="primary"
size="50px">
</q-spinner>
<q-spinner v-if="isLoading" color="primary" size="50px"> </q-spinner>
<div
v-if="items && !items.length"
class="text-subtitle1 text-grey-7 q-pa-md">
class="text-subtitle1 text-grey-7 q-pa-md"
>
{{ $t('noItemsFound') }}
</div>
<div
v-if="!items && !isLoading"
class="text-subtitle1 text-grey-7 q-pa-md">
class="text-subtitle1 text-grey-7 q-pa-md"
>
{{ $t('pleaseSetFilter') }}
</div>
<q-card
class="my-card"
v-for="item in items"
:key="item.id">
<q-card class="my-card" v-for="item in items" :key="item.id">
<img :src="`${$imageBase}/catalog/200x200/${item.image}`" />
<q-card-section>
<div class="name text-subtitle1">
{{ item.longName }}
</div>
<div class="sub-name text-uppercase text-subtitle1 text-grey-7 ellipsize q-pt-xs">
<div
class="sub-name text-uppercase text-subtitle1 text-grey-7 ellipsize q-pt-xs"
>
{{ item.subName }}
</div>
<div class="tags q-pt-xs">
<div v-for="tag in item.tags" :key="tag.tagFk">
<span class="text-grey-7">{{tag.tag.name}}</span> {{tag.value}}
<span class="text-grey-7">{{ tag.tag.name }}</span>
{{ tag.value }}
</div>
</div>
</q-card-section>
<q-card-actions class="actions justify-between">
<div class="q-pl-sm">
<span class="available bg-green text-white">{{item.available}}</span>
<span class="available bg-green text-white">{{
item.available
}}</span>
{{ $t('from') }}
<span class="price">{{ currency(item.buy?.price3) }}</span>
</div>
@ -211,7 +205,8 @@
icon="add_shopping_cart"
:title="$t('buy')"
@click="showItem(item)"
flat>
flat
>
</q-btn>
</q-card-actions>
</q-card>
@ -223,10 +218,11 @@
</template>
</q-infinite-scroll>
<q-dialog v-model="showItemDialog">
<q-card style="width: 25em;">
<q-card style="width: 25em">
<q-img
:src="`${$imageBase}/catalog/200x200/${item.image}`"
:ratio="5/3">
:ratio="5 / 3"
>
<div class="absolute-bottom text-center q-pa-xs">
<div class="text-subtitle1">
{{ item.longName }}
@ -237,24 +233,19 @@
<div class="text-uppercase text-subtitle1 text-grey-7 ellipsize">
{{ item.subName }}
</div>
<div class="text-grey-7">
#{{item.id}}
</div>
<div class="text-grey-7">#{{ item.id }}</div>
</q-card-section>
<q-card-section>
<div v-for="tag in item.tags" :key="tag.tagFk">
<span class="text-grey-7">{{tag.tag.name}}</span> {{tag.value}}
<span class="text-grey-7">{{ tag.tag.name }}</span>
{{ tag.value }}
</div>
</q-card-section>
<q-card-actions align="right">
<q-btn
@click="showItemDialog = false"
flat>
<q-btn @click="showItemDialog = false" flat>
{{ $t('cancel') }}
</q-btn>
<q-btn
@click="showItemDialog = false"
flat>
<q-btn @click="showItemDialog = false" flat>
{{ $t('accept') }}
</q-btn>
</q-card-actions>
@ -266,7 +257,8 @@
to="/ecomerce/basket"
icon="shopping_cart"
color="accent"
:title="$t('shoppingCart')"/>
:title="$t('shoppingCart')"
/>
</q-page-sticky>
</div>
</template>
@ -284,7 +276,7 @@
& > p {
margin: 0;
padding: .4em 0;
padding: 0.4em 0;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
@ -298,7 +290,7 @@
width: 55px;
&.active {
background: rgba(0, 0, 0, .08);
background: rgba(0, 0, 0, 0.08);
}
& > img {
height: 40px;
@ -311,8 +303,8 @@
overflow: hidden;
}
.available {
padding: .15em;
border-radius: .2em;
padding: 0.15em;
border-radius: 0.2em;
font-size: 1.3em;
}
.price {
@ -323,7 +315,8 @@
max-width: 17.5em;
height: 32.5em;
overflow: hidden;
.name, .sub-name {
.name,
.sub-name {
line-height: 1.3em;
}
.ellipsize {
@ -376,22 +369,28 @@ export default {
{
label: this.$t('relevancy'),
value: 'relevancy DESC, longName'
}, {
},
{
label: this.$t('name'),
value: 'longName'
}, {
},
{
label: this.$t('siceAsc'),
value: 'size ASC'
}, {
},
{
label: this.$t('sizeDesc'),
value: 'size DESC'
}, {
},
{
label: this.$t('priceAsc'),
value: 'price ASC'
}, {
},
{
label: this.$t('priceDesc'),
value: 'price DESC'
}, {
},
{
label: this.$t('available'),
value: 'available'
}
@ -482,12 +481,13 @@ export default {
let subtitle
if (this.category) {
const category = this.categories.find(i => i.id === this.category) || {}
const category =
this.categories.find((i) => i.id === this.category) || {}
title = category.name
}
if (this.typeId) {
this.type = this.orgTypes.find(i => i.id === this.typeId)
this.type = this.orgTypes.find((i) => i.id === this.typeId)
subtitle = title
title = this.type && this.type.name
} else {
@ -558,9 +558,10 @@ export default {
params,
cancelToken: this.source.token
}
return this.$axios.get('Items/catalog', config)
.then(res => this.onItemsGet(res))
.catch(err => this.onItemsError(err))
return this.$axios
.get('Items/catalog', config)
.then((res) => this.onItemsGet(res))
.catch((err) => this.onItemsError(err))
.finally(() => (this.cancel = null))
},
onItemsError (err) {
@ -574,12 +575,9 @@ export default {
if (tag.filter) {
tag.hasFilter = true
tag.useRange =
tag.filter.max ||
tag.filter.min
tag.useRange = tag.filter.max || tag.filter.min
} else {
tag.useRange = tag.isQuantitative &&
tag.values.length > this.maxTags
tag.useRange = tag.isQuantitative && tag.values.length > this.maxTags
this.resetTagFilter(tag)
}
@ -624,12 +622,15 @@ export default {
},
filterType (val, update) {
if (val === '') {
update(() => { this.types = this.orgTypes })
update(() => {
this.types = this.orgTypes
})
} else {
update(() => {
const needle = val.toLowerCase()
this.types = this.orgTypes.filter(type =>
type.name.toLowerCase().indexOf(needle) > -1)
this.types = this.orgTypes.filter(
(type) => type.name.toLowerCase().indexOf(needle) > -1
)
})
}
},
@ -643,8 +644,9 @@ export default {
addressFk: conf.addressFk,
agencyModeFk: conf.agencyModeFk
}
this.$axios.get(`Items/${item.id}/calcCatalog`, { params })
.then(res => (this.lots = res.data))
this.$axios
.get(`Items/${item.id}/calcCatalog`, { params })
.then((res) => (this.lots = res.data))
}
}
}

View File

@ -7,12 +7,14 @@
dark
standout
dense
rounded />
rounded
/>
</Teleport>
<div class="vn-w-sm">
<div
v-if="!invoices?.length"
class="text-subtitle1 text-center text-grey-7 q-pa-md">
class="text-subtitle1 text-center text-grey-7 q-pa-md"
>
{{ $t('noInvoicesFound') }}
</div>
<q-card v-if="invoices?.length">
@ -22,7 +24,8 @@
:rows="invoices"
row-key="id"
hide-header
hide-bottom>
hide-bottom
>
<template v-slot:body="props">
<q-tr :props="props">
<q-td key="ref" :props="props">
@ -42,13 +45,15 @@
:href="invoiceUrl(props.row.id)"
target="_blank"
flat
round/>
round
/>
<q-icon
v-else
name="warning"
:title="$t('notDownloadable')"
color="warning"
size="24px"/>
size="24px"
/>
</q-td>
</q-tr>
</template>
@ -63,7 +68,7 @@ import { date, currency } from 'src/lib/filters.js'
export default {
name: 'OrdersPendingIndex',
data () {
const curYear = (new Date()).getFullYear()
const curYear = new Date().getFullYear()
const years = []
for (let year = curYear - 5; year <= curYear; year++) {
@ -116,11 +121,14 @@ export default {
},
invoiceUrl (id) {
return '?' + new URLSearchParams({
return (
'?' +
new URLSearchParams({
srv: 'rest:dms/invoice',
invoice: id,
access_token: this.$user.token
}).toString()
)
}
}
}

View File

@ -2,34 +2,31 @@
<Teleport :to="$actions">
<div class="balance">
<span class="label">{{ $t('balance') }}</span>
<span
class="amount"
:class="{negative: debt < 0}">
<span class="amount" :class="{ negative: debt < 0 }">
{{ currency(debt || 0) }}
</span>
<q-icon
name="info"
:title="$t('paymentInfo')"
class="info"
size="24px"/>
<q-icon name="info" :title="$t('paymentInfo')" class="info" size="24px" />
</div>
<q-btn
icon="payments"
:label="$t('makePayment')"
@click="onPayClick()"
rounded
no-caps/>
no-caps
/>
<q-btn
to="/ecomerce/basket"
icon="shopping_cart"
:label="$t('shoppingCart')"
rounded
no-caps/>
no-caps
/>
</Teleport>
<div class="vn-w-sm">
<div
v-if="!orders?.length"
class="text-subtitle1 text-center text-grey-7 q-pa-md">
class="text-subtitle1 text-center text-grey-7 q-pa-md"
>
{{ $t('noOrdersFound') }}
</div>
<q-card v-if="orders?.length">
@ -39,7 +36,8 @@
:key="order.id"
:to="`ticket/${order.id}`"
clickable
v-ripple>
v-ripple
>
<q-item-section>
<q-item-label>
{{ date(order.landed, 'ddd, MMMM Do') }}
@ -48,9 +46,7 @@
<q-item-label caption>{{ order.nickname }}</q-item-label>
<q-item-label caption>{{ order.agency }}</q-item-label>
</q-item-section>
<q-item-section side top>
{{order.total}}
</q-item-section>
<q-item-section side top> {{ order.total }} </q-item-section>
</q-item>
</q-list>
</q-card>
@ -60,7 +56,8 @@
icon="add_shopping_cart"
color="accent"
to="/ecomerce/catalog"
:title="$t('startOrder')"/>
:title="$t('startOrder')"
/>
</q-page-sticky>
</div>
</template>
@ -107,12 +104,8 @@ export default {
async mounted () {
await this.tpv.check(this.$route)
this.orders = await this.$jApi.query(
'CALL myTicket_list(NULL, NULL)'
)
this.debt = await this.$jApi.getValue(
'SELECT -myClient_getDebt(NULL)'
)
this.orders = await this.$jApi.query('CALL myTicket_list(NULL, NULL)')
this.debt = await this.$jApi.getValue('SELECT -myClient_getDebt(NULL)')
},
methods: {

View File

@ -5,7 +5,8 @@
:label="$t('printDeliveryNote')"
@click="onPrintClick()"
rounded
no-caps/>
no-caps
/>
</Teleport>
<div>
<q-card class="vn-w-sm">
@ -14,22 +15,31 @@
</q-card-section>
<q-card-section>
<div class="text-h6">{{ $t('shippingInformation') }}</div>
<div>{{$t('preparation')}} {{date(ticket.shipped, 'ddd, MMMM Do')}}</div>
<div>{{$t('delivery')}} {{date(ticket.shipped, 'ddd, MMMM Do')}}</div>
<div>{{$t(ticket.method != 'PICKUP' ? 'agency' : 'warehouse')}} {{ticket.agency}}</div>
<div>
{{ $t('preparation') }} {{ date(ticket.shipped, 'ddd, MMMM Do') }}
</div>
<div>
{{ $t('delivery') }} {{ date(ticket.shipped, 'ddd, MMMM Do') }}
</div>
<div>
{{ $t(ticket.method != 'PICKUP' ? 'agency' : 'warehouse') }}
{{ ticket.agency }}
</div>
</q-card-section>
<q-card-section>
<div class="text-h6">{{ $t('deliveryAddress') }}</div>
<div>{{ ticket.nickname }}</div>
<div>{{ ticket.street }}</div>
<div>{{ticket.postalCode}} {{ticket.city}} ({{ticket.province}})</div>
<div>
{{ ticket.postalCode }} {{ ticket.city }} ({{ ticket.province }})
</div>
</q-card-section>
<q-separator inset />
<q-list v-for="row in rows" :key="row.itemFk">
<q-item>
<q-item-section avatar>
<q-avatar size="68px">
<img :src="`${$app.imageUrl}/catalog/200x200/${row.image}`">
<img :src="`${$app.imageUrl}/catalog/200x200/${row.image}`" />
</q-avatar>
</q-item-section>
<q-item-section>
@ -87,10 +97,7 @@ export default {
'CALL myTicket_get(#ticket)',
params
)
this.rows = await this.$jApi.query(
'CALL myTicket_getRows(#ticket)',
params
)
this.rows = await this.$jApi.query('CALL myTicket_getRows(#ticket)', params)
this.services = await this.$jApi.query(
'CALL myTicket_getServices(#ticket)',
params
@ -120,7 +127,9 @@ export default {
recipientId: this.$user.id,
type: 'deliveryNote'
})
window.open(`/api/Tickets/${this.ticket.id}/delivery-note-pdf?${params.toString()}`)
window.open(
`/api/Tickets/${this.ticket.id}/delivery-note-pdf?${params.toString()}`
)
}
}
}

View File

@ -1,13 +1,11 @@
<template>
<div class="fullscreen bg-accent text-white text-center q-pa-md flex flex-center">
<div
class="fullscreen bg-accent text-white text-center q-pa-md flex flex-center"
>
<div>
<div style="font-size: 30vh">
404
</div>
<div style="font-size: 30vh">404</div>
<div class="text-h2" style="opacity:.4">
Oops. Nothing here...
</div>
<div class="text-h2" style="opacity: 0.4">Oops. Nothing here...</div>
<q-btn
class="q-mt-xl"

View File

@ -4,7 +4,7 @@
alt="Quasar logo"
src="~assets/quasar-logo-vertical.svg"
style="width: 200px; height: 200px"
>
/>
</q-page>
</template>

View File

@ -2,25 +2,18 @@
<div class="main">
<div class="header">
<router-link to="/" class="block">
<img
src="statics/logo.svg"
alt="Verdnatura"
class="block"
/>
<img src="statics/logo.svg" alt="Verdnatura" class="block" />
</router-link>
</div>
<q-form @submit="onLogin" class="q-gutter-y-md">
<div class="q-gutter-y-sm">
<q-input
v-model="email"
:label="$t('user')"
autofocus
/>
<q-input v-model="email" :label="$t('user')" autofocus />
<q-input
v-model="password"
ref="password"
:label="$t('password')"
:type="showPwd ? 'password' : 'text'">
:type="showPwd ? 'password' : 'text'"
>
<template v-slot:append>
<q-icon
:name="showPwd ? 'visibility_off' : 'visibility'"
@ -71,9 +64,7 @@
{{ $t('signUp') }}
</a>
</p>
<p class="contact">
{{$t('loginPhone')}} · {{$t('loginMail')}}
</p>
<p class="contact">{{ $t('loginPhone') }} · {{ $t('loginMail') }}</p>
</div>
</div>
</template>
@ -106,13 +97,13 @@ a {
height: 50px;
}
.password-forgotten {
font-size: .8rem;
font-size: 0.8rem;
}
.footer {
margin-bottom: $login-margin-top;
margin-top: $login-margin-between;
text-align: center;
font-size: .8rem;
font-size: 0.8rem;
.contact {
margin-top: 15px;

View File

@ -4,7 +4,7 @@
<q-icon
name="contact_support"
class="block q-mx-auto text-accent"
style="font-size: 120px;"
style="font-size: 120px"
/>
</div>
<div>
@ -20,7 +20,7 @@
<q-input
v-model="email"
:label="$t('user')"
:rules="[ val => !!val || $t('inputEmail')]"
:rules="[(val) => !!val || $t('inputEmail')]"
autofocus
/>
<div class="q-mt-lg">
@ -56,7 +56,7 @@
}
a {
color: inherit;
font-size: .8rem;
font-size: 0.8rem;
}
</style>

View File

@ -4,7 +4,7 @@
<q-icon
name="check"
class="block q-mx-auto text-accent"
style="font-size: 120px;"
style="font-size: 120px"
/>
</q-card-section>
<q-card-section>
@ -19,7 +19,8 @@
:type="showPwd ? 'password' : 'text'"
autofocus
hint=""
filled>
filled
>
<template v-slot:append>
<q-icon
:name="showPwd ? 'visibility_off' : 'visibility'"
@ -32,9 +33,10 @@
v-model="repeatPassword"
:label="$t('repeatPassword')"
:type="showRpPwd ? 'password' : 'text'"
:rules="[value => value == password || $t('repeatPasswordError')]"
:rules="[(value) => value == password || $t('repeatPasswordError')]"
hint=""
filled>
filled
>
<template v-slot:append>
<q-icon
:name="showRpPwd ? 'visibility_off' : 'visibility'"
@ -78,9 +80,13 @@ export default {
const headers = {
Authorization: this.$route.query.access_token
}
await this.$axios.post('users/reset-password', {
await this.$axios.post(
'users/reset-password',
{
newPassword: this.password
}, { headers })
},
{ headers }
)
this.$q.notify({
message: this.$t('passwordResetSuccessfully'),

View File

@ -1,6 +1,11 @@
import { route } from 'quasar/wrappers'
import { appStore } from 'stores/app'
import { createRouter, createMemoryHistory, createWebHistory, createWebHashHistory } from 'vue-router'
import {
createRouter,
createMemoryHistory,
createWebHistory,
createWebHashHistory
} from 'vue-router'
import routes from './routes'
/*
@ -15,7 +20,9 @@ import routes from './routes'
export default route(function (/* { store, ssrContext } */) {
const createHistory = process.env.SERVER
? createMemoryHistory
: (process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory)
: process.env.VUE_ROUTER_MODE === 'history'
? createWebHistory
: createWebHashHistory
const Router = createRouter({
scrollBehavior: () => ({ left: 0, top: 0 }),
@ -24,7 +31,9 @@ export default route(function (/* { store, ssrContext } */) {
// Leave this as is and make changes in quasar.conf.js instead!
// quasar.conf.js -> build -> vueRouterMode
// quasar.conf.js -> build -> publicPath
history: createHistory(process.env.MODE === 'ssr' ? void 0 : process.env.VUE_ROUTER_BASE)
history: createHistory(
process.env.MODE === 'ssr' ? void 0 : process.env.VUE_ROUTER_BASE
)
})
Router.afterEach((to, from) => {

View File

@ -1,4 +1,3 @@
const routes = [
{
path: '/login',
@ -8,17 +7,20 @@ const routes = [
name: 'login',
path: '/login/:email?',
component: () => import('pages/Login/Login.vue')
}, {
},
{
name: 'rememberPassword',
path: '/remember-password',
component: () => import('pages/Login/RememberPassword.vue')
}, {
},
{
name: 'resetPassword',
path: '/reset-password',
component: () => import('pages/Login/ResetPassword.vue')
}
]
}, {
},
{
path: '/',
component: () => import('layouts/MainLayout.vue'),
children: [
@ -26,23 +28,28 @@ const routes = [
name: '',
path: '',
component: () => import('src/pages/Cms/Home.vue')
}, {
},
{
name: 'home',
path: '/cms/home',
component: () => import('src/pages/Cms/Home.vue')
}, {
},
{
name: 'orders',
path: '/ecomerce/orders',
component: () => import('pages/Ecomerce/Orders.vue')
}, {
},
{
name: 'ticket',
path: '/ecomerce/ticket/:id',
component: () => import('pages/Ecomerce/Ticket.vue')
}, {
},
{
name: 'invoices',
path: '/ecomerce/invoices',
component: () => import('pages/Ecomerce/Invoices.vue')
}, {
},
{
name: 'catalog',
path: '/ecomerce/catalog/:category?/:type?',
component: () => import('pages/Ecomerce/Catalog.vue')

View File

@ -12,9 +12,7 @@ export const appStore = defineStore('hedera', {
actions: {
async loadConfig () {
const imageUrl = await jApi.getValue(
'SELECT url FROM imageConfig'
)
const imageUrl = await jApi.getValue('SELECT url FROM imageConfig')
this.$patch({ imageUrl })
}
}

View File

@ -1,10 +1,10 @@
/* eslint-disable */
// THIS FEATURE-FLAG FILE IS AUTOGENERATED,
// REMOVAL OR CHANGES WILL CAUSE RELATED TYPES TO STOP WORKING
import "quasar/dist/types/feature-flag";
import 'quasar/dist/types/feature-flag'
declare module "quasar/dist/types/feature-flag" {
declare module 'quasar/dist/types/feature-flag' {
interface QuasarFeatureFlags {
store: true;
store: true
}
}

View File

@ -8,14 +8,16 @@ export const tpvStore = defineStore('tpv', {
const status = route.query.tpvStatus
if (!(order && status)) return null
await jApi.execQuery(
'CALL myTpvTransaction_end(#order, #status)',
{ order, status }
)
await jApi.execQuery('CALL myTpvTransaction_end(#order, #status)', {
order,
status
})
if (status === 'ko') {
const retry = confirm('retryPayQuestion')
if (retry) { this.retryPay(order) }
if (retry) {
this.retryPay(order)
}
}
return status
@ -61,7 +63,9 @@ export const tpvStore = defineStore('tpv', {
input.name = field
form.appendChild(input)
if (postValues[field]) { input.value = postValues[field] }
if (postValues[field]) {
input.value = postValues[field]
}
}
form.submit()
@ -73,7 +77,9 @@ export const tpvStore = defineStore('tpv', {
path += location.pathname
path += location.search ? location.search : ''
path += '#/ecomerce/orders'
path += '?' + new URLSearchParams({
path +=
'?' +
new URLSearchParams({
tpvStatus: status,
tpvOrder: '_transactionId_'
}).toString()

View File

@ -4,8 +4,7 @@ import { api, jApi } from 'boot/axios'
export const userStore = defineStore('user', {
state: () => {
const token =
sessionStorage.getItem('vnToken') ||
localStorage.getItem('vnToken')
sessionStorage.getItem('vnToken') || localStorage.getItem('vnToken')
return {
token,
@ -16,7 +15,7 @@ export const userStore = defineStore('user', {
},
getters: {
loggedIn: state => state.token != null
loggedIn: (state) => state.token != null
},
actions: {