Merge pull request #28 from paoloar77/Booking_Events

Booking events
This commit is contained in:
Paolo Arena
2019-10-14 09:54:51 +02:00
committed by GitHub
46 changed files with 29829 additions and 716 deletions

26852
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

1
src/common/shared_nodejs.js Symbolic link
View File

@@ -0,0 +1 @@
../../../freeplanet_serverside/server/tools/shared_nodejs.js

View File

@@ -0,0 +1,7 @@
export const shared_consts = {
fieldsUserToChange() {
return ['username', 'email', 'name', 'surname', 'perm', 'date_reg']
}
}

View File

@@ -0,0 +1,215 @@
$graytext: #555;
.calendar {
position: relative;
}
.my-event {
width: 100%;
position: absolute;
font-size: 12px;
}
.flex-container {
background-color: #ccc;
padding: 10px;
display: flex;
flex-direction: row;
align-items: stretch;
}
.flex-item {
background-color: #9f9f9f;
padding: 10px;
margin: 10px;
color: #fff;
font-size: 1rem;
}
.cal {
color: black;
font-size: 0.75rem;
font-weight: 400;
line-height: 1.25rem;
letter-spacing: 0.03333em;
&__title {
color: red;
font-weight: 700;
font-size: 1rem;
padding-bottom: 10px;
}
&__details {
color: black;
}
&__hours {
color: blue;
&-title {
color: $graytext;
}
&-content {
font-weight: 400;
}
}
&__where {
margin-top: 10px;
color: blue;
&-title {
color: $graytext;
}
&-content {
color: darkblue;
}
}
&__when {
margin-top: 10px;
color: blue;
&-title {
color: $graytext;
}
&-content {
color: darkblue;
}
}
&__teacher {
margin-top: 10px;
&-title {
color: $graytext;
}
&-content {
color: darkblue;
}
}
&__img {
width: 100px;
height: 100px;
padding: 10px;
}
}
.listaev {
color: black;
font-size: 0.75rem;
font-weight: 400;
line-height: 1.25rem;
letter-spacing: 0.03333em;
&__date {
font-weight: bold;
color: #2ba0fd;
font-size: 1rem;
}
&__title {
color: red;
font-weight: 700;
letter-spacing: 0.066em;
}
&__details {
color: black;
}
&__tdimg {
width: 150px;
height: 150px;
}
&__table {
margin: 10px;
border: solid 1px #4198ef;
border-radius: 1rem;
padding: 2px;
}
&__table tr {
border: solid 1px #4198ef;
border-radius: 1rem;
}
&__align_center_mobile {
text-align: left;
@media (max-width: 718px) {
text-align: center;
display: flex;
}
}
&__img {
padding: 0.5rem !important;
float: left;
width: 150px;
height: 150px;
border-radius: 1rem;
@media (max-width: 718px) {
// PER VERSIONE MOBILE
float: none;
text-align: center;
margin: 0 auto;
}
}
}
@media (max-width: 718px) {
.q-chip__content {
white-space: normal !important;
}
.q-chip > div {
white-space: normal !important;
}
.inline > div {
white-space: normal !important;
}
}
.mytoolbar {
padding: 0 2px !important;
}
.margin_avatar, .margin_avatar2, .margin_with {
margin-left: 0;
}
@media (max-width: 400px) {
.margin_avatar {
margin-left: 28px;
}
.margin_avatar2 {
margin-left: 38px;
}
.margin_with {
margin-left: 7px;
}
}
.chipbooked {
position: absolute;
left: 40px;
@media (max-width: 400px) {
position: initial;
}
}
.windowcol {
background-color: #ffffff;
// background: radial-gradient(circle, #ffffff 0%, #94dbfb 100%)
}
.mysel{
color: white;
}

View File

