Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"vue-property-decorator": "^7.0.0",
"vue-router": "^3.0.2",
"vuex": "^3.0.1",
"vuex-smart-module": "^0.2.0",
"webfontloader": "^1.6.28"
},
"devDependencies": {
Expand Down
180 changes: 106 additions & 74 deletions src/store.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import Vue from "vue";
import Vuex from "vuex";
import {
Getters,
Mutations,
Actions,
Module,
createStore
} from "vuex-smart-module";

import { orderBy } from "lodash";
import firebase from "firebase";
Expand All @@ -9,82 +16,107 @@ Vue.use(Vuex);

const octokit = new Octokit();

export default new Vuex.Store({
state: {
isWebFontLoading: true,
accessToken: null,
keywords: [] as Array<string>
},
getters: {
isSignIn(state) {
return state.accessToken !== null;
}
},
mutations: {
setIsWebFontLoading(state, { isWebFontLoading }) {
state.isWebFontLoading = isWebFontLoading;
},
setAccessToken(state, { accessToken }) {
state.accessToken = accessToken;
},
clearAccessToken(state) {
state.accessToken = null;
},
addKeyword(state, { keyword }) {
state.keywords.push(keyword);
},
clearKeywords(state) {
state.keywords = [];
},
setKeywords(state, { keyword }: { keyword: string }) {
state.keywords = keyword.trim().split(" ");
class State {
isWebFontLoading = true;
accessToken?: string;
keywords: Array<string> = [];
}

class Getter extends Getters<State> {
get isSignIn(): boolean {
return this.state.accessToken !== undefined;
}
}

class Mutation extends Mutations<State> {
setIsWebFontLoading({ isWebFontLoading }: { isWebFontLoading: boolean }) {
this.state.isWebFontLoading = isWebFontLoading;
}

setAccessToken({ accessToken }: { accessToken: string }) {
this.state.accessToken = accessToken;
}

clearAccessToken() {
this.state.accessToken = undefined;
}

addKeyword({ keyword }: { keyword: string }) {
this.state.keywords.push(keyword);
}

clearKeywords() {
this.state.keywords = [];
}

setKeywords({ keyword }: { keyword: string }) {
this.state.keywords = keyword.trim().split(" ");
}
}

class Action extends Actions<State, Getter, Mutation, Action> {
setupAuthenticate({ accessToken }: { accessToken: string }) {
octokit.authenticate({
type: "token",
token: accessToken
});
}

setAccessToken({ accessToken }: { accessToken: string }) {
this.commit("setAccessToken", { accessToken });
localStorage.setItem("accessToken", accessToken);
this.dispatch("setupAuthenticate", { accessToken });
}

loadAccessToken() {
const accessToken = localStorage.getItem("accessToken");
if (accessToken) {
this.dispatch("setAccessToken", { accessToken });
}
},
actions: {
loadAccessToken(context) {
const accessToken = localStorage.getItem("accessToken");
if (accessToken) {
context.dispatch("setAccessToken", { accessToken });
}
},
async signIn() {
const provider = new firebase.auth.GithubAuthProvider();
await firebase.auth().signInWithRedirect(provider);
},
setAccessToken(context, { accessToken }) {
context.commit("setAccessToken", { accessToken });
localStorage.setItem("accessToken", accessToken);
context.dispatch("setupAuthenticate", { accessToken });
},
async signOut(context) {
context.commit("clearAccessToken");
localStorage.removeItem("accessToken");
},
setupAuthenticate(_, { accessToken }) {
octokit.authenticate({
type: "token",
token: accessToken
});
},
async search(context) {
const promisedResults = context.state.keywords.map(async keyword => {
const { data } = await octokit.search.code({
q: keyword
});

return {
keyword,
total: data.total_count as number
};
}

async signIn() {
const provider = new firebase.auth.GithubAuthProvider();
await firebase.auth().signInWithRedirect(provider);
}

signOut() {
// XXXX: payload?
this.commit("clearAccessToken", undefined);
localStorage.removeItem("accessToken");
}

async search() {
const promisedResults = this.state.keywords.map(async keyword => {
const { data } = await octokit.search.code({
q: keyword
});

const results = await Promise.all(promisedResults);
const orderedResults = orderBy(
results,
["total", "keyword"],
["desc", "asc"]
).map((result, index) => ({ rank: index + 1, ...result }));
return orderedResults;
}
return {
keyword,
total: data.total_count as number
};
});

const results = await Promise.all(promisedResults);
const orderedResults = orderBy(
results,
["total", "keyword"],
["desc", "asc"]
).map((result, index) => ({ rank: index + 1, ...result }));
return orderedResults;
}
}

export const rootModule = new Module({
state: State,
getters: Getter,
mutations: Mutation,
actions: Action
});

const store = createStore(rootModule, {
strict: process.env.NODE_ENV !== "production"
});

export default store;
16 changes: 8 additions & 8 deletions src/views/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import Octokit from "@octokit/rest";

import { Component, Vue, Watch } from "vue-property-decorator";

import store from "@/store";
import store, { rootModule } from "@/store";
import KeywordInput from "@/components/KeywordInput.vue";
import SearchButton from "@/components/SearchButton.vue";
import SignInButton from "@/components/SignInButton.vue";
Expand All @@ -37,27 +37,27 @@ export default class Home extends Vue {
private octokit?: Octokit;
private results = [];
private keyword: string = "";
private context = rootModule.context(store);

async signOut() {
await store.dispatch("signOut");
await this.context.dispatch("signOut", undefined);
this.$router.push({ path: "/sign-in" });
}
async created() {
this.octokit = new Octokit();
this.octokit.authenticate({
type: "token",
token: store.state.accessToken!
this.context.dispatch("setupAuthenticate", {
accessToken: this.context.state.accessToken!
});

if (this.$route.query.q) {
this.keyword = this.$route.query.q as string;
this.context.commit("setKeywords", { keyword: this.keyword });
this.search();
}
}
async search() {
this.$store.commit("setKeywords", { keyword: this.keyword });
this.context.commit("setKeywords", { keyword: this.keyword });

const results = await this.$store.dispatch("search");
const results = await this.context.dispatch("search", undefined);

this.results = results;
}
Expand Down
4 changes: 4 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8635,6 +8635,10 @@ vue@^2.5.17:
version "2.5.21"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.21.tgz#3d33dcd03bb813912ce894a8303ab553699c4a85"

vuex-smart-module@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/vuex-smart-module/-/vuex-smart-module-0.2.0.tgz#5954f636e8e0085dfe7ae810fead8e5783351d7f"

vuex@^3.0.1:
version "3.1.0"
resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.1.0.tgz#634b81515cf0cfe976bd1ffe9601755e51f843b9"
Expand Down