diff --git a/package.json b/package.json index 8683756..4fd48c9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,12 @@ { - "name": "sample", - "version": "0.1.0", + "name": "sample-vue-typescript", + "version": "1.0.0", + "description": "Sample project using typescript and bootstrap with vue", + "author": { + "name": "Vimlesh Patel", + "email": "vimlesh.0401@gmail.com", + "url": "https://github.com/vimlesh-0401/sample-vue-typescript" + }, "private": true, "scripts": { "serve": "vue-cli-service serve", diff --git a/src/App.vue b/src/App.vue index 74df185..43146ee 100644 --- a/src/App.vue +++ b/src/App.vue @@ -5,8 +5,8 @@ Sample App - First Module - Second Module + Sample Component + Login Component diff --git a/src/app/baluster/api.ts b/src/app/baluster/api.ts new file mode 100644 index 0000000..963dda9 --- /dev/null +++ b/src/app/baluster/api.ts @@ -0,0 +1,7 @@ +import { HTTP, CLIENT } from '../../http'; + +export const api = { + fetchPickets(params: any) { + return HTTP.get('https://api.adviceslip.com/advice', {responseType: 'json'}); + }, +}; diff --git a/src/app/baluster/components/BalusterMasterCard.vue b/src/app/baluster/components/BalusterMasterCard.vue new file mode 100644 index 0000000..4af2868 --- /dev/null +++ b/src/app/baluster/components/BalusterMasterCard.vue @@ -0,0 +1,19 @@ + + + diff --git a/src/app/baluster/components/DefaultCard.vue b/src/app/baluster/components/DefaultCard.vue new file mode 100644 index 0000000..754eef8 --- /dev/null +++ b/src/app/baluster/components/DefaultCard.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/app/baluster/components/ParamountCard.vue b/src/app/baluster/components/ParamountCard.vue new file mode 100644 index 0000000..a056b51 --- /dev/null +++ b/src/app/baluster/components/ParamountCard.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/app/baluster/components/PronouncementCard.vue b/src/app/baluster/components/PronouncementCard.vue new file mode 100644 index 0000000..76eca1d --- /dev/null +++ b/src/app/baluster/components/PronouncementCard.vue @@ -0,0 +1,17 @@ + + + \ No newline at end of file diff --git a/src/app/baluster/components/index.ts b/src/app/baluster/components/index.ts new file mode 100644 index 0000000..c02008d --- /dev/null +++ b/src/app/baluster/components/index.ts @@ -0,0 +1,4 @@ +export { default as BalusterMasterCard } from './BalusterMasterCard.vue'; +export { default as ParamountCard } from './ParamountCard.vue'; +export { default as PronouncementCard } from './PronouncementCard.vue'; +export { default as DefaultCard } from './DefaultCard.vue'; diff --git a/src/app/baluster/index.ts b/src/app/baluster/index.ts new file mode 100644 index 0000000..1646055 --- /dev/null +++ b/src/app/baluster/index.ts @@ -0,0 +1,2 @@ +export { default as routes } from './routes'; +export { jamb as vuex } from './vuex'; diff --git a/src/app/baluster/routes.ts b/src/app/baluster/routes.ts new file mode 100644 index 0000000..e0e723a --- /dev/null +++ b/src/app/baluster/routes.ts @@ -0,0 +1,19 @@ +import { DefaultCard, BalusterMasterCard, ParamountCard, PronouncementCard } from './components'; + +export default [ + { + path: '/baluster', + component: BalusterMasterCard, + children: [ + { + path: '/', + components: { + default: DefaultCard, + paramount: ParamountCard, + pronouncement: PronouncementCard, + }, + name: 'baluster', + }, + ], + }, +]; diff --git a/src/app/baluster/vuex/actions.ts b/src/app/baluster/vuex/actions.ts new file mode 100644 index 0000000..e2f72ba --- /dev/null +++ b/src/app/baluster/vuex/actions.ts @@ -0,0 +1,11 @@ +import { ActionTree } from 'vuex'; +import { JambState } from './types'; +import { RootState } from '@/app/types'; +import { api } from '../api'; +export const actions: ActionTree = { + pickets({commit}): any { + api.fetchPickets({}).then((response: any) => { + console.log(response); + }); + }, +}; diff --git a/src/app/baluster/vuex/getters.ts b/src/app/baluster/vuex/getters.ts new file mode 100644 index 0000000..67a8527 --- /dev/null +++ b/src/app/baluster/vuex/getters.ts @@ -0,0 +1,10 @@ +import { GetterTree } from 'vuex'; +import { JambState } from './types'; +import { RootState } from '../../types'; + +export const getters: GetterTree = { + columns(state): string { + const {message} = state; + return message; + }, +}; diff --git a/src/app/baluster/vuex/index.ts b/src/app/baluster/vuex/index.ts new file mode 100644 index 0000000..e991815 --- /dev/null +++ b/src/app/baluster/vuex/index.ts @@ -0,0 +1,22 @@ +import { Module } from 'vuex'; +import { getters } from './getters'; +import { actions } from './actions'; +import { mutations } from './mutations'; + +import { RootState } from '../../types'; +import { JambState } from './types'; + +export const state: JambState = { + message: '', + error: false, +}; + +const namespaced: boolean = true; + +export const jamb: Module = { + namespaced, + state, + getters, + actions, + mutations, +}; diff --git a/src/app/baluster/vuex/mutations.ts b/src/app/baluster/vuex/mutations.ts new file mode 100644 index 0000000..153e481 --- /dev/null +++ b/src/app/baluster/vuex/mutations.ts @@ -0,0 +1,14 @@ +import { MutationTree } from 'vuex'; +import { JambState } from './types'; + +export const mutations: MutationTree = { + sampleDataLoaded(state, payload: string) { + state.message = payload; + state.error = false; + }, + + sampleError(state) { + state.error = true; + state.message = ''; + }, +}; diff --git a/src/app/baluster/vuex/types.ts b/src/app/baluster/vuex/types.ts new file mode 100644 index 0000000..3fe9f90 --- /dev/null +++ b/src/app/baluster/vuex/types.ts @@ -0,0 +1,4 @@ +export interface JambState { + message: string; + error: boolean; +} diff --git a/src/app/login/api.ts b/src/app/login/api.ts index ff8caf3..27d1dbd 100644 --- a/src/app/login/api.ts +++ b/src/app/login/api.ts @@ -1,11 +1,7 @@ -import { HTTP, CLIENT } from '../../http'; +import { HTTP } from '../../http'; export const api = { getServerStatus(params: any) { - params.client_id = CLIENT.client_id; - params.client_secret = CLIENT.client_secret; - params.scope = CLIENT.scope; - return HTTP.get('https://randomuser.me/api/', {responseType: 'json'}); }, }; diff --git a/src/app/login/components/LoginBaseCard.vue b/src/app/login/components/LoginBaseCard.vue index f790211..c633f45 100644 --- a/src/app/login/components/LoginBaseCard.vue +++ b/src/app/login/components/LoginBaseCard.vue @@ -18,6 +18,11 @@ + +

+ {{quote.quote}} +

+
@@ -26,10 +31,13 @@ import Vue from 'vue'; import { State, Action, Getter } from 'vuex-class'; import { LoginState, User} from '../vuex/types'; + import { FeedCardMixin } from '@/app/mixins'; + import { Mixins } from 'vue-mixin-decorator'; + const namespace: string = 'login'; @Component - export default class LoginBaseCard extends Vue { + export default class LoginBaseCard extends Mixins(FeedCardMixin) { @State('login') private login!: LoginState; @Action('fetchData', {namespace}) private fetchData: any; @Getter('name', {namespace}) private name!: string; diff --git a/src/app/mixins/api.ts b/src/app/mixins/api.ts index ea8c32a..5d141c2 100644 --- a/src/app/mixins/api.ts +++ b/src/app/mixins/api.ts @@ -4,4 +4,15 @@ export const api = { getLocation(params: any) { return HTTP.get('https://restcountries.eu/rest/v2/regionalbloc/SAARC', {responseType: 'json'}); }, + + getFeeds() { + return HTTP.get( + 'http://quotesondesign.com//wp-json/posts?filter[orderby]=rand&filter[posts_per_page]=1', + ); + }, + getQuote() { + return HTTP.get( + 'https://talaikis.com/api/quotes/random/', + ); + }, }; diff --git a/src/app/mixins/index.ts b/src/app/mixins/index.ts index f710cf5..de95ffc 100644 --- a/src/app/mixins/index.ts +++ b/src/app/mixins/index.ts @@ -1 +1,3 @@ export { location as vuex } from './vuex'; +export { Location as LocationMixin } from './mixin/location'; +export { FeedCard as FeedCardMixin } from './mixin/feed_card'; diff --git a/src/app/mixins/mixin/feed_card.ts b/src/app/mixins/mixin/feed_card.ts new file mode 100644 index 0000000..584e778 --- /dev/null +++ b/src/app/mixins/mixin/feed_card.ts @@ -0,0 +1,17 @@ +import { Mixin } from 'vue-mixin-decorator'; +import Vue from 'vue'; +import { Action, State, Getter } from 'vuex-class'; +import { MixinState, QuoteState } from '../vuex/types'; + +@Mixin +export class FeedCard extends Vue { + @State('mixins') private mixin!: MixinState; + @Action('feedData', {namespace: 'mixins'}) private feedData: any; + @Action('quoteData', {namespace: 'mixins'}) private quoteData: any; + @Getter('getQuoteState', {namespace: 'mixins'}) private quote!: QuoteState; + public created() { + this.feedData().then(() => { + this.quoteData(); + }); + } +} diff --git a/src/app/mixins/mixin/location.ts b/src/app/mixins/mixin/location.ts index cee144b..4fde7f6 100644 --- a/src/app/mixins/mixin/location.ts +++ b/src/app/mixins/mixin/location.ts @@ -1,13 +1,12 @@ import { Mixin } from 'vue-mixin-decorator'; import Vue from 'vue'; import { State, Getter, Action } from 'vuex-class'; -import { LocationState } from '../vuex/types'; @Mixin export class Location extends Vue { - @State('mixins') private location!: LocationState; @Action('locationData', {namespace: 'mixins'}) private locationData: any; @Getter('list', {namespace: 'mixins'}) private list: any; + @Getter('sliderList', {namespace: 'mixins'}) private sliderList: any; private created() { this.locationData(); diff --git a/src/app/mixins/vuex/actions.ts b/src/app/mixins/vuex/actions.ts index ef1d69f..0e8b1d2 100644 --- a/src/app/mixins/vuex/actions.ts +++ b/src/app/mixins/vuex/actions.ts @@ -1,11 +1,22 @@ import { ActionTree } from 'vuex'; -import { LocationState } from './types'; +import { MixinState } from './types'; import { RootState } from '@/app/types'; import { api } from '../api'; -export const actions: ActionTree = { +export const actions: ActionTree = { locationData({commit}): any { api.getLocation({}).then((response: any) => { commit('sampleLocationLoaded', response.data); }); }, + + feedData({commit}): any { + return api.getFeeds().then((response: any) => { + commit('sampleFeedsLoaded', response.data); + }); + }, + quoteData({commit}): any { + return api.getQuote().then((response) => { + commit('sampleQuoteLoaded', response.data); + }); + }, }; diff --git a/src/app/mixins/vuex/getters.ts b/src/app/mixins/vuex/getters.ts index 37e143f..3e93276 100644 --- a/src/app/mixins/vuex/getters.ts +++ b/src/app/mixins/vuex/getters.ts @@ -1,11 +1,32 @@ import { GetterTree } from 'vuex'; -import { LocationState } from './types'; +import { MixinState, QuoteState, CountryState } from './types'; import { RootState } from '../../types'; -export const getters: GetterTree = { +export const getters: GetterTree = { list(state): any { - return state && state.list.map((l: any) => { - return { name: l.name, capital: l.capital, population: l.population, region: l.region }; + const { countries } = state; + return countries.map((c) => c); + }, + sliderList(state): any { + const {countries} = state; + return countries && countries.map((l: CountryState) => { + return { + name: l.name, + flag: l.flag, + info: { + capital: l.capital, + population: l.population, + region: l.region, + languages: l.languages.join(', '), + nativeName: l.nativeName, + area: l.area, + }, + }; }); }, + + getQuoteState(state): QuoteState { + const {quote} = state; + return quote ? quote : {author: '', quote: '', category: ''}; + }, }; diff --git a/src/app/mixins/vuex/index.ts b/src/app/mixins/vuex/index.ts index bafc89e..a6ce383 100644 --- a/src/app/mixins/vuex/index.ts +++ b/src/app/mixins/vuex/index.ts @@ -4,16 +4,19 @@ import { actions } from './actions'; import { mutations } from './mutations'; import { RootState } from '../../types'; -import { LocationState } from './types'; +import { MixinState } from './types'; -export const state: LocationState = { - list: [], - error: false, +export const state: MixinState = { + feed: undefined, + quote: undefined, + country: undefined, + countries: [], + feeds: [], }; const namespaced: boolean = true; -export const location: Module = { +export const location: Module = { namespaced, state, getters, diff --git a/src/app/mixins/vuex/mutations.ts b/src/app/mixins/vuex/mutations.ts index 8523428..1faf5c8 100644 --- a/src/app/mixins/vuex/mutations.ts +++ b/src/app/mixins/vuex/mutations.ts @@ -1,14 +1,36 @@ import { MutationTree } from 'vuex'; -import { LocationState } from './types'; +import { MixinState, QuoteState, FeedState, CountryState } from './types'; -export const mutations: MutationTree = { +export const mutations: MutationTree = { sampleLocationLoaded(state, payload: any) { - state.list = payload; - state.error = false; + for (const c of payload) { + const country: CountryState = { + name: c.name, + flag: c.flag, + capital: c.capital, + population: c.population, + region: c.region, + languages: c.languages.map((lang: any) => lang.name), + nativeName: c.nativeName, + area: c.area, + }; + state.countries.push(country); + } }, locationError(state) { - state.error = true; - state.list = []; + state.country = undefined; + }, + + sampleQuoteLoaded(state, payload: any) { + const quote: QuoteState = { author: payload.author, category: payload.cat, quote: payload.quote }; + state.quote = quote; + }, + + sampleFeedsLoaded(state, payload: any) { + for (const f of payload) { + const feed: FeedState = {id: f.ID, content: f.content, title: f.title}; + state.feeds.push(feed); + } }, }; diff --git a/src/app/mixins/vuex/types.ts b/src/app/mixins/vuex/types.ts index 7014e36..334d7d1 100644 --- a/src/app/mixins/vuex/types.ts +++ b/src/app/mixins/vuex/types.ts @@ -1,4 +1,30 @@ -export interface LocationState { - list: any; - error: boolean; +export interface CountryState { + name: string; + flag: string; + capital: string; + population: string; + region: string; + languages: string[]; + nativeName: string; + area: number; +} + +export interface FeedState { + id: number; + title: string; + content: string; +} + +export interface QuoteState { + author: string; + category: string; + quote: string; +} + +export interface MixinState { + country?: CountryState; + countries: CountryState[]; + feed?: FeedState; + feeds: FeedState[]; + quote?: QuoteState; } diff --git a/src/app/routes.ts b/src/app/routes.ts index 9b49756..3739afc 100644 --- a/src/app/routes.ts +++ b/src/app/routes.ts @@ -1,7 +1,9 @@ import { routes as login } from './login'; import { routes as sample } from './sample'; +import { routes as jamb } from './baluster'; export default [ ...login, ...sample, + ...jamb, ]; diff --git a/src/app/sample/components/SampleComponent.vue b/src/app/sample/components/SampleComponent.vue index 72f9ddd..36efeb9 100644 --- a/src/app/sample/components/SampleComponent.vue +++ b/src/app/sample/components/SampleComponent.vue @@ -6,13 +6,34 @@

{{message}}

- Second Module + Login Component + + + + + + + + @@ -22,18 +43,43 @@ import Component from 'vue-class-component'; import { State, Action, Getter } from 'vuex-class'; import { SampleState } from '../vuex/types'; - import { Location } from '@/app/mixins/mixin/location'; + import { LocationMixin } from '@/app/mixins'; import { Mixins } from 'vue-mixin-decorator'; const namespace: string = 'sample'; - @Component - export default class SampleComponent extends Mixins(Location) { + /** + * router callback wont be called if you define them inside component class. + * You need to register them before component resolve. + */ + @Component({ + beforeRouteEnter: (to, from , next) => { + next(); + }, + }) + export default class SampleComponent extends Mixins(LocationMixin) { @Action('sampleData', {namespace}) private sampleData: any; @State('sample') private sample!: SampleState; @Getter('message', {namespace}) private message!: string; + private data() { + return { + slide: 0, + }; + } private mounted() { this.sampleData(); } + private onSlideStart(slide: any) { + console.log('Slide Start: ' + slide); + } + private onSlideEnd(slide: any) { + console.log('Slide End: ' + slide); + } } + + diff --git a/src/app/sample/routes.ts b/src/app/sample/routes.ts index 18d0e14..ec35c1d 100644 --- a/src/app/sample/routes.ts +++ b/src/app/sample/routes.ts @@ -1,9 +1,14 @@ import { SampleComponent } from './components'; +import { Route } from 'vue-router'; export default [ { path: '/sample-component', component: SampleComponent, + name: 'sample.component', + beforeEnter: (to: Route, from: Route, next: any) => { + next(); + }, }, { path: '', diff --git a/src/app/vuex.ts b/src/app/vuex.ts index 3ccc6b6..9a96679 100644 --- a/src/app/vuex.ts +++ b/src/app/vuex.ts @@ -1,8 +1,11 @@ import { vuex as login } from './login'; import { vuex as sample } from './sample'; import { vuex as mixins } from './mixins'; +import { vuex as jamb } from './baluster'; + export default { login, sample, mixins, + jamb, }; diff --git a/src/http.ts b/src/http.ts index 9893337..76d3403 100644 --- a/src/http.ts +++ b/src/http.ts @@ -1,14 +1,12 @@ import axios from 'axios'; -/** - * Move these configurations to evn specific files. - */ + const config = { NODE_ENV: process.env.NODE_ENV, - BASE_URL: process.env.baseURL, + BASE_URL: process.env.VUE_APP_BASE_URL, CLIENT: { - scope: '"user"', - client_id: process.env.client_id, - client_secret: process.env.client_secret, + SCOPE: process.env.VUE_APP_SCOPE, + CLIENT_ID: process.env.VUE_APP_CLIENT_ID, + CLIENT_SECRET: process.env.VUE_APP_CLIENT_SECRET, }, }; diff --git a/src/router.ts b/src/router.ts index 067df4d..4306db4 100644 --- a/src/router.ts +++ b/src/router.ts @@ -1,5 +1,5 @@ import Vue from 'vue'; -import Router from 'vue-router'; +import Router, { Route } from 'vue-router'; import { routes } from './app'; Vue.use(Router); @@ -14,8 +14,16 @@ const router = new Router({ * Configure pre request checks and router validations. * Access control. */ -router.beforeEach((to, from, next) => { +router.beforeEach((to: Route, from: Route, next: any) => { next(); }); +router.beforeResolve((to: Route, from: Route, next: any) => { + next(); +}); + +router.afterEach((to: Route, from: Route) => { + // Here do something after everything is ready. +}); + export default router; diff --git a/vue.config.js b/vue.config.js index b359cf2..72f2dd1 100644 --- a/vue.config.js +++ b/vue.config.js @@ -8,11 +8,27 @@ module.exports = { alias: { '@': `${projectRoot}/src`, '~': `${projectRoot}/src/assets`, - 'HTTP': `${projectRoot}/src`, } }, devServer: { - // open: true, + open: true, + setup: (app, server) => { + const CONFIG_CHECKS = ['VUE_APP_CLIENT_ID', 'VUE_APP_CLIENT_SECRET', 'VUE_APP_BASE_URL', 'VUE_APP_SCOPE' ]; + + for (const key of CONFIG_CHECKS) { + if (process.env[key] === undefined) { + throw new Error(`value for ${key} is not defined.. Please setup .env variables.`); + } + } + }, + before: (app, server) => { + // app.get('/api/status', (request, response) => { + // }) + }, + overlay: { + warnings: true, + errors: true, + }, } } } \ No newline at end of file