@@ -0,0 +1,861 @@
import Vue from 'vue'
import { Component, Prop, Watch } from 'vue-property-decorator'
import { CalendarStore, UserStore } from '@store'
import { Logo } from '../../components/logo/index'
import { Footer } from '../../components/Footer/index'
import { tools } from '../../store/Modules/tools'
import { toolsext, func_tools } from '@src/store/Modules/toolsext'
import { db_data } from '@src/db/db_data'
import { colors, Screen, Platform, date } from 'quasar'
import { CTitle } from '../../components/CTitle/index'
import { CImgText } from '../../components/CImgText/index'
import { stop, prevent, stopAndPrevent } from 'quasar/src/utils/event'
import QDateScroller from '@quasar/quasar-app-extension-qscroller/src/component/QDateScroller'
import QDateTimeScroller from '@quasar/quasar-app-extension-qscroller/src/component/QDateTimeScroller'
import { CTodo } from '@src/components/todos/CTodo'
import { SingleProject } from '@src/components/projects/SingleProject'
import { IEvents } from '@src/model'
import { IBookedEvent, IBookedEventPage, EState } from '@src/model/Calendar'
import { costanti } from '@src/store/Modules/costanti'
import router from '@router'
import { static_data } from '@src/db/static_data'
import translate from '@src/globalroutines/util'
import { lists } from '../../store/Modules/lists'
@Component({
name: 'CEventsCalendar',
components: { Logo, Footer, CTitle, CImgText, QDateTimeScroller, QDateScroller }
})
export default class CEventsCalendar extends Vue {
public $t: any
public $q
public calendarView = 'month'
public selectedDate = '2019-04-01'
public formDefault = {
title: '',
details: '',
allDay: false,
dateTimeStart: '',
dateTimeEnd: '',
icon: '',
bgcolor: '#0000FF'
}
public formbookEventDefault: IBookedEvent = {
userId: '',
msgbooking: '',
infoevent: '',
numpeople: 1,
datebooked: tools.getDateNow(),
booked: false,
modified: false
}
public mioalert = false
public dateFormatter: any = ''
public titleFormatter: any = null
public keyValue = 0
public direction = 'forward'
public weekdays = [1, 2, 3, 4, 5, 6, 0]
public viewOptions = [
{ label: 'Day', value: 'day' },
{ label: '5 Day', value: '5day' },
{ label: 'Week', value: 'week' },
{ label: 'Month', value: 'month' }
]
public addEvent = false
public bookEventpage: IBookedEventPage = {
show: false,
bookedevent: null,
state: EState.None
}
public contextDay = null
public eventForm = { ...this.formDefault }
public bookEventForm = { ...this.formbookEventDefault }
public displayEvent = false
public myevent = null
// public events = []
public gmt = ''
public dragging = false
public draggedEvent = null
public ignoreNextSwipe = false
public showDateScrollerAllDay = false
public showDateTimeScrollerStart = false
public showDateTimeScrollerEnd = false
@Watch('locale')
public checkloc() {
this.updateFormatters()
}
public resources = [
{
label: 'John'
},
{
label: 'Mary'
},
{
label: 'Susan'
},
{
label: 'Olivia'
},
{
label: 'Board Room'
},
{
label: 'Room-1'
},
{
label: 'Room-2'
}
]
public $refs: {
calendar: any
}
// public eventdata =
// [
// {
// id: 1,
// summary: 'Test myevent',
// description: 'Some extra info goes here',
// location: 'Office of the Divine Randomness, 1232 Main St., Denver, CO',
// start: {
// dateTime: '2019-07-09T14:00:00', // ISO 8601 formatted
// timeZone: 'America/New_York' // Timezone listed as a separate IANA code
// },
// end: {
// dateTime: '2019-07-11T16:30:00',
// timeZone: 'American/New_York'
// },
// color: 'positive',
// attendees: [
// {
// id: 5,
// email: 'somebody@somewhere.com',
// displayName: 'John Q. Public',
// organizer: false,
// self: false,
// resource: false
// }
// ]
// },
// {
// id: 2,
// summary: 'Test all-day myevent',
// description: 'Some extra info goes here',
// start: {
// date: '2018-02-16' // A date variable indicates an all-day myevent
// },
// end: {
// date: '2018-02-19'
// }
// },
// {
// id: 3,
// summary: 'Some other test myevent',
// description: 'Some extra info goes here',
// start: {
// dateTime: '2018-02-17T10:00:00+0500', // timezone embedded in dateTime
// },
// end: {
// dateTime: '2018-02-17T12:30:00+0500',
// }
// }
// ]
get title_cal() {
if (this.titleFormatter && this.locale) {
const mydate = new Date(this.selectedDate)
return this.titleFormatter.format(mydate)
}
return ''
}
get intervalRangeStep() {
return CalendarStore.state.intervalRangeStep
}
get resourceWidth() {
return CalendarStore.state.resourceWidth
}
get intervalHeight() {
return CalendarStore.state.intervalHeight
}
get shortIntervalLabel() {
return CalendarStore.state.shortIntervalLabel
}
get shortWeekdayLabel() {
return CalendarStore.state.shortWeekdayLabel
}
get hideHeader() {
return CalendarStore.state.hideHeader
}
get showDayOfYearLabel() {
return CalendarStore.state.showDayOfYearLabel
}
get shortMonthLabel() {
return CalendarStore.state.shortMonthLabel
}
get enableThemes() {
return CalendarStore.state.enableThemes
}
get resourceHeight() {
return CalendarStore.state.resourceHeight
}
get noScroll() {
return CalendarStore.state.noScroll
}
get maxDays() {
return CalendarStore.state.maxDays
}
get hour24Format() {
return CalendarStore.state.hour24Format
}
get showWorkWeeks() {
return CalendarStore.state.showWorkWeeks
}
get dayHeight() {
return CalendarStore.state.dayHeight
}
get theme() {
return CalendarStore.state.theme
}
get locale() {
return CalendarStore.state.locale
}
get showMonthLabel() {
return CalendarStore.state.showMonthLabel
}
get intervalStart() {
return CalendarStore.state.intervalRange.min * (1 / CalendarStore.state.intervalRangeStep)
}
get intervalCount() {
return (CalendarStore.state.intervalRange.max - CalendarStore.state.intervalRange.min) * (1 / CalendarStore.state.intervalRangeStep)
}
get editable() {
return CalendarStore.state.editable
}
public mounted() {
this.selectedDate = this.formatDate(tools.getDateNow())
this.$root.$on('calendar:next', this.calendarNext)
this.$root.$on('calendar:prev', this.calendarPrev)
this.$root.$on('calendar:today', this.calendarToday)
// CalendarStore.state.eventlist = events
this.updateFormatters()
}
public beforeMount() {
CalendarStore.state.locale = toolsext.getLocale()
this.updateFormatters()
}
public beforeDestroy() {
this.$root.$off('calendar:next', this.calendarNext)
this.$root.$off('calendar:prev', this.calendarPrev)
this.$root.$off('calendar:today', this.calendarToday)
}
get containerStyle() {
const styles = { height: '' }
if (this.calendarView !== 'month' || (this.calendarView === 'month' && CalendarStore.state.dayHeight === 0)) {
styles.height = `calc(100vh - ${CalendarStore.state.titlebarHeight}px)`
}
return styles
}
// convert the events into a map of lists keyed by date
get eventsMap() {
// console.log('eventsMap')
const map = {}
CalendarStore.state.eventlist.forEach((myevent) => (map[myevent.date] = map[myevent.date] || []).push(myevent))
return map
}
get addOrUpdateEvent() {
if (this.contextDay && this.contextDay.bgcolor) {
return 'Update'
}
return 'Add'
}
get scrollerPopupStyle160() {
if (this.$q.screen.lt.sm) {
return {
width: '100vw',
height: '100vh'
}
} else {
return {
maxHeight: '400px',
height: '400px',
width: '160px'
}
}
}
get scrollerPopupStyle280() {
if (this.$q.screen.lt.sm) {
return {
width: '100vw',
height: '100vh'
}
} else {
return {
maxHeight: '400px',
height: '400px',
width: '280px'
}
}
}
public showEvent(eventparam: IEvents) {
// console.log('showEvent - INIZIO')
this.myevent = eventparam
this.displayEvent = true
// console.log('showEvent - FINE ' + myevent)
}
public getEndTime(eventparam) {
let endTime = new Date(eventparam.date + ' ' + eventparam.time + ':00')
endTime = date.addToDate(endTime, { minutes: eventparam.duration })
endTime = date.formatDate(endTime, 'HH:mm')
return endTime
}
public onDateChanged(mydate) {
this.calendarView = 'day'
}
public resourceClicked(resource) {
console.log('resource clicked:', resource)
}
public resourceDayClicked(resource) {
console.log('resource:day clicked:', resource)
}
public resetForm() {
this.eventForm = { ...this.formDefault }
}
public addEventMenu(day, type) {
// console.log('addeventmenu editable = ', this.editable)
if (this.calendarView === 'scheduler' || this.calendarView === 'week-scheduler' || this.calendarView === 'month-scheduler' || !this.editable) {
return
}
this.resetForm()
this.contextDay = { ...day }
let timestamp
if (this.contextDay.hasTime === true) {
timestamp = this.getTimestamp(this.adjustTimestamp(this.contextDay))
const startTime = new Date(timestamp)
const endTime = date.addToDate(startTime, { hours: 1 })
this.eventForm.dateTimeEnd = this.formatDate(endTime) + ' ' + this.formatTime(endTime) // endTime.toString()
} else {
timestamp = this.contextDay.date + ' 00:00'
}
this.eventForm.dateTimeStart = timestamp
this.eventForm.allDay = this.contextDay.hasTime === false
this.eventForm.bgcolor = '#0000FF' // starting color
this.addEvent = true // show dialog
}
public addBookEventMenu(eventparam) {
if (!UserStore.state.isLogged || !UserStore.state.verified_email) {
this.$router.push('/signin')
} else {
console.log('addBookEventMenu')
this.resetForm()
this.myevent = eventparam
// this.bookEventForm.msgbooking = translate('cal.bookingtextdefault') + ' ' + tools.gettextevent(this.myevent)
this.bookEventForm.msgbooking = ''
this.bookEventForm.numpeople = 1
this.bookEventpage.state = EState.Creating
this.displayEvent = false
this.bookEventpage.show = true // show dialog
}
}
public clEvent(event: IEvents) {
return (this.isAlreadyBooked(event) ? 'text-left bg-light-green-1' : 'text-left')
}
public editEvent(eventparam) {
console.log('editEvent - INIZIO')
this.resetForm()
this.contextDay = { ...eventparam }
let timestamp
if (eventparam.time) {
timestamp = eventparam.date + ' ' + eventparam.time
const startTime = new Date(timestamp)
const endTime = date.addToDate(startTime, { minutes: eventparam.duration })
this.eventForm.dateTimeStart = this.formatDate(startTime) + ' ' + this.formatTime(startTime) // endTime.toString()
this.eventForm.dateTimeEnd = this.formatDate(endTime) + ' ' + this.formatTime(endTime) // endTime.toString()
} else {
timestamp = eventparam.date
this.eventForm.dateTimeStart = timestamp
}
this.eventForm.allDay = !eventparam.time
this.eventForm.bgcolor = eventparam.bgcolor
this.eventForm.icon = eventparam.icon
this.eventForm.title = eventparam.title
this.eventForm.details = eventparam.details
this.addEvent = true // show dialog
}
public deleteEvent(eventparam) {
const index = this.findEventIndex(eventparam)
if (index >= 0) {
CalendarStore.state.eventlist.splice(index, 1)
}
}
public findEventIndex(eventparam) {
for (let i = 0; i < CalendarStore.state.eventlist.length; ++i) {
if (eventparam.title === CalendarStore.state.eventlist[i].title &&
eventparam.details === CalendarStore.state.eventlist[i].details &&
eventparam.date === CalendarStore.state.eventlist[i].date) {
return i
}
}
}
public formatDate(mydate: any) {
let d = void 0
if (mydate !== void 0) {
d = new Date(mydate)
} else {
d = new Date()
}
const month = '' + (d.getMonth() + 1)
const day = '' + d.getDate()
const year = d.getFullYear()
return [year, tools.padTime(month), tools.padTime(day)].join('-')
}
get tools() {
return tools
}
get toolsext() {
return toolsext
}
get func_tools() {
return func_tools
}
public formatTime(mydate) {
const d = mydate !== void 0 ? new Date(mydate) : new Date(),
hours = '' + d.getHours(),
minutes = '' + d.getMinutes()
return [tools.padTime(hours), tools.padTime(minutes)].join(':')
}
public getDuration(dateTimeStart, dateTimeEnd, unit) {
const start = new Date(dateTimeStart)
const end = new Date(dateTimeEnd)
const diff = date.getDateDiff(end, start, unit)
return diff
}
public saveEvent() {
const self = this
// ++Todo VALIDATE this.$refs.myevent
if (true) {
// close the dialog
self.addEvent = false
const form = { ...self.eventForm }
let update = false
if (self.contextDay.bgcolor) {
// an update
update = true
} else {
// an add
}
const data: IEvents = {
time: '',
duration: 0,
duration2: 0,
title: form.title,
details: form.details,
icon: form.icon,
bgcolor: form.bgcolor,
date: String(form.dateTimeStart).slice(0, 10).replace(/\//g, '-')
}
if (form.allDay === false) {
// get time into separate var
data.time = String(form.dateTimeStart).slice(11, 16)
data.duration = self.getDuration(form.dateTimeStart, form.dateTimeEnd, 'minutes')
}
if (update === true) {
const index = self.findEventIndex(self.contextDay)
if (index >= 0) {
// @ts-ignore
CalendarStore.state.eventlist.splice(index, 1, { ...data })
}
} else {
// add to events array
// @ts-ignore
CalendarStore.state.eventlist.push(data)
}
self.contextDay = null
}
}
public EditBookEvent(myevent: IEvents) {
this.myevent = myevent
const bookedevent = CalendarStore.getters.findEventBooked(myevent, false)
console.log('bookedevent', bookedevent)
if (bookedevent) {
this.bookEventForm._id = bookedevent._id
this.bookEventForm.numpeople = bookedevent.numpeople
this.bookEventForm.infoevent = bookedevent.infoevent
this.bookEventForm.msgbooking = bookedevent.msgbooking
this.bookEventForm.booked = bookedevent.booked
this.bookEventForm.datebooked = bookedevent.datebooked
}
this.bookEventpage.state = EState.Modifying
this.bookEventpage.bookedevent = bookedevent
this.bookEventpage.show = true
}
get hasModifiedBooking() {
return (this.bookEventpage.bookedevent.numpeople !== this.bookEventForm.numpeople) ||
(this.bookEventpage.bookedevent.msgbooking !== this.bookEventForm.msgbooking) ||
(this.bookEventpage.bookedevent.booked !== this.bookEventForm.booked)
}
public sendMsg(myevent: IEvents) {
// ..
}
public saveBookEvent(myevent: IEvents) {
const self = this
// ++Todo VALIDATE this.$refs.myevent
if (true) {
// close the dialog
self.bookEventpage.show = false
// self.bookEventForm.booked = self.bookEventForm.bookedcheck
const data: IBookedEvent = {
userId: UserStore.state.userId,
id_bookedevent: myevent._id,
numpeople: self.bookEventForm.numpeople,
infoevent: tools.gettextevent(myevent),
msgbooking: self.bookEventForm.msgbooking,
booked: self.bookEventForm.booked,
datebooked: tools.getDateNow(),
modified: (self.bookEventpage.state !== EState.Creating)
}
this.BookEvent(data).then((ris) => {
if (ris)
tools.showPositiveNotif(self.$q, self.$t('cal.booked') + ' ' + self.$t('cal.event') + ' "' + myevent.title + '"')
else
tools.showNegativeNotif(self.$q, self.$t('cal.booked_error'))
})
self.contextDay = null
}
}
public showOffset(days) {
if (days.length === 0) return
let val = ''
val = tools.padTime(new Date(this.getTimestamp(days[0])).getTimezoneOffset() / 60)
if (Number.isNaN(Number(val))) return ''
return 'GMT-' + val
}
public adjustTimestamp(day) {
day.minute = day.minute < 15 || day.minute >= 45 ? 0 : 30
return day
}
public getTimestamp(day) {
return day.date + ' ' + tools.padTime(day.hour) + ':' + tools.padTime(day.minute) + ':00.000'
}
public updateFormatters() {
try {
// console.log('tools.getLocale() =', tools.getLocale())
// console.log('Calendar', CalendarStore.state.locale)
this.dateFormatter = new Intl.DateTimeFormat(tools.getLocale() || void 0, {
weekday: CalendarStore.state.shortWeekdayLabel ? 'short' : 'long',
month: CalendarStore.state.shortMonthLabel ? 'short' : 'long',
day: 'numeric',
year: 'numeric',
timeZone: 'UTC'
})
this.titleFormatter = new Intl.DateTimeFormat(this.locale || void 0, {
month: this.shortMonthLabel ? 'short' : 'long',
year: 'numeric',
timeZone: 'UTC'
})
} catch (e) {
console.error('Intl.DateTimeFormat not supported')
this.dateFormatter = void 0
}
}
public handleSwipe({ evt, ...info }) {
if (this.dragging === false) {
if (info.duration >= 30 && this.ignoreNextSwipe === false) {
if (info.direction === 'right') {
this.calendarPrev()
} else if (info.direction === 'left') {
this.calendarNext()
}
} else {
this.ignoreNextSwipe = false
}
}
stopAndPrevent(evt)
}
public onDragEnter(ev, eventparam) {
prevent(ev)
}
public onDragStart(ev, eventparam) {
this.dragging = true
this.draggedEvent = eventparam
stop(ev)
}
public onDragEnd(ev, eventparam) {
stopAndPrevent(ev)
this.resetDrag()
}
public onDragOver(ev, day, type) {
if (type === 'day') {
stopAndPrevent(ev)
return this.draggedEvent.date !== day.date
} else if (type === 'interval') {
stopAndPrevent(ev)
return this.draggedEvent.date !== day.date && this.draggedEvent.time !== day.time
}
}
public onDrop(ev, day, type) {
ev.preventDefault()
ev.stopPropagation()
if (type === 'day') {
this.draggedEvent.date = day.date
this.draggedEvent.side = void 0
} else if (type === 'interval') {
this.draggedEvent.date = day.date
this.draggedEvent.time = day.time
this.draggedEvent.side = void 0
}
}
public resetDrag() {
this.draggedEvent = void 0
this.dragging = false
if (Platform.is.desktop) {
this.ignoreNextSwipe = true
}
}
public async BookEvent(eventparam: IBookedEvent) {
return await CalendarStore.actions.BookEvent(eventparam)
}
public isAlreadyBooked(eventparam: IEvents) {
return CalendarStore.getters.findEventBooked(eventparam, true)
}
public getEventDate(eventparam) {
const parts = eventparam.date.split('-')
const mydate = new Date(parts[0], parts[1] - 1, parts[2])
return this.dateFormatter.format(mydate)
}
public badgeClasses(eventparam, type) {
const cssColor = tools.isCssColor(eventparam.bgcolor)
const isHeader = type === 'header'
return {
[`text-white bg-${eventparam.bgcolor}`]: !cssColor,
'full-width': !isHeader && (!eventparam.side || eventparam.side === 'full'),
'left-side': !isHeader && eventparam.side === 'left',
'right-side': !isHeader && eventparam.side === 'right'
}
}
public badgeStyles(eventparam, type, timeStartPos, timeDurationHeight) {
const s = { color: '', top: '', height: '' }
if (tools.isCssColor(eventparam.bgcolor)) {
s['background-color'] = eventparam.bgcolor
s.color = colors.luminosity(eventparam.bgcolor) > 0.5 ? 'black' : 'white'
}
if (timeStartPos) {
s.top = timeStartPos(eventparam.time) + 'px'
}
if (timeDurationHeight) {
s.height = timeDurationHeight(eventparam.duration) + 'px'
}
s['align-items'] = 'flex-start'
return s
}
public calendarNext() {
this.$refs.calendar.next()
}
public calendarPrev() {
this.$refs.calendar.prev()
}
public calendarToday(today) {
this.selectedDate = today
}
public SetToday() {
this.$root.$emit('calendar:today', this.formatDate(tools.getDateNow()))
}
public onChanged(data) {
// uncomment to see data in console
// let { start, end } = data
// console.log('onChanged:', start, end)
}
public onMoved(moved) {
// uncomment to see data in console
// console.log('onMoved:', moved)
}
public getEventList() {
const eventsloc = []
const datenow = tools.addDays(tools.getDateNow(), -1)
for (let i = 0; i < CalendarStore.state.eventlist.length; ++i) {
// console.log(' ciclo i = ', i, CalendarStore.state.eventlist[i])
const dateEvent = new Date(CalendarStore.state.eventlist[i].date + ' 00:00:00')
if (dateEvent >= datenow) {
eventsloc.push(CalendarStore.state.eventlist[i])
}
}
return eventsloc
}
public getEvents(dt) {
const eventsloc = []
for (let i = 0; i < CalendarStore.state.eventlist.length; ++i) {
let added = false
// console.log(' ciclo i = ', i, CalendarStore.state.eventlist[i])
if (CalendarStore.state.eventlist[i].date === dt) {
if (CalendarStore.state.eventlist[i].time) {
if (eventsloc.length > 0) {
// check for overlapping times
const startTime = new Date(CalendarStore.state.eventlist[i].date + ' ' + CalendarStore.state.eventlist[i].time)
const endTime = date.addToDate(startTime, { minutes: CalendarStore.state.eventlist[i].duration })
for (let j = 0; j < eventsloc.length; ++j) {
const startTime2 = new Date(eventsloc[j].date + ' ' + eventsloc[j].time)
const endTime2 = date.addToDate(startTime2, { minutes: eventsloc[j].duration2 })
if (date.isBetweenDates(startTime, startTime2, endTime2) || date.isBetweenDates(endTime, startTime2, endTime2)) {
eventsloc[j].side = 'left'
// CalendarStore.state.eventlist[i].side = 'right'
eventsloc.push(CalendarStore.state.eventlist[i])
added = true
break
}
}
}
}
if (!added) {
// CalendarStore.state.eventlist[i].side = void 0
eventsloc.push(CalendarStore.state.eventlist[i])
}
} else if (CalendarStore.state.eventlist[i].days) {
// check for overlapping dates
const startDate = new Date(CalendarStore.state.eventlist[i].date + ' 00:00:00')
const endDate = date.addToDate(startDate, { days: CalendarStore.state.eventlist[i].days })
if (date.isBetweenDates(dt, startDate, endDate)) {
eventsloc.push(CalendarStore.state.eventlist[i])
added = true
}
}
}
return eventsloc
}
get static_data() {
return static_data
}
get EState() {
return EState
}
get checkseinviaMsg() {
return (this.bookEventpage.state === EState.Creating) && (!this.bookEventForm.booked)
}
get getTitleBtnBooking() {
if (this.bookEventpage.state === EState.Creating) {
return this.$t('dialog.book')
} else {
return this.$t('dialog.update')
}
}
get mythis() {
return this
}
}

View File

@@ -0,0 +1,623 @@
$t('
<template>
<div class="landing">
<CTitle imgbackground="../../statics/images/calendario_eventi.jpg"
headtitle="Calendario Eventi" sizes="max-height: 120px"></CTitle>
<q-page class="column">
<!-- display an myevent -->
<q-dialog v-model="displayEvent">
<q-card v-if="myevent">
<q-toolbar :class="tools.displayClasses(myevent)"
:style="tools.displayStyles(myevent) + ` min-width: `+ tools.myheight_dialog() + `px;`">
<q-toolbar-title>
{{ $t('cal.event') }}
</q-toolbar-title>
<q-btn v-if="editable" flat round color="white" icon="delete" v-close-popup
@click="deleteEvent(myevent)"></q-btn>
<q-btn v-if="editable" flat round color="white" icon="edit" v-close-popup
@click="editEvent(myevent)"></q-btn>
<q-btn flat round color="white" icon="cancel" v-close-popup></q-btn>
</q-toolbar>
<q-card-section class="inset-shadow">
<q-img :src="`../../statics/`+myevent.img"
class="absolute-top"
style="height: 150px;">
</q-img>
<div style="margin-top: 150px;">
<div v-if="myevent.allDay" class="text-caption">{{ getEventDate(myevent) }}</div>
<div class="cal__title">{{myevent.title}}</div>
<div class="cal__details" v-html="myevent.details"></div>
<div v-if="myevent.teacher" class="cal__teacher">
<span class="cal__teacher-title">{{$t('cal.teacher')}}: <span
class="margin_with"></span></span>
<!--<span class="cal__teacher-content">{{myevent.teacher}}</span>-->
<span class="cal__teacher-content">
<q-chip>
<q-avatar>
<img :src="`../../statics/images/avatar/` + myevent.avatar">
</q-avatar>
<span class="cal__teacher-content">{{myevent.teacher}}</span>
</q-chip>
<span v-if="myevent.avatar2 && myevent.teacher2" class="margin_avatar2"></span>
<q-chip v-if="myevent.avatar2 && myevent.teacher2">
<q-avatar>
<img :src="`../../statics/images/avatar/` + myevent.avatar2">
</q-avatar>
<span class="cal__teacher-content">{{myevent.teacher2}}</span>
</q-chip>
</span>
</div>
<div v-if="myevent.where" class="cal__where">
<span v-if="tools.isMobile()"><br/></span>
<span class="cal__where-title">{{$t('cal.where')}}: </span>
<span class="cal__where-content">
<q-chip>
<q-avatar v-if="myevent.whereicon">
<img :src="`../../statics/images/avatar/` + myevent.whereicon">
</q-avatar>
<q-avatar color="blue" font-size="20px" text-color="white" icon="home">
</q-avatar>
<span class="cal__teacher-content">{{myevent.where}}</span>
</q-chip>
</span>
</div>
<div v-if="myevent.date" class="cal__when">
<span class="cal__where-title">{{$t('cal.when')}}: </span>
<span class="cal__where-content">{{func_tools.getDateStr(myevent.date)}}</span>
<span v-if="myevent.days > 1" class="cal__where-content"> - {{func_tools.getDateStr(tools.addDays(myevent.date, myevent.days - 1))}}<br/></span>
<span v-if="myevent.infoextra" class="cal__hours">
<span class="cal__hours-title">{{$t('cal.hours')}}: </span>
<span class="cal__hours-content">{{ myevent.infoextra }} </span>
</span>
<span v-else>
<span v-if="myevent.time" class="cal__hours">
-
<span class="cal__hours-title">{{$t('cal.hours')}}: </span>
<span class="cal__hours-content">{{$t('cal.starttime')}} {{ myevent.time }} {{$t('cal.endtime')}}: {{
getEndTime(myevent) }}</span>
</span>
</span>
</div>
<p v-if="myevent.linkpdf" style="margin-top: 10px; text-align: center">
<q-btn size="md" type="a" :href="`../../statics/` + myevent.linkpdf"
target="_blank" rounded color="primary" icon="info" :label="$t('cal.showinfo')">
</q-btn>
</p>
</div>
</q-card-section>
<q-card-actions align="right">
<q-btn rounded v-if="!myevent.nobookable && static_data.functionality.BOOKING_EVENTS"
color="primary" @click="addBookEventMenu(myevent)"
:label="$t('cal.booking')">
</q-btn>
<q-btn v-else :label="$t('dialog.ok')" color="primary" v-close-popup></q-btn>
</q-card-actions>
</q-card>
</q-dialog>
<!-- add/edit an myevent -->
<q-dialog v-model="addEvent" no-backdrop-dismiss>
<q-card v-if="addEvent" :style="`min-width: `+ tools.myheight_dialog() + `px;`">
<q-toolbar class="bg-primary text-white">
<q-toolbar-title>
{{ addOrUpdateEvent }} Event
</q-toolbar-title>
<q-btn flat round color="white" icon="close" v-close-popup></q-btn>
</q-toolbar>
<q-card-section class="inset-shadow">
<q-form
v-if="contextDay"
ref='myevent'
class="q-gutter-md">
<q-input v-model="eventForm.title" autofocus label="Title"
:rules="[v => v && v.length > 0 || 'Field cannot be empty']"></q-input>
<q-input type="textarea" v-model="eventForm.details"
:label="$t('cal.details')"></q-input>
<q-checkbox v-model="eventForm.allDay" :label="$t('cal.alldayevent')"></q-checkbox>
<q-input v-if="eventForm.allDay" color="blue-6" filled
v-model="eventForm.dateTimeStart"
:label="$t('cal.enterdate')" mask="####-##-##">
<template #append>
<q-icon name="event" class="cursor-pointer">
<q-popup-proxy v-model="showDateScrollerAllDay">
<q-date-scroller
v-model="eventForm.dateTimeStart"
:locale="locale"
:hour24-format="true"
:rounded-borders="true"
border-color="#2196f3"
bar-color="#2196f3"
color="white"
background-color="primary"
inner-color="primary"
inner-background-color="white"
:style="scrollerPopupStyle160"
@close="() => { showDateScrollerAllDay = false }"
/>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
<div v-else class="q-gutter-sm">
<q-input color="blue-6" outlined v-model="eventForm.dateTimeStart"
:label="$t('cal.enterdate')" mask="####-##-## ##:##">
<template #append>
<q-icon name="event" class="cursor-pointer">
<q-popup-proxy v-model="showDateTimeScrollerStart">
<q-date-time-scroller
v-model="eventForm.dateTimeStart"
:locale="locale"
:hour24-format="true"
:rounded-borders="true"
border-color="#2196f3"
bar-color="#2196f3"
color="white"
background-color="primary"
inner-color="primary"
inner-background-color="white"
:style="scrollerPopupStyle280"
@close="() => { showDateTimeScrollerStart = false }"
/>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
<q-input color="blue-6" outlined v-model="eventForm.dateTimeEnd"
:label="$t('cal.enterEndDateTime')" mask="####-##-## ##:##">
<template #append>
<q-icon name="event" class="cursor-pointer">
<q-popup-proxy v-model="showDateTimeScrollerEnd">
<q-date-time-scroller
v-model="eventForm.dateTimeEnd"
:locale="locale"
:hour24-format="true"
:rounded-borders="true"
border-color="#2196f3"
bar-color="#2196f3"
color="white"
background-color="primary"
inner-color="primary"
inner-background-color="white"
:style="scrollerPopupStyle280"
@close="() => { showDateTimeScrollerEnd = false }"
/>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
</div>
<q-input v-model="eventForm.infoextra" :label="$t('cal.infoextra')"></q-input>
<q-input v-model="eventForm.icon" label="Icon"></q-input>
<q-input
filled
v-model="eventForm.bgcolor"
>
<template #append>
<q-icon name="colorize" class="cursor-pointer">
<q-popup-proxy>
<q-color v-model="eventForm.bgcolor"></q-color>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
</q-form>
</q-card-section>
<q-card-actions align="right">
<q-btn flat :label="$t('dialog.ok')" color="primary" @click="saveEvent"></q-btn>
<q-btn flat :label="$t('dialog.cancel')" color="primary" v-close-popup></q-btn>
</q-card-actions>
</q-card>
</q-dialog>
<q-dialog v-model="bookEventpage.show" no-backdrop-dismiss>
<q-card v-if="bookEventpage.show" :style="`min-width: `+ tools.myheight_dialog() + `px;`">
<q-toolbar class="bg-primary text-white">
<q-toolbar-title>
{{$t('cal.booking')}}
</q-toolbar-title>
<q-btn flat round color="white" icon="close" v-close-popup></q-btn>
</q-toolbar>
<q-card-section class="inset-shadow">
<q-img :src="`../../statics/`+myevent.img"
class="absolute-top"
style="height: 150px;">
</q-img>
<div style="margin-top: 150px;">
<div v-if="myevent.allDay" class="text-caption">{{ getEventDate(myevent) }}</div>
<div class="cal__title">{{myevent.title}}</div>
<div v-if="myevent.date" class="cal__when">
<span class="cal__where-title">{{$t('cal.when')}}: </span>
<span class="cal__where-content">{{func_tools.getDateStr(myevent.date)}}</span>
<span v-if="myevent.days > 1" class="cal__where-content"> - {{func_tools.getDateStr(tools.addDays(myevent.date, myevent.days - 1))}}<br/></span>
<span v-if="myevent.infoextra" class="cal__hours">
<span class="cal__hours-title">{{$t('cal.hours')}}: </span>
<span class="cal__hours-content">{{ myevent.infoextra }} </span>
</span>
<span v-else>
<span v-if="myevent.time" class="cal__hours">
-
<span class="cal__hours-title">{{$t('cal.hours')}}: </span>
<span class="cal__hours-content"><span v-if="!tools.isMobile()">{{$t('cal.starttime')}} </span>{{ myevent.time }} <span v-if="!tools.isMobile()">{{$t('cal.endtime')}} </span><span v-else> - </span> {{
getEndTime(myevent) }}</span>
</span>
</span>
</div>
<div class="q-pa-xs">
<q-card class="text-white windowcol">
<q-card-section>
<q-checkbox :disable="(bookEventpage.bookedevent && bookEventpage.bookedevent.booked) || (bookEventpage.bookedevent === undefined)" style="color: black;" v-model="bookEventForm.booked" :label="$t('cal.bookingtextdefault')" color="green">
</q-checkbox>
<div v-if="bookEventForm.booked" class="q-gutter-md centermydiv" style="max-width: 150px; margin-top:10px;">
<q-select
rounded outlined v-model="bookEventForm.numpeople"
:options="tools.SelectListNumPeople"
:label="$t('cal.selnumpeople')" emit-value map-options>
</q-select>
</div>
<q-input v-model="bookEventForm.msgbooking" :label="$t('cal.msgbooking')+':'" autogrow>
</q-input>
</q-card-section>
</q-card>
</div>
<p v-if="myevent.linkpdf" style="margin-top: 10px; text-align: center">
<q-btn size="md" type="a" :href="`../../statics/` + myevent.linkpdf"
target="_blank" rounded color="primary" icon="info" :label="$t('cal.showinfo')">
</q-btn>
</p>
</div>
</q-card-section>
<q-card-actions align="right">
<q-btn v-if="bookEventpage.state === EState.Modifying" flat :label="$t('cal.cancelbooking')"
color="negative" @click="tools.CancelBookingEvent(mythis, myevent, bookEventForm._id, true)"></q-btn>
<q-btn v-if="checkseinviaMsg" flat :label="$t('dialog.sendmsg')" color="primary" @click="sendMsg(myevent)"></q-btn>
<q-btn v-else flat :label="getTitleBtnBooking" color="primary" @click="saveBookEvent(myevent)"
:disable="!(bookEventpage.state === EState.Creating || hasModifiedBooking)"></q-btn>
<q-btn flat :label="$t('dialog.cancel')" color="primary" v-close-popup></q-btn>
</q-card-actions>
</q-card>
</q-dialog>
<!--v-touch-swipe.mouse.left.right="handleSwipe" -->
<!-- the calendar -->
<div>
<q-toolbar class="mytoolbar">
<q-btn color="primary" round icon="keyboard_arrow_left" @click="calendarPrev"/>
<q-btn color="primary" round icon="keyboard_arrow_right" @click="calendarNext"/>
<q-separator vertical/>
<q-btn color="primary" :label="$t('dialog.today')" class="q-mx-md" @click="SetToday"></q-btn>
<q-separator vertical/>
<q-btn label="GG" color="primary" @click="calendarView = 'day'"/>
<q-btn label="Set" color="primary" @click="calendarView = 'week'"/>
<q-btn label="Mese" color="primary" @click="calendarView = 'month'"/>
<q-space/>
</q-toolbar>
<q-separator/>
<div class="text-center"><span
class="q-mr-xl q-toolbar__title nowrap text-blue">{{ title_cal }}</span>
</div>
<!--
:theme="theme"
:enable-themes="enableThemes === true"
-->
<q-calendar
ref="calendar"
class="calendar"
:key="keyValue"
v-model="selectedDate"
:locale="locale"
:maxDays="maxDays"
animated
transition-prev="slide-right"
transition-next="slide-left"
:dragOverFunc="onDragOver"
:dropFunc="onDrop"
:view="calendarView"
:weekdays="weekdays"
:interval-minutes="60 * intervalRangeStep"
:interval-start="intervalStart"
:interval-count="intervalCount"
:hour24-format="hour24Format"
:short-month-label="shortMonthLabel"
:show-day-of-year-label="showDayOfYearLabel"
:hide-header="hideHeader"
:no-scroll="noScroll"
:short-weekday-label="shortWeekdayLabel"
:short-interval-label="shortIntervalLabel"
:interval-height="intervalHeight"
:resource-height="resourceHeight"
:resource-width="resourceWidth"
:day-height="dayHeight"
:show-month-label="showMonthLabel"
:show-work-weeks="showWorkWeeks"
:resources="resources"
@change="onChanged"
@moved="onMoved"
@click:date="onDateChanged"
@click:interval="addEventMenu"
@click:time="addEventMenu"
@click:day="addEventMenu"
@click:week="addEventMenu"
@click:resource="resourceClicked"
@click:resource:day="resourceDayClicked"
dayPadding="35px 2px"
>
<template #day="{ date }">
<template v-for="(event, index) in getEvents(date)">
<q-badge
:key="index"
style="width: 100%; cursor: pointer;"
class="ellipsis"
:class="badgeClasses(event, 'day')"
:style="badgeStyles(event, 'day')"
@click.stop.prevent="showEvent(event)"
:draggable="true"
@dragstart.native="(e) => onDragStart(e, event)"
@dragend.native="(e) => onDragEnd(e, event)"
@dragenter.native="(e) => onDragEnter(e, event)"
@touchmove.native="(e) => {}"
>
<q-icon v-if="event.icon" :name="event.icon" class="q-mr-xs"></q-icon>
<span class="ellipsis">{{ event.title }}</span>
</q-badge>
</template>
</template>
<template #day-header="{ date }">
<div class="row justify-center">
<template v-for="(event, index) in eventsMap[date]">
<q-badge
v-if="!event.time"
:key="index"
style="width: 100%; cursor: pointer;"
class="ellipsis"
:class="badgeClasses(event, 'header')"
:style="badgeStyles(event, 'header')"
@click.stop.prevent="showEvent(event)"
:draggable="true"
@dragstart.native="(e) => onDragStart(e, event)"
@dragend.native="(e) => onDragEnd(e, event)"
@dragenter.native="(e) => onDragEnter(e, event)"
@touchmove.native="(e) => {}"
>
<q-icon v-if="event.icon" :name="event.icon" class="q-mr-xs"></q-icon>
<span class="ellipsis">{{ event.title }}</span>
</q-badge>
<q-badge
v-else
:key="index"
class="q-ma-xs"
:class="badgeClasses(event, 'header')"
:style="badgeStyles(event, 'header')"
style="width: 10px; max-width: 10px; height: 10px; max-height: 10px"
/>
</template>
</div>
</template>
<template #day-body="{ date, timeStartPos, timeDurationHeight }">
<template v-for="(event, index) in getEvents(date)">
<q-badge
v-if="event.time"
:key="index"
class="my-event justify-center ellipsis"
:class="badgeClasses(event, 'body')"
:style="badgeStyles(event, 'body', timeStartPos, timeDurationHeight)"
@click.stop.prevent="showEvent(event)"
:draggable="true"
@dragstart.native="(e) => onDragStart(e, event)"
@dragend.native="(e) => onDragEnd(e, event)"
@dragenter.native="(e) => onDragEnter(e, event)"
@touchmove.native="(e) => {}"
>
<q-icon v-if="event.icon" :name="event.icon" class="q-mr-xs"></q-icon>
<span class="ellipsis">{{ event.title }}</span>
</q-badge>
</template>
</template>
</q-calendar>
</div>
</q-page>
<div>
<p class="text-subtitle1 text-red text-center">LISTA PROSSIMI EVENTI:</p>
<q-markup-table wrap-cells bordered separator="horizontal" class="listaev__table">
<tbody>
<tr v-for="(event, index) in getEventList()" class="listaev listaev__table">
<td :class="clEvent(event)">
<p class="listaev__align_center_mobile">
<img :src="`../../statics/`+event.img"
class="text-left padding_cell listaev__tdimg listaev__img">
<q-chip dense v-if="isAlreadyBooked(event)" class="cltexth4 chipbooked shadow-5"
color="green" text-color="white"
icon="event_available"
dense>{{$t('cal.booked')}}
</q-chip>
</p>
<div class="listaev__date listaev__align_center_mobile">
<div v-if="event.infoextra">
<span class="listaev__date">{{func_tools.getDateStr(event.date)}} - <span
class="cal__hours-content">{{ event.infoextra }}</span> </span>
</div>
<div v-else>
<div v-if="event.date" class="listaev__date">
{{func_tools.getDateStr(event.date)}}
<span v-if="event.time" class="cal__hours-content"> - {{ event.time }} <span
v-if="event.duration">- {{ getEndTime(event) }}</span></span>
<span v-if="event.days > 1"><br/>{{func_tools.getDateStr(tools.addDays(event.date, event.days - 1))}}</span>
</div>
</div>
</div>
<div class="">
<div style="margin: 10px;"></div>
<div class="listaev__align_center_mobile">
<!-- Se c'è un link, allora -->
<q-btn v-if="event.linkpdf" size="md" type="a"
:href="`../../statics/` + event.linkpdf"
target="_blank"
ripple rounded :label="event.title" :icon="event.icon"
:color="event.bgcolor" text-color="white" glossy>
</q-btn>
<!-- altrimenti mostra solo Chip -->
<div v-else>
<div v-if="tools.isMobile()" class="cltexth3"
:style="`background-color: ${event.bgcolor} !important; color: white !important;`">
{{event.title}}
</div>
<q-chip v-else class="cltexth3" :color="event.bgcolor" text-color="white"
:icon="event.icon"
dense>{{event.title}}
</q-chip>
</div>
</div>
<div style="margin: 10px;"></div>
<p class="listaev__details" v-html="event.details"></p>
<div v-if="event.teacher" class="">
<span class="cal__teacher-title">{{$t('cal.teacher')}}: <span
class="margin_with"></span></span>
<q-chip>
<q-avatar>
<img :src="`../../statics/images/avatar/` + event.avatar">
</q-avatar>
<span class="cal__teacher-content">{{event.teacher}}</span>
</q-chip>
<span v-if="event.avatar2" class="margin_avatar2"></span>
<q-chip v-if="event.avatar2 && event.teacher2">
<q-avatar>
<img :src="`../../statics/images/avatar/` + event.avatar2">
</q-avatar>
<span class="cal__teacher-content">{{event.teacher2}}</span>
</q-chip>
<span v-if="event.where" class="">
<span v-if="tools.isMobile()"><br/></span>
<span class="cal__where-title">{{$t('cal.where')}}: </span>
<q-chip>
<q-avatar v-if="event.whereicon">
<img :src="`../../statics/images/avatar/` + event.whereicon">
</q-avatar>
<q-avatar color="blue" font-size="20px" text-color="white" icon="home">
</q-avatar>
<span class="cal__teacher-content">{{event.where}}</span>
</q-chip>
</span>
</div>
<p class="text-center">
<span v-if="event.linkpdf" class="">
<q-btn size="md" type="a" :href="`../../statics/` + event.linkpdf"
target="_blank" rounded color="primary" icon="info"
:label="$t('cal.showinfo')">
</q-btn>
</span>
</p>
<div class="row justify-end">
<q-btn rounded outline
v-if="!event.nobookable && !isAlreadyBooked(event) && static_data.functionality.BOOKING_EVENTS"
color="primary" @click="addBookEventMenu(event)"
:label="$t('cal.booking')">
</q-btn>
<q-btn rounded outline
v-if="!event.nobookable && isAlreadyBooked(event) && static_data.functionality.BOOKING_EVENTS"
text-color="red"
@click.native="EditBookEvent(event)"
:label="$t('cal.modifybooking')">
</q-btn>
<!--
<q-btn push rounded v-if="!event.nobookable && isAlreadyBooked(event)" color="positive" @click="BookEvent(event)"
:label="$t('cal.booked')">
</q-btn>
-->
</div>
</div>
</td>
</tr>
</tbody>
</q-markup-table>
<!-- Example of a Dialog with a Card -->
<!--
<q-dialog v-model="card">
<q-card>
<q-img src="https://media-cdn.tripadvisor.com/media/photo-s/0a/47/a8/91/chicken-salad-sandwich.jpg" />
<q-card-section>
<q-btn
fab
color="primary"
icon="place"
class="absolute"
style="top: 0; right: 12px; transform: translateY(-50%);"
/>
<div class="row no-wrap items-center">
<div class="col text-h6 ellipsis">Cafe Basilico</div>
<div class="col-auto text-grey q-pt-md">
<q-icon name="place" /> 250 ft
</div>
</div>
<q-rating v-model="stars" :max="5" size="32px" />
</q-card-section>
<q-card-section>
<div class="text-subtitle1">$Italian, Cafe</div>
<div class="text-subtitle2 text-grey">Small plates, salads & sandwiches in an intimate setting.</div>
</q-card-section>
<q-separator />
<q-card-actions>
<q-btn flat round icon="event" v-close-popup />
<q-btn flat v-close-popup>5:30PM</q-btn>
<q-btn flat v-close-popup>7:30PM</q-btn>
<q-btn flat v-close-popup>9:00PM</q-btn>
<q-btn flat color="primary" v-close-popup>Reserve</q-btn>
</q-card-actions>
</q-card>
</q-dialog>
-->
</div>
</div>
</template>
<script lang="ts" src="./CEventsCalendar.ts">
</script>
<style lang="scss" scoped>
@import './CEventsCalendar.scss';
</style>

View File

@@ -0,0 +1 @@
export {default as CEventsCalendar} from './CEventsCalendar.vue'

View File

@@ -0,0 +1,67 @@
import Vue from 'vue'
import { Component, Prop } from 'vue-property-decorator'
import { UserStore } from '../../store/Modules/index'
import { tools } from '../../store/Modules/tools'
import { shared_consts } from '../../common/shared_vuejs'
import { ICategory } from '../../model'
@Component({
})
export default class CGridTableRec extends Vue {
@Prop({required: true}) public mytitle: string
@Prop({required: true}) public mylist: any[]
@Prop({required: true}) public mycolumns: any[]
@Prop({required: true}) public colkey: string
public $q
public $t
public loading: boolean = false
public paginationControl: {
page: number,
rowsPerPage: number // specifying this determines pagination is server-side
} = { page: 1, rowsPerPage: 10 }
public serverData: any [] = []
public idsel: string = ''
public colsel: string = ''
public separator: 'horizontal'
public filter: string = ''
public selected: any[] = []
public dark: boolean = true
get tableClass() {
if (this.dark) {
return 'bg-black'
}
}
public selItem(item, colsel) {
console.log('item', item)
this.idsel = item._id
this.colsel = colsel
console.log('this.idsel', this.idsel)
}
public SaveValue(newVal, valinitial) {
console.log('SaveValue', newVal, 'selected', this.selected)
const mydata = {}
mydata[this.colsel] = newVal
mydata[this.colkey] = this.idsel
console.log('this.idsel', this.idsel, 'this.colsel', this.colsel)
console.table(mydata)
this.$emit('save', mydata)
}
public created() {
this.serverData = this.mylist.slice() // [{ chiave: 'chiave1', valore: 'valore 1' }]
}
}

View File

@@ -0,0 +1,50 @@
<template>
<div class="q-pa-sm">
<q-table
:title="mytitle"
:data="serverData"
:columns="mycolumns"
:filter="filter"
:pagination.sync="paginationControl"
:row-key="colkey">
<!--<template v-slot:top="props">-->
<div class="col-2 q-table__title">{{ mytitle }}</div>
<q-space/>
<q-tr slot="body" slot-scope="props" :props="props">
<q-td v-for="col in mycolumns" :key="col.name" :props="props">
<div v-if="col.action">
<q-btn flat round color="red" icon="fas fa-trash-alt"
@click="col.clickfunz"></q-btn>
</div>
<div v-else>
{{ props.row[col.name] }}
<q-popup-edit v-model="props.row[col.name]" :disable="col.disable" :title="col.title" buttons
@save="SaveValue" @show="selItem(props.row, col.field)">
<q-input v-model="props.row[col.name]"/>
</q-popup-edit>
</div>
</q-td>
</q-tr>
<!--
<q-btn
flat round dense
:icon="props.inFullscreen ? 'fullscreen_exit' : 'fullscreen'"
@click="props.toggleFullscreen"
class="q-ml-md">
</q-btn>
-->
<!--</template>-->
</q-table>
</div>
</template>
<script lang="ts" src="./CGridTableRec.ts">
</script>
<style lang="scss" scoped>
@import './CGridTableRec.scss';
</style>

View File

@@ -0,0 +1 @@
export {default as CGridTableRec} from './CGridTableRec.vue'

View File

@@ -0,0 +1,5 @@
.signin {
width: 100%;
margin: 0 auto;
max-width: 450px;
}

View File

@@ -0,0 +1,168 @@
import Vue from 'vue'
import { GlobalStore } from '@store'
import { UserStore } from '../../store/Modules'
import { Component, Prop, Watch } from 'vue-property-decorator'
import { serv_constants } from '../../store/Modules/serv_constants'
import { tools } from '../../store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
import { ISigninOptions, IUserState } from 'model'
import { TSignin, validations } from './CSignIn-validate'
import { validationMixin } from 'vuelidate'
import { Logo } from '../logo'
import router from '@router'
import globalroutines from '../../globalroutines/index'
import { ICategory } from '../../model'
// import {Loading, QSpinnerFacebook, QSpinnerGears} from 'quasar'
@Component({
name: 'CSignIn',
mixins: [validationMixin],
validations,
components: { Logo }
})
export default class CSignIn extends Vue {
@Prop({ required: true }) public mythis: any
public $v
public loading: boolean
public $t: any
public iswaitingforRes: boolean = false
public signin: ISigninOptions = {
username: process.env.TEST_USERNAME || '',
password: process.env.TEST_PASSWORD || ''
}
public created() {
this.$v.$reset()
if (UserStore.state.resStatus === serv_constants.RIS_CODE__HTTP_FORBIDDEN_INVALID_TOKEN) {
this.$emit('showNotif', 'fetch.error_doppiologin')
}
// this.$myconfig.socialLogin.facebook = true
// console.log('PROVA fb:', this.$myconfig.socialLogin.facebook)
}
public env() {
return process.env
}
public getlinkforgetpwd() {
return '/requestresetpwd'
}
public errorMsg(cosa: string, item: any) {
try {
if (!item.$error) {
return ''
}
if (item.$params.email && !item.email) {
return this.$t('reg.err.email')
}
if (!item.required) {
return this.$t('reg.err.required')
}
if (!item.minLength) {
return this.$t('reg.err.atleast') + ` ${item.$params.minLength.min} ` + this.$t('reg.err.char')
}
if (!item.maxLength) {
return this.$t('reg.err.notmore') + ` ${item.$params.maxLength.max} ` + this.$t('reg.err.char')
}
return ''
} catch (error) {
// console.log("ERR : " + error);
}
}
public redirect(response) {
this.loading = false
window.location.href = response.data.redirect
}
public error(error) {
this.loading = false
// this.$errorHandler(this, error)
}
public facebook() {
this.loading = true
// this.$axios.get('/backend/loginFacebook')
// .then((response) => this.redirect(response))
// .catch((error) => this.error(error))
}
public google() {
// ...
}
public submit() {
// console.log('submit LOGIN')
this.$v.signin.$touch()
if (this.$v.signin.$error) {
this.$emit('showNotif', 'reg.err.errore_generico')
return
}
this.$emit('loginInCorso')
// disable Button Login:
this.iswaitingforRes = true
if (process.env.DEBUG) {
// console.log('this.signin', this.signin)
}
UserStore.actions.signin(this.signin)
.then((riscode) => {
// console.log('signin FINITO CALL: riscode=', riscode)
if (riscode === tools.OK) {
// router.push('/signin')
}
return riscode
})
.then((riscode) => {
if (process.env.DEBUG) {
// console.log(' riscode(1) =', riscode)
}
return riscode
})
.then((riscode) => {
if (riscode === tools.OK) {
// console.log(' -> eseguo $emit(loginOk)')
this.$emit('loginOk')
// GlobalStore.actions.createPushSubscription()
// .then((rissub) => {
// // ...
// })
// .catch((e) => {
// console.log('ERROR Subscription = ' + e)
// })
} else {
this.$emit('checkErrors', riscode)
}
this.iswaitingforRes = false
})
.catch((error) => {
// console.log('ERROR SIGNIN = ' + error)
this.$emit('checkErrors', error)
})
// console.log(' END submit')
}
}

View File

@@ -0,0 +1,74 @@
<template>
<div>
<div class="text-center">
<p>
<logo></logo>
</p>
</div>
<!--Prova URL : {{env('PROVA_PAOLO')}}-->
<form>
<div class="q-gutter-xs">
<q-input
v-model="signin.username"
rounded outlined
@blur="$v.signin.username.$touch"
:error="$v.signin.username.$error"
:error-message="`${errorMsg('username', $v.signin.username)}`"
:label="$t('reg.username_login')">
<template v-slot:prepend>
<q-icon name="person"/>
</template>
</q-input>
<q-input
v-model="signin.password"
type="password"
rounded outlined
@blur="$v.signin.password.$touch"
:error="$v.signin.password.$error"
:error-message="`${errorMsg('password', $v.signin.password)}`"
:label="$t('reg.password')">
<template v-slot:prepend>
<q-icon name="vpn_key"/>
</template>
</q-input>
<div>
<a :href="getlinkforgetpwd">{{$t('reg.forgetpassword')}}</a>
</div>
<br>
<q-card class="flex flex-center">
<!--<q-btn v-if="$myconfig.socialLogin.facebook" :loading="loading" class="q-mb-md q-mr-md" rounded icon="fab fa-facebook-f" size="sm" color="blue-10" text-color="white" @click="facebook" :label="$t('components.authentication.login.facebook')"/>-->
<!--
<q-btn v-if="$myconfig.socialLogin.facebook" class="q-mb-md q-mr-md" rounded icon="fab fa-facebook-f" size="sm" color="blue-10" text-color="white" @click="facebook" :label="$t('components.authentication.login.facebook')"/>
<q-btn v-if="$myconfig.socialLogin.google" class="q-mb-md q-mr-md" rounded icon="fab fa-google" size="sm" color="deep-orange-14" text-color="white" @click="google" :label="$t('components.authentication.login.google')"/>
-->
</q-card>
<div align="center">
<q-btn rounded size="lg" color="primary" @click="submit"
:disable="$v.$error || iswaitingforRes">{{$t('login.enter')}}
</q-btn>
</div>
<div align="center" style="margin-top:10px;">
<q-btn flat rounded size="lg" color="primary" to="/signup">{{$t('reg.submit')}}
</q-btn>
</div>
</div>
</form>
</div>
</template>
<script lang="ts" src="./CSignIn.ts">
</script>
<style lang="scss" scoped>
@import './CSignIn.scss';
</style>

View File

@@ -0,0 +1 @@
export {default as CSignIn} from './CSignIn.vue'

View File

@@ -0,0 +1,37 @@
import { ISignupOptions } from 'model'
import { email, minLength, required, sameAs } from 'vuelidate/lib/validators'
// import { ValidationRuleset } from 'vuelidate'
import { complexity, registeredemail, registereduser } from '../../validation'
export interface TSignup { signup: ISignupOptions, validationGroup: string[] }
export const validations = {
signup: {
repeatPassword: {
required,
sameAsPassword: sameAs('password')
},
password: {
complexity,
required
},
username: {
registereduser,
required
},
name: {
required
},
surname: {
required
},
email: {
email,
registeredemail,
required
},
terms: {
required
}
}
}

View File

@@ -0,0 +1,12 @@
.signup {
width: 100%;
margin: 0 auto;
max-width: 450px;
}
.wrapper {
display: flex;
align-items: center;
justify-content: center;
}

View File

@@ -0,0 +1,177 @@
import Vue from 'vue'
import { Component, Prop, Watch } from 'vue-property-decorator'
import { UserStore } from '@store'
import { tools } from '../../store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
import { ISignupOptions, IUserState } from 'model'
import { validations, TSignup } from './CSignUp-validate'
import { validationMixin } from 'vuelidate'
import { Logo } from '../../components/logo'
// import {Loading, QSpinnerFacebook, QSpinnerGears} from 'quasar'
@Component({
name: 'CSignUp',
mixins: [validationMixin],
validations,
components: { Logo }
})
export default class CSignUp extends Vue {
public $v
public $q
public $t: any
public duplicate_email: boolean = false
public duplicate_username: boolean = false
public signup: ISignupOptions = {
email: process.env.TEST_EMAIL || '',
username: process.env.TEST_USERNAME || '',
name: process.env.TEST_NAME || '',
surname: process.env.TEST_SURNAME || '',
password: process.env.TEST_PASSWORD || '',
repeatPassword: process.env.TEST_PASSWORD || '',
terms: !process.env.PROD
}
public created() {
this.$v.$reset()
}
public mounted() {
}
get allowSubmit() {
const error = this.$v.$error || this.$v.$invalid
return !error
}
/*
validations: {
isAsync: true,
form: {
email: {
required, email,
isUnique: value => {
if (value === '') return true;
return axios.get(process.env.MONGODB_HOST + '/email/' + value)
.then(res => {
return (res.status !== 200)
}).catch((e) => {
return true;
})
}
},
password: {required, minLength: minLength(8), maxLength: maxLength(20)},
username: {
required, minLength: minLength(6), maxLength: maxLength(20),
isUnique: value => {
if (value === '') return true;
return axios.get(process.env.MONGODB_HOST + '/users/' + value)
.then(res => {
return (res.status !== 200)
}).catch((e) => {
return true;
})
}
},
repeatPassword: {
sameAsPassword: sameAs('password')
},
terms: {required},
}
}, */
public env() {
return process.env
}
public errorMsg(cosa: string, item: any) {
try {
if (!item.$error) { return '' }
if (item.$params.email && !item.email) { return this.$t('reg.err.email') }
if (cosa === 'repeatpassword') {
if (!item.sameAsPassword) {
return this.$t('reg.err.sameaspassword')
}
}
if (!item.required) { return this.$t('reg.err.required') }
if (cosa === 'email') {
// console.log("EMAIL " + item.isUnique);
// console.log(item);
if (!item.isUnique) { return this.$t('reg.err.duplicate_email') }
} else if (cosa === 'username') {
// console.log(item);
if (!item.isUnique) { return this.$t('reg.err.duplicate_username') }
} else if ((cosa === 'name') || (cosa === 'surname')) {
// console.log(item);
}
if (!item.complexity) { return this.$t('reg.err.complexity') }
if (!item.minLength) { return this.$t('reg.err.atleast') + ` ${item.$params.minLength.min} ` + this.$t('reg.err.char') }
if (!item.maxLength) { return this.$t('reg.err.notmore') + ` ${item.$params.maxLength.max} ` + this.$t('reg.err.char') }
return ''
} catch (error) {
// console.log("ERR : " + error);
}
}
public SignUpcheckErrors(riscode: number) {
console.log('SignUpcheckErrors', riscode)
if (riscode === tools.DUPLICATE_EMAIL_ID) {
tools.showNotif(this.$q, this.$t('reg.err.duplicate_email'))
} else if (riscode === tools.DUPLICATE_USERNAME_ID) {
tools.showNotif(this.$q, this.$t('reg.err.duplicate_username'))
} else if (riscode === tools.ERR_SERVERFETCH) {
tools.showNotif(this.$q, this.$t('fetch.errore_server'))
} else if (riscode === tools.ERR_GENERICO) {
const msg = this.$t('fetch.errore_generico') + UserStore.mutations.getMsgError(riscode)
tools.showNotif(this.$q, msg)
} else if (riscode === tools.OK) {
this.$router.push('/signin')
tools.showNotif(this.$q, this.$t('components.authentication.email_verification.link_sent'), {color: 'warning', textColor: 'black'})
} else {
tools.showNotif(this.$q, 'Errore num ' + riscode)
}
}
public submitOk() {
this.$v.signup.$touch()
this.duplicate_email = false
this.duplicate_username = false
if (!this.signup.terms) {
tools.showNotif(this.$q, this.$t('reg.err.terms'))
return
}
if (this.$v.signup.$error) {
tools.showNotif(this.$q, this.$t('reg.err.errore_generico'))
return
}
this.$q.loading.show({ message: this.$t('reg.incorso') })
console.log(this.signup)
UserStore.actions.signup(this.signup)
.then((riscode) => {
tools.SignUpcheckErrors(this, riscode)
this.$q.loading.hide()
}).catch((error) => {
console.log('ERROR = ' + error)
this.$q.loading.hide()
})
}
}

View File

@@ -0,0 +1,144 @@
<template>
<div>
<div class="text-center">
<p>
<logo></logo>
</p>
</div>
<!--Prova URL : {{env('PROVA_PAOLO')}}-->
<div class="q-gutter-xs">
<q-input
v-model="signup.email"
rounded outlined
@blur="$v.signup.email.$touch"
:error="$v.signup.email.$error"
:error-message="errorMsg('email', $v.signup.email)"
bottom-slots
debounce="1000"
:label="$t('reg.email')">
<template v-slot:prepend>
<q-icon name="email"/>
</template>
</q-input>
<q-input
v-model="signup.username"
rounded outlined
@blur="$v.signup.username.$touch"
:error="$v.signup.username.$error"
bottom-slots
debounce="1000"
:error-message="errorMsg('username', $v.signup.username)"
:label="$t('reg.username')">
<template v-slot:prepend>
<q-icon name="person"/>
</template>
</q-input>
<q-input
v-model="signup.name"
rounded outlined
@blur="$v.signup.name.$touch"
:error="$v.signup.name.$error"
bottom-slots
debounce="1000"
:error-message="errorMsg('name', $v.signup.name)"
:label="$t('reg.name')">
<template v-slot:prepend>
<q-icon name="person"/>
</template>
</q-input>
<q-input
v-model="signup.surname"
rounded outlined
@blur="$v.signup.surname.$touch"
:error="$v.signup.surname.$error"
bottom-slots
debounce="1000"
:error-message="errorMsg('surname', $v.signup.surname)"
:label="$t('reg.surname')">
<template v-slot:prepend>
<q-icon name="person"/>
</template>
</q-input>
<q-input
v-model="signup.password"
type="password"
rounded outlined
@blur="$v.signup.password.$touch"
:error="$v.signup.password.$error"
:error-message="`${errorMsg('password', $v.signup.password)}`"
bottom-slots
:label="$t('reg.password')">
<template v-slot:prepend>
<q-icon name="vpn_key"/>
</template>
</q-input>
<q-input
v-model="signup.repeatPassword"
type="password"
rounded outlined
@blur="$v.signup.repeatPassword.$touch"
:error="$v.signup.repeatPassword.$error"
:error-message="`${errorMsg('repeatpassword', $v.signup.repeatPassword)}`"
bottom-slots
:label="$t('reg.repeatPassword')">
<template v-slot:prepend>
<q-icon name="vpn_key"/>
</template>
</q-input>
<!--:hint="$t('reg.tips.repeatpassword')"-->
<q-checkbox
v-model="signup.terms"
color="secondary"
@blur="$v.signup.terms.$touch"
:error="$v.signup.terms.$error"
:error-message="`${errorMsg('terms', $v.signup.terms)}`"
:label="$t('reg.terms')">
</q-checkbox>
<br>
<div class="wrapper">
<q-btn rounded size="lg" color="positive" @click="submitOk" :disabled='!allowSubmit'>
{{$t('reg.submit')}}
</q-btn>
</div>
</div>
<!--
<div align="center">
<q-btn rounded size="lg" color="primary" @click="submitOk" :disable="">{{$t('reg.submit')}}
</q-btn>
</div>
-->
</div>
</template>
<script lang="ts" src="./CSignUp.ts">
</script>
<style lang="scss" scoped>
@import './CSignUp.scss';
</style>

View File

@@ -0,0 +1 @@
export {default as CSignUp} from './CSignUp.vue'

View File

@@ -295,3 +295,4 @@ canvas {
margin: 1px; margin: 1px;
margin-bottom: 5px; margin-bottom: 5px;
} }

View File

@@ -3,6 +3,7 @@ import Component from 'vue-class-component'
import drawer from '../../layouts/drawer/drawer.vue' import drawer from '../../layouts/drawer/drawer.vue'
import messagePopover from '../../layouts/toolbar/messagePopover/messagePopover.vue' import messagePopover from '../../layouts/toolbar/messagePopover/messagePopover.vue'
import { CSignIn } from '../../components/CSignIn'
import { GlobalStore, UserStore } from '@modules' import { GlobalStore, UserStore } from '@modules'
// import { StateConnection } from '../../model' // import { StateConnection } from '../../model'
@@ -12,12 +13,13 @@ import { toolsext } from '@src/store/Modules/toolsext'
import Quasar, { Screen } from 'quasar' import Quasar, { Screen } from 'quasar'
import { static_data } from '../../db/static_data' import { static_data } from '../../db/static_data'
import globalroutines from '../../globalroutines'
@Component({ @Component({
name: 'Header', name: 'Header',
components: { components: {
drawer, drawer,
messagePopover messagePopover, CSignIn
} }
}) })
@@ -330,11 +332,11 @@ export default class Header extends Vue {
public logoutHandler() { public logoutHandler() {
UserStore.actions.logout() UserStore.actions.logout()
.then(() => { .then(() => {
this.$router.replace('/logout') // this.$router.replace('/logout')
//
setTimeout(() => { // setTimeout(() => {
this.$router.replace('/') // this.$router.replace('/')
}, 1000) // }, 1000)
tools.showNotif(this.$q, this.$t('logout.uscito'), {icon: 'exit_to_app'}) tools.showNotif(this.$q, this.$t('logout.uscito'), {icon: 'exit_to_app'})
}) })
@@ -347,4 +349,33 @@ export default class Header extends Vue {
get isLogged() { get isLogged() {
return UserStore.state.isLogged return UserStore.state.isLogged
} }
get isVerified() {
return UserStore.state.verified_email
}
public loginOk() {
tools.loginOk(this, false)
}
public loginInCorso() {
tools.loginInCorso(this)
}
public checkErrors(riscode) {
tools.SignIncheckErrors(this, riscode)
}
public showNotif(msgcode) {
tools.showNotif(this.$q, this.$t(msgcode))
}
public mythis() {
return this
}
public clickregister() {
this.right = false
this.$router.replace('/signup')
}
} }

View File

@@ -132,27 +132,46 @@
<div id="profile"> <div id="profile">
<q-img class="absolute-top" src="../../statics/images/landing_first_section.png" <q-img class="absolute-top" src="../../statics/images/landing_first_section.png"
style="height: 150px"> style="height: 150px">
<div class="absolute-bottom bg-transparent text-black center_img">
<q-avatar class="q-mb-sm center_img">
<img src="../../statics/images/avatar-1.svg">
</q-avatar>
<q-btn class="absolute-top-right" style="margin-top: 9px; margin-right: 12px; color: white;" dense flat round icon="close" @click="right = !right">
</q-btn>
<div v-if="Username" class="text-weight-bold text-user">{{ Username }} - {{ myName }}</div>
<div v-else class="text-italic">{{ $t('user.loggati') }}</div>
<!--<span class="text-white" v-if="Verificato"> {{$t('reg.verificato')}} </span>-->
<!--<span class="text-white background-red" v-else> {{$t('reg.non_verificato')}} </span>-->
<div v-if="Username" id="user-actions">
<q-btn round color="primary" icon="person"></q-btn>
<q-btn round color="warning" icon="lock"></q-btn>
<q-btn round color="secondary" icon="exit_to_app" @click='logoutHandler'></q-btn>
</div>
</div>
</q-img> </q-img>
<div class="absolute-top bg-transparent text-black center_img" style="margin-top: 10px;">
<q-avatar class="q-mb-sm center_img">
<img src="../../statics/images/avatar-1.svg">
</q-avatar>
<q-btn class="absolute-top-right" style="margin-right: 10px; color: white;"
dense flat round icon="close" @click="right = !right">
</q-btn>
<div v-if="isLogged" class="text-weight-bold text-user">{{ Username }} - {{ myName }} <span v-if="isAdmin"> [Admin]</span></div>
<div v-else class="text-user text-italic bg-red">
{{ $t('user.loggati') }}
</div>
<div v-if="isLogged && !isVerified" class="text-verified">{{
$t('components.authentication.email_verification.verify_email') }}
</div>
<!--<span class="text-white" v-if="Verificato"> {{$t('reg.verificato')}} </span>-->
<!--<span class="text-white background-red" v-else> {{$t('reg.non_verificato')}} </span>-->
<div v-if="isLogged" id="user-actions" class="text-center">
<q-btn round color="primary" icon="person"></q-btn>
<q-btn round color="warning" icon="lock"></q-btn>
<q-btn round color="secondary" icon="exit_to_app" @click='logoutHandler'></q-btn>
</div>
</div>
<div style="margin-top:120px;"></div>
<div v-show="!isLogged">
<div class="q-ma-md" style="">
<CSignIn :mythis="mythis"
@loginOk="loginOk"
@loginInCorso="loginInCorso"
@checkErrors="checkErrors"
@showNotif="showNotif">
</CSignIn>
</div>
</div>
</div> </div>
</q-drawer> </q-drawer>

View File

@@ -9,7 +9,11 @@ export * from './CTitle'
export * from './CImgText' export * from './CImgText'
export * from './CImgTitle' export * from './CImgTitle'
export * from './CPreloadImages' export * from './CPreloadImages'
export * from './CSignIn'
export * from './CSignUp'
export * from './CEventsCalendar'
export * from './CDate' export * from './CDate'
export * from './BannerCookies' export * from './BannerCookies'
export * from './PagePolicy' export * from './PagePolicy'
export * from './FormNewsletter' export * from './FormNewsletter'
export * from './CGridTableRec'

View File

@@ -17,7 +17,6 @@
} }
#profile { #profile {
height: 130px;
background-color: #009688; background-color: #009688;
} }

