Commit 286a4442 authored by Anton's avatar Anton

initial files from mbjs-quasar

parents
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
# Ignore generated files
dist/*
README.md
_book/*
module.exports = {
root: true,
parser: 'babel-eslint',
parserOptions: {
sourceType: 'module'
},
env: {
es6: true,
node: true,
mocha: true
},
// https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
extends: [
'standard'
],
// required to lint *.vue files
plugins: [
'import'
],
globals: {},
// add your custom rules here
'rules': {
// allow paren-less arrow functions
'arrow-parens': 0,
'one-var': 0,
'import/first': 0,
'import/named': 2,
'import/namespace': 2,
'import/default': 2,
'import/export': 2,
'no-return-await': 0,
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'brace-style': [2, 'stroustrup', { 'allowSingleLine': true }]
}
}
# Node.js
node_modules
bower_components
*.log
*.db
*.nedb
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/dictionaries
# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.xml
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
# Gradle:
.idea/**/gradle.xml
.idea/**/libraries
# CMake
cmake-build-debug/
cmake-build-release/
# Mongo Explorer plugin:
.idea/**/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Book build output
_book
# eBook build output
*.epub
*.mobi
*.pdf
# JetBrains
.idea
# nyc coverage
.nyc_output
# Quasar Components - Shared
> Set of general components for Motion Bank web applications
<template lang="pug">
q-btn(@click="$router.back()", color="lightgrey", icon="keyboard_backspace", round, flat, small)
</template>
<script>
export default {}
</script>
import BackButton from './BackButton'
export {
BackButton
}
<template lang="pug">
.shadow-6
q-datetime-picker.full-width(v-model="modelCalendar", dark)
.text-center.q-px-md
q-btn.full-width.q-ma-md(@click="resetTime", label="Today", no-caps)
</template>
<script>
export default {
watch: {
modelCalendar: function () {
this.$emit('calendarChange', this.modelCalendar)
}
},
methods: {
resetTime () {
this.$emit('timeReset', 'date')
this.modelCalendar = Date.now()
}
},
data () {
return {
modelCalendar: null
}
}
}
</script>
<style scoped lang="stylus">
</style>
<template lang="pug">
.row.col-12
// CALENDAR
//
q-collapsible.col-xs-12.col-lg-6.q-mb-lg(group="somegroup", icon="event_note",
:label="formatDate(modelCalendar, 'MMM Do, YYYY')")
calendar(@timeReset="reset", @calendarChange="calendarChange")
// TIME
//
q-collapsible.col-xs-12.col-lg-6.q-mb-lg(group="somegroup", icon="access_time",
:label="formatDate(modelCalendar, 'HH:mm:ss:SSS')")
slider-time(:resettime="modelCalendar", @sliderChange="sliderChange", @timeReset="reset")
</template>
<script>
import Calendar from './Calendar'
import SliderTime from '../forms/SliderTime'
import { date } from 'quasar'
// import { DateTime } from 'luxon'
export default {
components: {
Calendar,
SliderTime
},
watch: {
modelCalendar: function (val) {
if (val == null) this.modelCalendar = Date.now()
}
},
methods: {
emitString (val) {
console.log(val, '--------')
// console.log(val, parseInt(this.formatDate(val, 'M')))
// let valNew = DateTime.local().toISO()
// let valNew = DateTime.fromString(val).toISO()
// this.$emit('getTimeAndDate', val)
// this.$emit('getTimeAndDate', valNew)
},
calendarChange (val) {
this.modelCalendar = date.adjustDate(this.modelCalendar, {
year: date.formatDate(val, 'YYYY'),
month: date.formatDate(val, 'M')
})
// FIXME: days can't be adjusted. Bug in Quasar? Find workaround.
/* this.modelCalendar = date.adjustDate(this.modelCalendar, {
day: date.formatDate(val, 's') }) */
// console.log(this.formatDate(val, 'D'))
// let newDate = date.buildDate({year: 2010, day: 5, hours: 15, milliseconds: 123})
// const { addToDate } = date
// let newDate = addToDate(new Date(), { days: 7, months: 1 })
// console.log(newDate)
/*
let dt = DateTime.fromObject({
year: parseInt(this.formatDate(val, 'YYYY')),
month: parseInt(this.formatDate(val, 'M')),
day: parseInt(this.formatDate(val, 'D')),
hour: parseInt(this.formatDate(this.modelCalendar, 'H')),
minute: parseInt(this.formatDate(this.modelCalendar, 'm')),
second: parseInt(this.formatDate(this.modelCalendar, 's'))
}) */
// console.log(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second)
this.emitString(this.modelCalendar)
// this.emitString(dt)
},
sliderChange (val) {
switch (val.target) {
case 'hours':
this.modelCalendar = date.adjustDate(this.modelCalendar, { hours: val.val })
break
case 'minutes':
this.modelCalendar = date.adjustDate(this.modelCalendar, { minutes: val.val })
break
case 'seconds':
this.modelCalendar = date.adjustDate(this.modelCalendar, { seconds: val.val })
break
case 'milliseconds':
this.modelCalendar = date.adjustDate(this.modelCalendar, { milliseconds: val.val })
break
}
this.emitString(this.modelCalendar)
},
formatDate (val, format) {
if (val) return date.formatDate(val, format)
},
reset (val) {
let dateNow = Date.now()
switch (val) {
case 'date':
this.modelCalendar = date.adjustDate(this.modelCalendar, {
year: date.formatDate(dateNow, 'YYYY'),
month: date.formatDate(dateNow, 'M') })
// FIXME: days can't be adjusted. Bug in Quasar?
/* this.modelCalendar = date.adjustDate(this.modelCalendar, {
day: date.formatDate(dateNow, 'D') }) */
break
case 'time':
this.modelCalendar = date.adjustDate(this.modelCalendar, {
hours: date.formatDate(dateNow, 'H'),
minutes: date.formatDate(dateNow, 'm'),
seconds: date.formatDate(dateNow, 's'),
milliseconds: date.formatDate(dateNow, 'SSS') })
break
}
// console.log(date.formatDate(dateNow, 'D'))
}
},
data () {
return {
modelCalendar: Date.now()
}
}
}
</script>
<style scoped lang="stylus">
</style>
<template lang="pug">
q-btn(:dark="true", outline, icon-right="clear", :color="active ? 'primary' : 'light'",
@click="clickHandler", type="submit")
slot
</template>
<script>
export default {
props: ['active', 'click'],
methods: {
clickHandler (...args) {
if (typeof this.click === 'function') {
this.click(args)
}
}
}
}
</script>
<style scoped>
</style>
<template lang="pug">
form.form-wrap
div.form-top
slot(name="form-top-item").item
div.form-middle
slot(name="form-middle-item")
div.form-bottom
slot(name="form-bottom-item")
</template>
<script>
export default {}
</script>
<style scoped>
.form-wrap {
margin: 2em 0;
padding: 2em;
background-color: beige;
box-shadow: 0 0 20px 0 rgba( 0, 0, 0, .2 );
}
.form-bottom {
background-color: #f9f9f9;
margin: 2em;
text-align: center;
}
.form-bottom > * {
background-color: #555;
color: white;
padding: .2em .5em;
margin: 1em;
border-radius: .2em;
}
</style>
<template lang="pug">
// form.column.md-gutter.justify-between.items-around.full-width(v-on:submit.prevent="handleSubmit")
form(v-on:submit.prevent="handleSubmit")
// .row.md-gutter.justify-between.items-between
div
template(v-if="loaded", v-for="(field, key) in fields")
form-row-checkbox.col-sm-12.no-margin(
v-if="isType(field.type, 'checkbox')",
v-model="local[key]",
:type="field.type",
:validation="$v.local[key]",
:attributes="field.attributes",
:label="$t(field.label)",
:helper-label="$t(field.helperLabel)",
:error-label="$t(field.errorLabel)",
:class="{ 'col-xl-6': !field.fullWidth, 'col-12': field.fullWidth }"
)
form-row.col-sm-12.no-margin(
v-else,
v-model="local[key]",
:type="field.type",
:select-options="field.options",
:autocomplete-options="field.autocompleteOptions",
:validation="field.validators ? $v.local[key] : undefined",
:attributes="field.attributes",
:label="$t(field.label)",
:helper-label="$t(field.helperLabel)",
:error-label="$t(field.errorLabel)",
:class="{ 'col-xl-6': !field.fullWidth, 'col-12': field.fullWidth }"
)
.row.xs-gutter.full-width.justify-end.items-end
slot(name="form-buttons-add")
slot(name="form-buttons")
submit-button.q-mt-md(
:active="maySubmit",
) {{ $t(schema.submit.label) || $t('buttons.submit') }}
mb-notification-service
</template>
<script>
import Vue from 'vue'
import Vuelidate from 'vuelidate'
import Promise from 'bluebird'
import FormRow from './FormRow'
import FormRowCheckbox from './FormRowCheckbox'
import SubmitButton from './SubmitButton'
import {
Loading,
QSpinnerPuff
} from 'quasar'
Vue.use(Vuelidate)
export default {
components: {
FormRow,
FormRowCheckbox,
SubmitButton
},
props: ['value', 'schema'],
data () {
return {
typemap: {
'password': 'text'
},
local: undefined,
loaded: false
}
},
mounted () {
this.initForm()
},
computed: {
initial () {
const initial = {}
for (let key in this.fields) {
if (this.fields[key].initial) {
initial[key] = this.fields[key].initial
}
}
return this.$store.state.forms[this.schema.state] || initial
},
fields: function () {
return this.schema && this.schema.fields
? this.schema.fields : {}
},
validators () {
const validators = {}
for (let key in this.fields) {
if (this.fields[key].validators) {
validators[key] = this.fields[key].validators
}
}
return validators
},
isDirty () {
let dirty = false
if (this.$v && this.$v.local) {
for (let key in this.local) {
if (this.$v.local[key] && this.$v.local[key].$dirty) {
dirty = true
}
}
return dirty
}
},
maySubmit () {
return (!this.$v && !this.$v.local) ||
(!this.$v.local.$invalid && this.isDirty)
}
},
methods: {
initForm () {
const ctx = this
if (this.value && typeof this.value.then === 'function') {
this.value.then(data => {
ctx.local = data.toObject ? data.toObject() : data
ctx.loaded = true
})
}
else {
this.local = (this.value && this.value.toObject ? this.value.toObject() : this.value) || this.initial
this.loaded = true
}
},
handleSubmit () {
if (this.maySubmit &&
typeof this.schema.submit.handler === 'function') {
const { $store, schema } = this
Loading.show({
spinner: QSpinnerPuff,
spinnerSize: 200,
spinnerColor: 'grey'
})
Promise.resolve()
.then(schema.submit.handler)
.then(function (res) {
let message = schema.submit ? schema.submit.message : undefined
message = message || (res ? res.message() : 'messages.submit_success')
Loading.hide()
$store.commit('notifications/addMessage', {
body: message,
type: 'success'
})
if (schema.state) {
$store.commit(`forms/${schema.state}`, null)
}
})
.catch(function (err) {
Loading.hide()
console.debug('Form submit:', err)
$store.commit('notifications/addMessage', {
body: err.message
? `${err.message}${err.code
? ' (' + err.code + ')' : ''}`
: 'messages.submit_error',
mode: 'alert',
type: 'error'
})
})
}
},
isType (type, test) {
return this.typemap[type]
? this.typemap[type] === test : type === test
}
},
watch: {
local: {
handler (data) {
if (!data) {
this.initForm()
}
this.$emit('input', data)
if (this.schema.state) {
this.$store.commit(`forms/${this.schema.state}`, data)
}
},
deep: true
}
},
validations () {
return { local: this.validators }
}
}
</script>
<style></style>
<template lang="pug">
q-input(v-if="type === 'hidden'", :type="type", v-model="local")
q-field(v-else, :dark="true", :label="fieldLabel", :error="validation ? validation.$error : undefined",
:error-label="errorLabel", :helper="helperLabel || ''")
q-select(v-if="type === 'select'", :float-label="label", :dark="true", v-model="local", :options="selectOptions")
q-chips-input.q-my-md(v-else-if="type === 'chips'", :float-label="label", :dark="true", v-model="local",
chips-color="white", chips-bg-color="grey", @duplicate="duplicate()")
q-autocomplete.bg-grey-9(@search="autocompleteSearch", @selected="autocompleteSelected")
q-input(v-else, :dark="true", :float-label="label", :type="type", v-model="local", :attributes="attributes")
</template>
<script>
export default {
props: [
'value',
'attributes',
'validation',
'type',
'label',
'fieldLabel',
'errorLabel',
'helperLabel',
'selectOptions',
'autocompleteOptions'
],
data () {
return {
local: undefined
}
},
computed: {
error () {
if (this.type === 'hidden') return
return this.validation && this.validation.$error
}
},
watch: {
local (val) {
if (this.type === 'hidden') return
if (this.validation) {
this.validation.$touch()
}
this.$emit('input', val)
},
tags (val) {
if (this.validation) {
this.validation.$touch()
}
this.$emit('input', val)
},
value (val) {
this.local = val
}
},
methods: {
duplicate () {
this.$q.notify(this.$t('errors.item_exists'))
},
autocompleteSearch (input, done) {
if (!Array.isArray(this.autocompleteOptions)) return done([])
const regex = new RegExp(input, 'i')
const filtered = this.autocompleteOptions.filter(term => regex.test(term))
done(filtered.map(term => {
return { value: term, label: term }
}))
},
autocompleteSelected (item) {
console.debug('autocomplete selected', item)
}
},
created () {
this.local = this.value
if (this.type === 'hidden') return
if (this.validation) {
this.validation.$reset()
}
}
}
</script>
<style scoped lang="stylus">
</style>
<template lang="pug">
q-field(:dark="true", :error="validation ? validation.$error : undefined")
q-checkbox(:dark="true", :label="label", color="primary", v-model="local")
</template>
<script>
export default {
props: ['value', 'validation', 'type', 'label'],
data () {
return {
local: false
}
},
computed: {
error () {
return this.validation && this.validation.$error
}
},
watch: {
local (val) {
if (this.validation) {
this.validation.$touch()
}
this.$emit('input', val)
}
},
created () {
this.local = typeof this.value === 'boolean' ? this.value : false
}
}
</script>
<style></style>
<template lang="pug">
q-list.no-border.shadow-6
slider-time-row.q-mx-lg(v-for="(row, i) in rows",
@sliderChange="sliderChange",
:resettime="resettime", :key="i", :max="row.max", :suffix="row.suffix", :type="row.type")
q-item
q-item-main.text-center
q-btn.full-width(@click="resetTime", label="Now", no-caps)