Migration step
This commit is contained in:
parent
73a8d045a6
commit
b06dacc4ce
|
@ -0,0 +1,44 @@
|
||||||
|
{
|
||||||
|
"name": "ImageCollection",
|
||||||
|
"base": "PersistedModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "hedera.imageCollection"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "Number",
|
||||||
|
"description": "Identifier"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "String",
|
||||||
|
"id": true,
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"desc": {
|
||||||
|
"type": "String",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"maxWidth": {
|
||||||
|
"type": "Number",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"maxHeight": {
|
||||||
|
"type": "Number",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"schema": {
|
||||||
|
"type": "String",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"table": {
|
||||||
|
"type": "String",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"column": {
|
||||||
|
"type": "String",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('upload', {
|
||||||
|
description: 'Uploads an image',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'file',
|
||||||
|
type: 'String',
|
||||||
|
description: 'The image file'
|
||||||
|
}, {
|
||||||
|
arg: 'name',
|
||||||
|
type: 'String',
|
||||||
|
description: 'The image name'
|
||||||
|
}, {
|
||||||
|
arg: 'collectionFk',
|
||||||
|
type: 'String',
|
||||||
|
description: 'The collection'
|
||||||
|
}, {
|
||||||
|
arg: 'ctx',
|
||||||
|
type: 'Object',
|
||||||
|
http: {source: 'context'}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: 'Boolean',
|
||||||
|
description: 'Success or failed',
|
||||||
|
root: true,
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/upload`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.upload = async (file, name, collectionFk) => {
|
||||||
|
let $ = Self.app.models;
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"name": "Image",
|
||||||
|
"base": "PersistedModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "hedera.image"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "Number",
|
||||||
|
"id": true,
|
||||||
|
"description": "Identifier"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "String",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"updated": {
|
||||||
|
"type": "Number"
|
||||||
|
},
|
||||||
|
"nRefs": {
|
||||||
|
"type": "Number",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"collection": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "ImageCollection",
|
||||||
|
"foreignKey": "collectionFk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"name": "Link",
|
||||||
|
"base": "PersistedModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "hedera.link"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "number",
|
||||||
|
"required": true,
|
||||||
|
"id": true
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"link": {
|
||||||
|
"type": "string",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"type": "string",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"name": "NewTag",
|
||||||
|
"base": "PersistedModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "hedera.newsTag"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "String",
|
||||||
|
"id": true,
|
||||||
|
"description": "Identifier"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "String",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"acls": [
|
||||||
|
{
|
||||||
|
"accessType": "READ",
|
||||||
|
"principalType": "ROLE",
|
||||||
|
"principalId": "$everyone",
|
||||||
|
"permission": "ALLOW"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -24,13 +24,10 @@
|
||||||
"type": "String",
|
"type": "String",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
"userFk": {
|
|
||||||
"type": "Number",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"created": {
|
"created": {
|
||||||
"type": "Date",
|
"type": "Date",
|
||||||
"required": true
|
"required": true,
|
||||||
|
"defaultFn": "now"
|
||||||
},
|
},
|
||||||
"priority": {
|
"priority": {
|
||||||
"type": "Number",
|
"type": "Number",
|
||||||
|
@ -41,6 +38,13 @@
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"relations": {
|
||||||
|
"user": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Account",
|
||||||
|
"foreignKey": "userFk"
|
||||||
|
}
|
||||||
|
},
|
||||||
"acls": [
|
"acls": [
|
||||||
{
|
{
|
||||||
"accessType": "READ",
|
"accessType": "READ",
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"name": "UserSession",
|
||||||
|
"description": "Sessions",
|
||||||
|
"base": "PersistedModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "hedera.userSession"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"ssid": {
|
||||||
|
"type": "String",
|
||||||
|
"id": true
|
||||||
|
},
|
||||||
|
"created": {
|
||||||
|
"type": "Date",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"lastUpdate": {
|
||||||
|
"type": "Date",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"userVisit": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "VisitUser",
|
||||||
|
"foreignKey": "userVisitFk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"name": "VisitAccess",
|
||||||
|
"description": "Visit accesses",
|
||||||
|
"base": "PersistedModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "hedera.visitAccess"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "Number",
|
||||||
|
"id": true,
|
||||||
|
"description": "Identifier"
|
||||||
|
},
|
||||||
|
"stamp": {
|
||||||
|
"type": "Date",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"ip": {
|
||||||
|
"type": "Number"
|
||||||
|
},
|
||||||
|
"referer": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"agent": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "VisitAgent",
|
||||||
|
"foreignKey": "agentFk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"name": "VisitAgent",
|
||||||
|
"description": "Agents visits",
|
||||||
|
"base": "PersistedModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "hedera.visitAgent"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "Number",
|
||||||
|
"id": true,
|
||||||
|
"description": "Identifier"
|
||||||
|
},
|
||||||
|
"platform": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"browser": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"javascript": {
|
||||||
|
"type": "Boolean"
|
||||||
|
},
|
||||||
|
"cookies": {
|
||||||
|
"type": "Boolean"
|
||||||
|
},
|
||||||
|
"agent": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"visit": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Visit",
|
||||||
|
"foreignKey": "visitFk"
|
||||||
|
},
|
||||||
|
"firstAccess": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "VisitAccess",
|
||||||
|
"foreignKey": "firstAccessFk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"name": "VisitUser",
|
||||||
|
"description": "User visits",
|
||||||
|
"base": "PersistedModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "hedera.visitUser"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "Number",
|
||||||
|
"id": true,
|
||||||
|
"description": "Identifier"
|
||||||
|
},
|
||||||
|
"stamp": {
|
||||||
|
"type": "Date",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"access": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "VisitAccess",
|
||||||
|
"foreignKey": "accessFk"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Account",
|
||||||
|
"foreignKey": "userFk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('listByBrowser', {
|
||||||
|
description: 'Get the list of visits grouped by browser',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'from',
|
||||||
|
type: 'Date',
|
||||||
|
description: 'The from date'
|
||||||
|
}, {
|
||||||
|
arg: 'to',
|
||||||
|
type: 'Date',
|
||||||
|
description: 'The to date'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: ['Object'],
|
||||||
|
description: 'The visits list',
|
||||||
|
root: true,
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/listByBrowser`,
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.listByBrowser = (from, to, cb) => {
|
||||||
|
Self.dataSource.connector.query(
|
||||||
|
`CALL hedera.visit_listByBrowser(?, ?)`,
|
||||||
|
[from, to],
|
||||||
|
(err, res) => {
|
||||||
|
if (err) return cb(err)
|
||||||
|
return cb(null, res[0])
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"name": "Visit",
|
||||||
|
"description": "Visits",
|
||||||
|
"base": "PersistedModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "hedera.visit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "Number",
|
||||||
|
"id": true,
|
||||||
|
"description": "Identifier"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"firstAgent": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "VisitAgent",
|
||||||
|
"foreignKey": "firstAgentFk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -80,6 +80,12 @@
|
||||||
"Inbound": {
|
"Inbound": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"Image": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
|
"ImageCollection": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"ItemCategory": {
|
"ItemCategory": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
@ -95,9 +101,15 @@
|
||||||
"Language": {
|
"Language": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"Link": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"New": {
|
"New": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"NewTag": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"OrderRow": {
|
"OrderRow": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
@ -131,6 +143,21 @@
|
||||||
"UserPassword": {
|
"UserPassword": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"UserSession": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
|
"Visit": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
|
"VisitAccess": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
|
"VisitAgent": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
|
"VisitUser": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"Warehouse": {
|
"Warehouse": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -14,13 +14,13 @@
|
||||||
"back": "nodemon --inspect --watch back back/server/server.js"
|
"back": "nodemon --inspect --watch back back/server/server.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@quasar/extras": "^1.1.2",
|
"@quasar/extras": "^1.2.0",
|
||||||
"axios": "^0.18.1",
|
"axios": "^0.18.1",
|
||||||
"quasar": "^1.0.0-rc.4",
|
"quasar": "^1.0.5",
|
||||||
"vue-i18n": "^7.3.3"
|
"vue-i18n": "^7.3.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@quasar/app": "^1.0.0-rc.6",
|
"@quasar/app": "^1.0.4",
|
||||||
"@vue/eslint-config-standard": "^4.0.0",
|
"@vue/eslint-config-standard": "^4.0.0",
|
||||||
"babel-eslint": "^10.0.1",
|
"babel-eslint": "^10.0.1",
|
||||||
"eslint": "^5.16.0",
|
"eslint": "^5.16.0",
|
||||||
|
|
|
@ -7,6 +7,7 @@ module.exports = function (ctx) {
|
||||||
boot: [
|
boot: [
|
||||||
'i18n',
|
'i18n',
|
||||||
'axios',
|
'axios',
|
||||||
|
'filters',
|
||||||
'state'
|
'state'
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@ module.exports = function (ctx) {
|
||||||
// framework: 'all', // --- includes everything; for dev only!
|
// framework: 'all', // --- includes everything; for dev only!
|
||||||
framework: {
|
framework: {
|
||||||
components: [
|
components: [
|
||||||
|
'QAvatar',
|
||||||
'QBadge',
|
'QBadge',
|
||||||
'QBtn',
|
'QBtn',
|
||||||
'QCarousel',
|
'QCarousel',
|
||||||
|
@ -38,6 +40,7 @@ module.exports = function (ctx) {
|
||||||
'QDate',
|
'QDate',
|
||||||
'QDialog',
|
'QDialog',
|
||||||
'QDrawer',
|
'QDrawer',
|
||||||
|
'QEditor',
|
||||||
'QExpansionItem',
|
'QExpansionItem',
|
||||||
'QHeader',
|
'QHeader',
|
||||||
'QIcon',
|
'QIcon',
|
||||||
|
@ -58,6 +61,7 @@ module.exports = function (ctx) {
|
||||||
'QRange',
|
'QRange',
|
||||||
'QSelect',
|
'QSelect',
|
||||||
'QSeparator',
|
'QSeparator',
|
||||||
|
'QSlideTransition',
|
||||||
'QSpinner',
|
'QSpinner',
|
||||||
'QTab',
|
'QTab',
|
||||||
'QTabs',
|
'QTabs',
|
||||||
|
@ -66,7 +70,8 @@ module.exports = function (ctx) {
|
||||||
'QRouteTab',
|
'QRouteTab',
|
||||||
'QToolbar',
|
'QToolbar',
|
||||||
'QToolbarTitle',
|
'QToolbarTitle',
|
||||||
'QTooltip'
|
'QTooltip',
|
||||||
|
'QUploader'
|
||||||
],
|
],
|
||||||
|
|
||||||
directives: [
|
directives: [
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
export default async ({ Vue }) => {
|
export default async ({ Vue }) => {
|
||||||
|
Vue.prototype.$apiBase = `//${location.hostname}:3000/api/`
|
||||||
Vue.prototype.$axios = axios
|
Vue.prototype.$axios = axios
|
||||||
axios.defaults.baseURL = `//${location.hostname}:3000/api/`
|
axios.defaults.baseURL = Vue.prototype.$apiBase
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
|
||||||
|
import { date as qdate } from 'quasar'
|
||||||
|
|
||||||
|
export default async ({ app, Vue }) => {
|
||||||
|
let i18n = app.i18n
|
||||||
|
|
||||||
|
function currency (val) {
|
||||||
|
return val ? val.toFixed(2) + '€' : val
|
||||||
|
}
|
||||||
|
|
||||||
|
function date (val, format) {
|
||||||
|
if (val == null) return val
|
||||||
|
if (!(val instanceof Date)) {
|
||||||
|
val = new Date(val)
|
||||||
|
}
|
||||||
|
return qdate.formatDate(val, format, app.i18n.t('date'))
|
||||||
|
}
|
||||||
|
|
||||||
|
function relDate (val) {
|
||||||
|
if (val == null) return val
|
||||||
|
if (!(val instanceof Date)) {
|
||||||
|
val = new Date(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
let dif = qdate.getDateDiff(new Date(), val, 'days')
|
||||||
|
let day
|
||||||
|
|
||||||
|
switch (dif) {
|
||||||
|
case 0:
|
||||||
|
day = 'today'
|
||||||
|
break
|
||||||
|
case 1:
|
||||||
|
day = 'yesterday'
|
||||||
|
break
|
||||||
|
case -1:
|
||||||
|
day = 'tomorrow'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if (day) {
|
||||||
|
day = i18n.t(day)
|
||||||
|
} else {
|
||||||
|
if (dif > 0 && dif <= 7) {
|
||||||
|
day = qdate.formatDate(val, 'ddd', i18n.t('date'))
|
||||||
|
} else {
|
||||||
|
day = qdate.formatDate(val, 'ddd, MMMM Do', i18n.t('date'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return day
|
||||||
|
}
|
||||||
|
|
||||||
|
function relTime (val) {
|
||||||
|
if (val == null) return val
|
||||||
|
if (!(val instanceof Date)) {
|
||||||
|
val = new Date(val)
|
||||||
|
}
|
||||||
|
return relDate(val) + ' ' + qdate.formatDate(val, 'H:mm:ss')
|
||||||
|
}
|
||||||
|
|
||||||
|
Vue.filter('currency', currency)
|
||||||
|
Vue.filter('date', date)
|
||||||
|
Vue.filter('relDate', relDate)
|
||||||
|
Vue.filter('relTime', relTime)
|
||||||
|
}
|
|
@ -5,9 +5,10 @@ export default async ({ app, Vue }) => {
|
||||||
let state = Vue.observable({
|
let state = Vue.observable({
|
||||||
userId: 1437,
|
userId: 1437,
|
||||||
userName: null,
|
userName: null,
|
||||||
|
layout: null,
|
||||||
title: null,
|
title: null,
|
||||||
subtitle: null,
|
subtitle: null,
|
||||||
search: null,
|
useRightDrawer: false,
|
||||||
rightDrawerOpen: true
|
rightDrawerOpen: true
|
||||||
})
|
})
|
||||||
Vue.prototype.$state = state
|
Vue.prototype.$state = state
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
import Toolbar from './Toolbar'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Toolbar
|
||||||
|
},
|
||||||
|
beforeRouteEnter (to, from, next) {
|
||||||
|
next(vm => {})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Toolbar',
|
||||||
|
mounted () {
|
||||||
|
this.toolbar = this.$state.layout.$refs.toolbar
|
||||||
|
this.toolbar.appendChild(this.$el)
|
||||||
|
},
|
||||||
|
beforeDestroy () {
|
||||||
|
this.toolbar.removeChild(this.$el)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
.vn-w-md
|
.vn-w-md
|
||||||
width 30em
|
width 30em
|
||||||
|
.vn-w-lg
|
||||||
|
width 45em
|
||||||
.vn-pp
|
.vn-pp
|
||||||
padding 1em
|
padding 1em
|
||||||
|
|
||||||
|
|
|
@ -7,14 +7,26 @@ export default {
|
||||||
search: 'Search',
|
search: 'Search',
|
||||||
accept: 'Accept',
|
accept: 'Accept',
|
||||||
cancel: 'Cancel',
|
cancel: 'Cancel',
|
||||||
|
refresh: 'Refresh',
|
||||||
save: 'Save',
|
save: 'Save',
|
||||||
delete: 'Delete',
|
delete: 'Delete',
|
||||||
add: 'Add',
|
add: 'Add',
|
||||||
|
edit: 'Edit',
|
||||||
create: 'create',
|
create: 'create',
|
||||||
|
orderBy: 'Ordenar by',
|
||||||
|
rowLimit: 'Row limit',
|
||||||
dataSaved: 'Data saved!',
|
dataSaved: 'Data saved!',
|
||||||
noDataFound: 'No data found',
|
noDataFound: 'No data found',
|
||||||
areYouSureDelete: 'Are you sure you want to delete?',
|
areYouSureDelete: 'Are you sure you want to delete?',
|
||||||
|
removedSuccess: 'Item removed successfully',
|
||||||
|
createdSuccess: 'Item created successfully',
|
||||||
fieldIsRequired: 'Field is required',
|
fieldIsRequired: 'Field is required',
|
||||||
|
setSearchFilter: 'Please, set a search filter',
|
||||||
|
today: 'Today',
|
||||||
|
yesterday: 'Yesterday',
|
||||||
|
tomorrow: 'Tomorrow',
|
||||||
|
fromDate: 'From',
|
||||||
|
toDate: 'To',
|
||||||
date: {
|
date: {
|
||||||
days: [
|
days: [
|
||||||
'Sunday',
|
'Sunday',
|
||||||
|
@ -66,14 +78,26 @@ export default {
|
||||||
|
|
||||||
// Layout
|
// Layout
|
||||||
login: 'Login',
|
login: 'Login',
|
||||||
|
logout: 'Logout',
|
||||||
visitor: 'Visitor',
|
visitor: 'Visitor',
|
||||||
|
|
||||||
// Menu
|
// Menu
|
||||||
home: 'Home',
|
home: 'Home',
|
||||||
catalog: 'Catalog',
|
catalog: 'Catalog',
|
||||||
orders: 'Orders',
|
orders: 'Orders',
|
||||||
|
order: 'Pending order',
|
||||||
|
ticket: 'Order',
|
||||||
conditions: 'Conditions',
|
conditions: 'Conditions',
|
||||||
about: 'About us',
|
about: 'About us',
|
||||||
|
admin: 'Administration',
|
||||||
|
panel: 'Control panel',
|
||||||
|
users: 'Users',
|
||||||
|
connections: 'Connections',
|
||||||
|
visits: 'Visits',
|
||||||
|
news: 'News',
|
||||||
|
newEdit: 'Edit new',
|
||||||
|
images: 'Images',
|
||||||
|
items: 'Items',
|
||||||
config: 'Configuration',
|
config: 'Configuration',
|
||||||
user: 'User',
|
user: 'User',
|
||||||
addresses: 'Addresses',
|
addresses: 'Addresses',
|
||||||
|
@ -113,7 +137,6 @@ export default {
|
||||||
categories: 'Categories',
|
categories: 'Categories',
|
||||||
category: 'Category',
|
category: 'Category',
|
||||||
family: 'Family',
|
family: 'Family',
|
||||||
orderBy: 'Ordenar by',
|
|
||||||
name: 'Name',
|
name: 'Name',
|
||||||
relevancy: 'Relevancy',
|
relevancy: 'Relevancy',
|
||||||
priceAsc: 'Acending price',
|
priceAsc: 'Acending price',
|
||||||
|
@ -137,6 +160,27 @@ export default {
|
||||||
// About
|
// About
|
||||||
aboutDesc: 'Verdnatura offers all services for your florist.',
|
aboutDesc: 'Verdnatura offers all services for your florist.',
|
||||||
|
|
||||||
|
// Connections
|
||||||
|
nConnections: '{0} connections',
|
||||||
|
refreshRate: 'Refresh rate',
|
||||||
|
lastAction: 'Last actions',
|
||||||
|
sessionInit: 'Login',
|
||||||
|
nSeconds: '{0} seconds',
|
||||||
|
dontRefresh: 'Do not refresh',
|
||||||
|
|
||||||
|
// Visits
|
||||||
|
visitsCount: '{0} visits, {1} new',
|
||||||
|
|
||||||
|
// New
|
||||||
|
title: 'Title',
|
||||||
|
image: 'Image',
|
||||||
|
tag: 'Tag',
|
||||||
|
priority: 'Priority',
|
||||||
|
text: 'Text',
|
||||||
|
|
||||||
|
// User
|
||||||
|
accessLog: 'Access log',
|
||||||
|
|
||||||
// Config
|
// Config
|
||||||
userName: 'Username',
|
userName: 'Username',
|
||||||
nickname: 'Nickname',
|
nickname: 'Nickname',
|
||||||
|
|
|
@ -7,14 +7,26 @@ export default {
|
||||||
search: 'Buscar',
|
search: 'Buscar',
|
||||||
accept: 'Aceptar',
|
accept: 'Aceptar',
|
||||||
cancel: 'Cancelar',
|
cancel: 'Cancelar',
|
||||||
|
refresh: 'Actualizar',
|
||||||
save: 'Guardar',
|
save: 'Guardar',
|
||||||
delete: 'Borrar',
|
delete: 'Borrar',
|
||||||
add: 'Añadir',
|
add: 'Añadir',
|
||||||
|
edit: 'Editar',
|
||||||
create: 'Crear',
|
create: 'Crear',
|
||||||
|
orderBy: 'Ordenar por',
|
||||||
|
rowLimit: 'Límite de registros',
|
||||||
dataSaved: '¡Datos guardados!',
|
dataSaved: '¡Datos guardados!',
|
||||||
noDataFound: 'No se han encontrado datos',
|
noDataFound: 'No se han encontrado datos',
|
||||||
areYouSureDelete: '¿Seguro que quieres eliminar?',
|
areYouSureDelete: '¿Seguro que quieres eliminar?',
|
||||||
|
removedSuccess: 'Elemento eliminado correctamente',
|
||||||
|
createdSuccess: 'Elemento creado correctamente',
|
||||||
fieldIsRequired: 'Campo requerido',
|
fieldIsRequired: 'Campo requerido',
|
||||||
|
setSearchFilter: 'Por favor, establece un filtro de búsqueda',
|
||||||
|
today: 'Hoy',
|
||||||
|
yesterday: 'Ayer',
|
||||||
|
tomorrow: 'Mañana',
|
||||||
|
fromDate: 'Desde',
|
||||||
|
toDate: 'Hasta',
|
||||||
date: {
|
date: {
|
||||||
days: [
|
days: [
|
||||||
'Domingo',
|
'Domingo',
|
||||||
|
@ -73,8 +85,19 @@ export default {
|
||||||
home: 'Inicio',
|
home: 'Inicio',
|
||||||
catalog: 'Catálogo',
|
catalog: 'Catálogo',
|
||||||
orders: 'Pedidos',
|
orders: 'Pedidos',
|
||||||
|
order: 'Pedido pendiente',
|
||||||
|
ticket: 'Pedido',
|
||||||
conditions: 'Condiciones',
|
conditions: 'Condiciones',
|
||||||
about: 'Sobre nosotros',
|
about: 'Sobre nosotros',
|
||||||
|
admin: 'Administración',
|
||||||
|
panel: 'Panel de control',
|
||||||
|
users: 'Usuarios',
|
||||||
|
connections: 'Conexiones',
|
||||||
|
visits: 'Visitas',
|
||||||
|
news: 'Noticias',
|
||||||
|
newEdit: 'Editar noticia',
|
||||||
|
images: 'Imágenes',
|
||||||
|
items: 'Artículos',
|
||||||
config: 'Configuración',
|
config: 'Configuración',
|
||||||
user: 'Usuario',
|
user: 'Usuario',
|
||||||
addresses: 'Direcciones',
|
addresses: 'Direcciones',
|
||||||
|
@ -114,7 +137,6 @@ export default {
|
||||||
categories: 'Categorias',
|
categories: 'Categorias',
|
||||||
category: 'Categoria',
|
category: 'Categoria',
|
||||||
family: 'Familia',
|
family: 'Familia',
|
||||||
orderBy: 'Ordenar por',
|
|
||||||
name: 'Nombre',
|
name: 'Nombre',
|
||||||
relevancy: 'Relevancia',
|
relevancy: 'Relevancia',
|
||||||
priceAsc: 'Precio ascendente',
|
priceAsc: 'Precio ascendente',
|
||||||
|
@ -138,6 +160,27 @@ export default {
|
||||||
// About
|
// About
|
||||||
aboutDesc: 'Verdnatura te ofrece todos los servicios que necesita tu floristería.',
|
aboutDesc: 'Verdnatura te ofrece todos los servicios que necesita tu floristería.',
|
||||||
|
|
||||||
|
// Connections
|
||||||
|
nConnections: '{0} connexiones',
|
||||||
|
refreshRate: 'Frecuencia de actualización',
|
||||||
|
lastAction: 'Última acción',
|
||||||
|
sessionInit: 'Inicio sesión',
|
||||||
|
nSeconds: '{0} segundos',
|
||||||
|
dontRefresh: 'No refrescar',
|
||||||
|
|
||||||
|
// Visits
|
||||||
|
visitsCount: '{0} visitas, {1} nuevas',
|
||||||
|
|
||||||
|
// New
|
||||||
|
title: 'Título',
|
||||||
|
image: 'Imagen',
|
||||||
|
tag: 'Etiqueta',
|
||||||
|
priority: 'Prioridad',
|
||||||
|
text: 'Texto',
|
||||||
|
|
||||||
|
// User
|
||||||
|
accessLog: 'Registro de accesos',
|
||||||
|
|
||||||
// Config
|
// Config
|
||||||
userName: 'Nombre de usuario',
|
userName: 'Nombre de usuario',
|
||||||
nickname: 'Nombre a mostrar',
|
nickname: 'Nombre a mostrar',
|
||||||
|
|
|
@ -7,8 +7,7 @@
|
||||||
dense
|
dense
|
||||||
round
|
round
|
||||||
@click="leftDrawerOpen = !leftDrawerOpen"
|
@click="leftDrawerOpen = !leftDrawerOpen"
|
||||||
aria-label="Menu"
|
aria-label="Menu">
|
||||||
>
|
|
||||||
<q-icon name="menu" />
|
<q-icon name="menu" />
|
||||||
</q-btn>
|
</q-btn>
|
||||||
<q-toolbar-title class="title">
|
<q-toolbar-title class="title">
|
||||||
|
@ -25,41 +24,20 @@
|
||||||
:label="$t('login')"
|
:label="$t('login')"
|
||||||
to="/login"
|
to="/login"
|
||||||
/>
|
/>
|
||||||
<q-input
|
<div ref="toolbar"/>
|
||||||
v-if="$router.currentRoute.name == 'catalog'"
|
|
||||||
v-model="$state.search"
|
|
||||||
debounce="500"
|
|
||||||
class="q-mr-sm"
|
|
||||||
dark
|
|
||||||
dense
|
|
||||||
standout>
|
|
||||||
<template v-slot:append>
|
|
||||||
<q-icon
|
|
||||||
v-if="$state.search === ''"
|
|
||||||
name="search"
|
|
||||||
/>
|
|
||||||
<q-icon
|
|
||||||
v-else
|
|
||||||
name="clear"
|
|
||||||
class="cursor-pointer"
|
|
||||||
@click="$state.search = ''"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</q-input>
|
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="$router.currentRoute.name == 'catalog'"
|
v-if="$state.useRightDrawer"
|
||||||
@click="$state.rightDrawerOpen = !$state.rightDrawerOpen"
|
@click="$state.rightDrawerOpen = !$state.rightDrawerOpen"
|
||||||
aria-label="Menu"
|
aria-label="Menu"
|
||||||
flat
|
flat
|
||||||
dense
|
dense
|
||||||
round>
|
round>
|
||||||
<q-icon name="menu" />
|
<q-icon name="menu"/>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
</q-toolbar>
|
</q-toolbar>
|
||||||
</q-header>
|
</q-header>
|
||||||
<q-drawer
|
<q-drawer
|
||||||
v-model="leftDrawerOpen"
|
v-model="leftDrawerOpen"
|
||||||
content-class="bg-grey-2"
|
|
||||||
behavior="mobile"
|
behavior="mobile"
|
||||||
elevated
|
elevated
|
||||||
overlay>
|
overlay>
|
||||||
|
@ -70,46 +48,32 @@
|
||||||
<q-btn flat round dense icon="exit_to_app" :title="$t('logout')" @click="logout()" />
|
<q-btn flat round dense icon="exit_to_app" :title="$t('logout')" @click="logout()" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<q-list class="text-body1">
|
<q-list
|
||||||
<q-item clickable :to="{name: 'home'}">
|
class="text-body1"
|
||||||
|
v-for="item in menu"
|
||||||
|
:key="item.name">
|
||||||
|
<q-item
|
||||||
|
v-if="!item.childs"
|
||||||
|
:to="{name: item.name}">
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label>{{$t('home')}}</q-item-label>
|
<q-item-label>{{$t(item.name)}}</q-item-label>
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item clickable :to="{name: 'catalog'}">
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label>{{$t('catalog')}}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item clickable :to="{name: 'orders'}">
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label>{{$t('orders')}}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item clickable :to="{name: 'conditions'}">
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label>{{$t('conditions')}}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item clickable :to="{name: 'about'}">
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label>{{$t('about')}}</q-item-label>
|
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
<q-expansion-item
|
<q-expansion-item
|
||||||
expand-icon-toggle
|
v-if="item.childs"
|
||||||
expand-separator
|
:label="$t(item.name)"
|
||||||
:label="$t('config')">
|
expand-separator>
|
||||||
<q-item clickable :to="{name: 'config'}">
|
<q-list>
|
||||||
<q-item-section>
|
<q-item
|
||||||
<q-item-label>{{$t('user')}}</q-item-label>
|
v-for="subitem in item.childs"
|
||||||
</q-item-section>
|
:key="subitem.name"
|
||||||
</q-item>
|
:to="{name: subitem.name}"
|
||||||
<q-item clickable :to="{name: 'addresses'}">
|
class="q-pl-lg">
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label>{{$t('addresses')}}</q-item-label>
|
<q-item-label>{{$t(subitem.name)}}</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
|
</q-list>
|
||||||
</q-expansion-item>
|
</q-expansion-item>
|
||||||
</q-list>
|
</q-list>
|
||||||
</q-drawer>
|
</q-drawer>
|
||||||
|
@ -140,9 +104,41 @@ export default {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
leftDrawerOpen: false, // this.$q.platform.is.desktop
|
leftDrawerOpen: false, // this.$q.platform.is.desktop
|
||||||
search: ''
|
search: '',
|
||||||
|
menu: [
|
||||||
|
{ name: 'home' },
|
||||||
|
{ name: 'catalog' },
|
||||||
|
{ name: 'orders' },
|
||||||
|
{ name: 'conditions' },
|
||||||
|
{ name: 'about' },
|
||||||
|
{
|
||||||
|
name: 'admin',
|
||||||
|
childs: [
|
||||||
|
{ name: 'panel' },
|
||||||
|
{ name: 'users' },
|
||||||
|
{ name: 'connections' },
|
||||||
|
{ name: 'visits' },
|
||||||
|
{ name: 'news' },
|
||||||
|
{ name: 'images' },
|
||||||
|
{ name: 'items' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'config',
|
||||||
|
childs: [
|
||||||
|
{ name: 'user' },
|
||||||
|
{ name: 'addresses' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
created () {
|
||||||
|
this.$state.layout = this
|
||||||
|
},
|
||||||
|
destroyed () {
|
||||||
|
this.$state.layout = null
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
openURL,
|
openURL,
|
||||||
logout () {
|
logout () {
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
<template>
|
||||||
|
<div class="vn-pp row justify-center">
|
||||||
|
<div class="vn-w-md">
|
||||||
|
<q-card>
|
||||||
|
<q-card-section>
|
||||||
|
<div>{{user.nickname}}</div>
|
||||||
|
<div class="text-caption">#{{user.id}}</div>
|
||||||
|
<div class="text-caption">{{user.name}}</div>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
<q-card class="q-mt-md">
|
||||||
|
<q-list bordered separator>
|
||||||
|
<q-item v-if="visits && !visits.length">
|
||||||
|
<q-item-section class="text-center">
|
||||||
|
{{$t('noDataFound')}}
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item
|
||||||
|
v-for="visit in visits"
|
||||||
|
:key="visit.id">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>{{visit.stamp | date('ddd, MMMM Do H:mm')}}</q-item-label>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{visit.access.agent.platform}} -
|
||||||
|
{{visit.access.agent.browser}}
|
||||||
|
{{visit.access.agent.version}}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'AccessLog',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
user: {},
|
||||||
|
visits: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
let filter = {
|
||||||
|
fields: ['id', 'nickname', 'name']
|
||||||
|
}
|
||||||
|
this.$axios.get(`Accounts/${this.$route.params.user}`, { params: { filter } })
|
||||||
|
.then(res => (this.user = res.data))
|
||||||
|
|
||||||
|
filter = {
|
||||||
|
fields: ['stamp', 'accessFk'],
|
||||||
|
where: { userFk: this.$route.params.user },
|
||||||
|
order: 'stamp DESC',
|
||||||
|
limit: 10,
|
||||||
|
include: {
|
||||||
|
relation: 'access',
|
||||||
|
scope: {
|
||||||
|
fields: ['agentFk'],
|
||||||
|
include: {
|
||||||
|
relation: 'agent',
|
||||||
|
scope: {
|
||||||
|
fields: [
|
||||||
|
'platform',
|
||||||
|
'browser',
|
||||||
|
'version'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.$axios.get(`VisitUsers`, { params: { filter } })
|
||||||
|
.then(res => (this.visits = res.data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,67 +1,59 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="vn-pp row justify-center">
|
<div class="vn-pp row justify-center">
|
||||||
<q-card class="vn-w-md">
|
<q-card class="vn-w-md">
|
||||||
<q-card-section class="q-gutter-md">
|
<q-card-section class="q-gutter-md">
|
||||||
<q-input v-model="address.nickname" :label="$t('consignatary')" />
|
<q-input v-model="address.nickname" :label="$t('consignatary')" />
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section class="q-gutter-md">
|
<q-card-section class="q-gutter-md">
|
||||||
<q-input v-model="address.street" :label="$t('street')" />
|
<q-input v-model="address.street" :label="$t('street')" />
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section class="q-gutter-md">
|
<q-card-section class="q-gutter-md">
|
||||||
<q-input v-model="address.city" :label="$t('city')" />
|
<q-input v-model="address.city" :label="$t('city')" />
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section class="q-gutter-md">
|
<q-card-section class="q-gutter-md">
|
||||||
<q-input v-model="address.postalCode" :label="$t('postalCode')" />
|
<q-input v-model="address.postalCode" :label="$t('postalCode')" />
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section class="q-gutter-md">
|
<q-card-section class="q-gutter-md">
|
||||||
<q-select
|
<q-select
|
||||||
v-model="country"
|
v-model="country"
|
||||||
:label="$t('country')"
|
:label="$t('country')"
|
||||||
:options="countries"
|
:options="countries"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
option-label="country"/>
|
option-label="country"/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section class="q-gutter-md">
|
<q-card-section class="q-gutter-md">
|
||||||
<q-select
|
<q-select
|
||||||
v-model="province"
|
v-model="province"
|
||||||
:label="$t('province')"
|
:label="$t('province')"
|
||||||
:options="provinces"
|
:options="provinces"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
option-label="name"/>
|
option-label="name"/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section class="q-gutter-md">
|
<q-card-section class="q-gutter-md">
|
||||||
<q-input v-model="address.phone" :label="$t('phone')" />
|
<q-input v-model="address.phone" :label="$t('phone')" />
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-actions class="justify-center">
|
</q-card>
|
||||||
<q-btn
|
<q-page-sticky position="bottom-right" :offset="[18, 18]">
|
||||||
:label="$t('cancel')"
|
<q-btn
|
||||||
to="/addresses"
|
:title="$t(id ? 'save' : 'create')"
|
||||||
flat/>
|
icon="check"
|
||||||
<q-btn
|
color="accent"
|
||||||
v-if="addressId"
|
@click="onSave"
|
||||||
:label="$t('save')"
|
fab/>
|
||||||
@click="onSave"
|
</q-page-sticky>
|
||||||
flat/>
|
</div>
|
||||||
<q-btn
|
|
||||||
v-if="!addressId"
|
|
||||||
:label="$t('create')"
|
|
||||||
@click="onSave"
|
|
||||||
flat/>
|
|
||||||
</q-card-actions>
|
|
||||||
</q-card>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import Page from 'components/Page'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Address',
|
name: 'Address',
|
||||||
|
mixins: [Page],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
address: {},
|
address: {},
|
||||||
addressId: null,
|
id: null,
|
||||||
provinces: null,
|
provinces: null,
|
||||||
countries: null,
|
countries: null,
|
||||||
province: null,
|
province: null,
|
||||||
|
@ -94,16 +86,16 @@ export default {
|
||||||
if (!this.address.provinceFk) return
|
if (!this.address.provinceFk) return
|
||||||
this.address.provinceFk = value && value.id
|
this.address.provinceFk = value && value.id
|
||||||
},
|
},
|
||||||
'this.$route.params.address': function () {
|
'this.$route.params.id': function () {
|
||||||
this.loadAddress()
|
this.loadAddress()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
loadAddress () {
|
loadAddress () {
|
||||||
this.addressId = this.$route.params.address
|
this.id = this.$route.params.id
|
||||||
this.address = {}
|
this.address = {}
|
||||||
|
|
||||||
if (this.addressId) {
|
if (this.id) {
|
||||||
let filter = {
|
let filter = {
|
||||||
fields: [
|
fields: [
|
||||||
'id',
|
'id',
|
||||||
|
@ -121,7 +113,7 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.$axios.get(`Addresses/${this.addressId}`, { params: { filter } })
|
this.$axios.get(`Addresses/${this.id}`, { params: { filter } })
|
||||||
.then(res => (this.address = res.data))
|
.then(res => (this.address = res.data))
|
||||||
} else {
|
} else {
|
||||||
this.address = {
|
this.address = {
|
||||||
|
@ -152,19 +144,25 @@ export default {
|
||||||
if (province) this.province = province
|
if (province) this.province = province
|
||||||
},
|
},
|
||||||
onSave () {
|
onSave () {
|
||||||
if (this.addressId) {
|
let promise
|
||||||
this.$axios.patch(`Addresses/${this.addressId}`, this.address)
|
let message
|
||||||
.then(res => {
|
|
||||||
this.$q.notify(this.$t('dataSaved'))
|
if (this.id) {
|
||||||
this.$router.push('/addresses')
|
promise = this.$axios.patch(`Addresses/${this.id}`, this.address)
|
||||||
})
|
message = 'dataSaved'
|
||||||
} else {
|
} else {
|
||||||
this.$axios.post(`Addresses`, this.address)
|
promise = this.$axios.post(`Addresses`, this.address)
|
||||||
.then(res => {
|
message = 'addressCreated'
|
||||||
this.$q.notify(this.$t('addressCreated'))
|
|
||||||
this.$router.push('/addresses')
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
promise.then(res => {
|
||||||
|
this.$q.notify({
|
||||||
|
message: this.$t(message),
|
||||||
|
icon: 'check',
|
||||||
|
color: 'green-6'
|
||||||
|
})
|
||||||
|
this.$router.go(-1)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="vn-pp row justify-center">
|
<div class="vn-pp row justify-center">
|
||||||
|
<div
|
||||||
|
v-if="addresses && !addresses.length"
|
||||||
|
class="text-subtitle1 text-center text-grey-7 q-pa-md">
|
||||||
|
{{$t('noDataFound')}}
|
||||||
|
</div>
|
||||||
<q-card class="vn-w-md">
|
<q-card class="vn-w-md">
|
||||||
<q-list bordered separator>
|
<q-list bordered separator>
|
||||||
<q-item v-if="addresses && !addresses.length">
|
|
||||||
{{$t('noDataFound')}}
|
|
||||||
</q-item>
|
|
||||||
<q-item
|
<q-item
|
||||||
v-for="(address, index) in addresses"
|
v-for="(address, index) in addresses"
|
||||||
:key="address.id"
|
:key="address.id"
|
||||||
|
@ -73,9 +75,6 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'Addresses',
|
name: 'Addresses',
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<template>
|
||||||
|
<router-view></router-view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Admin'
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,8 +1,29 @@
|
||||||
<template>
|
<template>
|
||||||
<div style="padding-bottom: 5em;">
|
<div style="padding-bottom: 5em;">
|
||||||
|
<toolbar>
|
||||||
|
<q-input
|
||||||
|
v-model="search"
|
||||||
|
debounce="500"
|
||||||
|
class="q-mr-sm"
|
||||||
|
dark
|
||||||
|
dense
|
||||||
|
standout>
|
||||||
|
<template v-slot:append>
|
||||||
|
<q-icon
|
||||||
|
v-if="search === ''"
|
||||||
|
name="search"
|
||||||
|
/>
|
||||||
|
<q-icon
|
||||||
|
v-else
|
||||||
|
name="clear"
|
||||||
|
class="cursor-pointer"
|
||||||
|
@click="search = ''"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</toolbar>
|
||||||
<q-drawer
|
<q-drawer
|
||||||
v-model="$state.rightDrawerOpen"
|
v-model="$state.rightDrawerOpen"
|
||||||
content-class="bg-grey-2"
|
|
||||||
side="right"
|
side="right"
|
||||||
elevated>
|
elevated>
|
||||||
<div class="q-pa-md">
|
<div class="q-pa-md">
|
||||||
|
@ -238,6 +259,7 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import Page from 'components/Page'
|
||||||
import { date } from 'quasar'
|
import { date } from 'quasar'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
|
@ -245,10 +267,11 @@ const CancelToken = axios.CancelToken
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Catalog',
|
name: 'Catalog',
|
||||||
|
mixins: [Page],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
uid: 0,
|
uid: 0,
|
||||||
search: null,
|
search: '',
|
||||||
date: date.formatDate(new Date(), 'YYYY/MM/DD'),
|
date: date.formatDate(new Date(), 'YYYY/MM/DD'),
|
||||||
category: null,
|
category: null,
|
||||||
categories: [],
|
categories: [],
|
||||||
|
@ -296,6 +319,9 @@ export default {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
created () {
|
||||||
|
this.$state.useRightDrawer = true
|
||||||
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.$axios.get('ItemCategories')
|
this.$axios.get('ItemCategories')
|
||||||
.then(res => (this.categories = res.data))
|
.then(res => (this.categories = res.data))
|
||||||
|
@ -333,7 +359,7 @@ export default {
|
||||||
.then(res => (this.orgTypes = res.data))
|
.then(res => (this.orgTypes = res.data))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'$state.search': function (value) {
|
search (value) {
|
||||||
let location = { params: this.$route.params }
|
let location = { params: this.$route.params }
|
||||||
if (value) location.query = { search: value }
|
if (value) location.query = { search: value }
|
||||||
this.$router.push(location)
|
this.$router.push(location)
|
||||||
|
@ -349,7 +375,6 @@ export default {
|
||||||
this.category = category
|
this.category = category
|
||||||
this.typeId = category ? type : null
|
this.typeId = category ? type : null
|
||||||
this.search = route.query.search || ''
|
this.search = route.query.search || ''
|
||||||
this.$state.search = this.search
|
|
||||||
this.tags = []
|
this.tags = []
|
||||||
|
|
||||||
this.refreshTitle()
|
this.refreshTitle()
|
||||||
|
@ -513,9 +538,6 @@ export default {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
filters: {
|
|
||||||
currency: i => i ? i.toFixed(2) + '€' : i
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="q-pa-md row justify-center q-gutter-md">
|
<div class="text-subtitle1 text-center text-grey-7 q-pa-lg">
|
||||||
<q-card>
|
Sorry this section is under construction
|
||||||
<q-card-section>
|
|
||||||
{{$t('conditionsDesc')}}
|
|
||||||
</q-card-section>
|
|
||||||
</q-card>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,32 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="my-list q-pa-md">
|
<div class="vn-pp row justify-center">
|
||||||
<q-card>
|
<toolbar>
|
||||||
<q-card-section>
|
<q-select
|
||||||
<q-select v-model="yearFilter" :options="years" :label="$t('ordersMadeAt')" />
|
v-model="yearFilter"
|
||||||
</q-card-section>
|
:options="years"
|
||||||
</q-card>
|
:label="$t('ordersMadeAt')"
|
||||||
<q-card class="q-mt-md">
|
style="min-width: 12em;"
|
||||||
|
dark
|
||||||
|
dense
|
||||||
|
standout/>
|
||||||
|
</toolbar>
|
||||||
|
<div
|
||||||
|
v-if="tickets && !tickets.length"
|
||||||
|
class="text-subtitle1 text-center text-grey-7 q-pa-md">
|
||||||
|
{{$t('noOrdersFound')}}
|
||||||
|
</div>
|
||||||
|
<q-card
|
||||||
|
v-if="tickets && tickets.length"
|
||||||
|
class="vn-w-md">
|
||||||
<q-list bordered separator>
|
<q-list bordered separator>
|
||||||
<q-item v-if="!tickets.length">
|
|
||||||
{{$t('noOrdersFound')}}
|
|
||||||
</q-item>
|
|
||||||
<q-item
|
<q-item
|
||||||
v-for="ticket in tickets"
|
v-for="ticket in tickets"
|
||||||
:key="ticket.id"
|
:key="ticket.id"
|
||||||
|
:to="`/ticket/${ticket.id}`"
|
||||||
clickable
|
clickable
|
||||||
v-ripple>
|
v-ripple>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label>{{formatDate(ticket.landed)}}</q-item-label>
|
<q-item-label>{{ticket.landed | date('ddd, MMMM Do')}}</q-item-label>
|
||||||
<q-item-label caption>#{{ticket.id}}</q-item-label>
|
<q-item-label caption>#{{ticket.id}}</q-item-label>
|
||||||
<q-item-label caption>{{ticket.address.nickname}}</q-item-label>
|
<q-item-label caption>{{ticket.address.nickname}}</q-item-label>
|
||||||
<q-item-label caption>{{ticket.address.city}}</q-item-label>
|
<q-item-label caption>{{ticket.address.city}}</q-item-label>
|
||||||
|
@ -39,23 +49,17 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
|
||||||
.my-list
|
|
||||||
max-width 30em
|
|
||||||
margin auto
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import Page from 'components/Page'
|
||||||
import { date } from 'quasar'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Orders',
|
name: 'Orders',
|
||||||
|
mixins: [Page],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
yearFilter: null,
|
yearFilter: null,
|
||||||
years: [],
|
years: [],
|
||||||
tickets: []
|
tickets: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
|
@ -87,11 +91,6 @@ export default {
|
||||||
this.$axios.get('Tickets', { params })
|
this.$axios.get('Tickets', { params })
|
||||||
.then(res => (this.tickets = res.data))
|
.then(res => (this.tickets = res.data))
|
||||||
}
|
}
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
formatDate (value) {
|
|
||||||
return date.formatDate(value, 'ddd, MMMM Do', this.$t('date'))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -0,0 +1,211 @@
|
||||||
|
<template>
|
||||||
|
<div class="vn-pp row justify-center">
|
||||||
|
<toolbar>
|
||||||
|
<div class="row">
|
||||||
|
<q-badge
|
||||||
|
v-if="count != null"
|
||||||
|
class="text-subtitle1 q-mr-sm"
|
||||||
|
color="secondary">
|
||||||
|
{{$t('nConnections', [count])}}
|
||||||
|
</q-badge>
|
||||||
|
</div>
|
||||||
|
</toolbar>
|
||||||
|
<q-drawer
|
||||||
|
v-model="$state.rightDrawerOpen"
|
||||||
|
side="right"
|
||||||
|
elevated>
|
||||||
|
<div class="q-pa-md">
|
||||||
|
<q-select
|
||||||
|
:label="$t('refreshRate')"
|
||||||
|
v-model="rate"
|
||||||
|
:options="rates"
|
||||||
|
@input="setTimeout"
|
||||||
|
emit-value>
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<q-icon name="timer"/>
|
||||||
|
</template>
|
||||||
|
</q-select>
|
||||||
|
<q-select
|
||||||
|
:label="$t('orderBy')"
|
||||||
|
v-model="order"
|
||||||
|
:options="orderOptions"
|
||||||
|
@input="refresh"
|
||||||
|
emit-value>
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<q-icon name="sort"/>
|
||||||
|
</template>
|
||||||
|
</q-select>
|
||||||
|
</div>
|
||||||
|
</q-drawer>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
v-if="connections && !connections.length"
|
||||||
|
class="text-subtitle1 text-center text-grey-7 q-pa-md">
|
||||||
|
{{$t('noDataFound')}}
|
||||||
|
</div>
|
||||||
|
<q-infinite-scroll
|
||||||
|
ref="scroll"
|
||||||
|
@load="onLoad"
|
||||||
|
scroll-taget="html"
|
||||||
|
:offset="500">
|
||||||
|
<q-card class="vn-w-md">
|
||||||
|
<q-list bordered separator>
|
||||||
|
<q-item
|
||||||
|
v-for="conn in connections"
|
||||||
|
:key="conn.id"
|
||||||
|
:to="`/access-log/${conn.userVisit.user.id}`"
|
||||||
|
:title="$t('accessLog')"
|
||||||
|
clickable>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>
|
||||||
|
{{conn.userVisit.user.nickname}}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{conn.lastUpdate | relTime}}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{conn.userVisit.access.agent.platform}} -
|
||||||
|
{{conn.userVisit.access.agent.browser}}
|
||||||
|
{{conn.userVisit.access.agent.version}}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-card>
|
||||||
|
<template slot="loading">
|
||||||
|
<div class="row justify-center q-my-md">
|
||||||
|
<q-spinner color="primary" name="dots" size="40px" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</q-infinite-scroll>
|
||||||
|
</div>
|
||||||
|
<q-page-sticky position="bottom-right" :offset="[18, 18]">
|
||||||
|
<q-btn
|
||||||
|
fab
|
||||||
|
icon="refresh"
|
||||||
|
color="accent"
|
||||||
|
@click="refresh"
|
||||||
|
:title="$t('refresh')"
|
||||||
|
/>
|
||||||
|
</q-page-sticky>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Page from 'components/Page'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Connections',
|
||||||
|
mixins: [Page],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
connections: null,
|
||||||
|
pageSize: 30,
|
||||||
|
limit: 0,
|
||||||
|
rate: 5,
|
||||||
|
count: null,
|
||||||
|
rates: [
|
||||||
|
{
|
||||||
|
label: this.$t('dontRefresh'),
|
||||||
|
value: null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
order: 'lastUpdate DESC',
|
||||||
|
orderOptions: [
|
||||||
|
{
|
||||||
|
label: this.$t('lastAction'),
|
||||||
|
value: 'lastUpdate DESC'
|
||||||
|
}, {
|
||||||
|
label: this.$t('sessionInit'),
|
||||||
|
value: 'created DESC'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.$state.useRightDrawer = true
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
let seconds = [1, 2, 5, 10, 30]
|
||||||
|
for (let secs of seconds) {
|
||||||
|
this.rates.push({
|
||||||
|
label: this.$t('nSeconds', [secs]),
|
||||||
|
value: secs
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeDestroy () {
|
||||||
|
this.clearTimeout()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onLoad (index, done) {
|
||||||
|
this.limit = this.pageSize * index
|
||||||
|
this.refresh()
|
||||||
|
.then(() => {
|
||||||
|
done(this.connections.length < this.limit)
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
done(true)
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
},
|
||||||
|
refresh () {
|
||||||
|
this.clearTimeout()
|
||||||
|
let where = { userVisitFk: { neq: null } }
|
||||||
|
let filter = {
|
||||||
|
fields: ['created', 'lastUpdate', 'userVisitFk'],
|
||||||
|
order: this.order,
|
||||||
|
limit: this.limit,
|
||||||
|
where,
|
||||||
|
include: {
|
||||||
|
relation: 'userVisit',
|
||||||
|
scope: {
|
||||||
|
fields: ['accessFk', 'userFk'],
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
relation: 'access',
|
||||||
|
scope: {
|
||||||
|
fields: ['agentFk'],
|
||||||
|
include: {
|
||||||
|
relation: 'agent',
|
||||||
|
scope: {
|
||||||
|
fields: [
|
||||||
|
'platform',
|
||||||
|
'browser',
|
||||||
|
'version'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
relation: 'user',
|
||||||
|
scope: {
|
||||||
|
fields: ['id', 'nickname']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.$axios.get(`UserSessions`, { params: { filter } })
|
||||||
|
.then(res => (this.connections = res.data))
|
||||||
|
.then(() => this.$axios.get(`UserSessions/count`, { params: { where } }))
|
||||||
|
.then(res => (this.count = res.data.count))
|
||||||
|
.finally(() => this.setTimeout())
|
||||||
|
},
|
||||||
|
setTimeout () {
|
||||||
|
this.clearTimeout()
|
||||||
|
if (this.rate) {
|
||||||
|
this.timeout = setTimeout(
|
||||||
|
() => this.refresh(), this.rate * 1000)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clearTimeout () {
|
||||||
|
if (this.timeout) {
|
||||||
|
clearTimeout(this.timeout)
|
||||||
|
this.timeout = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,14 @@
|
||||||
|
<template>
|
||||||
|
<div class="text-subtitle1 text-center text-grey-7 q-pa-lg">
|
||||||
|
Sorry this section is under construction
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Images'
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -150,7 +150,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
let params = { filter: { order: 'created DESC' } }
|
let params = { filter: { order: 'priority, created DESC' } }
|
||||||
this.$axios.get('News', { params })
|
this.$axios.get('News', { params })
|
||||||
.then(res => (this.news = res.data))
|
.then(res => (this.news = res.data))
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<template>
|
||||||
|
<div class="text-subtitle1 text-center text-grey-7 q-pa-lg">
|
||||||
|
Sorry this section is under construction
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Items'
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,284 @@
|
||||||
|
<template>
|
||||||
|
<div class="vn-pp row justify-center">
|
||||||
|
<q-card class="vn-w-lg">
|
||||||
|
<q-img
|
||||||
|
:src="`${$imageBase}/news/full/${myNew.image}`"
|
||||||
|
:ratio="16/4">
|
||||||
|
<q-btn
|
||||||
|
@click="editImage = true"
|
||||||
|
:title="$t('edit')"
|
||||||
|
icon="edit"
|
||||||
|
round
|
||||||
|
color="accent"
|
||||||
|
class="absolute-bottom-right"
|
||||||
|
style="bottom: .6em; right: .6em;"/>
|
||||||
|
</q-img>
|
||||||
|
<q-card-section>
|
||||||
|
<q-input
|
||||||
|
v-model="myNew.title"
|
||||||
|
:label="$t('title')" />
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-section>
|
||||||
|
<div class="row">
|
||||||
|
<q-select
|
||||||
|
v-model="myNew.tag"
|
||||||
|
:label="$t('tag')"
|
||||||
|
:options="tags"
|
||||||
|
option-value="name"
|
||||||
|
option-label="name"
|
||||||
|
emit-value
|
||||||
|
class="col"/>
|
||||||
|
<q-select
|
||||||
|
v-model="myNew.priority"
|
||||||
|
:label="$t('priority')"
|
||||||
|
:options="priorities"
|
||||||
|
class="col q-ml-md"/>
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-section>
|
||||||
|
<q-editor
|
||||||
|
v-model="myNew.text"
|
||||||
|
min-height="20em"
|
||||||
|
:toolbar="tools"/>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
<q-dialog v-model="editImage" persistent>
|
||||||
|
<q-card style="width: 25em;">
|
||||||
|
<q-card-section>
|
||||||
|
<q-select
|
||||||
|
v-model="image"
|
||||||
|
:label="$t('image')"
|
||||||
|
:options="images"
|
||||||
|
@filter="filterImages"
|
||||||
|
option-value="name"
|
||||||
|
option-label="name"
|
||||||
|
new-value-mode="add"
|
||||||
|
@new-value="addImage"
|
||||||
|
emit-value
|
||||||
|
use-input
|
||||||
|
hide-selected
|
||||||
|
fill-input
|
||||||
|
input-debounce="0">
|
||||||
|
<template v-slot:option="scope">
|
||||||
|
<q-item
|
||||||
|
v-bind="scope.itemProps"
|
||||||
|
v-on="scope.itemEvents">
|
||||||
|
<q-item-section avatar>
|
||||||
|
<q-avatar>
|
||||||
|
<img :src="`${$imageBase}/${imageCollection}/200x200/${scope.opt.name}`">
|
||||||
|
</q-avatar>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>{{scope.opt.name}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</template>
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<q-avatar>
|
||||||
|
<img :src="`${$imageBase}/${imageCollection}/200x200/${image}`">
|
||||||
|
</q-avatar>
|
||||||
|
</template>
|
||||||
|
<template v-slot:after>
|
||||||
|
<q-btn
|
||||||
|
icon="add_a_photo"
|
||||||
|
@click="showUploader = !showUploader"
|
||||||
|
:title="$t('edit')"
|
||||||
|
:disable="!image"
|
||||||
|
:color="showUploader ? 'primary' : null"
|
||||||
|
flat
|
||||||
|
round
|
||||||
|
dense/>
|
||||||
|
</template>
|
||||||
|
</q-select>
|
||||||
|
<q-slide-transition>
|
||||||
|
<q-uploader
|
||||||
|
ref="uploader"
|
||||||
|
v-show="showUploader"
|
||||||
|
:url="`${$apiBase}/Images/upload`"
|
||||||
|
auto-upload
|
||||||
|
class="q-mt-md"
|
||||||
|
flat
|
||||||
|
bordered/>
|
||||||
|
</q-slide-transition>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-actions align="right">
|
||||||
|
<q-btn
|
||||||
|
:label="$t('cancel')"
|
||||||
|
v-close-popup
|
||||||
|
color="primary"
|
||||||
|
flat/>
|
||||||
|
<q-btn
|
||||||
|
:label="$t('accept')"
|
||||||
|
@click="onEditImage"
|
||||||
|
color="primary"
|
||||||
|
flat/>
|
||||||
|
</q-card-actions>
|
||||||
|
</q-card>
|
||||||
|
</q-dialog>
|
||||||
|
<q-page-sticky position="bottom-right" :offset="[18, 18]">
|
||||||
|
<q-btn
|
||||||
|
:title="$t(id ? 'save' : 'create')"
|
||||||
|
icon="check"
|
||||||
|
color="accent"
|
||||||
|
@click="onSave"
|
||||||
|
fab/>
|
||||||
|
</q-page-sticky>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Page from 'components/Page'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'New',
|
||||||
|
mixins: [Page],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
myNew: { text: '' },
|
||||||
|
id: null,
|
||||||
|
tags: null,
|
||||||
|
priorities: [1, 2, 3],
|
||||||
|
image: null,
|
||||||
|
editImage: false,
|
||||||
|
showUploader: false,
|
||||||
|
imageCollection: 'news',
|
||||||
|
images: [],
|
||||||
|
tools: [
|
||||||
|
['left', 'center', 'right', 'justify'],
|
||||||
|
['bold', 'italic', 'underline', 'removeFormat'],
|
||||||
|
['token', 'hr', 'link', 'custom_btn', 'print', 'fullscreen'],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
icon: this.$q.iconSet.editor.formatting,
|
||||||
|
list: 'no-icons',
|
||||||
|
options: [
|
||||||
|
'p',
|
||||||
|
'h1',
|
||||||
|
'h2',
|
||||||
|
'h3',
|
||||||
|
'h4',
|
||||||
|
'h5',
|
||||||
|
'h6',
|
||||||
|
'code'
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
icon: this.$q.iconSet.editor.fontSize,
|
||||||
|
fixedLabel: true,
|
||||||
|
fixedIcon: true,
|
||||||
|
list: 'no-icons',
|
||||||
|
options: [
|
||||||
|
'size-1',
|
||||||
|
'size-2',
|
||||||
|
'size-3',
|
||||||
|
'size-4',
|
||||||
|
'size-5',
|
||||||
|
'size-6',
|
||||||
|
'size-7'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
['quote', 'unordered', 'ordered'],
|
||||||
|
['undo', 'redo']
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
let filter = {
|
||||||
|
fields: ['name']
|
||||||
|
}
|
||||||
|
this.$axios.get('NewTags', { params: { filter } })
|
||||||
|
.then(res => (this.tags = res.data))
|
||||||
|
|
||||||
|
this.loadNew()
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'this.$route.params.id': function () {
|
||||||
|
this.loadNew()
|
||||||
|
},
|
||||||
|
image () {
|
||||||
|
this.showUploader = false
|
||||||
|
},
|
||||||
|
showUploader () {
|
||||||
|
this.$refs.uploader.reset()
|
||||||
|
},
|
||||||
|
editImage () {
|
||||||
|
if (this.editImage) {
|
||||||
|
this.image = this.myNew.image
|
||||||
|
} else {
|
||||||
|
this.showUploader = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
loadNew () {
|
||||||
|
this.id = this.$route.params.id
|
||||||
|
this.new = { text: '' }
|
||||||
|
|
||||||
|
if (this.id) {
|
||||||
|
let filter = {
|
||||||
|
fields: [
|
||||||
|
'id',
|
||||||
|
'title',
|
||||||
|
'text',
|
||||||
|
'image',
|
||||||
|
'userFk',
|
||||||
|
'priority',
|
||||||
|
'tag'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
this.$axios.get(`News/${this.id}`, { params: { filter } })
|
||||||
|
.then(res => (this.myNew = res.data))
|
||||||
|
} else {
|
||||||
|
this.new = {
|
||||||
|
userFk: this.$state.userId,
|
||||||
|
tag: 'new',
|
||||||
|
priority: 1,
|
||||||
|
text: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSave () {
|
||||||
|
let promise
|
||||||
|
let message
|
||||||
|
|
||||||
|
if (this.id) {
|
||||||
|
promise = this.$axios.patch(`News/${this.id}`, this.myNew)
|
||||||
|
message = 'dataSaved'
|
||||||
|
} else {
|
||||||
|
promise = this.$axios.post(`News`, this.myNew)
|
||||||
|
message = 'createdSuccess'
|
||||||
|
}
|
||||||
|
|
||||||
|
promise.then(res => {
|
||||||
|
this.$q.notify({
|
||||||
|
message: this.$t(message),
|
||||||
|
icon: 'check',
|
||||||
|
color: 'green-6'
|
||||||
|
})
|
||||||
|
this.$router.go(-1)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
filterImages (val, update, abort) {
|
||||||
|
let filter = {
|
||||||
|
where: {
|
||||||
|
name: { like: `${val}%` },
|
||||||
|
collectionFk: this.imageCollection
|
||||||
|
},
|
||||||
|
limit: !val ? 50 : undefined
|
||||||
|
}
|
||||||
|
this.$axios.get(`Images`, { params: { filter } })
|
||||||
|
.then(res => {
|
||||||
|
update(() => (this.images = res.data))
|
||||||
|
})
|
||||||
|
.catch(() => abort())
|
||||||
|
},
|
||||||
|
onEditImage () {
|
||||||
|
this.myNew.image = this.image
|
||||||
|
this.editImage = false
|
||||||
|
},
|
||||||
|
addImage (inputValue, doneFn) {
|
||||||
|
console.log(inputValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,123 @@
|
||||||
|
<template>
|
||||||
|
<div class="vn-pp row justify-center">
|
||||||
|
<div
|
||||||
|
v-if="news && !news.length"
|
||||||
|
class="text-subtitle1 text-center text-grey-7 q-pa-md">
|
||||||
|
{{$t('noDataFound')}}
|
||||||
|
</div>
|
||||||
|
<q-card class="vn-w-md">
|
||||||
|
<q-list bordered separator>
|
||||||
|
<q-item
|
||||||
|
v-for="(myNew, index) in news"
|
||||||
|
:key="myNew.id"
|
||||||
|
:to="`/new/${myNew.id}`"
|
||||||
|
clickable
|
||||||
|
v-ripple>
|
||||||
|
<q-item-section avatar>
|
||||||
|
<q-avatar rounded>
|
||||||
|
<img :src="`${$imageBase}/news/200x200/${myNew.image}`">
|
||||||
|
</q-avatar>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label class="ellipsis">
|
||||||
|
{{myNew.title}}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label class="ellipsis" caption>
|
||||||
|
{{myNew.created | relTime}}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label class="ellipsis" caption>
|
||||||
|
{{myNew.user.nickname}}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section side top>
|
||||||
|
<q-btn
|
||||||
|
icon="delete"
|
||||||
|
@click="remove(index, $event)"
|
||||||
|
:title="$t('delete')"
|
||||||
|
size="12px"
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
round/>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-card>
|
||||||
|
<q-dialog v-model="confirm" persistent>
|
||||||
|
<q-card>
|
||||||
|
<q-card-section class="row items-center">
|
||||||
|
{{$t('areYouSureDelete')}}
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-actions align="right">
|
||||||
|
<q-btn
|
||||||
|
:label="$t('cancel')"
|
||||||
|
v-close-popup
|
||||||
|
flat
|
||||||
|
color="primary"/>
|
||||||
|
<q-btn
|
||||||
|
:label="$t('accept')"
|
||||||
|
@click="confirmDeletion(deleteIndex)"
|
||||||
|
v-close-popup
|
||||||
|
flat
|
||||||
|
color="primary"/>
|
||||||
|
</q-card-actions>
|
||||||
|
</q-card>
|
||||||
|
</q-dialog>
|
||||||
|
<q-page-sticky position="bottom-right" :offset="[18, 18]">
|
||||||
|
<q-btn
|
||||||
|
fab
|
||||||
|
icon="add"
|
||||||
|
color="accent"
|
||||||
|
to="/new"
|
||||||
|
:title="$t('add')"/>
|
||||||
|
</q-page-sticky>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'News',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
news: null,
|
||||||
|
confirm: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
let filter = {
|
||||||
|
fields: [
|
||||||
|
'id',
|
||||||
|
'title',
|
||||||
|
'text',
|
||||||
|
'image',
|
||||||
|
'userFk',
|
||||||
|
'created',
|
||||||
|
'tag'
|
||||||
|
],
|
||||||
|
order: 'priority, created DESC',
|
||||||
|
include: {
|
||||||
|
relation: 'user',
|
||||||
|
scope: {
|
||||||
|
fields: ['nickname']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.$axios.get('News', { params: { filter } })
|
||||||
|
.then(res => (this.news = res.data))
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
remove (index, event) {
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
this.confirm = true
|
||||||
|
this.deleteIndex = index
|
||||||
|
},
|
||||||
|
confirmDeletion (index) {
|
||||||
|
this.$axios.delete(`News/${this.news[index].id}`)
|
||||||
|
.then(res => {
|
||||||
|
this.news.splice(index, 1)
|
||||||
|
this.$q.notify(this.$t('removedSuccess'))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,14 @@
|
||||||
|
<template>
|
||||||
|
<div class="text-subtitle1 text-center text-grey-7 q-pa-lg">
|
||||||
|
Sorry this section is under construction
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Order'
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -7,15 +7,6 @@
|
||||||
<q-route-tab to="/orders/confirmed" icon="check" :label="$t('confirmed')" />
|
<q-route-tab to="/orders/confirmed" icon="check" :label="$t('confirmed')" />
|
||||||
</q-tabs>
|
</q-tabs>
|
||||||
<router-view></router-view>
|
<router-view></router-view>
|
||||||
<q-page-sticky position="bottom-right" :offset="[18, 18]">
|
|
||||||
<q-btn
|
|
||||||
fab
|
|
||||||
icon="add_shopping_cart"
|
|
||||||
color="accent"
|
|
||||||
:to="{name: 'catalog'}"
|
|
||||||
:title="$t('startOrder')"
|
|
||||||
/>
|
|
||||||
</q-page-sticky>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -24,7 +15,9 @@
|
||||||
export default {
|
export default {
|
||||||
name: 'Orders',
|
name: 'Orders',
|
||||||
mounted () {
|
mounted () {
|
||||||
this.$router.replace('/orders/pending')
|
if (this.$route.path === '/orders') {
|
||||||
|
this.$router.replace('/orders/pending')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
<template>
|
||||||
|
<div class="vn-pp row justify-center">
|
||||||
|
<q-card class="vn-w-md">
|
||||||
|
<q-list bordered>
|
||||||
|
<a
|
||||||
|
v-for="link in links"
|
||||||
|
:key="link.id"
|
||||||
|
:href="link.link">
|
||||||
|
<q-item clickable>
|
||||||
|
<q-item-section avatar>
|
||||||
|
<q-avatar square>
|
||||||
|
<img :src="`${$imageBase}/link/full/${link.image}`">
|
||||||
|
</q-avatar>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>{{link.name}}</q-item-label>
|
||||||
|
<q-item-label caption>{{link.description}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-separator/>
|
||||||
|
</a>
|
||||||
|
</q-list>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
a
|
||||||
|
display block
|
||||||
|
text-decoration inherit
|
||||||
|
color: inherit
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Page from 'components/Page'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Panel',
|
||||||
|
mixins: [Page],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
links: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
let filter = {
|
||||||
|
order: 'name'
|
||||||
|
}
|
||||||
|
this.$axios.get('Links', { params: { filter } })
|
||||||
|
.then(res => (this.links = res.data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,17 +1,22 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="my-list q-pa-md">
|
<div class="vn-pp row justify-center">
|
||||||
<q-card>
|
<div
|
||||||
|
v-if="orders && !orders.length"
|
||||||
|
class="text-subtitle1 text-center text-grey-7 q-pa-md">
|
||||||
|
{{$t('noOrdersFound')}}
|
||||||
|
</div>
|
||||||
|
<q-card
|
||||||
|
v-if="orders && orders.length"
|
||||||
|
class="vn-w-md">
|
||||||
<q-list bordered separator>
|
<q-list bordered separator>
|
||||||
<q-item v-if="!orders.length">
|
|
||||||
{{$t('noOrdersFound')}}
|
|
||||||
</q-item>
|
|
||||||
<q-item
|
<q-item
|
||||||
v-for="order in orders"
|
v-for="order in orders"
|
||||||
:key="order.id"
|
:key="order.id"
|
||||||
|
:to="`/order/${order.id}`"
|
||||||
clickable
|
clickable
|
||||||
v-ripple>
|
v-ripple>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label>{{formatDate(order.landed)}}</q-item-label>
|
<q-item-label>{{order.landed | date('ddd, MMMM Do')}}</q-item-label>
|
||||||
<q-item-label caption>#{{order.id}}</q-item-label>
|
<q-item-label caption>#{{order.id}}</q-item-label>
|
||||||
<q-item-label caption>{{order.address.nickname}}</q-item-label>
|
<q-item-label caption>{{order.address.nickname}}</q-item-label>
|
||||||
<q-item-label caption>{{order.address.city}}</q-item-label>
|
<q-item-label caption>{{order.address.city}}</q-item-label>
|
||||||
|
@ -22,24 +27,24 @@
|
||||||
</q-item>
|
</q-item>
|
||||||
</q-list>
|
</q-list>
|
||||||
</q-card>
|
</q-card>
|
||||||
|
<q-page-sticky position="bottom-right" :offset="[18, 18]">
|
||||||
|
<q-btn
|
||||||
|
fab
|
||||||
|
icon="add_shopping_cart"
|
||||||
|
color="accent"
|
||||||
|
:to="{name: 'catalog'}"
|
||||||
|
:title="$t('startOrder')"
|
||||||
|
/>
|
||||||
|
</q-page-sticky>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
|
||||||
.my-list
|
|
||||||
max-width 30em
|
|
||||||
margin auto
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import { date } from 'quasar'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Orders',
|
name: 'Orders',
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
orders: []
|
orders: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
|
@ -54,11 +59,6 @@ export default {
|
||||||
} }
|
} }
|
||||||
this.$axios.get('Orders', { params })
|
this.$axios.get('Orders', { params })
|
||||||
.then(res => (this.orders = res.data))
|
.then(res => (this.orders = res.data))
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
formatDate (value) {
|
|
||||||
return date.formatDate(value, 'ddd, MMMM Do', this.$t('date'))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<template>
|
||||||
|
<div class="text-subtitle1 text-center text-grey-7 q-pa-lg">
|
||||||
|
Sorry this section is under construction
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Ticket'
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,5 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="vn-pp row justify-center">
|
<div class="vn-pp row justify-center">
|
||||||
|
<toolbar>
|
||||||
|
<q-btn
|
||||||
|
:label="$t('changePassword')"
|
||||||
|
icon="vpn_key"
|
||||||
|
:to="{ query: { changePassword: true } }"
|
||||||
|
flat/>
|
||||||
|
</toolbar>
|
||||||
<q-card class="vn-w-md">
|
<q-card class="vn-w-md">
|
||||||
<q-card-section class="q-gutter-md">
|
<q-card-section class="q-gutter-md">
|
||||||
<q-input
|
<q-input
|
||||||
|
@ -18,16 +25,15 @@
|
||||||
v-model="user.lang"
|
v-model="user.lang"
|
||||||
:label="$t('language')"
|
:label="$t('language')"
|
||||||
:options="languages"
|
:options="languages"
|
||||||
option-value="id"
|
option-value="code"
|
||||||
option-label="name" />
|
option-label="name"
|
||||||
|
emit-value/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section class="q-gutter-md">
|
<q-card-section class="q-gutter-md">
|
||||||
<q-checkbox v-model="receiveInvoices" :label="$t('receiveInvoiceByEmail')" />
|
<q-checkbox
|
||||||
|
v-model="receiveInvoices"
|
||||||
|
:label="$t('receiveInvoiceByEmail')" />
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-actions class="justify-center">
|
|
||||||
<q-btn flat :label="$t('changePassword')" :to="{ query: { changePassword: true } }"/>
|
|
||||||
<q-btn flat :label="$t('save')" @click="onSave"/>
|
|
||||||
</q-card-actions>
|
|
||||||
</q-card>
|
</q-card>
|
||||||
<q-dialog v-model="changePassword" persistent>
|
<q-dialog v-model="changePassword" persistent>
|
||||||
<q-card style="width: 25em;">
|
<q-card style="width: 25em;">
|
||||||
|
@ -72,7 +78,7 @@
|
||||||
<q-card-actions align="right">
|
<q-card-actions align="right">
|
||||||
<q-btn
|
<q-btn
|
||||||
:label="$t('cancel')"
|
:label="$t('cancel')"
|
||||||
to="/config"
|
to="/user"
|
||||||
flat
|
flat
|
||||||
color="primary"/>
|
color="primary"/>
|
||||||
<q-btn
|
<q-btn
|
||||||
|
@ -83,15 +89,23 @@
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
|
<q-page-sticky position="bottom-right" :offset="[18, 18]">
|
||||||
|
<q-btn
|
||||||
|
:title="$t('save')"
|
||||||
|
icon="check"
|
||||||
|
color="accent"
|
||||||
|
@click="onSave"
|
||||||
|
fab/>
|
||||||
|
</q-page-sticky>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import Page from 'components/Page'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Config',
|
name: 'User',
|
||||||
|
mixins: [Page],
|
||||||
props: {
|
props: {
|
||||||
changePassword: {
|
changePassword: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
@ -148,16 +162,24 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onChangePassword: function () {
|
onChangePassword: function () {
|
||||||
this.$q.notify(this.$t('passwordChanged'))
|
|
||||||
this.$router.push('/config')
|
|
||||||
|
|
||||||
this.oldPassword = ''
|
this.oldPassword = ''
|
||||||
this.newPassword = ''
|
this.newPassword = ''
|
||||||
this.repeatPassword = ''
|
this.repeatPassword = ''
|
||||||
|
|
||||||
|
this.$router.push({})
|
||||||
|
this.$q.notify({
|
||||||
|
message: this.$t('passwordChanged'),
|
||||||
|
icon: 'check',
|
||||||
|
color: 'green-6'
|
||||||
|
})
|
||||||
},
|
},
|
||||||
onSave () {
|
onSave () {
|
||||||
this.$axios.patch(`Accounts/${this.$state.userId}`, this.user)
|
this.$axios.patch(`Accounts/${this.$state.userId}`, this.user)
|
||||||
.then(res => (this.$q.notify(this.$t('dataSaved'))))
|
.then(res => (this.$q.notify({
|
||||||
|
message: this.$t('dataSaved'),
|
||||||
|
icon: 'check',
|
||||||
|
color: 'green-6'
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
<template>
|
||||||
|
<div class="vn-pp row justify-center">
|
||||||
|
<toolbar>
|
||||||
|
<q-input
|
||||||
|
v-model="search"
|
||||||
|
debounce="500"
|
||||||
|
class="q-mr-sm"
|
||||||
|
dark
|
||||||
|
dense
|
||||||
|
standout>
|
||||||
|
<template v-slot:append>
|
||||||
|
<q-icon
|
||||||
|
v-if="search === ''"
|
||||||
|
name="search"
|
||||||
|
/>
|
||||||
|
<q-icon
|
||||||
|
v-else
|
||||||
|
name="clear"
|
||||||
|
class="cursor-pointer"
|
||||||
|
@click="search = ''"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</toolbar>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
v-if="!users || !users.length"
|
||||||
|
class="text-subtitle1 text-center text-grey-7 q-pa-md">
|
||||||
|
<span v-if="!users">
|
||||||
|
{{$t('setSearchFilter')}}
|
||||||
|
</span>
|
||||||
|
<span v-else>
|
||||||
|
{{$t('noDataFound')}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<q-card class="vn-w-md">
|
||||||
|
<q-list bordered separator>
|
||||||
|
<q-item
|
||||||
|
v-for="user in users"
|
||||||
|
:key="user.id"
|
||||||
|
:to="`/access-log/${user.id}`"
|
||||||
|
:title="$t('accessLog')"
|
||||||
|
clickable>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>{{user.nickname}}</q-item-label>
|
||||||
|
<q-item-label caption>#{{user.id}}</q-item-label>
|
||||||
|
<q-item-label caption>{{user.name}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Page from 'components/Page'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Users',
|
||||||
|
mixins: [Page],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
users: null,
|
||||||
|
search: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.onRouteChange(this.$route)
|
||||||
|
},
|
||||||
|
beforeRouteUpdate (to, from, next) {
|
||||||
|
this.onRouteChange(to)
|
||||||
|
next()
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
search (value) {
|
||||||
|
let location = {}
|
||||||
|
if (value) location.query = { search: value }
|
||||||
|
this.$router.push(location)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onRouteChange (route) {
|
||||||
|
this.users = null
|
||||||
|
this.search = route.query.search || ''
|
||||||
|
if (!this.search) return
|
||||||
|
|
||||||
|
let where = {}
|
||||||
|
|
||||||
|
if (/^[0-9]+$/.test(this.search)) {
|
||||||
|
where.id = this.search
|
||||||
|
} else {
|
||||||
|
where = {
|
||||||
|
or: [
|
||||||
|
{ name: { like: `%${this.search}%` } },
|
||||||
|
{ nickname: { like: `%${this.search}%` } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let filter = {
|
||||||
|
fields: ['id', 'nickname', 'name', 'active'],
|
||||||
|
order: 'name',
|
||||||
|
limit: 25,
|
||||||
|
where
|
||||||
|
}
|
||||||
|
this.$axios.get('Accounts', { params: { filter } })
|
||||||
|
.then(res => (this.users = res.data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,144 @@
|
||||||
|
<template>
|
||||||
|
<div class="vn-pp row justify-center">
|
||||||
|
<toolbar>
|
||||||
|
<q-badge
|
||||||
|
v-if="count != null"
|
||||||
|
class="text-subtitle1 q-mr-sm"
|
||||||
|
color="secondary">
|
||||||
|
{{$t('visitsCount', [count, newCount])}}
|
||||||
|
</q-badge>
|
||||||
|
</toolbar>
|
||||||
|
<q-drawer
|
||||||
|
v-model="$state.rightDrawerOpen"
|
||||||
|
side="right"
|
||||||
|
elevated>
|
||||||
|
<div class="q-pa-md">
|
||||||
|
<q-input
|
||||||
|
:label="$t('fromDate')"
|
||||||
|
v-model="from"
|
||||||
|
:rules="['date']"
|
||||||
|
mask="date">
|
||||||
|
<template v-slot:append>
|
||||||
|
<q-icon name="event" class="cursor-pointer">
|
||||||
|
<q-popup-proxy ref="qDateProxyFrom" anchor="bottom left" self="top middle">
|
||||||
|
<q-date
|
||||||
|
v-model="from"
|
||||||
|
@input="() => $refs.qDateProxyFrom.hide()"
|
||||||
|
:options="optionsFn"/>
|
||||||
|
</q-popup-proxy>
|
||||||
|
</q-icon>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
<q-input
|
||||||
|
:label="$t('toDate')"
|
||||||
|
v-model="to"
|
||||||
|
:rules="['date']"
|
||||||
|
mask="date">
|
||||||
|
<template v-slot:append>
|
||||||
|
<q-icon name="event" class="cursor-pointer">
|
||||||
|
<q-popup-proxy ref="qDateProxyTo" anchor="bottom left" self="top middle">
|
||||||
|
<q-date
|
||||||
|
v-model="to"
|
||||||
|
@input="() => $refs.qDateProxyTo.hide()"
|
||||||
|
:options="optionsFn"/>
|
||||||
|
</q-popup-proxy>
|
||||||
|
</q-icon>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</div>
|
||||||
|
</q-drawer>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
v-if="visits && !visits.length"
|
||||||
|
class="text-subtitle1 text-center text-grey-7 q-pa-md">
|
||||||
|
{{$t('noDataFound')}}
|
||||||
|
</div>
|
||||||
|
<q-card class="vn-w-md">
|
||||||
|
<q-list bordered separator>
|
||||||
|
<q-item
|
||||||
|
v-for="visit in visits"
|
||||||
|
:key="visit.browser">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>
|
||||||
|
{{visit.browser}} {{visit.minVersion}} - {{visit.maxVersion}}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{$t('visitsCount', [visit.visits, visit.newVisits])}}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{visit.lastVisit | relTime}}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
<q-page-sticky position="bottom-right" :offset="[18, 18]">
|
||||||
|
<q-btn
|
||||||
|
fab
|
||||||
|
icon="refresh"
|
||||||
|
color="accent"
|
||||||
|
@click="refresh"
|
||||||
|
:title="$t('refresh')"
|
||||||
|
/>
|
||||||
|
</q-page-sticky>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Page from 'components/Page'
|
||||||
|
import { date } from 'quasar'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Visits',
|
||||||
|
mixins: [Page],
|
||||||
|
data () {
|
||||||
|
let today = date.formatDate(new Date(), 'YYYY/MM/DD')
|
||||||
|
return {
|
||||||
|
visits: null,
|
||||||
|
from: today,
|
||||||
|
to: today,
|
||||||
|
count: null,
|
||||||
|
newCount: null,
|
||||||
|
today
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.$state.useRightDrawer = true
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.refresh()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
refresh () {
|
||||||
|
let params = {
|
||||||
|
from: new Date(this.from),
|
||||||
|
to: new Date(this.to)
|
||||||
|
}
|
||||||
|
this.visits = null
|
||||||
|
return this.$axios.get(`Visits/listByBrowser`, { params })
|
||||||
|
.then(res => (this.visits = res.data))
|
||||||
|
},
|
||||||
|
optionsFn (date) {
|
||||||
|
return date <= this.today
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
from () {
|
||||||
|
this.refresh()
|
||||||
|
},
|
||||||
|
to () {
|
||||||
|
this.refresh()
|
||||||
|
},
|
||||||
|
visits () {
|
||||||
|
if (this.visits) {
|
||||||
|
this.count = this.visits.reduce((a, i) => a + i.visits, 0)
|
||||||
|
this.newCount = this.visits.reduce((a, i) => a + i.newVisits, 0)
|
||||||
|
} else {
|
||||||
|
this.count = null
|
||||||
|
this.newCount = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -26,9 +26,11 @@ export default function (/* { store, ssrContext } */) {
|
||||||
if (from.name === to.name) return
|
if (from.name === to.name) return
|
||||||
let app = Router.app
|
let app = Router.app
|
||||||
Object.assign(app.$state, {
|
Object.assign(app.$state, {
|
||||||
title: app.$t(to.name),
|
title: app.$t(to.name || 'home'),
|
||||||
titleColor: null,
|
titleColor: null,
|
||||||
subtitle: null
|
subtitle: null,
|
||||||
|
useRightDrawer: false,
|
||||||
|
rightDrawerOpen: true
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -22,13 +22,23 @@ const routes = [
|
||||||
component: () => import('pages/Orders.vue'),
|
component: () => import('pages/Orders.vue'),
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
|
name: 'pending',
|
||||||
path: 'pending',
|
path: 'pending',
|
||||||
component: () => import('pages/Pending.vue')
|
component: () => import('pages/Pending.vue')
|
||||||
}, {
|
}, {
|
||||||
|
name: 'confirmed',
|
||||||
path: 'confirmed',
|
path: 'confirmed',
|
||||||
component: () => import('pages/Confirmed.vue')
|
component: () => import('pages/Confirmed.vue')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
}, {
|
||||||
|
name: 'order',
|
||||||
|
path: '/order/:order',
|
||||||
|
component: () => import('pages/Order.vue')
|
||||||
|
}, {
|
||||||
|
name: 'ticket',
|
||||||
|
path: '/ticket/:ticket',
|
||||||
|
component: () => import('pages/Ticket.vue')
|
||||||
}, {
|
}, {
|
||||||
name: 'conditions',
|
name: 'conditions',
|
||||||
path: '/conditions',
|
path: '/conditions',
|
||||||
|
@ -38,13 +48,52 @@ const routes = [
|
||||||
path: '/about',
|
path: '/about',
|
||||||
component: () => import('pages/About.vue')
|
component: () => import('pages/About.vue')
|
||||||
}, {
|
}, {
|
||||||
name: 'register',
|
name: 'admin',
|
||||||
path: '/register',
|
path: '/admin',
|
||||||
component: () => import('pages/Register.vue')
|
component: () => import('pages/Admin.vue'),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'panel',
|
||||||
|
path: 'panel',
|
||||||
|
component: () => import('pages/Panel.vue')
|
||||||
|
}, {
|
||||||
|
name: 'users',
|
||||||
|
path: 'users',
|
||||||
|
component: () => import('pages/Users.vue')
|
||||||
|
}, {
|
||||||
|
name: 'connections',
|
||||||
|
path: 'connections',
|
||||||
|
component: () => import('pages/Connections.vue')
|
||||||
|
}, {
|
||||||
|
name: 'visits',
|
||||||
|
path: 'visits',
|
||||||
|
component: () => import('pages/Visits.vue')
|
||||||
|
}, {
|
||||||
|
name: 'news',
|
||||||
|
path: 'news',
|
||||||
|
component: () => import('pages/News.vue')
|
||||||
|
}, {
|
||||||
|
name: 'images',
|
||||||
|
path: 'images',
|
||||||
|
component: () => import('pages/Images.vue')
|
||||||
|
}, {
|
||||||
|
name: 'items',
|
||||||
|
path: 'items',
|
||||||
|
component: () => import('pages/Items.vue')
|
||||||
|
}
|
||||||
|
]
|
||||||
}, {
|
}, {
|
||||||
name: 'config',
|
name: 'accessLog',
|
||||||
path: '/config',
|
path: '/access-log/:user',
|
||||||
component: () => import('pages/Config.vue'),
|
component: () => import('pages/AccessLog.vue')
|
||||||
|
}, {
|
||||||
|
name: 'newEdit',
|
||||||
|
path: '/new/:id?',
|
||||||
|
component: () => import('pages/New.vue')
|
||||||
|
}, {
|
||||||
|
name: 'user',
|
||||||
|
path: '/user',
|
||||||
|
component: () => import('pages/User.vue'),
|
||||||
props: route => ({
|
props: route => ({
|
||||||
changePassword: String(route.query.changePassword) === 'true'
|
changePassword: String(route.query.changePassword) === 'true'
|
||||||
})
|
})
|
||||||
|
@ -54,8 +103,12 @@ const routes = [
|
||||||
component: () => import('pages/Addresses.vue')
|
component: () => import('pages/Addresses.vue')
|
||||||
}, {
|
}, {
|
||||||
name: 'addressEdit',
|
name: 'addressEdit',
|
||||||
path: '/address/:address?',
|
path: '/address/:id?',
|
||||||
component: () => import('pages/Address.vue')
|
component: () => import('pages/Address.vue')
|
||||||
|
}, {
|
||||||
|
name: 'register',
|
||||||
|
path: '/register',
|
||||||
|
component: () => import('pages/Register.vue')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}, {
|
}, {
|
||||||
|
|
Loading…
Reference in New Issue