View File

@@ -64,5 +64,4 @@ export default class MenuOne extends Vue {
} }
} }
} }

View File

@@ -23,6 +23,8 @@ export interface IEvents {
} }
export interface IBookedEvent { export interface IBookedEvent {
_id?: any
userId: string
id_bookedevent?: any id_bookedevent?: any
numpeople: number numpeople: number
infoevent: string infoevent: string

View File

@@ -200,3 +200,4 @@ export interface IFunctionality {
SHOW_ONLY_POLICY?: boolean SHOW_ONLY_POLICY?: boolean
BOOKING_EVENTS?: boolean BOOKING_EVENTS?: boolean
} }

View File

@@ -31,4 +31,12 @@ export interface IUserState {
x_auth_token?: string x_auth_token?: string
isLogged?: boolean isLogged?: boolean
isAdmin?: boolean isAdmin?: boolean
usersList?: IUserList[]
}
export interface IUserList {
_id: string
username: string
name?: string
surname?: string
} }

View File

@@ -1,5 +1,3 @@
import { IBookingState } from '@src/model/BookingStore'
export * from './UserStore' export * from './UserStore'
export * from './GlobalStore' export * from './GlobalStore'
export * from './signin-option' export * from './signin-option'
@@ -13,4 +11,3 @@ export * from './Projects'
export * from './Calendar' export * from './Calendar'
export * from './Estimate' export * from './Estimate'
export * from './BookingStore'

