Initial commit

This commit is contained in:
Matej Glasnák committed 2022-11-21 05:42:38 +01:00
commit d76f4258f7
231 files changed
+27803

No files matched your search

+48
View File
@@ -0,0 +1,48 @@
# W / Auth
- This plugin is used for managing logged user, and will automatically inject auth store to your main store
# Required third-party plugins
- `npm i vuex@4 && npm i axios-auth-refresh`
# Required internal plugins
- w/axios
# Installation
1. Create store.ts in `@/store.ts` and initialize vuex store
2. Import `@/store.ts` in `main.ts`
3. Import w/auth in `main.ts`
# Installation example
- main.ts
```javascript
import store from '@/store'
import auth from '@/plugins/w/auth'
const app = createApp(App)
.use(store)
.use(auth)
```
- store.ts
```javascript
import { createStore } from 'vuex'
export default createStore({
modules: {}
})
```
# Store actions
```javascript
this.$store.dispatch('auth/login', credentials)
this.$store.dispatch('auth/signup', credentials)
this.$store.dispatch('auth/logout')
this.$store.dispatch('auth/forgotPassword', credentials)
this.$store.dispatch('auth/resetPassword', credentials)
this.$store.dispatch('auth/refreshToken')
this.$store.dispatch('auth/userInfo')
this.$store.dispatch('auth/updateUserInfo', user)
```
# Store getters
```javascript
this.$store.getters['auth/isLoggedIn']
this.$store.getters['auth/user']
```
+173
View File
@@ -0,0 +1,173 @@
import axios from '@/plugins/w/axios/models/axios'
import './refreshExpired'
export default {
namespaced: true,
state: {
status: '',
_token: localStorage.getItem('wzo_vue_user_token') || '',
user: JSON.parse(localStorage.getItem('wzo_vue_user_user') || '{}'),
},
mutations: {
auth_request(state: any) {
state.status = 'loading'
},
auth_success(state: any, data: any) {
state.status = 'success'
if (data.token) {
state._token = data.token
localStorage.setItem('wzo_vue_user_token', data.token)
}
if (data.user) {
state.user = data.user
localStorage.setItem('wzo_vue_user_user', JSON.stringify(data.user))
}
},
auth_error(state: any) {
state.status = 'error'
state._token = ''
localStorage.removeItem('wzo_vue_user_token')
localStorage.removeItem('wzo_vue_user_user')
},
logout(state: any) {
state.status = ''
state._token = ''
state.user = null
localStorage.removeItem('wzo_vue_user_token')
localStorage.removeItem('wzo_vue_user_user')
}
},
actions: {
login({commit}: {commit: any}, credentials: any) {
return new Promise((resolve, reject) => {
commit('auth_request')
axios.post_data('v1/auth/login', credentials)
.then((response: any) => {
const token = response.token
const user = response.user
commit('auth_success', {
token: token,
user: user
})
resolve(response)
}).catch(error => {
commit('auth_error')
reject(error)
})
})
},
signup({commit }: {commit: any}, credentials: any) {
return new Promise((resolve, reject) => {
commit('auth_request')
axios.post_data('v1/auth/signup', credentials)
.then((response: any) => {
const token = response.token
const user = response.user
commit('auth_success', {
token: token,
user: user
})
resolve(response)
}).catch(error => {
commit('auth_error')
reject(error)
})
})
},
logout({commit}: {commit: any}) {
return new Promise((resolve) => {
axios.post_auth_data('v1/auth/invalidate')
.finally(() => {
commit('logout')
resolve(null)
})
})
},
forgotPassword(credentials: any) {
return new Promise((resolve, reject) => {
axios.post_auth_data('v1/auth/forgot', credentials)
.then(response => resolve(response))
.catch(error => reject(error))
})
},
resetPassword(credentials: any) {
return new Promise((resolve, reject) => {
axios.post_auth_data('v1/auth/reset', credentials)
.then(response => resolve(response))
.catch(error => reject(error))
})
},
async refreshToken({commit}: {commit: any}) {
try {
const response: any = await axios.post_auth_data('v1/auth/refresh')
const token = response.token
const user = response.user
commit('auth_success', {
token: token,
user: user
})
return token
} catch (error) {
commit('auth_error')
console.error(error)
}
},
async userInfo({commit}: {commit: any}) {
return new Promise((resolve, reject) => {
axios.get_auth_data('v1/auth/info')
.then((response: any) => {
const user = response.user
commit('auth_success', {
user: user
})
resolve(user)
}).catch(error => {
reject(error)
})
})
},
updateUserInfo({commit}: {commit: any}, data: any) {
return new Promise((resolve, reject) => {
axios.post_auth_data('v1/auth/info', data)
.then((response: any) => {
const user = response.user
commit('auth_success', {
user: user
})
resolve(user)
}).catch(error => {
reject(error)
})
})
},
},
getters: {
isLoggedIn: (state: any) => {
return !!state._token
},
// authStatus: (state: any) => {
// return state.status
// },
user: (state: any) => {
return state.user
}
// token: (state: any) => {
// return state._token
// }
}
}
+14
View File
@@ -0,0 +1,14 @@
import { App } from 'vue'
import { Options } from './types'
import auth from './auth.store'
export default {
install: (app: App, options: Options) => {
if (options && options.disabled == true) return
if (!app.config.globalProperties.$store)
return console.warn('[w/auth] Could not initialize. App does not have vuex store added.')
app.config.globalProperties.$store.registerModule('auth', auth)
}
}
@@ -0,0 +1,11 @@
import store from '@/store'
export default async function(to, from, next) {
if (to.matched.some((record) => record.meta.requiresAuth)) {
if (!store.getters['auth/isLoggedIn']) {
return next({ name: 'login' })
}
}
return next()
}
+16
View File
@@ -0,0 +1,16 @@
import store from '@/store'
import axios from 'axios'
import createAuthRefreshInterceptor from 'axios-auth-refresh'
axios.interceptors.request.use(request => {
request.headers['Authorization'] = `Bearer ${store.getters['user/token']}`
return request
})
const refreshAuthLogic = failedRequest => store.dispatch('user/refreshToken').then(token => {
failedRequest.response.config.headers.Authorization = `Bearer ${token}`
return Promise.resolve()
})
createAuthRefreshInterceptor(axios, refreshAuthLogic)
+3
View File
@@ -0,0 +1,3 @@
export interface Options {
disabled?: Boolean
}
+53
View File
@@ -0,0 +1,53 @@
# W / Axios
- This plugin will add axios (this.$axios) with custom functions
# Required internal plugins
- w/auth
# Installation
1. Install plugin in `main.ts`
```javascript
import axios from '@/plugins/w/axios'
const app = createApp(App)
.use(auth)
.use(axios)
```
2. Create `.env` in app root directory
3. Add `VUE_APP_WAXIOS_URL=defaultBaseUrl` to `.env`
# Examples
1. Call without authorization header
```javascript
this.$axios.get('v1/courses')
```
2. Call with authorization header
```javascript
this.$axios.get_auth('v1/courses')
```
3. Call that will return directly response.data.data
```javascript
this.$axios.get_data('v1/courses')
this.$axios.get_auth_data('v1/courses')
```
# Public functions
```javascript
async get(url: string, config?: any)
async get_data(url: string, config?: any)
async get_auth(url: string, config?: any)
async get_auth_data(url: string, config?: any)
async post(url: string, config?: any)
async post_data(url: string, config?: any)
async post_auth(url: string, config?: any)
async post_auth_data(url: string, config?: any)
async patch(url: string, config?: any)
async patch_data(url: string, config?: any)
async patch_auth(url: string, config?: any)
async patch_auth_data(url: string, config?: any)
async delete(url: string, config?: any)
async delete_data(url: string, config?: any)
async delete_auth(url: string, config?: any)
async delete_auth_data(url: string, config?: any)
```
+11
View File
@@ -0,0 +1,11 @@
import { App } from 'vue'
import { Options } from './types'
import axios from './models/axios'
export default {
install: (app: App, options: Options) => {
if (options && options.disabled === true) return
app.config.globalProperties.$axios = axios
}
}
+158
View File
@@ -0,0 +1,158 @@
import axios from 'axios'
import store from '@/store'
axios.defaults.baseURL = process.env.VUE_APP_WAXIOS_URL
export default {
async get(url: string, config?: any) {
return axios.get(url, config)
.then(response => response.data)
.catch(error => Promise.reject(error))
},
async get_auth(url: string, config?: any) {
config = this._config(config)
return axios.get(url, config)
.then(response => response.data)
.catch(error => Promise.reject(error))
},
async get_data(url: string, config?: any) {
return axios.get(url, config)
.then(response => response.data.data)
.catch(error => Promise.reject(error.response))
},
async get_auth_data(url: string, config?: any) {
config = this._config(config)
return axios.get(url, config)
.then(response => Promise.resolve(response.data.data))
.catch(error => Promise.reject(error.response))
},
async post(url: string, params = null, config?: any) {
return axios.post(url, params, config)
.then(response => response.data)
.catch(error => Promise.reject(error))
},
async post_auth(url: string, params = null, config?: any) {
config = this._config(config)
return axios.post(url, params, config)
.then(response => response.data)
.catch(error => Promise.reject(error))
},
async post_data(url: string, params = null, config?: any) {
return axios.post(url, params, config)
.then(response => response.data.data)
.catch(error => Promise.reject(error.response))
},
async post_auth_data(url: string, params = null, config?: any) {
config = this._config(config)
return axios.post(url, params, config)
.then(response => response.data.data)
.catch(error => Promise.reject(error.response))
},
async delete(url: string, config?: any) {
return axios.delete(url, config)
.then(response => response.data)
.catch(error => Promise.reject(error))
},
async delete_auth(url: string, config?: any) {
config = this._config(config)
return axios.delete(url, config)
.then(response => response.data)
.catch(error => Promise.reject(error))
},
async delete_data(url: string, config?: any) {
return axios.delete(url, config)
.then(response => response.data.data)
.catch(error => Promise.reject(error.response))
},
async delete_auth_data(url: string, config?: any) {
config = this._config(config)
return axios.delete(url, config)
.then(response => response.data.data)
.catch(error => Promise.reject(error.response))
},
async patch(url: string, params = null, config?: any) {
return axios.patch(url, params, config)
.then(response => response.data)
.catch(error => Promise.reject(error))
},
async patch_auth(url: string, params = null, config?: any) {
config = this._config(config)
return axios.patch(url, params, config)
.then(response => response.data)
.catch(error => Promise.reject(error))
},
async patch_data(url: string, params = null, config?: any) {
return axios.patch(url, params, config)
.then(response => response.data.data)
.catch(error => Promise.reject(error.response))
},
async patch_auth_data(url: string, params = null, config?: any) {
config = this._config(config)
return axios.patch(url, params, config)
.then(response => response.data.data)
.catch(error => Promise.reject(error.response))
},
async put(url: string, params = null, config?: any) {
return axios.put(url, params, config)
.then(response => response.data)
.catch(error => Promise.reject(error))
},
async put_auth(url: string, params = null, config?: any) {
config = this._config(config)
return axios.put(url, params, config)
.then(response => response.data)
.catch(error => Promise.reject(error))
},
async put_data(url: string, params = null, config?: any) {
return axios.put(url, params, config)
.then(response => response.data.data)
.catch(error => Promise.reject(error.response))
},
async put_auth_data(url: string, params = null, config?: any) {
config = this._config(config)
return axios.put(url, params, config)
.then(response => response.data.data)
.catch(error => Promise.reject(error.response))
},
_config(config: any) {
if (config) console.error('NOT IMPLEMENTED')
return {
headers: {
Authorization: `Bearer ${store.getters['auth/token']}`
}
}
}
}
+3
View File
@@ -0,0 +1,3 @@
export interface Options {
disabled?: Boolean
}
+35
View File
@@ -0,0 +1,35 @@
# W / Events
- This plugin will add mitt global events to your app
- https://www.npmjs.com/package/mitt
# Required third-party plugins
`$ npm i mitt@2`
# Import in `main.ts`
```javascript
import events from '@/plugins/w/events'
const app = createApp(App)
.use(events)
```
# Examples
1. Listen for event
```javascript
this.eventBus.on('eventname', (optionalData) => ...do something)
```
2. Listen for all events
```javascript
this.eventBus.on('*', (optionalData) => ...do something)
```
3. Fire event
```javascript
this.eventBus.emit('eventname', optionalData)
```
4. Clear all event listeners
```javascript
this.eventBus.all.clear()
```
5. More on https://www.npmjs.com/package/mitt
+11
View File
@@ -0,0 +1,11 @@
import { Options } from './types'
import mitt from 'mitt'
export default {
install: (app, options: Options) => {
if (options && options.disabled === true) return
const eventBus = mitt()
app.config.globalProperties.eventBus = eventBus
}
}
+3
View File
@@ -0,0 +1,3 @@
export interface Options {
disabled?: Boolean
}
+56
View File
@@ -0,0 +1,56 @@
# W / i18n
- This plugin will add translations to your app
- It will automatically add language header to axios requests
# Required third-party plugins
`npm i vue-i18n@9.2.0-beta.22 && npm i vue-i18n-extract@1.2.3 && npm i @capacitor/storage && npm i axios`
# Installation
1. Install all required plugins listed above
2. Create src/locales folder
3. Create language files (see later in exmaples)
4. Configure available languages in main.ts (see later in exmaples)
5. Install plugin `app.use(i18n, options)` (see later in exmaples)
# Installation examples
1. Language file (sk.json)
```json
{
"error": "chyba"
}
```
2. Language configuration and plugin install in `main.ts`
```javascript
import i18n from '@/plugins/w/i18n'
import { Options as WOptions } from '@/plugins/w/w/types'
const options: WOptions = {
languages: [
{title: "Slovenský", flag: "sk", value: "sk"},
{title: "English", flag: "en", value: "en"}
],
defaultLanguage: 'sk'
}
const app = createApp(App)
.use(i18n, options)
```
# Public functions and variables
- Plugin will add public $w18n variable (`this.$w18n`)
```javascript
public currentLanguage: Ref<Language> = ref();
public availableLanguages: Language[];
public vendorI18n: I18nType
public defaultLanguage: Language | null;
public changeLanguage(language: Language) {...}
```
# Interfaces
```javascript
export interface Language {
value: string,
title: string,
flag?: string
}
```
@@ -0,0 +1,56 @@
<template>
<div>
<ion-list lines="none">
<ion-item v-for="item in $w18n.availableLanguages" :key="item.id" @click="languageSelected(item)">
<span :class="`flag ${item.flag}`" :style="{ backgroundImage: `url('${bg}')` }"></span>{{ item.title }}
</ion-item>
</ion-list>
</div>
</template>
<script>
import bg from "./img/flags.png"
import { popoverController } from "@ionic/vue"
export default {
data() {
return {
bg
}
},
methods: {
languageSelected(language) {
this.$w18n.changeLanguage(language)
// this.eventBus.emit("language-changed", language)
popoverController.dismiss()
}
}
}
</script>
<style lang="sass" scoped>
.flag
width: 52px
height: 39px
transform: scale(0.5)
&.sk
background-position: 0 -8569px
&.en
background-position: 0 -3444px
&.cz
background-position: 0 -2337px
&.pl
background-position: 0 -7626px
ion-item
color: #fff
--background: #2C2E30
--border-color: #2C2E30
&:hover
cursor: pointer !important
</style>
Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

