Skip to content

Commit

Permalink
Merge pull request #7 from chouglesaud/feature/decouple-business-logi…
Browse files Browse the repository at this point in the history
…c-with-framework

Feature/decouple business logic with framework
  • Loading branch information
chouglesaud authored Dec 9, 2020
2 parents 7412171 + 9df5129 commit 04d74dd
Show file tree
Hide file tree
Showing 58 changed files with 383 additions and 320 deletions.
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"@octokit/core": "^3.2.0",
"axios": "^0.21.0",
"core-js": "^3.6.5",
"object-scan": "^13.6.5",
Expand All @@ -17,8 +16,8 @@
"vuex": "^3.4.0"
},
"devDependencies": {
"@types/node": "^14.14.6",
"@mdi/font": "^5.8.55",
"@types/node": "^14.14.6",
"@typescript-eslint/eslint-plugin": "^2.33.0",
"@typescript-eslint/parser": "^2.33.0",
"@vue/cli-plugin-babel": "~4.5.0",
Expand Down
3 changes: 3 additions & 0 deletions src/config/apiConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const apiConfig = {
githubBaseUrl: 'https://api.github.com/',
};
10 changes: 5 additions & 5 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import Vue from 'vue';
import App from './App.vue';
import store from './store';
import vuetify from './plugins/vuetify';
import App from '@/shared/App.vue';
import store from './shared/infra/store';
import vuetify from '@/shared/infra/plugins/vuetify';
import './assets/main.css';
Vue.config.productionTip = false;

window.onload = () => {
document.addEventListener('DOMContentLoaded', () => {
const repositree = document.createElement('div');
const body = document.body;
body.prepend(repositree);
Expand All @@ -15,4 +15,4 @@ window.onload = () => {
vuetify,
render: h => h(App),
}).$mount(repositree);
};
});
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { mapState } from 'vuex';
export default {
name: 'SideBarLocation',
data() {
const right = JSON.parse(localStorage.getItem('sidebar-location'));
const right = JSON.parse(localStorage.getItem('repositree-location'));
return {
sideBarLocation: right ? 'right' : 'left',
};
Expand All @@ -32,8 +32,8 @@ export default {
watch: {
sideBarLocation(val) {
const right = val === 'right' ? true : false;
localStorage.setItem('sidebar-location', right);
this.$store.state['ui']['right'] = right;
localStorage.setItem('repositree-location', right);
this.$store.state['right'] = right;
},
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@
v-if="apiStatus === 200"
color="primary"
:dense="true"
loading-icon="$loading"
v-model="tree"
item-key="id"
:items="items"
:open="open"
@update:open="getOpen"
loading-icon="$loading"
:transition="true"
@update:open="getOpen"
open-on-click
>
<template v-slot:label="{ item, open }">
<div class="node-container flex-row-start-center">
<div
class="node flex-row-start-center "
v-if="item.type === 'tree'"
:style="{ paddingLeft: `${item.depth * 8}px` }"
:style="{ paddingLeft: calculatePadding(item.depth) }"
>
<v-icon v-if="!open" small class="v-icon icon notranslate v-icon--link"
>$chevronRight</v-icon
Expand All @@ -42,7 +42,7 @@
<a
v-else
class="node flex-row-start-center leaf-node"
:style="{ paddingLeft: `${item.depth * 8}px` }"
:style="{ paddingLeft: calculatePadding(item.depth) }"
:href="generateURL('blob', item.path)"
@click="
e => {
Expand All @@ -63,11 +63,11 @@
</template>

<script>
import { files } from '../../plugins/files';
import { mapActions, mapState } from 'vuex';
import { githubPjaxAdapter } from '../../modules/Tree/domain/githubPjaxAdapter';
import { files } from '@/shared/infra/plugins/files';
import { githubPjaxService } from '../services';
import Message from './components/Message';
import Loading from '../ui/Loading/Loading';
import Loading from '@/shared/components/Loading/Loading';
export default {
name: 'Tree',
Expand All @@ -82,7 +82,7 @@ export default {
},
computed: {
...mapState('tree', ['repository', 'items', 'active', 'tree', 'open', 'openNodes']),
...mapState('tree', ['repoMetadata', 'items', 'active', 'tree', 'open', 'openNodes']),
...mapState(['apiStatus', 'loading']),
},
mounted() {
Expand All @@ -92,25 +92,28 @@ export default {
document.addEventListener(
'pjax:success',
async () => {
this.$store.state['tree']['repository']['href'] = window.location.href;
await this.getOpenPathFromUrl();
this.$store.state['tree']['repoMetadata']['url'] = window.location.href;
await this.updateOpenNodes();
},
false
);
});
},
methods: {
...mapActions('tree', ['loadTree', 'getOpenPathFromUrl']),
...mapActions('tree', ['loadTree', 'updateOpenNodes']),
generateURL(type, path) {
return `/${this.repository.owner}/${this.repository.name}/${type}/${this.repository.branch}/${path}`;
return `/${this.repoMetadata.owner}/${this.repoMetadata.name}/${type}/${this.repoMetadata.branch}/${path}`;
},
async loadFile(e, url) {
e.preventDefault();
await githubPjaxAdapter.loadFileBy(url);
await githubPjaxService.loadFileBy(url);
},
getOpen(nodes) {
this.$store.state['tree']['openNodes'] = nodes;
},
calculatePadding(value) {
return `${value * 8}px`;
},
},
};
</script>
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
35 changes: 19 additions & 16 deletions src/modules/Tree/domain/Tree.ts → src/modules/Tree/models/Tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,29 @@ import { Node } from './Node';

export class Tree {
public nodes: any;
constructor() {
private constructor() {
this.nodes = {};
}
public addRoot(node: Node): void {
public static createBy(sortedNodesByLevel: any[]): Tree {
const tree = new Tree();

sortedNodesByLevel.forEach((level: any[], levelIndex: number) => {
level.forEach((item: any) => {
if (levelIndex < 1) {
tree.addRoot(new Node(item));
} else {
tree.addChild(new Node(item), levelIndex);
}
});
});
tree.removeUselessNodes();
return tree;
}
private addRoot(node: Node): void {
const path = this.findPathOf(node);
this.nodes[path] = node;
}
public addChild(node: Node, level: number): void {
private addChild(node: Node, level: number): void {
const childrenLimit = 100;
const path = this.findPathOf(node).split('/');
let tempLevel = 0,
Expand All @@ -30,25 +45,13 @@ export class Tree {
parentNode = parentNode.find(path[tempLevel]);
}
}
public filter(): object {
private removeUselessNodes() {
for (const [key] of Object.entries(this.nodes)) {
if (this.nodes[key].depth > 1) {
delete this.nodes[key];
}
}
return this.nodes;
}
public transform() {
return this.convertObjectToArray(this.filter());
}
private convertObjectToArray(obj: any): any[] {
const array: any = [];
for (const key in obj) {
array.push(obj[key]);
}
return array;
}

private findPathOf(node: Node): string {
return node.path;
}
Expand Down
30 changes: 30 additions & 0 deletions src/modules/Tree/services/TreeService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { apiConfig } from '@/config/apiConfig';
import { BaseAPI } from '@/shared/services/BaseAPI';

type GithubBaseTreeOptions = {
owner: string;
name: string;
branch: string;
accessToken?: string | null;
};

export class TreeService extends BaseAPI {
public nodes: any[];
constructor() {
super();
this.baseUrl = apiConfig.githubBaseUrl;
this.nodes = [];
}
public async getGithubBaseTree(option: GithubBaseTreeOptions): Promise<any> {
const url = `repos/${option.owner}/${option.name}/git/trees/${option.branch}?recursive=1`;

return await this.axiosInstance.get(`${this.baseUrl}${url}`, {
headers: option.accessToken
? {
accept: 'application/vnd.github.v3+json',
authorization: `token ${option.accessToken}`,
}
: null,
});
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import PjaxAdapter, { PjaxAdapterProps } from '@/modules/util/PjaxAdapter/PjaxAdapter';
import PjaxService, { PjaxServiceProps } from '@/shared/services/PjaxService';

const config: PjaxAdapterProps = {
const config: PjaxServiceProps = {
host: 'https://github.com',
query:
'_pjax=%23js-repo-pjax-container%2C%20div%5Bitemtype%3D%22http%3A%2F%2Fschema.org%2FSoftwareSourceCode%22%5D%20main%2C%20%5Bdata-pjax-container%5D',
pjaxContainer:
'#js-repo-pjax-container, div[itemtype="http://schema.org/SoftwareSourceCode"] main, [data-pjax-container]',
};
const githubPjaxAdapter = new PjaxAdapter(config);
const githubPjaxService = new PjaxService(config);

export { githubPjaxAdapter };
export { githubPjaxService };
5 changes: 5 additions & 0 deletions src/modules/Tree/services/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { githubPjaxService } from './githubPjaxService';
import { TreeService } from './TreeService';

const treeService = new TreeService();
export { treeService, githubPjaxService };
62 changes: 62 additions & 0 deletions src/modules/Tree/store/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import store from '@/shared/infra/store';
import GithubScraper from '@/shared/utils/GithubScraper';
import GithubUrl from '@/shared/utils/GithubUrl';
import { Tree } from '../models/Tree';
import { treeService } from '../services';
import { TreeUtil } from '../utils/TreeUtil';
import { githubBlobAndTreeUrlPattern } from '@/shared/utils/githubUrlPatterns';

export default {
async loadTree({ state, dispatch }) {
store.state['loading'] = true;

const { owner, name } = GithubUrl.getOwnerAndRepoName(),
branch = GithubScraper.getBranchName(),
repoMetadata = {
owner,
name,
branch,
url: window.location.href,
},
accessToken = localStorage.getItem('pacrepo');

try {
const response = await treeService.getGithubBaseTree({
owner,
name,
branch,
accessToken,
});
const apiNodes: any[] = response.data.tree,
nodesInTreeFirstOrder = await TreeUtil.getNodesInTreeFirstOrder(apiNodes),
sortedNodesByLevel = await TreeUtil.getNodesSortedByLevel(nodesInTreeFirstOrder),
{ nodes } = Tree.createBy(sortedNodesByLevel);

store.state['apiStatus'] = 200;
state['repoMetadata'] = repoMetadata;
state['items'] = TreeUtil.convertObjectToArray(nodes);
store.state['loading'] = false;
} catch (error) {
store.state['apiStatus'] = 401;
state['repoMetadata'] = {};
store.state['loading'] = false;
}
await dispatch('updateOpenNodes');
},
async updateOpenNodes({ state }): Promise<void> {
const url = state['repoMetadata']['url'];
const branch = state['repoMetadata']['branch'];

const matchedData = await githubBlobAndTreeUrlPattern({ branch }).match(url);

if (GithubUrl.hasTypeBlobAndTree(matchedData)) {
const fullPath = GithubUrl.getFullPathFrom(matchedData);
if (fullPath.length > 0) {
state['open'] = [...state['openNodes'], ...GithubUrl.getIndividualPathListFrom(fullPath)];
}
}
},
collapseAll({ state }): void {
state['open'] = [];
},
};
8 changes: 8 additions & 0 deletions src/modules/Tree/store/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import state from './state';
import actions from './actions';

export const tree: any = {
namespaced: true,
state,
actions,
};
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export default {
repository: {
href: '',
owner: '',
repoMetadata: {
name: '',
owner: '',
branch: '',
url: '',
},
open: [],
openNodes: [],
Expand Down
37 changes: 37 additions & 0 deletions src/modules/Tree/utils/TreeUtil.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
export class TreeUtil {
public static async getNodesInTreeFirstOrder(nodes: any[]): Promise<any[]> {
const treeList: any = [];
const blobList: any = [];

nodes.forEach((node: any) => {
const treeNode = {
path: node.path,
type: node.type,
};
if (treeNode.type === 'tree') {
treeList.push(treeNode);
} else {
blobList.push(treeNode);
}
});
return [...treeList, ...blobList];
}
public static async getNodesSortedByLevel(nodes: any[]): Promise<any[]> {
const sortedNodes: any = [];
nodes.forEach((node: any) => {
const depth = node.path.split('/').length - 1;
if (!sortedNodes[depth]) {
sortedNodes[depth] = [];
}
sortedNodes[depth].push(node);
});
return sortedNodes;
}
public static convertObjectToArray(obj: {}): any[] {
const array: any = [];
for (const key in obj) {
array.push(obj[key]);
}
return array;
}
}
Loading

0 comments on commit 04d74dd

Please sign in to comment.