View File

@@ -2,6 +2,17 @@ import msg_website from '../db/i18n_website'
const msgglobal = { const msgglobal = {
it: { it: {
otherpages: {
admin : {
menu: 'Amministrazione',
eventlist: 'Prenotazioni',
usereventlist: 'Prenotazioni Utenti',
userlist: 'Lista Utenti',
},
},
sendmsg: {
write: 'scrive'
},
dialog: { dialog: {
ok: 'Ok', ok: 'Ok',
yes: 'Si', yes: 'Si',
@@ -11,6 +22,7 @@ const msgglobal = {
update: 'Aggiorna', update: 'Aggiorna',
today: 'Oggi', today: 'Oggi',
book: 'Prenota', book: 'Prenota',
sendmsg: 'Invia Msg',
msg: { msg: {
titledeleteTask: 'Elimina Task', titledeleteTask: 'Elimina Task',
deleteTask: "Vuoi Eliminare {mytodo}?" deleteTask: "Vuoi Eliminare {mytodo}?"
@@ -19,6 +31,10 @@ const msgglobal = {
comp: { comp: {
Conta: "Conta", Conta: "Conta",
}, },
db: {
recupdated: 'Record Aggiornato',
recfailed: 'Errore durante aggiornamento Record'
},
components: { components: {
authentication: { authentication: {
login: { login: {
@@ -50,6 +66,8 @@ const msgglobal = {
incorso: 'Registrazione in corso...', incorso: 'Registrazione in corso...',
richiesto: 'Campo Richiesto', richiesto: 'Campo Richiesto',
email: 'Email', email: 'Email',
date_reg: 'Data Reg.',
perm: 'Permessi',
username: 'Nome Utente', username: 'Nome Utente',
name: 'Nome', name: 'Nome',
surname: 'Cognome', surname: 'Cognome',
@@ -178,9 +196,13 @@ const msgglobal = {
eventstartdatetime: 'Data e Ora Inizio Evento', eventstartdatetime: 'Data e Ora Inizio Evento',
enterEndDateTime: 'Data e Ora Fine Evento', enterEndDateTime: 'Data e Ora Fine Evento',
selnumpeople: 'Partecipanti', selnumpeople: 'Partecipanti',
selnumpeople_short: 'Num',
msgbooking: 'Messaggio da inviare', msgbooking: 'Messaggio da inviare',
showinfo: 'Vedi Info',
bookingtextdefault: 'Mi prenoto all\'evento', bookingtextdefault: 'Mi prenoto all\'evento',
bookingtextdefault_of: 'di' bookingtextdefault_of: 'di',
data: 'Data',
teachertitle: 'Insegnante',
}, },
newsletter: { newsletter: {
title: 'Desideri ricevere la nostra Newsletter?', title: 'Desideri ricevere la nostra Newsletter?',
@@ -200,6 +222,17 @@ const msgglobal = {
cookies: 'Usiamo i Cookie per una migliore prestazione web.' cookies: 'Usiamo i Cookie per una migliore prestazione web.'
}, },
es: { es: {
otherpages: {
admin : {
menu: 'Administración',
eventlist: 'Reserva',
usereventlist: 'Reserva Usuarios',
userlist: 'Lista de usuarios',
},
},
sendmsg: {
write: 'escribe'
},
dialog: { dialog: {
ok: 'Vale', ok: 'Vale',
yes: 'Sí', yes: 'Sí',
@@ -209,6 +242,7 @@ const msgglobal = {
update: 'Actualiza', update: 'Actualiza',
today: 'Hoy', today: 'Hoy',
book: 'Reserva', book: 'Reserva',
sendmsg: 'Envia Mensaje',
msg: { msg: {
titledeleteTask: 'Borrar Tarea', titledeleteTask: 'Borrar Tarea',
deleteTask: 'Quieres borrar {mytodo}?' deleteTask: 'Quieres borrar {mytodo}?'
@@ -217,6 +251,10 @@ const msgglobal = {
comp: { comp: {
Conta: "Conta", Conta: "Conta",
}, },
db: {
recupdated: 'Registro Actualizado',
recfailed: 'Error durante el registro de actualización'
},
components: { components: {
authentication: { authentication: {
login: { login: {
@@ -248,6 +286,8 @@ const msgglobal = {
incorso: 'Registro en curso...', incorso: 'Registro en curso...',
richiesto: 'Campo requerido', richiesto: 'Campo requerido',
email: 'Email', email: 'Email',
date_reg: 'Fecha Reg.',
perm: 'Permisos',
username: 'Nombre usuario', username: 'Nombre usuario',
name: 'Nombre', name: 'Nombre',
surname: 'Apellido', surname: 'Apellido',
@@ -370,9 +410,13 @@ const msgglobal = {
eventstartdatetime: 'Evento de inicio de fecha y hora', eventstartdatetime: 'Evento de inicio de fecha y hora',
enterEndDateTime: 'Fecha y hora del evento final', enterEndDateTime: 'Fecha y hora del evento final',
selnumpeople: 'Partecipantes', selnumpeople: 'Partecipantes',
selnumpeople_short: 'Num',
msgbooking: 'Mensaje para enviar', msgbooking: 'Mensaje para enviar',
showinfo: 'Ver Info',
bookingtextdefault: 'Reservo el evento', bookingtextdefault: 'Reservo el evento',
bookingtextdefault_of: 'de', bookingtextdefault_of: 'de',
data: 'Fecha',
teachertitle: 'Maestro',
}, },
newsletter: { newsletter: {
title: '¿Desea recibir nuestro boletín informativo?', title: '¿Desea recibir nuestro boletín informativo?',
@@ -392,6 +436,17 @@ const msgglobal = {
cookies: 'Utilizamos cookies para un mejor rendimiento web.' cookies: 'Utilizamos cookies para un mejor rendimiento web.'
}, },
fr: { fr: {
otherpages: {
admin : {
menu: 'Administration',
eventlist: 'Réservation',
usereventlist: 'Réservation Utilisateur',
userlist: 'Liste d\'utilisateurs',
},
},
sendmsg: {
write: 'écrit'
},
dialog: { dialog: {
ok: 'Bien', ok: 'Bien',
yes: 'Oui', yes: 'Oui',
@@ -401,6 +456,7 @@ const msgglobal = {
cancel: 'annuler', cancel: 'annuler',
today: 'Aujourd\'hui', today: 'Aujourd\'hui',
book: 'Réserve', book: 'Réserve',
sendmsg: 'Envoyer Msg',
msg: { msg: {
titledeleteTask: 'Supprimer la tâche', titledeleteTask: 'Supprimer la tâche',
deleteTask: 'Voulez-vous supprimer {mytodo}?' deleteTask: 'Voulez-vous supprimer {mytodo}?'
@@ -409,6 +465,10 @@ const msgglobal = {
comp: { comp: {
Conta: "Conta", Conta: "Conta",
}, },
db: {
recupdated: 'Enregistrement mis à jour',
recfailed: 'Erreur lors de la mise à jour'
},
components: { components: {
authentication: { authentication: {
login: { login: {
@@ -439,6 +499,8 @@ const msgglobal = {
incorso: 'Inscription en cours...', incorso: 'Inscription en cours...',
richiesto: 'Champ obligatoire', richiesto: 'Champ obligatoire',
email: 'Email', email: 'Email',
date_reg: 'Date Inscript.',
perm: 'Autorisations',
username: 'Nom d\'utilisateur', username: 'Nom d\'utilisateur',
name: 'Nom', name: 'Nom',
surname: 'Prénom', surname: 'Prénom',
@@ -561,9 +623,13 @@ const msgglobal = {
eventstartdatetime: 'Date de début et heure de l\'événement', eventstartdatetime: 'Date de début et heure de l\'événement',
enterEndDateTime: 'Date et heure de l\'événement final', enterEndDateTime: 'Date et heure de l\'événement final',
selnumpeople: 'Participants', selnumpeople: 'Participants',
selnumpeople_short: 'Num',
msgbooking: 'Message à envoyer', msgbooking: 'Message à envoyer',
showinfo: 'Voir Info',
bookingtextdefault: 'Je réserve l\'événement', bookingtextdefault: 'Je réserve l\'événement',
bookingtextdefault_of: 'du', bookingtextdefault_of: 'du',
data: 'Date',
teachertitle: 'Professeur',
}, },
newsletter: { newsletter: {
title: 'Souhaitez-vous recevoir notre newsletter?', title: 'Souhaitez-vous recevoir notre newsletter?',
@@ -583,6 +649,17 @@ const msgglobal = {
cookies: 'Nous utilisons des cookies pour améliorer les performances Web.' cookies: 'Nous utilisons des cookies pour améliorer les performances Web.'
}, },
enUs: { enUs: {
otherpages: {
admin : {
menu: 'Administration',
eventlist: 'Booking',
usereventlist: 'Users Booking',
userlist: 'Users List',
},
},
sendmsg: {
write: 'write'
},
dialog: { dialog: {
ok: 'Ok', ok: 'Ok',
yes: 'Yes', yes: 'Yes',
@@ -592,6 +669,7 @@ const msgglobal = {
cancel: 'Cancel', cancel: 'Cancel',
today: 'Today', today: 'Today',
book: 'Book', book: 'Book',
sendmsg: 'Send Msg',
msg: { msg: {
titledeleteTask: 'Delete Task', titledeleteTask: 'Delete Task',
deleteTask: 'Delete Task {mytodo}?' deleteTask: 'Delete Task {mytodo}?'
@@ -600,6 +678,10 @@ const msgglobal = {
comp: { comp: {
Conta: "Count", Conta: "Count",
}, },
db: {
recupdated: 'Record Updated',
recfailed: 'Error during update Record'
},
components: { components: {
authentication: { authentication: {
login: { login: {
@@ -630,6 +712,8 @@ const msgglobal = {
incorso: 'Registration please wait...', incorso: 'Registration please wait...',
richiesto: 'Field Required', richiesto: 'Field Required',
email: 'Email', email: 'Email',
date_reg: 'Reg. Date',
perm: 'Permissions',
username_login: 'Username or email', username_login: 'Username or email',
username: 'Username', username: 'Username',
name: 'Name', name: 'Name',
@@ -751,9 +835,13 @@ const msgglobal = {
eventstartdatetime: 'Event start date and time', eventstartdatetime: 'Event start date and time',
enterEndDateTime: 'Event end date and time', enterEndDateTime: 'Event end date and time',
selnumpeople: 'Participants', selnumpeople: 'Participants',
selnumpeople_short: 'Num',
msgbooking: 'Message to send', msgbooking: 'Message to send',
showinfo: 'Show Info',
bookingtextdefault: 'I book the event', bookingtextdefault: 'I book the event',
bookingtextdefault_of: 'of', bookingtextdefault_of: 'of',
data: 'Date',
teachertitle: 'Teacher',
}, },
newsletter: { newsletter: {
title: 'Would you like to receive our Newsletter?', title: 'Would you like to receive our Newsletter?',
@@ -773,6 +861,17 @@ const msgglobal = {
cookies: 'We use cookies for better web performance.' cookies: 'We use cookies for better web performance.'
}, },
de: { de: {
otherpages: {
admin : {
menu: 'Administration',
eventlist: 'Booking',
usereventlist: 'Users Booking',
userlist: 'Users List',
},
},
sendmsg: {
write: 'write'
},
dialog: { dialog: {
ok: 'Ok', ok: 'Ok',
yes: 'Yes', yes: 'Yes',
@@ -782,6 +881,7 @@ const msgglobal = {
cancel: 'Cancel', cancel: 'Cancel',
today: 'Today', today: 'Today',
book: 'Book', book: 'Book',
sendmsg: 'Send Msg',
msg: { msg: {
titledeleteTask: 'Delete Task', titledeleteTask: 'Delete Task',
deleteTask: 'Delete Task {mytodo}?' deleteTask: 'Delete Task {mytodo}?'
@@ -790,6 +890,10 @@ const msgglobal = {
comp: { comp: {
Conta: "Count", Conta: "Count",
}, },
db: {
recupdated: 'Record Updated',
recfailed: 'Error during update Record'
},
components: { components: {
authentication: { authentication: {
login: { login: {
@@ -821,6 +925,8 @@ const msgglobal = {
incorso: 'Registration please wait...', incorso: 'Registration please wait...',
richiesto: 'Field Required', richiesto: 'Field Required',
email: 'Email', email: 'Email',
date_reg: 'Reg. Date',
perm: 'Permissions',
username_login: 'Username or email', username_login: 'Username or email',
username: 'Username', username: 'Username',
name: 'Name', name: 'Name',
@@ -943,9 +1049,13 @@ const msgglobal = {
eventstartdatetime: 'Event start date and time', eventstartdatetime: 'Event start date and time',
enterEndDateTime: 'Event end date and time', enterEndDateTime: 'Event end date and time',
selnumpeople: 'Participants', selnumpeople: 'Participants',
selnumpeople_short: 'Num',
msgbooking: 'Message to send', msgbooking: 'Message to send',
showinfo: 'Show Info',
bookingtextdefault: 'I book the event', bookingtextdefault: 'I book the event',
bookingtextdefault_of: 'of', bookingtextdefault_of: 'of',
data: 'Date',
teachertitle: 'Teacher',
}, },
newsletter: { newsletter: {
title: 'Would you like to receive our Newsletter?', title: 'Would you like to receive our Newsletter?',

View File

@@ -1,65 +0,0 @@
import { ICfgServer, IConfig, IBookingState, IListRoutes, IMenuList, StateConnection } from 'model'
import { storeBuilder } from './Store/Store'
import Vue from 'vue'
import translate from './../../globalroutines/util'
import urlBase64ToUint8Array from '../../js/utility'
import Api from '@api'
import * as Types from '@src/store/Api/ApiTypes'
import { costanti } from '@src/store/Modules/costanti'
import { tools } from '@src/store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
import { GlobalStore, Projects, Todos, UserStore } from '@store'
import { static_data } from '@src/db/static_data'
import { db_data } from '@src/db/db_data'
import { IEvents } from '../../model'
import { serv_constants } from '@src/store/Modules/serv_constants'
const state: IBookingState = {
bookinglist: []
}
const b = storeBuilder.module<IBookingState>('BookingModule', state)
// Getters
namespace Getters {
export const getters = {
}
}
namespace Mutations {
export const mutations = {
}
}
namespace Actions {
async function loadAfterLogin(context) {
return true
}
export const actions = {
loadAfterLogin: b.dispatch(loadAfterLogin)
}
}
const stateGetter = b.state()
// Module
const BookingModule = {
get state() {
return stateGetter()
},
actions: Actions.actions,
getters: Getters.getters,
mutations: Mutations.mutations
}
export default BookingModule

View File

@@ -19,6 +19,7 @@ import globalroutines from './../../globalroutines/index'
import { cfgrouter } from '../../router/route-config' import { cfgrouter } from '../../router/route-config'
import { static_data } from '@src/db/static_data'
// import { static_data } from '@src/db/static_data' // import { static_data } from '@src/db/static_data'
let stateConnDefault = 'online' let stateConnDefault = 'online'
@@ -285,6 +286,7 @@ namespace Actions {
} }
function createPushSubscription(context) { function createPushSubscription(context) {
console.log('createPushSubscription')
// If Already subscribed, don't send to the Server DB // If Already subscribed, don't send to the Server DB
// if (state.wasAlreadySubOnDb) { // if (state.wasAlreadySubOnDb) {
@@ -296,6 +298,9 @@ namespace Actions {
// return // return
// } // }
if (!static_data.functionality.PWA)
return
if (!('serviceWorker' in navigator)) { if (!('serviceWorker' in navigator)) {
return return
} }
@@ -417,23 +422,25 @@ namespace Actions {
await globalroutines(null, 'clearalldata', table, null) await globalroutines(null, 'clearalldata', table, null)
} }
if ('serviceWorker' in navigator) { if (static_data.functionality.PWA) {
// REMOVE ALL SUBSCRIPTION if ('serviceWorker' in navigator) {
console.log('REMOVE ALL SUBSCRIPTION...') // REMOVE ALL SUBSCRIPTION
await navigator.serviceWorker.ready.then((reg) => { console.log('REMOVE ALL SUBSCRIPTION...')
console.log('... Ready') await navigator.serviceWorker.ready.then((reg) => {
reg.pushManager.getSubscription().then((subscription) => { console.log('... Ready')
console.log(' Found Subscription...') reg.pushManager.getSubscription().then((subscription) => {
if (subscription) { console.log(' Found Subscription...')
subscription.unsubscribe().then((successful) => { if (subscription) {
// You've successfully unsubscribed subscription.unsubscribe().then((successful) => {
console.log('You\'ve successfully unsubscribed') // You've successfully unsubscribed
}).catch((e) => { console.log('You\'ve successfully unsubscribed')
// Unsubscription failed }).catch((e) => {
}) // Unsubscription failed
} })
}
})
}) })
}) }
} }
await deleteSubscriptionToServer(context) await deleteSubscriptionToServer(context)
@@ -473,10 +480,15 @@ namespace Actions {
.then((res) => { .then((res) => {
state.networkDataReceived = true state.networkDataReceived = true
console.log('******* checkUpdates RES :', res.data.cfgServer) // console.log('******* checkUpdates RES :', res.data.cfgServer)
if (res.data.cfgServer) { if (res.data.cfgServer) {
state.cfgServer = [...res.data.cfgServer] state.cfgServer = [...res.data.cfgServer]
console.log('res.data.cfgServer', res.data.cfgServer) // console.log('res.data.cfgServer', res.data.cfgServer)
}
// console.log('res.data.userslist', res.data.usersList)
if (res.data.usersList) {
UserStore.mutations.setusersList(res.data.usersList)
} }
// console.log('********** res', 'state.todos', state.todos, 'checkPending', checkPending) // console.log('********** res', 'state.todos', state.todos, 'checkPending', checkPending)

View File

@@ -10,6 +10,7 @@ import translate from '../../../../globalroutines/util'
import * as Types from '../../../Api/ApiTypes' import * as Types from '../../../Api/ApiTypes'
import { db_data } from '@src/db/db_data' import { db_data } from '@src/db/db_data'
import { UserStore } from '@store' import { UserStore } from '@store'
import { lists } from '@src/store/Modules/lists'
// State // State
const state: ICalendarState = { const state: ICalendarState = {
@@ -46,12 +47,30 @@ const stateGetter = b.state()
namespace Getters { namespace Getters {
const findEventBooked = b.read((mystate: ICalendarState) => (myevent: IEvents, isconfirmed: boolean) => { const findEventBooked = b.read((mystate: ICalendarState) => (myevent: IEvents, isconfirmed: boolean) => {
return mystate.bookedevent.find((bookedevent) => (bookedevent.id_bookedevent === myevent._id) && ((isconfirmed && bookedevent.booked) || (!isconfirmed))) return mystate.bookedevent.find((bookedevent) => (bookedevent.id_bookedevent === myevent._id) && (bookedevent.userId === UserStore.state.userId) && ((isconfirmed && bookedevent.booked) || (!isconfirmed)))
}, 'findEventBooked') }, 'findEventBooked')
const getNumParticipants = b.read((mystate: ICalendarState) => (myevent: IEvents, showall) => {
const myarr = mystate.bookedevent.filter((bookedevent) => (bookedevent.id_bookedevent === myevent._id) && (bookedevent.booked) && (showall || (!showall && bookedevent.userId === UserStore.state.userId) ))
if (myarr)
return myarr.reduce((sum, bookedevent) => sum + bookedevent.numpeople, 0)
else
return 0
}, 'getNumParticipants')
const getEventsBookedByIdEvent = b.read((mystate: ICalendarState) => (idevent, showall) => {
return mystate.bookedevent.filter((bookedevent) => (bookedevent.id_bookedevent === idevent) && (bookedevent.booked) && (showall || (!showall && bookedevent.userId === UserStore.state.userId) ))
}, 'getEventsBookedByIdEvent')
export const getters = { export const getters = {
get findEventBooked() { get findEventBooked() {
return findEventBooked() return findEventBooked()
},
get getNumParticipants() {
return getNumParticipants()
},
get getEventsBookedByIdEvent() {
return getEventsBookedByIdEvent()
} }
} }
@@ -70,7 +89,7 @@ namespace Mutations {
namespace Actions { namespace Actions {
async function loadAfterLogin(context) { async function loadAfterLogin(context) {
console.log('CalendarStore: loadAfterLogin') // console.log('CalendarStore: loadAfterLogin')
// Load local data // Load local data
state.editable = db_data.userdata.calendar_editable state.editable = db_data.userdata.calendar_editable
state.eventlist = db_data.events state.eventlist = db_data.events
@@ -82,11 +101,13 @@ namespace Actions {
} }
// Load local data // Load local data
console.log('CALENDAR loadAfterLogin', 'userid=', UserStore.state.userId) // console.log('CALENDAR loadAfterLogin', 'userid=', UserStore.state.userId)
let ris = null let ris = null
ris = await Api.SendReq('/booking/' + UserStore.state.userId + '/' + process.env.APP_ID, 'GET', null) const showall = UserStore.state.isAdmin ? '1' : '0'
ris = await Api.SendReq('/booking/' + UserStore.state.userId + '/' + process.env.APP_ID + '/' + showall, 'GET', null)
.then((res) => { .then((res) => {
if (res.data.bookedevent) { if (res.data.bookedevent) {
state.bookedevent = res.data.bookedevent state.bookedevent = res.data.bookedevent
@@ -106,6 +127,7 @@ namespace Actions {
function getparambyevent(bookevent) { function getparambyevent(bookevent) {
return { return {
_id: bookevent._id,
id_bookedevent: bookevent.id_bookedevent, id_bookedevent: bookevent.id_bookedevent,
infoevent: bookevent.infoevent, infoevent: bookevent.infoevent,
numpeople: bookevent.numpeople, numpeople: bookevent.numpeople,
@@ -113,7 +135,7 @@ namespace Actions {
datebooked: bookevent.datebooked, datebooked: bookevent.datebooked,
userId: UserStore.state.userId, userId: UserStore.state.userId,
booked: bookevent.booked, booked: bookevent.booked,
modified: bookevent.modified, modified: bookevent.modified
} }
} }
@@ -126,6 +148,7 @@ namespace Actions {
.then((res) => { .then((res) => {
if (res.status === 200) { if (res.status === 200) {
if (res.data.code === serv_constants.RIS_CODE_OK) { if (res.data.code === serv_constants.RIS_CODE_OK) {
bookevent._id = res.data.id
if (bookevent.modified) { if (bookevent.modified) {
const foundIndex = state.bookedevent.findIndex((x) => x.id_bookedevent === bookevent.id_bookedevent) const foundIndex = state.bookedevent.findIndex((x) => x.id_bookedevent === bookevent.id_bookedevent)
@@ -147,20 +170,16 @@ namespace Actions {
} }
async function CancelBookingEvent(context, event: IEvents) { async function CancelBookingEvent(context, { ideventbook, notify }) {
console.log('CALSTORE: CancelBookingEvent', event) console.log('CALSTORE: CancelBookingEvent', ideventbook, notify)
const myeventtoCancel = state.bookedevent.find((eventbooked) => (eventbooked.id_bookedevent === event._id)) return await Api.SendReq('/booking/' + ideventbook + '/' + notify + '/' + process.env.APP_ID, 'DELETE', null)
const param = getparambyevent(myeventtoCancel)
param.booked = false // Cancel Booking
return await Api.SendReq('/booking', 'POST', param)
.then((res) => { .then((res) => {
if (res.status === 200) { if (res.status === 200) {
if (res.data.code === serv_constants.RIS_CODE_OK) { if (res.data.code === serv_constants.RIS_CODE_OK) {
state.bookedevent = state.bookedevent.filter((eventbooked) => (eventbooked.id_bookedevent !== event._id)) // Remove this record from my list
state.bookedevent = state.bookedevent.filter((eventbooked) => (eventbooked._id !== ideventbook))
return true return true
} }
@@ -173,8 +192,6 @@ namespace Actions {
// UserStore.mutations.setErrorCatch(error) // UserStore.mutations.setErrorCatch(error)
return false return false
}) })
} }
export const actions = { export const actions = {

View File

@@ -1,5 +1,5 @@
import Api from '@api' import Api from '@api'
import { ISignupOptions, ISigninOptions, IUserState } from 'model' import { ISignupOptions, ISigninOptions, IUserState, IUserList } from 'model'
import { ILinkReg, IResult, IIdToken, IToken } from 'model/other' import { ILinkReg, IResult, IIdToken, IToken } from 'model/other'
import { storeBuilder } from './Store/Store' import { storeBuilder } from './Store/Store'
import router from '@router' import router from '@router'
@@ -7,13 +7,15 @@ import router from '@router'
import { serv_constants } from '../Modules/serv_constants' import { serv_constants } from '../Modules/serv_constants'
import { tools } from '../Modules/tools' import { tools } from '../Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext' import { toolsext } from '@src/store/Modules/toolsext'
import { GlobalStore, UserStore, Todos, Projects, BookingStore, CalendarStore } from '@store' import { GlobalStore, UserStore, Todos, Projects, CalendarStore } from '@store'
import globalroutines from './../../globalroutines/index' import globalroutines from './../../globalroutines/index'
import { static_data } from '@src/db/static_data' import { static_data } from '@src/db/static_data'
import { db_data } from '@src/db/db_data'
import translate from './../../globalroutines/util' import translate from './../../globalroutines/util'
import * as Types from '@src/store/Api/ApiTypes' import * as Types from '@src/store/Api/ApiTypes'
import { ICfgServer } from '@src/model'
const bcrypt = require('bcryptjs') const bcrypt = require('bcryptjs')
@@ -33,7 +35,8 @@ const state: IUserState = {
servercode: 0, servercode: 0,
x_auth_token: '', x_auth_token: '',
isLogged: false, isLogged: false,
isAdmin: false isAdmin: false,
usersList: []
} }
const b = storeBuilder.module<IUserState>('UserModule', state) const b = storeBuilder.module<IUserState>('UserModule', state)
@@ -81,6 +84,18 @@ namespace Getters {
return state.servercode return state.servercode
}, 'getServerCode') }, 'getServerCode')
const getNameSurnameByUserId = b.read((state: IUserState) => (userId: string) => {
const user = UserStore.getters.getUserByUserId(userId)
if (user)
return user.name + ' ' + user.surname
else
return '(' + userId + ')'
}, 'getNameSurnameByUserId')
const getUsersList = b.read((mystate: IUserState) => {
return mystate.usersList
}, 'getUsersList')
const IsMyFriend = b.read((state) => (userIdOwner) => { const IsMyFriend = b.read((state) => (userIdOwner) => {
// ++TODO Check if userIdOwner is my friend // ++TODO Check if userIdOwner is my friend
// userIdOwner is my friend ? // userIdOwner is my friend ?
@@ -93,6 +108,10 @@ namespace Getters {
return true return true
}, 'IsMyGroup') }, 'IsMyGroup')
const getUserByUserId = b.read((mystate: IUserState) => (userId): IUserState => {
return mystate.usersList.find((item) => item._id === userId)
}, 'getUserByUserId')
export const getters = { export const getters = {
get isUserInvalid() { get isUserInvalid() {
return isUserInvalid() return isUserInvalid()
@@ -114,6 +133,15 @@ namespace Getters {
}, },
get IsMyGroup() { get IsMyGroup() {
return IsMyGroup() return IsMyGroup()
},
get getNameSurnameByUserId() {
return getNameSurnameByUserId()
},
get getUserByUserId() {
return getUserByUserId()
},
get getUsersList() {
return getUsersList()
} }
// get fullName() { return fullName();}, // get fullName() { return fullName();},
} }
@@ -138,8 +166,10 @@ namespace Mutations {
state.tokens.push({ access: 'auth', token: state.x_auth_token, data_login: tools.getDateNow() }) state.tokens.push({ access: 'auth', token: state.x_auth_token, data_login: tools.getDateNow() })
// ++Todo: Settings Users Admin // ++Todo: Settings Users Admin
if (state.username === 'paoloar77') { if (db_data.adminUsers.includes(state.username)) {
state.isAdmin = true state.isAdmin = true
} else {
state.isAdmin = false
} }
// console.log('state.tokens', state.tokens) // console.log('state.tokens', state.tokens)
@@ -149,6 +179,11 @@ namespace Mutations {
state.password = newstr state.password = newstr
} }
function setusersList(mystate: IUserState, usersList: IUserList[]) {
// console.log('setusersList', usersList)
mystate.usersList = [...usersList]
}
function setemail(state: IUserState, newstr: string) { function setemail(state: IUserState, newstr: string) {
state.email = newstr state.email = newstr
} }
@@ -198,9 +233,14 @@ namespace Mutations {
state.name = '' state.name = ''
state.surname = '' state.surname = ''
resetArrToken(state.tokens) resetArrToken(state.tokens)
state.x_auth_token = ''
state.verified_email = false state.verified_email = false
state.categorySel = 'personal' state.categorySel = 'personal'
state.servercode = 0
state.resStatus = 0
state.isLogged = false
state.isAdmin = false
state.x_auth_token = ''
} }
function setErrorCatch(state: IUserState, axerr: Types.AxiosError) { function setErrorCatch(state: IUserState, axerr: Types.AxiosError) {
@@ -240,7 +280,8 @@ namespace Mutations {
setAuth: b.commit(setAuth), setAuth: b.commit(setAuth),
clearAuthData: b.commit(clearAuthData), clearAuthData: b.commit(clearAuthData),
setErrorCatch: b.commit(setErrorCatch), setErrorCatch: b.commit(setErrorCatch),
getMsgError: b.commit(getMsgError) getMsgError: b.commit(getMsgError),
setusersList: b.commit(setusersList)
} }
} }
@@ -279,6 +320,15 @@ namespace Actions {
} }
async function saveUserChange(context, user: IUserState) {
console.log('saveUserChange', user)
return await Api.SendReq(`/users/${user.userId}`, 'PATCH', { user })
.then((res) => {
return (res.data.code === serv_constants.RIS_CODE_OK)
})
}
async function requestpwd(context, paramquery: IUserState) { async function requestpwd(context, paramquery: IUserState) {
const usertosend = { const usertosend = {
@@ -384,7 +434,9 @@ namespace Actions {
localStorage.setItem(tools.localStorage.token, state.x_auth_token) localStorage.setItem(tools.localStorage.token, state.x_auth_token)
localStorage.setItem(tools.localStorage.expirationDate, expirationDate.toString()) localStorage.setItem(tools.localStorage.expirationDate, expirationDate.toString())
localStorage.setItem(tools.localStorage.verified_email, String(false)) localStorage.setItem(tools.localStorage.verified_email, String(false))
state.isLogged = true
// Even if you has registered, you have to SignIn first
state.isLogged = false
// dispatch('storeUser', authData); // dispatch('storeUser', authData);
// dispatch('setLogoutTimer', myres.data.expiresIn); // dispatch('setLogoutTimer', myres.data.expiresIn);
@@ -554,14 +606,14 @@ namespace Actions {
// state.isLogged = true // state.isLogged = true
state.isLogged = isLogged state.isLogged = isLogged
if (isLogged) { if (isLogged) {
console.log('state.isLogged') // console.log('state.isLogged', state.isLogged)
GlobalStore.mutations.setleftDrawerOpen(localStorage.getItem(tools.localStorage.leftDrawerOpen) === 'true') GlobalStore.mutations.setleftDrawerOpen(localStorage.getItem(tools.localStorage.leftDrawerOpen) === 'true')
GlobalStore.mutations.setCategorySel(localStorage.getItem(tools.localStorage.categorySel)) GlobalStore.mutations.setCategorySel(localStorage.getItem(tools.localStorage.categorySel))
GlobalStore.actions.checkUpdates() GlobalStore.actions.checkUpdates()
} }
const p = await BookingStore.actions.loadAfterLogin()
const p2 = await CalendarStore.actions.loadAfterLogin() const p2 = await CalendarStore.actions.loadAfterLogin()
const p3 = await GlobalStore.actions.loadAfterLogin() const p3 = await GlobalStore.actions.loadAfterLogin()
@@ -572,7 +624,7 @@ namespace Actions {
if (static_data.functionality.ENABLE_PROJECTS_LOADING) if (static_data.functionality.ENABLE_PROJECTS_LOADING)
await Projects.actions.dbLoad({ checkPending: true, onlyiffirsttime: true }) await Projects.actions.dbLoad({ checkPending: true, onlyiffirsttime: true })
console.log('setGlobal: END') // console.log('setGlobal: END')
} }
async function autologin_FromLocalStorage(context) { async function autologin_FromLocalStorage(context) {
@@ -646,6 +698,7 @@ namespace Actions {
logout: b.dispatch(logout), logout: b.dispatch(logout),
requestpwd: b.dispatch(requestpwd), requestpwd: b.dispatch(requestpwd),
resetpwd: b.dispatch(resetpwd), resetpwd: b.dispatch(resetpwd),
saveUserChange: b.dispatch(saveUserChange),
signin: b.dispatch(signin), signin: b.dispatch(signin),
signup: b.dispatch(signup), signup: b.dispatch(signup),
vreg: b.dispatch(vreg) vreg: b.dispatch(vreg)

View File

@@ -1,6 +1,5 @@
export {storeBuilder} from './Store/Store' export {storeBuilder} from './Store/Store'
export {default as GlobalStore} from './GlobalStore' export {default as GlobalStore} from './GlobalStore'
export {default as BookingStore} from './BookingStore'
export {default as UserStore} from './UserStore' export {default as UserStore} from './UserStore'
export {default as Todos} from './Todos' export {default as Todos} from './Todos'
export {default as Projects} from './Projects' export {default as Projects} from './Projects'

View File

@@ -3,8 +3,18 @@ import globalroutines from './../../globalroutines/index'
import { costanti } from './costanti' import { costanti } from './costanti'
import { toolsext } from './toolsext' import { toolsext } from './toolsext'
import { translation } from './translation' import { translation } from './translation'
import Quasar, { date, Screen } from 'quasar' import Quasar, { colors, date, Screen } from 'quasar'
import { ICollaborations, IListRoutes, IMenuList, IParamDialog, IProject, ITodo, Privacy } from '@src/model' import {
IBookedEvent,
ICollaborations,
IEvents,
IListRoutes,
IMenuList,
IParamDialog,
IProject,
ITodo,
Privacy
} from '@src/model'
import * as ApiTables from '@src/store/Modules/ApiTables' import * as ApiTables from '@src/store/Modules/ApiTables'
import translate from '@src/globalroutines/util' import translate from '@src/globalroutines/util'
import { RouteNames } from '@src/router/route-names' import { RouteNames } from '@src/router/route-names'
@@ -13,6 +23,7 @@ import { lists } from './lists'
import { static_data } from '@src/db/static_data' import { static_data } from '@src/db/static_data'
import { IColl, ITimeLineEntry, ITimeLineMain } from '@src/model/GlobalStore' import { IColl, ITimeLineEntry, ITimeLineMain } from '@src/model/GlobalStore'
import { func_tools } from '@src/store/Modules/toolsext' import { func_tools } from '@src/store/Modules/toolsext'
import { serv_constants } from '@src/store/Modules/serv_constants'
export interface INotify { export interface INotify {
color?: string | 'primary' color?: string | 'primary'
@@ -1301,13 +1312,14 @@ export const tools = {
return result return result
}, },
executefunc(myself: any, myfunc: number, par: IParamDialog) { executefunc(myself: any, func: number, par: IParamDialog) {
if (myfunc === costanti.FuncDialog.CANCEL_BOOKING) { if (func === lists.MenuAction.DELETE) {
console.log(' ENTRATO ! CancelBookingEvent ') console.log('param1', par.param1)
CalendarStore.actions.CancelBookingEvent(par.param1).then((ris) => { CalendarStore.actions.CancelBookingEvent({ideventbook: par.param1, notify: par.param2 === true ? '1' : '0'}).then((ris) => {
if (ris) { if (ris) {
tools.showPositiveNotif(myself.$q, myself.$t('cal.canceledbooking') + ' "' + par.param1.title + '"') tools.showPositiveNotif(myself.$q, myself.$t('cal.canceledbooking') + ' "' + par.param1.title + '"')
myself.bookEventpage.show = false if (myself.bookEventpage)
myself.bookEventpage.show = false
} else } else
tools.showNegativeNotif(myself.$q, myself.$t('cal.cancelederrorbooking')) tools.showNegativeNotif(myself.$q, myself.$t('cal.cancelederrorbooking'))
}) })
@@ -1386,7 +1398,7 @@ export const tools = {
, ,
checkLangPassed(mylang) { checkLangPassed(mylang) {
console.log('checkLangPassed') // console.log('checkLangPassed')
const mybrowserLang = Quasar.lang.isoName const mybrowserLang = Quasar.lang.isoName
@@ -2077,7 +2089,7 @@ export const tools = {
return msg return msg
}, },
gettextevent(myevent) { gettextevent(myevent: IEvents) {
return '"' + myevent.title + '" (' + func_tools.getDateStr(myevent.date) + ') - ' + myevent.time return '"' + myevent.title + '" (' + func_tools.getDateStr(myevent.date) + ') - ' + myevent.time
}, },
@@ -2107,6 +2119,131 @@ export const tools = {
} else { } else {
return mythis.$t('msg.myAppName') return mythis.$t('msg.myAppName')
} }
},
loginOk(mythis, ispageLogin: boolean) {
// console.log('loginOk')
if (toolsext.getLocale() !== '') {
mythis.$i18n.locale = toolsext.getLocale()
} // Set Lang
else {
UserStore.mutations.setlang(mythis.$i18n.locale)
} // Set Lang
if (process.env.DEBUG) {
console.log('LANG ORA=', toolsext.getLocale())
}
globalroutines(mythis, 'loadapp', '')
tools.SignIncheckErrors(mythis, tools.OK, ispageLogin)
},
loginInCorso(mythis) {
// console.log('loginInCorso')
let msg = mythis.$t('login.incorso')
if (process.env.DEBUG) {
msg += ' ' + process.env.MONGODB_HOST
}
mythis.$q.loading.show({ message: msg })
},
SignIncheckErrors(mythis, riscode, ispageLogin?: boolean) {
// console.log('SignIncheckErrors: ', riscode)
try {
if (riscode === tools.OK) {
tools.showNotif(mythis.$q, mythis.$t('login.completato'), { color: 'positive', icon: 'check' })
if (ispageLogin) {
mythis.$router.push('/')
}
} else if (riscode === serv_constants.RIS_CODE_LOGIN_ERR) {
// Wait N seconds to avoid calling many times...
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('anything')
}, 3000)
}).then(() => {
setTimeout(() => {
console.log('HIDE...')
mythis.$q.loading.hide()
}, 500)
tools.showNotif(mythis.$q, mythis.$t('login.errato'), { color: 'negative', icon: 'notifications' })
mythis.iswaitingforRes = false
if (ispageLogin) {
mythis.$router.push('/signin')
}
})
} else if (riscode === tools.ERR_SERVERFETCH) {
tools.showNotif(mythis.$q, mythis.$t('fetch.errore_server'), { color: 'negative', icon: 'notifications' })
} else if (riscode === tools.ERR_GENERICO) {
const msg = mythis.$t('fetch.errore_generico') + UserStore.mutations.getMsgError(riscode)
tools.showNotif(mythis.$q, msg, { color: 'negative', icon: 'notifications' })
} else {
tools.showNotif(mythis.$q, 'Errore num ' + riscode, { color: 'negative', icon: 'notifications' })
}
if (riscode !== serv_constants.RIS_CODE_LOGIN_ERR) {
mythis.iswaitingforRes = false
setTimeout(() => {
mythis.$q.loading.hide()
}, 200)
}
} finally {
// ...
}
},
SignUpcheckErrors(mythis, riscode: number) {
console.log('SignUpcheckErrors', riscode)
if (riscode === tools.DUPLICATE_EMAIL_ID) {
tools.showNotif(mythis.$q, mythis.$t('reg.err.duplicate_email'))
} else if (riscode === tools.DUPLICATE_USERNAME_ID) {
tools.showNotif(mythis.$q, mythis.$t('reg.err.duplicate_username'))
} else if (riscode === tools.ERR_SERVERFETCH) {
tools.showNotif(mythis.$q, mythis.$t('fetch.errore_server'))
} else if (riscode === tools.ERR_GENERICO) {
const msg = mythis.$t('fetch.errore_generico') + UserStore.mutations.getMsgError(riscode)
tools.showNotif(mythis.$q, msg)
} else if (riscode === tools.OK) {
mythis.$router.push('/signin')
tools.showNotif(mythis.$q, mythis.$t('components.authentication.email_verification.link_sent'), {
color: 'warning',
textColor: 'black'
})
} else {
tools.showNotif(mythis.$q, 'Errore num ' + riscode)
}
},
isCssColor(color) {
return !!color && !!color.match(/^(#|(rgb|hsl)a?\()/)
},
displayClasses(eventparam) {
return {
[`bg-${eventparam.bgcolor}`]: !tools.isCssColor(eventparam.bgcolor),
'text-white': !tools.isCssColor(eventparam.bgcolor)
}
},
displayStyles(eventparam) {
const s = { color: '' }
if (tools.isCssColor(eventparam.bgcolor)) {
s['background-color'] = eventparam.bgcolor
s.color = colors.luminosity(eventparam.bgcolor) > 0.5 ? 'black' : 'white'
}
return s
},
CancelBookingEvent(mythis, eventparam: IEvents, bookeventid: string, notify: boolean) {
console.log('CancelBookingEvent ', eventparam)
tools.askConfirm(mythis.$q, translate('cal.titlebooking'), translate('cal.cancelbooking') + ' ' + tools.gettextevent(eventparam) + '?', translate('dialog.yes'), translate('dialog.no'), mythis, lists.MenuAction.DELETE, 0, { param1: bookeventid, param2: notify })
},
CancelUserRec(mythis, id) {
console.log('CancelUserRec', id)
tools.askConfirm(mythis.$q, translate('cal.titlebooking'), translate('cal.canceluser') + '?', translate('dialog.yes'), translate('dialog.no'), mythis, lists.MenuAction.DELETE, 0, { param1: id })
} }
// getLocale() { // getLocale() {

View File

@@ -38,6 +38,21 @@ export const func_tools = {
return DateFormatter.format(date) return DateFormatter.format(date)
} }
return mydate return mydate
},
getDateTimeShortStr(mydate) {
const DateFormatter = new Intl.DateTimeFormat(func_tools.getLocale() || void 0, {
hour: 'numeric',
minute: 'numeric',
day: 'numeric',
month: 'short'
// timeZone: 'UTC'
})
if (DateFormatter) {
const date = new Date(mydate)
return DateFormatter.format(date)
}
return mydate
} }
} }

View File

@@ -10,7 +10,7 @@ export function registeredemail(email: string) {
return res.status !== PayloadMessageTypes.statusfound return res.status !== PayloadMessageTypes.statusfound
} }
return Axios.get(VALIDATE_USER_URL + email) return Axios.get(VALIDATE_USER_URL + process.env.APP_ID + '/' + email)
.then(onSuccess) .then(onSuccess)
.catch((err) => { .catch((err) => {
return true return true

View File

@@ -7,15 +7,11 @@ const VALIDATE_USER_URL = process.env.MONGODB_HOST + '/users/'
export function registereduser(userName: string) { export function registereduser(userName: string) {
let config = {
params: { userName: userName }
}
let onSuccess = (res: AxiosResponse) => { let onSuccess = (res: AxiosResponse) => {
return res.status !== PayloadMessageTypes.statusfound return res.status !== PayloadMessageTypes.statusfound
} }
return Axios.get(VALIDATE_USER_URL + config.params.userName) return Axios.get(VALIDATE_USER_URL + process.env.APP_ID + '/' + userName)
.then(onSuccess) .then(onSuccess)
.catch((err) => { .catch((err) => {
return true return true

View File

@@ -1,218 +1,40 @@
import { GlobalStore } from '@store'
import { UserStore } from '../../../store/Modules'
import Vue from 'vue' import Vue from 'vue'
import { Component, Prop, Watch } from 'vue-property-decorator' import { Component, Prop, Watch } from 'vue-property-decorator'
import { serv_constants } from '../../../store/Modules/serv_constants' import { CSignIn } from '../../../components/CSignIn'
import { tools } from '../../../store/Modules/tools' import { toolsext } from '../../../store/Modules/toolsext'
import { toolsext } from '@src/store/Modules/toolsext' import { UserStore } from '../../../store/Modules'
import { ISigninOptions, IUserState } from 'model'
import { TSignin, validations } from './signin-validate'
import { validationMixin } from 'vuelidate'
import { Logo } from '../../../components/logo'
import router from '@router'
import globalroutines from '../../../globalroutines/index' import globalroutines from '../../../globalroutines/index'
import { tools } from '../../../store/Modules/tools'
// import {Loading, QSpinnerFacebook, QSpinnerGears} from 'quasar' // import {Loading, QSpinnerFacebook, QSpinnerGears} from 'quasar'
@Component({ @Component({
mixins: [validationMixin], components: { CSignIn }
validations,
components: { Logo }
}) })
export default class Signin extends Vue { export default class Signin extends Vue {
public $v public $v
public $q public $q
public loading: boolean
public $t: any
public iswaitingforRes: boolean = false
public signin: ISigninOptions = { public loginOk() {
username: process.env.TEST_USERNAME || '', tools.loginOk(this, true)
password: process.env.TEST_PASSWORD || ''
} }
public created() { public loginInCorso() {
this.$v.$reset() tools.loginInCorso(this)
if (UserStore.state.resStatus === serv_constants.RIS_CODE__HTTP_FORBIDDEN_INVALID_TOKEN) {
tools.showNotif(this.$q, this.$t('fetch.error_doppiologin'))
}
// this.$myconfig.socialLogin.facebook = true
// console.log('PROVA fb:', this.$myconfig.socialLogin.facebook)
}
public env() {
return process.env
}
public getlinkforgetpwd() {
return '/requestresetpwd'
}
public errorMsg(cosa: string, item: any) {
try {
if (!item.$error) {
return ''
}
if (item.$params.email && !item.email) {
return this.$t('reg.err.email')
}
if (!item.required) {
return this.$t('reg.err.required')
}
if (!item.minLength) {
return this.$t('reg.err.atleast') + ` ${item.$params.minLength.min} ` + this.$t('reg.err.char')
}
if (!item.maxLength) {
return this.$t('reg.err.notmore') + ` ${item.$params.maxLength.max} ` + this.$t('reg.err.char')
}
return ''
} catch (error) {
// console.log("ERR : " + error);
}
} }
public checkErrors(riscode) { public checkErrors(riscode) {
// console.log('checkErrors: ', riscode) tools.SignIncheckErrors(this, riscode, true)
try {
if (riscode === tools.OK) {
tools.showNotif(this.$q, this.$t('login.completato'), { color: 'positive', icon: 'check' })
this.$router.push('/')
} else if (riscode === serv_constants.RIS_CODE_LOGIN_ERR) {
// Wait N seconds to avoid calling many times...
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('anything')
}, 3000)
}).then(() => {
setTimeout(() => {
this.$q.loading.hide()
}, 200)
tools.showNotif(this.$q, this.$t('login.errato'))
this.iswaitingforRes = false
this.$router.push('/signin')
})
} else if (riscode === tools.ERR_SERVERFETCH) {
tools.showNotif(this.$q, this.$t('fetch.errore_server'))
} else if (riscode === tools.ERR_GENERICO) {
const msg = this.$t('fetch.errore_generico') + UserStore.mutations.getMsgError(riscode)
tools.showNotif(this.$q, msg)
} else {
tools.showNotif(this.$q, 'Errore num ' + riscode)
}
if (riscode !== serv_constants.RIS_CODE_LOGIN_ERR) {
this.iswaitingforRes = false
setTimeout(() => {
this.$q.loading.hide()
}, 200)
}
} finally {
}
} }
public redirect(response) { public showNotif(msgcode) {
this.loading = false tools.showNotif(this.$q, this.$t(msgcode))
window.location.href = response.data.redirect
} }
public error(error) { public mythis() {
this.loading = false return this
this.$errorHandler(this, error)
} }
public facebook() {
this.loading = true
this.$axios.get('/backend/loginFacebook')
.then((response) => this.redirect(response))
.catch((error) => this.error(error))
}
public google() {
}
public submit() {
console.log('submit LOGIN')
this.$v.signin.$touch()
if (this.$v.signin.$error) {
tools.showNotif(this.$q, this.$t('reg.err.errore_generico'))
return
}
let msg = this.$t('login.incorso')
if (process.env.DEBUG) {
msg += ' ' + process.env.MONGODB_HOST
}
this.$q.loading.show({ message: msg })
// disable Button Login:
this.iswaitingforRes = true
if (process.env.DEBUG) {
console.log('this.signin', this.signin)
}
UserStore.actions.signin(this.signin)
.then((riscode) => {
// console.log('signin FINITO CALL: riscode=', riscode)
if (riscode === tools.OK) {
// router.push('/signin')
}
return riscode
})
.then((riscode) => {
if (process.env.DEBUG) {
console.log(' riscode=', riscode)
}
if (toolsext.getLocale() !== '') {
this.$i18n.locale = toolsext.getLocale()
} // Set Lang
else {
UserStore.mutations.setlang(this.$i18n.locale)
} // Set Lang
if (process.env.DEBUG) {
console.log('LANG ORA=', toolsext.getLocale())
}
globalroutines(this, 'loadapp', '')
return riscode
})
.then((riscode) => {
if (riscode === tools.OK) {
GlobalStore.actions.createPushSubscription()
.then((rissub) => {
})
.catch((e) => {
console.log('ERROR Subscription = ' + e)
})
}
this.checkErrors(riscode)
})
.catch((error) => {
console.log('ERROR SIGNIN = ' + error)
this.checkErrors(error)
})
}
} }

View File

@@ -1,66 +1,12 @@
<template> <template>
<div> <q-page padding class="signin">
<q-page padding class="signin"> <CSignIn :mythis="mythis"
<div class="text-center"> @loginOk="loginOk"
<p> @loginInCorso="loginInCorso"
<logo></logo> @checkErrors="checkErrors"
</p> @showNotif="showNotif">
</div> </CSignIn>
</q-page>
<!--Prova URL : {{env('PROVA_PAOLO')}}-->
<form>
<div class="q-gutter-xs">
<q-input
v-model="signin.username"
rounded outlined
@blur="$v.signin.username.$touch"
:error="$v.signin.username.$error"
:error-message="`${errorMsg('username', $v.signin.username)}`"
:label="$t('reg.username_login')">
<template v-slot:prepend>
<q-icon name="person"/>
</template>
</q-input>
<q-input
v-model="signin.password"
type="password"
rounded outlined
@blur="$v.signin.password.$touch"
:error="$v.signin.password.$error"
:error-message="`${errorMsg('password', $v.signin.password)}`"
:label="$t('reg.password')">
<template v-slot:prepend>
<q-icon name="vpn_key"/>
</template>
</q-input>
<div>
<a :href="getlinkforgetpwd">{{$t('reg.forgetpassword')}}</a>
</div>
<br>
<q-card class="flex flex-center">
<!--<q-btn v-if="$myconfig.socialLogin.facebook" :loading="loading" class="q-mb-md q-mr-md" rounded icon="fab fa-facebook-f" size="sm" color="blue-10" text-color="white" @click="facebook" :label="$t('components.authentication.login.facebook')"/>-->
<!--
<q-btn v-if="$myconfig.socialLogin.facebook" class="q-mb-md q-mr-md" rounded icon="fab fa-facebook-f" size="sm" color="blue-10" text-color="white" @click="facebook" :label="$t('components.authentication.login.facebook')"/>
<q-btn v-if="$myconfig.socialLogin.google" class="q-mb-md q-mr-md" rounded icon="fab fa-google" size="sm" color="deep-orange-14" text-color="white" @click="google" :label="$t('components.authentication.login.google')"/>
-->
</q-card>
<div align="center">
<q-btn rounded size="lg" color="primary" @click="submit"
:disable="$v.$error || iswaitingforRes">{{$t('login.enter')}}
</q-btn>
</div>
</div>
</form>
</q-page>
</div>
</template> </template>
<script lang="ts" src="./signin.ts"> <script lang="ts" src="./signin.ts">

View File

@@ -3,174 +3,13 @@ import { Component, Prop, Watch } from 'vue-property-decorator'
import { UserStore } from '@store' import { UserStore } from '@store'
import { tools } from '../../../store/Modules/tools' import { tools } from '../../../store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext' import { toolsext } from '@src/store/Modules/toolsext'
import { CSignUp } from '../../../components/CSignUp'
import { ISignupOptions, IUserState } from 'model'
import { validations, TSignup } from './signup-validate'
import { validationMixin } from 'vuelidate'
import { Logo } from '../../../components/logo'
// import {Loading, QSpinnerFacebook, QSpinnerGears} from 'quasar'
@Component({ @Component({
mixins: [validationMixin], components: { CSignUp }
validations,
components: { Logo }
}) })
export default class Signup extends Vue { export default class Signup extends Vue {
public $v
public $q
public $t: any public $t: any
public duplicate_email: boolean = false
public duplicate_username: boolean = false
public signup: ISignupOptions = {
email: process.env.TEST_EMAIL || '',
username: process.env.TEST_USERNAME || '',
name: process.env.TEST_NAME || '',
surname: process.env.TEST_SURNAME || '',
password: process.env.TEST_PASSWORD || '',
repeatPassword: process.env.TEST_PASSWORD || '',
terms: !process.env.PROD
}
public created() {
this.$v.$reset()
}
public mounted() {
}
get allowSubmit() {
const error = this.$v.$error || this.$v.$invalid
return !error
}
/*
validations: {
isAsync: true,
form: {
email: {
required, email,
isUnique: value => {
if (value === '') return true;
return axios.get(process.env.MONGODB_HOST + '/email/' + value)
.then(res => {
return (res.status !== 200)
}).catch((e) => {
return true;
})
}
},
password: {required, minLength: minLength(8), maxLength: maxLength(20)},
username: {
required, minLength: minLength(6), maxLength: maxLength(20),
isUnique: value => {
if (value === '') return true;
return axios.get(process.env.MONGODB_HOST + '/users/' + value)
.then(res => {
return (res.status !== 200)
}).catch((e) => {
return true;
})
}
},
repeatPassword: {
sameAsPassword: sameAs('password')
},
terms: {required},
}
}, */
public env() {
return process.env
}
public errorMsg(cosa: string, item: any) {
try {
if (!item.$error) { return '' }
if (item.$params.email && !item.email) { return this.$t('reg.err.email') }
if (cosa === 'repeatpassword') {
if (!item.sameAsPassword) {
return this.$t('reg.err.sameaspassword')
}
}
if (!item.required) { return this.$t('reg.err.required') }
if (cosa === 'email') {
// console.log("EMAIL " + item.isUnique);
// console.log(item);
if (!item.isUnique) { return this.$t('reg.err.duplicate_email') }
} else if (cosa === 'username') {
// console.log(item);
if (!item.isUnique) { return this.$t('reg.err.duplicate_username') }
} else if ((cosa === 'name') || (cosa === 'surname')) {
// console.log(item);
}
if (!item.complexity) { return this.$t('reg.err.complexity') }
if (!item.minLength) { return this.$t('reg.err.atleast') + ` ${item.$params.minLength.min} ` + this.$t('reg.err.char') }
if (!item.maxLength) { return this.$t('reg.err.notmore') + ` ${item.$params.maxLength.max} ` + this.$t('reg.err.char') }
return ''
} catch (error) {
// console.log("ERR : " + error);
}
}
public checkErrors(riscode: number) {
console.log('checkErrors', riscode)
if (riscode === tools.DUPLICATE_EMAIL_ID) {
tools.showNotif(this.$q, this.$t('reg.err.duplicate_email'))
} else if (riscode === tools.DUPLICATE_USERNAME_ID) {
tools.showNotif(this.$q, this.$t('reg.err.duplicate_username'))
} else if (riscode === tools.ERR_SERVERFETCH) {
tools.showNotif(this.$q, this.$t('fetch.errore_server'))
} else if (riscode === tools.ERR_GENERICO) {
const msg = this.$t('fetch.errore_generico') + UserStore.mutations.getMsgError(riscode)
tools.showNotif(this.$q, msg)
} else if (riscode === tools.OK) {
this.$router.push('/signin')
tools.showNotif(this.$q, this.$t('components.authentication.email_verification.link_sent'), {color: 'warning', textColor: 'black'})
} else {
tools.showNotif(this.$q, 'Errore num ' + riscode)
}
}
public submitOk() {
this.$v.signup.$touch()
this.duplicate_email = false
this.duplicate_username = false
if (!this.signup.terms) {
tools.showNotif(this.$q, this.$t('reg.err.terms'))
return
}
if (this.$v.signup.$error) {
tools.showNotif(this.$q, this.$t('reg.err.errore_generico'))
return
}
this.$q.loading.show({ message: this.$t('reg.incorso') })
console.log(this.signup)
UserStore.actions.signup(this.signup)
.then((riscode) => {
this.checkErrors(riscode)
this.$q.loading.hide()
}).catch((error) => {
console.log('ERROR = ' + error)
this.$q.loading.hide()
})
}
} }

View File

@@ -1,139 +1,8 @@
<template> <template>
<q-page padding class="signup"> <q-page padding class="signup">
<div class="text-center"> <CSignUp>
<p>
<logo></logo>
</p>
</div>
<!--Prova URL : {{env('PROVA_PAOLO')}}-->
<div class="q-gutter-xs">
<q-input
v-model="signup.email"
rounded outlined
@blur="$v.signup.email.$touch"
:error="$v.signup.email.$error"
:error-message="errorMsg('email', $v.signup.email)"
bottom-slots
debounce="1000"
:label="$t('reg.email')">
<template v-slot:prepend>
<q-icon name="email"/>
</template>
</q-input>
<q-input
v-model="signup.username"
rounded outlined
@blur="$v.signup.username.$touch"
:error="$v.signup.username.$error"
bottom-slots
debounce="1000"
:error-message="errorMsg('username', $v.signup.username)"
:label="$t('reg.username')">
<template v-slot:prepend>
<q-icon name="person"/>
</template>
</q-input>
<q-input
v-model="signup.name"
rounded outlined
@blur="$v.signup.name.$touch"
:error="$v.signup.name.$error"
bottom-slots
debounce="1000"
:error-message="errorMsg('name', $v.signup.name)"
:label="$t('reg.name')">
<template v-slot:prepend>
<q-icon name="person"/>
</template>
</q-input>
<q-input
v-model="signup.surname"
rounded outlined
@blur="$v.signup.surname.$touch"
:error="$v.signup.surname.$error"
bottom-slots
debounce="1000"
:error-message="errorMsg('surname', $v.signup.surname)"
:label="$t('reg.surname')">
<template v-slot:prepend>
<q-icon name="person"/>
</template>
</q-input>
<q-input
v-model="signup.password"
type="password"
rounded outlined
@blur="$v.signup.password.$touch"
:error="$v.signup.password.$error"
:error-message="`${errorMsg('password', $v.signup.password)}`"
bottom-slots
:label="$t('reg.password')">
<template v-slot:prepend>
<q-icon name="vpn_key"/>
</template>
</q-input>
<q-input
v-model="signup.repeatPassword"
type="password"
rounded outlined
@blur="$v.signup.repeatPassword.$touch"
:error="$v.signup.repeatPassword.$error"
:error-message="`${errorMsg('repeatpassword', $v.signup.repeatPassword)}`"
bottom-slots
:label="$t('reg.repeatPassword')">
<template v-slot:prepend>
<q-icon name="vpn_key"/>
</template>
</q-input>
<!--:hint="$t('reg.tips.repeatpassword')"-->
<q-checkbox
v-model="signup.terms"
color="secondary"
@blur="$v.signup.terms.$touch"
:error="$v.signup.terms.$error"
:error-message="`${errorMsg('terms', $v.signup.terms)}`"
:label="$t('reg.terms')">
</q-checkbox>
<br>
<div class="wrapper">
<q-btn rounded size="lg" color="positive" @click="submitOk" :disabled='!allowSubmit'>
{{$t('reg.submit')}}
</q-btn>
</div>
</div>
<!--
<div align="center">
<q-btn rounded size="lg" color="primary" @click="submitOk" :disable="">{{$t('reg.submit')}}
</q-btn>
</div>
-->
</CSignUp>
</q-page> </q-page>
</template> </template>

View File

@@ -1101,10 +1101,10 @@
resolved "https://registry.yarnpkg.com/@positron/stack-trace/-/stack-trace-1.0.0.tgz#14fcc712a530038ef9be1ce6952315a839f466a8" resolved "https://registry.yarnpkg.com/@positron/stack-trace/-/stack-trace-1.0.0.tgz#14fcc712a530038ef9be1ce6952315a839f466a8"
integrity sha1-FPzHEqUwA475vhzmlSMVqDn0Zqg= integrity sha1-FPzHEqUwA475vhzmlSMVqDn0Zqg=
"@quasar/app@^1.1.4": "@quasar/app@^1.1.2":
version "1.1.4" version "1.2.1"
resolved "https://registry.yarnpkg.com/@quasar/app/-/app-1.1.4.tgz#2f4a04d4bf3c242388c78d189ceaca174a0ebfe1" resolved "https://registry.yarnpkg.com/@quasar/app/-/app-1.2.1.tgz#2cc23ed9230106ffc1605cc01de43395bff21405"
integrity sha512-jAzRi+rFVN6VPHCTlCcpH4ui6KHqA6pOPHqSdKnncYkkXGxqDwFumnTFjQfV1Iz5/+a0x3056y3i6n8QOFZ6Og== integrity sha512-cJaq56iTrIf0n1jjov2IRGCkjEA66iq+gPF7y1UAHr38s699pNPLugblvdqoFAa20ogDw/VtlrHOuQBcHoZSqQ==
dependencies: dependencies:
"@quasar/babel-preset-app" "1.1.6" "@quasar/babel-preset-app" "1.1.6"
"@quasar/fastclick" "1.1.4" "@quasar/fastclick" "1.1.4"
@@ -1205,6 +1205,11 @@
resolved "https://registry.yarnpkg.com/@quasar/fastclick/-/fastclick-1.1.4.tgz#21ed3e9a4387dcb43022a08af4ef08a5f1abf159" resolved "https://registry.yarnpkg.com/@quasar/fastclick/-/fastclick-1.1.4.tgz#21ed3e9a4387dcb43022a08af4ef08a5f1abf159"
integrity sha512-i9wbyV4iT+v4KhtHJynUFhH5LiEPvAEgSnwMqPN4hf/8uRe82nDl5qP5agrp2el1h0HzyBpbvHaW7NB0BPrtvA== integrity sha512-i9wbyV4iT+v4KhtHJynUFhH5LiEPvAEgSnwMqPN4hf/8uRe82nDl5qP5agrp2el1h0HzyBpbvHaW7NB0BPrtvA==
"@quasar/quasar-app-extension-colorize@^1.0.0-alpha.1":
version "1.0.0-alpha.1"
resolved "https://registry.yarnpkg.com/@quasar/quasar-app-extension-colorize/-/quasar-app-extension-colorize-1.0.0-alpha.1.tgz#55c8645c2b1d621f13264832f5a258d0114b4368"
integrity sha512-udmfCeDHFDO60bDrXCM+LihxZjUenFkAsYJP3MNRTIh/sUeLJdmzwEvZRlzrGMymJBlZhgL+C/arAn+su1Kyyg==
"@quasar/quasar-app-extension-typescript@^1.0.0-alpha.11": "@quasar/quasar-app-extension-typescript@^1.0.0-alpha.11":
version "1.0.0-beta.1" version "1.0.0-beta.1"
resolved "https://registry.yarnpkg.com/@quasar/quasar-app-extension-typescript/-/quasar-app-extension-typescript-1.0.0-beta.1.tgz#945aa301b51ac6e7e7766a6e7cceb736c289f7fb" resolved "https://registry.yarnpkg.com/@quasar/quasar-app-extension-typescript/-/quasar-app-extension-typescript-1.0.0-beta.1.tgz#945aa301b51ac6e7e7766a6e7cceb736c289f7fb"
@@ -11874,10 +11879,10 @@ quasar-extras@^2.0.8:
resolved "https://registry.yarnpkg.com/quasar-extras/-/quasar-extras-2.0.9.tgz#f3274f8cd8e054a76d0b52a2410ccf0cdfb197fd" resolved "https://registry.yarnpkg.com/quasar-extras/-/quasar-extras-2.0.9.tgz#f3274f8cd8e054a76d0b52a2410ccf0cdfb197fd"
integrity sha512-ifwaaop0GNuxlcD7Ams0X3f7S49es+2NlR/fI4YAMAOW70ZxTkD4QkAFsVhk7dNPcpPodSOTKAWDOPaO+MqsBg== integrity sha512-ifwaaop0GNuxlcD7Ams0X3f7S49es+2NlR/fI4YAMAOW70ZxTkD4QkAFsVhk7dNPcpPodSOTKAWDOPaO+MqsBg==
quasar@^1.1.7: quasar@^1.1.6:
version "1.1.7" version "1.2.1"
resolved "https://registry.yarnpkg.com/quasar/-/quasar-1.1.7.tgz#68803a898a2a34c3c0b8d9ea30d40298c4a8c976" resolved "https://registry.yarnpkg.com/quasar/-/quasar-1.2.1.tgz#83117f5b17adcc7c08526b9aadc4ca7c2ab21287"
integrity sha512-MNL3vSnz2fbc0OVXldJd9dxD5hRPvlKF4HZ4GWJ6u7uFDnbXUaeqUb0Sc3zwFhT1ozKRtJg/rcVsF2hSbOrixQ== integrity sha512-7PbX8HecdrDzpG9zcZk5PSuPRFicU6b07N9Dk0uk5N+2LNGEFGBwIuQnLeDpq03Xdv98Q6GpTTZNaWpXdYBZcg==
query-string@^4.1.0: query-string@^4.1.0:
version "4.3.4" version "4.3.4"