+22
View File
@@ -0,0 +1,22 @@
import { Options } from './types'
import { I18n } from './models/i18n'
import events from '@/plugins/w/events'
export default {
install: (app, options: Options) => {
if (options && options.disabled === true)
return
if (!options || !options.languages || !options.defaultLanguage)
return console.warn('[@wezeo/i18n] Could not initialize i18n. Missing configuration options.')
if (!app.config.globalProperties.eventBus) {
app.use(events)
}
const i18n = new I18n(options)
app.use(i18n.vendorI18n)
app.config.globalProperties.$w18n = i18n
}
}
+113
View File
@@ -0,0 +1,113 @@
import { Language, Options } from "../types"
import { Ref, ref } from 'vue'
import axios from 'axios'
import { createI18n, I18n as I18nType } from 'vue-i18n'
import { Storage } from '@capacitor/storage'
export class I18n {
public currentLanguage: Ref<Language> = ref();
public availableLanguages: Language[];
public vendorI18n: I18nType
public defaultLanguage: Language | null;
private languageKey: string;
constructor(properties: Options) {
this.availableLanguages = properties.languages || []
this.defaultLanguage = properties.languages.find(language => language.value == properties.defaultLanguage)
this.languageKey = properties.languageKey || process.env.VUE_APP_PLATFORM + '_language' || 'w18n_language'
this.vendorI18n = createI18n({
legacy: true,
fallbackLocale: this.defaultLanguage.value,
messages: this._loadLocaleMessages(),
missing: this._missingTranslation,
postTranslation: this._postTranslation,
})
this.initCurrentLanguage()
}
public async initCurrentLanguage() {
const { value } = await Storage.get({ key: this.languageKey })
if (value) {
this.currentLanguage.value = JSON.parse(value)
} else if (this.defaultLanguage) {
this.currentLanguage.value = this.defaultLanguage
} else if (this.availableLanguages[0]) {
this.currentLanguage.value = this.availableLanguages[0]
} else {
return console.error('[w18n] Could not init current language')
}
const availableLanguages = {}
this.availableLanguages.forEach(language => {
availableLanguages[language.value] = language.title
})
this.changeLanguage(this.currentLanguage.value)
// Translations.setup(this.currentLanguage.value.value, availableLanguages)
this._addAxiosHeaders()
}
public changeLanguage(language: Language) {
this.currentLanguage.value = language
this._addAxiosHeaders()
Storage.set({
key: this.languageKey,
value: JSON.stringify(language)
})
this.vendorI18n.global.locale = language.value
}
private _addAxiosHeaders() {
axios.interceptors.request.use(config => {
if (this.currentLanguage.value && this.currentLanguage.value.value) {
config.headers['Accept-Language'] = this.currentLanguage.value.value
}
return config
})
}
public _loadLocaleMessages(path = '@/locales') {
let locales
try {
locales = require.context(
'@/locales',
true,
/[A-Za-z0-9-_,\s]+\.json$/i
)
} catch (error) {
console.warn('[@wezeo/i18n] Could not initialize i18n. Missing folder /src/locales.')
return {}
}
const messages: {[key: string]: {[key: string]: string}} = {}
locales.keys().forEach((key) => {
const matched = key.match(/([A-Za-z0-9-_]+)\./i)
if (matched && matched.length > 1) {
const locale = matched[1]
messages[locale] = locales(key)
}
})
return messages
}
private _missingTranslation = (locale, key, instance?, type?) => {
return key
}
private _postTranslation = (translated) => {
return translated
}
}
+12
View File
@@ -0,0 +1,12 @@
export interface Language {
value: string,
title: string,
flag?: string
}
export interface Options {
languages: Language[],
defaultLanguage: string,
languageKey?: string,
disabled?: boolean
}
+11
View File
@@ -0,0 +1,11 @@
# W / Ionic
- This plugin will import all ionic components globally
# Import in `main.ts`
```javascript
import ionic from '@/plugins/w/ionic'
const app = createApp(App)
.use(ionic)
```
+82
View File
@@ -0,0 +1,82 @@
import { App } from 'vue'
import { Options } from './types'
import {
IonContent, IonPage, IonLabel, IonBackButton, IonCheckbox, IonText, IonButton, IonItem,
IonToolbar, IonHeader, IonFooter, IonSlides, IonSlide, IonRow, IonCol, IonGrid, IonInput, IonButtons,
IonIcon, IonList, IonTitle, IonMenu, IonRouterOutlet, IonMenuButton, IonSegment, IonSegmentButton, IonVirtualScroll,
IonTextarea, IonSearchbar, IonRefresherContent, IonRefresher, IonInfiniteScrollContent, IonInfiniteScroll, IonAvatar,
IonModal, IonRadioGroup, IonRadio, IonNote, IonCard, IonCardContent, IonTabBar, IonTabButton, IonMenuToggle, IonFab,
IonFabButton, IonReorderGroup, IonReorder, IonFabList, IonSelect, IonSelectOption, IonToggle, IonBadge, IonChip, IonTabs, IonItemGroup, IonThumbnail, IonItemSliding, IonItemOption, IonItemOptions, IonImg, IonSkeletonText, IonSpinner, IonSplitPane
} from '@ionic/vue'
export default {
install: (app: App, options: Options) => {
if (options && options.disabled === true) return
app.component('ion-content', IonContent)
app.component('ion-page', IonPage)
app.component('ion-label', IonLabel)
app.component('ion-back-button', IonBackButton)
app.component('ion-checkbox', IonCheckbox)
app.component('ion-text', IonText)
app.component('ion-button', IonButton)
app.component('ion-item', IonItem)
app.component('ion-item-group', IonItemGroup)
app.component('ion-item-sliding', IonItemSliding)
app.component('ion-item-option', IonItemOption)
app.component('ion-item-options', IonItemOptions)
app.component('ion-toolbar', IonToolbar)
app.component('ion-header', IonHeader)
app.component('ion-footer', IonFooter)
app.component('ion-slides', IonSlides)
app.component('ion-slide', IonSlide)
app.component('ion-spinner', IonSpinner)
app.component('ion-row', IonRow)
app.component('ion-col', IonCol)
app.component('ion-grid', IonGrid)
app.component('ion-input', IonInput)
app.component('ion-buttons', IonButtons)
app.component('ion-icon', IonIcon)
app.component('ion-img', IonImg)
app.component('ion-list', IonList)
app.component('ion-skeleton-text', IonSkeletonText)
app.component('ion-title', IonTitle)
app.component('ion-menu', IonMenu),
app.component('ion-split-pane', IonSplitPane)
app.component('ion-menu-button', IonMenuButton)
app.component('ion-router-outlet', IonRouterOutlet)
app.component('ion-segment', IonSegment)
app.component('ion-segment-button', IonSegmentButton)
app.component('ion-virtual-scroll', IonVirtualScroll)
app.component('ion-textarea', IonTextarea)
app.component('ion-searchbar', IonSearchbar)
app.component('ion-refresher-content', IonRefresherContent)
app.component('ion-refresher', IonRefresher)
app.component('ion-infinite-scroll-content', IonInfiniteScrollContent)
app.component('ion-infinite-scroll', IonInfiniteScroll)
app.component('ion-avatar', IonAvatar)
app.component('ion-thumbnail', IonThumbnail)
app.component('ion-modal', IonModal)
app.component('ion-radio-group', IonRadioGroup)
app.component('ion-radio', IonRadio)
app.component('ion-note', IonNote)
app.component('ion-card', IonCard)
app.component('ion-card-content', IonCardContent)
app.component('ion-tab-bar', IonTabBar)
app.component('ion-tab-button', IonTabButton),
app.component('ion-menu-toggle', IonMenuToggle)
app.component('ion-fab', IonFab)
app.component('ion-fab-button', IonFabButton)
app.component('ion-fab-list', IonFabList)
app.component('ion-reorder-group', IonReorderGroup)
app.component('ion-reorder', IonReorder)
app.component('ion-select', IonSelect)
app.component('ion-select-option', IonSelectOption)
app.component('ion-toggle', IonToggle)
app.component('ion-badge', IonBadge)
app.component('ion-chip', IonChip),
app.component('ion-tabs', IonTabs)
}
}
+3
View File
@@ -0,0 +1,3 @@
export interface Options {
disabled?: Boolean
}
@@ -0,0 +1,53 @@
<template>
<div>
<div v-if="!content"></div>
<div v-else-if="content?.error">{{ content.error }}</div>
<div v-else-if="(typeof content == 'array' && !array.length) || (typeof content == 'object' && !Object.values(content).length)">{{ emptyMessage }}</div>
<slot v-else></slot>
</div>
</template>
<script>
export default {
props: {
content: {
type: [Object, Array, Boolean],
default: null,
},
emptyMessage: {
type: String,
default: 'No items'
}
},
data() {
return {
loader: null
}
},
created() {
this.startLoading()
},
methods: {
async startLoading() {
if (!this.content)
this.loader = await this.$loading.show()
}
},
watch: {
content(newValue) {
if (newValue)
this.loader.hide()
}
}
}
</script>
<style lang="sass" scoped>
div
height: calc( 100vh - 329px )
</style>
+11
View File
@@ -0,0 +1,11 @@
import { App } from 'vue'
import { Options } from './types'
import WLoadable from './_components/w-loadable.vue'
export default {
install: (app: App, options: Options) => {
if (options && options.disabled === true) return
app.component('W-loadable', WLoadable)
}
}
@@ -0,0 +1,3 @@
export interface Options {
disabled?: Boolean
}
+27
View File
@@ -0,0 +1,27 @@
# W / Moxios
- This plugin will allow you to mock axios request reponses, so you don't have to wait for backend
# Required internal plugins
- w/axios
# Import in `main.ts`
```javascript
import mocks from '@/plugins/w/moxios'
const app = createApp(App)
.use(axios)
.use(mocks, {
routes: {
'GET comments/project/(id)': true,
// Other routes
}
})
```
# Usage
1. Create `mock` folder in `public`
2. Create mocks in `mock` folder. For eaxmple when we want to mock route `comments/project/1` we will create `comments` folder in `mock` folder, then `project` folder and then we will add `(pid).GET.json`. (Final path will be `/public/mock/comments/project/(id).GET.json`).
- NOTE: `(id)` will match any project id
- NOTE: You can change mocks path by adding `VUE_APP_PLATFORM=` variable to .env. Path will change to `/public/mock/${VUE_APP_PLATFORM}/...`
3. After calling `comments/project/1` we will get response from `/public/mock/comments/project/(id).GET.json` file
# Enable / Disable from local storage
- we can enable/disable moxios by typing `localStorage.setItem('isMoxios', 'true')` or `localStorage.setItem('isMoxios', 'false')`
+13
View File
@@ -0,0 +1,13 @@
import { App } from 'vue'
import { Moxios } from './models/moxios'
import { Options } from './types/index.js'
export default {
install: (app: App, options: Options) => {
const moxios = new Moxios()
if (!options || !options.routes || !Object.values(options.routes).length || options.disabled === true) return
moxios.mock(options.routes)
}
}
+73
View File
@@ -0,0 +1,73 @@
import axios from 'axios'
import { encodeGetParams, strToRegex } from '../utils/moxios.util'
export class Moxios {
_mocks = {}
constructor() {
axios.interceptors.request.use(this._redirectRequestToMock.bind(this))
this._mocks = {}
}
mock(append) {
for (const k in append) {
let m = append[k]
if (m === false) continue
m = {}
m.name = k
m.url = k.split(' ')[1]
if (!m.reUrl)
m.reUrl = strToRegex( m.url )
if (!m.matchMethod)
m.matchMethod = k.split(' ')[0].toLowerCase()
this._mocks[k] = m
}
}
_redirectRequestToMock(config) {
// if (localStorage['isMoxios'] == 'false') {
// return config
// }
const url = config.url.replace(/https?:\/\/[^/?]+/, '')
let mocked
for (const k in this._mocks) {
const m = this._mocks[k]
if (config.method == m.matchMethod && url.match(m.reUrl)) {
mocked = m
break
}
}
if (mocked) {
if (!mocked.fname)
process.env.VUE_APP_PLATFORM
? mocked.fname = `/mock/${process.env.VUE_APP_PLATFORM}/${mocked.url}.${config.method.toUpperCase()}.json`
: mocked.fname = `/mock/${mocked.url}.${config.method.toUpperCase()}.json`
console.log(mocked.fname = `/mock/${mocked.url}.${config.method.toUpperCase()}.json`)
const c = {
method: 'get',
url: window.location.origin + mocked.fname+'?___MOCK___&'+encodeGetParams(config.data||{}),
}
config = {...config, ...c}
}
return config
}
}
+4
View File
@@ -0,0 +1,4 @@
export interface Options {
disabled?: Boolean,
routes?: Object
}
@@ -0,0 +1,10 @@
export const encodeGetParams = p =>
Object.entries(p).map(kv => kv.map(encodeURIComponent).join('=')).join('&')
export function strToRegex(s) {
let re = s
re = re.replace(/\//g, '\\/')
re = re.replace(/\./g, '\\.')
re = re.replace(/\([^)]+\)/g, '[^/]+')
return re
}
+13
View File
@@ -0,0 +1,13 @@
# W / Route
- This plugin offers function to simplify routes in router.ts
# Required internal plugins
- w/auth
# Import in `router.ts`
```javascript
import wRoute from '@/plugins/w/route'
# Usage
### use every route in `router.ts` like this
```javascript
wRoute(string:name, string:path, () => import(string:component), boolen:requiresAuth),
```
+11
View File
@@ -0,0 +1,11 @@
import loginGuardIsLoggedIn from '@/plugins/w/auth/loginGuardIfMetaSet'
export default(title: string, path: string, component, requiresAuth: boolean = false) => {
return {
path,
name: title,
meta: { title, requiresAuth: requiresAuth },
component: component,
beforeEnter: loginGuardIsLoggedIn
}
}
+32
View File
@@ -0,0 +1,32 @@
# W / Toast
- This plugin will add global $toast variable, so you can easily use toast anywhere
- This plugin automatically supports w/i18n for translations
# Required internal plugins
- w/i18n
# Installation
1. Import in main.ts
```javascript
import wToast from '@/plugins/w/toast'
const app = createApp(App)
.use(wToast)
```
2. If you have installed w/i18n (you have to import i18n first), all messages will be automatically translated
# Examples
- toast will add global $toast property (this.$toast).
```javascript
1. this.$toast.error(error: any = 'Error', position: 'bottom' | 'middle' | 'top' = 'bottom')
2. this.$toast.success(message: any = 'Success', position: 'bottom' | 'middle' | 'top' = 'bottom')
3. this.$toast.custom(options: ToastOptions)
ToastOptions = {
message: any,
position: 'bottom' | 'middle' | 'top',
color: any,
duration: integer
}
```
+14
View File
@@ -0,0 +1,14 @@
import { Options } from './types'
// import { Toast } from './models/Toast'
import 'vue-toast-notification/dist/theme-sugar.css'
import VueToast from 'vue-toast-notification'
export default {
install: (app, options: Options) => {
if (options && options.disabled === true) return
app.use(VueToast)
// app.config.globalProperties.$wToast = new Toast()
}
}
+30
View File
@@ -0,0 +1,30 @@
// import { ToastPlugin } from '@ionic/vue'
// import { ToastPlugin} from '@ionic/core/dist/types/components/toast/toast-interface'
// import VueToast from 'vue-toast-notification'
// import utils from '../utils/toast.utils'
// export class Toast {
// success(message: any = 'Success', position: 'bottom' | 'middle' | 'top' = 'bottom') {
// const toast = this.$toast.open({
// message: utils.parseAndTranslate(message),
// type: 'success',
// position: position,
// duration: 2000
// })
// }
// error(error: any = 'Error', position: 'bottom' | 'middle' | 'top' = 'bottom') {
// const toast = this.$toast.open({
// message: utils.parseAndTranslate(error),
// type: 'error',
// position: position,
// duration: 2000
// })
// }
// }
// public async custom(options: ToastPlugin) {
// const toast = await ToastPlugin.open(options)
// toast.present()
// }
+3
View File
@@ -0,0 +1,3 @@
export interface Options {
disabled?: boolean
}
@@ -0,0 +1,36 @@
export default {
parseAndTranslate(data) {
const errorsArray = this._parseToArrayOfStrings(data)
return errorsArray.map(error => this._translate(error))
},
_parseToArrayOfStrings(data) {
if (typeof data == 'string') {
return [this._translate(data)]
}
if (data && data.error && typeof data.error == 'string') {
return [this._translate(data.error)]
}
if (data && data.error && typeof data.error == 'object') {
return Object.values(this._translate(data.error))
}
if (data.data && data.data.error && typeof data.data.error == 'string') {
return [this._translate(data.data.error)]
}
if (data && data.data && data.data.error && typeof data.data.error == 'object') {
return Object.values(data.data.error).map(error => this._translate(error[0]) + ' ')
}
if (data.statusText) {
return [this._translate(data.statusText)]
}
return [data]
}
}
+89
View File
@@ -0,0 +1,89 @@
# W / W
- This plugin will install all w plugins, so you don't have to install separately
# Required third-party plugins
`npm i vuex@4 && npm i axios && npm i mitt@2 && npm i vue-i18n@9.2.0-beta.22 && npm i vue-i18n-extract@1.2.3 && npm i @capacitor/storage && npm i axios-auth-refresh`
# note !!
## if you are getting erorrs with bad webpack version try this
'BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.'
### 1. install this module
```javascript
npm install --save node-polyfill-webpack-plugin
```
### 2. create in root directory
```javascript
vue.config.js
```
### 3. add this to vue.config.js
```javascript
const { defineConfig } = require("@vue/cli-service");
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin");
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false,
configureWebpack: {
plugins: [new NodePolyfillPlugin()],
optimization: {
splitChunks: {
chunks: "all",
},
},
},
});
```
- full documentation here: https://web3auth.io/docs/troubleshooting/webpack-issues#vuejs
# Required internal plugins
- w/auth
- w/axios
- w/events
- w/ionic
- w/i18n
- w/toast
- w/moxios
- w/route
# Installaton
1. Install all required plugins listed above
2. Set strict property in tsconfig to false
3. Create store.ts in @/
4. Add this to store.ts
```javascript
import { createStore } from 'vuex'
export default createStore({
modules: {}
})
```
5. Import store and w in main.ts (store has to be imported first)
```javascript
import w from '@/plugins/w/w'
const app = createApp(App)
.use(store)
.use(w)
```
# Options
- you can configure each plugin (for example disable it) separately, then you have to pass this object as second argument `.use(w, options)`
```javascript
import { Options as WOptions } from '@/plugins/w/w/types'
const options: WOptions = {
i18n: {
languages: [
{title: "Slovenský", flag: "sk", value: "sk"},
{title: "English", flag: "en", value: "en"}
],
defaultLanguage: 'sk'
}
}
```
# Examples
- each plugin has it's own readme with examples
+24
View File
@@ -0,0 +1,24 @@
import { App } from 'vue'
import { Options } from './types'
import axios from '@/plugins/w/axios'
import moxios from '@/plugins/w/moxios'
import events from '@/plugins/w/events'
import i18n from '@/plugins/w/i18n'
import ionic from '@/plugins/w/ionic'
import auth from '@/plugins/w/auth'
import toast from '@/plugins/w/toast'
import loadable from '@/plugins/w/loadable'
export default {
install: (app: App, options: Options = {}) => {
events.install(app, options.events)
axios.install(app, options.axios)
i18n.install(app, options.i18n)
moxios.install(app, options.moxios)
ionic.install(app, options.ionic)
auth.install(app, options.auth)
toast.install(app, options.toast)
loadable.install(app, options.loadable)
}
}
+19
View File
@@ -0,0 +1,19 @@
import { Options as AxiosOptions } from '@/plugins/w/axios/types'
import { Options as MoxiosOptions } from '@/plugins/w/moxios/types'
import { Options as EventsOptions } from '@/plugins/w/events/types'
import { Options as AuthOptions } from '@/plugins/w/auth/types'
import { Options as I18nOptions } from '@/plugins/w/i18n/types'
import { Options as IonicOptions } from '@/plugins/w/ionic/types'
import { Options as ToastOptions } from '@/plugins/w/toast/types'
import { Options as LoadableOptions } from '@/plugins/w/loadable/types'
export interface Options {
axios?: AxiosOptions,
moxios?: MoxiosOptions,
events?: EventsOptions,
auth?: AuthOptions,
i18n?: I18nOptions,
ionic?: IonicOptions,
toast?: ToastOptions,
loadable?: LoadableOptions
}