From 4fd92d913010888b7df3c4d6595b510fb80301bb Mon Sep 17 00:00:00 2001 From: Abhas Date: Wed, 11 Jul 2018 19:44:03 +0530 Subject: [PATCH] Add redux store and package --- package.json | 3 +- src/store/actions.ts | 34 ++++++++++ src/store/index.ts | 47 +------------ src/store/model.ts | 58 ++++++++++++++++ src/store/reducers.ts | 65 ++++++++++++++++++ src/types/index.ts | 149 +++++++++++++++++++++++------------------- yarn.lock | 21 ++++++ 7 files changed, 263 insertions(+), 114 deletions(-) create mode 100644 src/store/actions.ts create mode 100644 src/store/model.ts create mode 100644 src/store/reducers.ts diff --git a/package.json b/package.json index dd78813..b82e1b2 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,8 @@ "@octokit/rest": "^15.6.2", "babel-polyfill": "^6.26.0", "bottleneck": "^2.3.1", - "octonode": "^0.9.2" + "octonode": "^0.9.2", + "redux": "^4.0.0" }, "devDependencies": { "@types/jest": "^22.0.1", diff --git a/src/store/actions.ts b/src/store/actions.ts new file mode 100644 index 0000000..b818578 --- /dev/null +++ b/src/store/actions.ts @@ -0,0 +1,34 @@ +import { Action } from 'redux'; +import { FilterSteps, RepoFilterState } from './model'; + +export enum ActionNames { + InitUserName = 'InitUserName', + InitRepo = 'InitRepo', + AddRepoFilterStatus = 'AddRepoFilterStatus', +} + +export interface InitUserNameArgs extends Action { + payload: { + userName: string; + }; +} + +export interface InitRepoArgs extends Action { + payload: { + repoName: string; + }; +} + +export interface AddRepoFilterStatusArgs + extends Action { + payload: { + repoName: string; + filterStep: FilterSteps; + filterState: RepoFilterState[FilterSteps]; + }; +} + +export type ActionsType = + InitUserNameArgs + | InitRepoArgs + | AddRepoFilterStatusArgs; diff --git a/src/store/index.ts b/src/store/index.ts index 1d70389..2566556 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -1,44 +1,3 @@ -import { Store, createStore, applyMiddleware } from 'redux'; - -export namespace FailReasons { - export enum EachBranchBehindOrEven { - 'remote branch doesn\'t exist', - 'forked branch ahead' - }; - - export enum NotContributor { - 'contributor in self repo', - 'contributor in parent repo' - }; - - export enum NoCommits { - 'commit in self repo', - 'commit in parent repo' - }; - -} - -export interface GithubRepoFilterState { - eachBranchBehindOrEven: { - fail: boolean, - failReason: FailReasons.EachBranchBehindOrEven - failBranchName: string - }, - notContributor: { - fail: boolean, - failReason: FailReasons.NotContributor - }, - noCommits: { - fail: boolean, - failReason: FailReasons.NoCommits - } -} - -export type GithubRepoFilterStates = Map; - -export interface ApplicationState { - username: string; - repoStates: GithubRepoFilterStates; -} \ No newline at end of file +export * from './model'; +export * from './actions'; +export * from './reducers'; diff --git a/src/store/model.ts b/src/store/model.ts new file mode 100644 index 0000000..05f90c5 --- /dev/null +++ b/src/store/model.ts @@ -0,0 +1,58 @@ +import { Store, createStore, applyMiddleware } from 'redux'; + +export namespace FailReasons { + export enum EachBranchBehindOrEven { + "remote branch doesn't exist", + 'forked branch ahead', + } + + export enum NotContributor { + 'contributor in self repo', + 'contributor in parent repo', + } + + export enum NoCommits { + 'commit in self repo', + 'commit in parent repo', + } +} + +export enum FilterSteps { + eachBranchBehindOrEven = 'eachBranchBehindOrEven', + notContributor = 'notContributor', + noCommits = 'noCommits', +} + +export enum FilterStatus { + 'pass', + 'fail', + 'waiting', +} + +export interface RepoFilterState { + [FilterSteps.eachBranchBehindOrEven]: { + status: FilterStatus; + failReason?: FailReasons.EachBranchBehindOrEven; + failBranchName?: string; + }; + [FilterSteps.notContributor]: { + status: FilterStatus; + failReason?: FailReasons.NotContributor; + }; + [FilterSteps.noCommits]: { + status: FilterStatus; + failReason?: FailReasons.NoCommits; + }; +} + +export type RepoFilterStateMap = Map< + string, + { + filterState: RepoFilterState; + } +>; + +export interface ApplicationState { + username: string; + repoStateMap: RepoFilterStateMap; +} diff --git a/src/store/reducers.ts b/src/store/reducers.ts new file mode 100644 index 0000000..7e670d5 --- /dev/null +++ b/src/store/reducers.ts @@ -0,0 +1,65 @@ +import { Reducer, createStore, Store } from 'redux'; +import { ApplicationState, FilterStatus, RepoFilterState } from './model'; +import { ActionNames, InitUserNameArgs, InitRepoArgs, AddRepoFilterStatusArgs, ActionsType } from './actions'; + +export const initialState: ApplicationState = { + username: '', + repoStateMap: new Map() +}; + +export const reducer: Reducer = (state: ApplicationState = initialState, action) => { + // We'll augment the action type on the switch case to make sure we have + // all the cases handled. + switch (action.type) { + case ActionNames.InitUserName: + return { ...state, username: action.payload.userName }; + + case ActionNames.InitRepo: + { + const clonedAppState = new Map(state.repoStateMap); + clonedAppState.set(action.payload.repoName, { + filterState: { + eachBranchBehindOrEven: { + status: FilterStatus.waiting + }, + notContributor: { + status: FilterStatus.waiting + }, + noCommits: { + status: FilterStatus.waiting + } + } + }); + return { ...state, repoStateMap: clonedAppState }; + } + case ActionNames.AddRepoFilterStatus: + { + const clonedAppState = new Map(state.repoStateMap); + let clonedRepoState = JSON.parse(JSON.stringify(clonedAppState.get(action.payload.repoName))) as ( + { + filterState: RepoFilterState; + } | undefined + ); + + if (clonedRepoState !== undefined) { + clonedRepoState.filterState[action.payload.filterStep] = action.payload.filterState; + + clonedAppState.set(action.payload.repoName, clonedRepoState); + return { ...state, repoStateMap: clonedAppState }; + } else { + return state; + } + } + default: + return state; + } +}; + +export function createAppStore(): Store { + return createStore< + ApplicationState, ActionsType, {}, {} + >( + reducer, + initialState + ) as any as Store; +}; \ No newline at end of file diff --git a/src/types/index.ts b/src/types/index.ts index 1e5f073..e62828c 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -2,140 +2,151 @@ import * as Octokit from '@octokit/rest'; // +++ All typescript definitions +++ interface RequestOptions { - method: string; - url: string; - headers: any; - query?: string; - variables?: Variables; + method: string; + url: string; + headers: any; + query?: string; + variables?: Variables; } interface Result { - headers: { - status: string; - }; + headers: { + status: string; + }; } interface OctokitError { - code: number; - status: string; + code: number; + status: string; } export interface OctokitMod extends Octokit { - // The following are added because Octokit does not expose the hook.error, hook.before, and hook.after methods - hook: { - error: (when: 'request', callback: (error: OctokitError, options: RequestOptions) => void) => void; - before: (when: 'request', callback: (result: Result, options: RequestOptions) => void) => void; - after: (when: 'request', callback: (result: Result, options: RequestOptions) => void) => void; - }; + // The following are added because Octokit does not expose the hook.error, hook.before, and hook.after methods + hook: { + error: ( + when: 'request', + callback: (error: OctokitError, options: RequestOptions) => void + ) => void; + before: ( + when: 'request', + callback: (result: Result, options: RequestOptions) => void + ) => void; + after: ( + when: 'request', + callback: (result: Result, options: RequestOptions) => void + ) => void; + }; } interface Variables { - [key: string]: any; + [key: string]: any; } export interface ResponseWithDataArray { - data: T[]; + data: T[]; } interface ResponseWithMetaLink { - meta: { - link: string; - }; + meta: { + link: string; + }; } -export interface ResponseWithDataArrayAndMeta extends ResponseWithDataArray, ResponseWithMetaLink { -} +export interface ResponseWithDataArrayAndMeta + extends ResponseWithDataArray, + ResponseWithMetaLink {} export interface ResponseFromGetUserRepo extends ResponseWithMetaLink { - data: RepoFromGetUserRepo[]; + data: RepoFromGetUserRepo[]; } export interface ResponseFromGetBranches extends ResponseWithMetaLink { - data: BranchFromGetBranches[]; + data: BranchFromGetBranches[]; } export interface ResponseFromGetRepo { - data: RepoFromGetRepo; - meta: {}; + data: RepoFromGetRepo; + meta: {}; } export interface ResponseFromCompareCommits { - data: { - status: string; - ahead_by: number; - behind_by: number; - total_commits: number; - }; + data: { + status: string; + ahead_by: number; + behind_by: number; + total_commits: number; + }; } export interface ResponseFromGetContributors extends ResponseWithMetaLink { - data: OwnerFromGetContributors[] | undefined; + data: OwnerFromGetContributors[] | undefined; } export interface RepoFromGetUserRepo { - default_branch: string; - description: string; - fork: boolean; - full_name: string; - homepage: string; - id: number; - language: string; - name: string; - owner: OwnerFromGetUserRepo; - private: boolean; - pushed_at: string; - url: string; + default_branch: string; + description: string; + fork: boolean; + full_name: string; + homepage: string; + id: number; + language: string; + name: string; + owner: OwnerFromGetUserRepo; + private: boolean; + pushed_at: string; + url: string; } interface OwnerFromGetUserRepo { - avatar_url: string; - gravatar_id: string; - html_url: string; - id: number; - login: string; - repos_url: string; - type: UserType; + avatar_url: string; + gravatar_id: string; + html_url: string; + id: number; + login: string; + repos_url: string; + type: UserType; } export type OwnerFromGetContributors = OwnerFromGetUserRepo; enum UserType { - User = 'User' + User = 'User', } export interface BranchFromGetBranches { - name: string; - commit: CommitFromGetBranches; + name: string; + commit: CommitFromGetBranches; } interface CommitFromGetBranches { - sha: string; - url: string; + sha: string; + url: string; } interface RepoFromGetRepo { - parent: RepoFromGetUserRepo; + parent: RepoFromGetUserRepo; } export interface RepoNameWithUnusedFlag { - repoName: string; - unused: boolean; + repoName: string; + unused: boolean; } export interface RepoNameWithBranches { - repoName: string; - branches: BranchFromGetBranches[]; + repoName: string; + branches: BranchFromGetBranches[]; } export interface RepoNameWithParentRepo { - repoName: string; - parentRepo: RepoFromGetUserRepo; + repoName: string; + parentRepo: RepoFromGetUserRepo; } -export interface RepoNameWithBranchesAndParent extends RepoNameWithBranches, RepoNameWithParentRepo { -} +export interface RepoNameWithBranchesAndParent + extends RepoNameWithBranches, + RepoNameWithParentRepo {} export interface ObjectWithPerPage { - per_page?: number; + per_page?: number; } - // --- End all typescript definitions --- \ No newline at end of file +// --- End all typescript definitions --- diff --git a/yarn.lock b/yarn.lock index e52f7d0..54d0a05 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3450,6 +3450,10 @@ js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + js-yaml@3.6.1: version "3.6.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.6.1.tgz#6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30" @@ -3677,6 +3681,12 @@ loose-envify@^1.0.0: dependencies: js-tokens "^3.0.0" +loose-envify@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + loud-rejection@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" @@ -4664,6 +4674,13 @@ redent@^1.0.0: indent-string "^2.1.0" strip-indent "^1.0.1" +redux@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.0.tgz#aa698a92b729315d22b34a0553d7e6533555cc03" + dependencies: + loose-envify "^1.1.0" + symbol-observable "^1.2.0" + regenerate@^1.2.1: version "1.4.0" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" @@ -5354,6 +5371,10 @@ supports-color@^5.1.0, supports-color@^5.3.0: dependencies: has-flag "^3.0.0" +symbol-observable@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" + symbol-tree@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6"