Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#1936] Migrate app.vue to TypeScript #1938

Merged
merged 21 commits into from Mar 21, 2023
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
2efc530
Declare custom module for this.store and add type definitions
vvidday Mar 11, 2023
e3f84ac
Convert store.js to TypeScript
vvidday Mar 11, 2023
679eaa0
Add missing isOpen field to CommitResult (from #1866)
vvidday Mar 11, 2023
611ad6d
Remove unnecessary export statements in vuex.d.ts
vvidday Mar 11, 2023
97467d0
Add missing optional fields to fileResult schema
vvidday Mar 11, 2023
dfbb06f
Add app property to window object as any and add eslint exception
vvidday Mar 11, 2023
4bfc3aa
Convert app.vue to TypeScript
vvidday Mar 11, 2023
15a324e
Reorder options in app.vue according to required order
vvidday Mar 11, 2023
f24f3a8
Reuse StoreState interface in vuex.d.ts
vvidday Mar 13, 2023
d92fae8
Add types for state variable in store.ts
vvidday Mar 13, 2023
8746d0f
Merge branch 'master' into migrate-typescript-store
vvidday Mar 13, 2023
ac082a2
Add missing semicolons in StoreState interface
vvidday Mar 13, 2023
c010d83
Add eslint exception for empty interface false positive
vvidday Mar 13, 2023
6f7d133
Merge branch 'master' into migrate-typescript-app
ckcherry23 Mar 14, 2023
f958cae
Merge branch 'migrate-typescript-store' into migrate-typescript-app
vvidday Mar 17, 2023
39dd298
Merge branch 'master' into migrate-typescript-store
vvidday Mar 17, 2023
5421347
Merge branch 'migrate-typescript-store' into migrate-typescript-app
vvidday Mar 17, 2023
1e780e7
Add type for errorMessages, zoomInfo and authorshipInfo in app.vue an…
vvidday Mar 17, 2023
63346e8
Merge branch 'migrate-typescript-app' of github.com:vvidday/RepoSense…
vvidday Mar 17, 2023
3257baf
Merge master and resolve merge conflict
vvidday Mar 19, 2023
1b9ea44
Merge branch 'master' into migrate-typescript-app
dcshzj Mar 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
76 changes: 40 additions & 36 deletions frontend/src/app.vue
vvidday marked this conversation as resolved.
Show resolved Hide resolved
Expand Up @@ -75,24 +75,33 @@
input(type="file", accept=".zip", v-on:change="updateReportZip")
</template>

<script>
<script lang='ts'>
import JSZip from 'jszip';
import LoadingOverlay from 'vue-loading-overlay';
import { mapState } from 'vuex';
import { defineComponent } from 'vue';

import cResizer from './components/c-resizer.vue';
import cZoom from './views/c-zoom.vue';
import cSummary from './views/c-summary.vue';
import cAuthorship from './views/c-authorship.vue';
import { Repo } from './types/types';

const loadingResourcesMessage = 'Loading resources...';

const app = {
const app = defineComponent({
name: 'app',
components: {
LoadingOverlay,
cResizer,
cZoom,
cSummary,
cAuthorship,
},
data() {
return {
repos: {},
users: [],
repos: {} as { [key: string]: Repo },
users: [] as Repo[],
userUpdated: false,

loadingOverlayOpacity: 1,
Expand All @@ -103,6 +112,9 @@ const app = {
errorMessages: {},
};
},
computed: {
...mapState(['loadingOverlayCount', 'loadingOverlayMessage', 'isTabActive']),
},
watch: {
'$store.state.tabZoomInfo': function () {
if (this.$store.state.tabZoomInfo.isRefreshing) {
Expand All @@ -114,12 +126,23 @@ const app = {
this.activateTab('authorship');
},
},
created() {
try {
window.decodeHash();
} catch (error) {
this.userUpdated = false;
}
this.updateReportDir();
},
methods: {
// model functions //
updateReportZip(evt) {
updateReportZip(evt: Event) {
this.users = [];

JSZip.loadAsync(evt.target.files[0])
const target = evt.target as HTMLInputElement;
if (target.files === null) {
return;
}
JSZip.loadAsync(target.files[0])
.then((zip) => {
window.REPORT_ZIP = zip;
}, () => {
Expand All @@ -141,15 +164,16 @@ const app = {
this.userUpdated = false;
await this.$store.dispatch('incrementLoadingOverlayCountForceReload', 1);
try {
const summary = await window.api.loadSummary();
vvidday marked this conversation as resolved.
Show resolved Hide resolved
if (summary === null) {
return;
}
const {
creationDate,
reportGenerationTime,
errorMessages,
names,
} = await window.api.loadSummary();
if (names === null) {
return;
}
} = summary;
this.creationDate = creationDate;
this.reportGenerationTime = reportGenerationTime;
this.errorMessages = errorMessages;
Expand All @@ -168,7 +192,7 @@ const app = {
}
},
getUsers() {
const full = [];
const full: Repo[] = [];
Object.keys(this.repos).forEach((repo) => {
if (this.repos[repo].users) {
full.push(this.repos[repo]);
Expand All @@ -178,9 +202,9 @@ const app = {
},

// handle opening of sidebar //
activateTab(tabName) {
activateTab(tabName: string) {
if (this.$refs.tabWrapper) {
this.$refs.tabWrapper.scrollTop = 0;
(this.$refs.tabWrapper as HTMLElement).scrollTop = 0;
}

this.tabType = tabName;
Expand All @@ -189,7 +213,7 @@ const app = {
window.encodeHash();
},

renderAuthorShipTabHash(minDate, maxDate) {
renderAuthorShipTabHash(minDate: string, maxDate: string) {
vvidday marked this conversation as resolved.
Show resolved Hide resolved
const hash = window.hashParams;
const info = {
author: hash.tabAuthor,
Expand Down Expand Up @@ -298,27 +322,7 @@ const app = {
return REPOS[hashParams.tabRepo].location.location;
HCY123902 marked this conversation as resolved.
Show resolved Hide resolved
},
},

computed: {
...mapState(['loadingOverlayCount', 'loadingOverlayMessage', 'isTabActive']),
},

components: {
LoadingOverlay,
cResizer,
cZoom,
cSummary,
cAuthorship,
},
created() {
try {
window.decodeHash();
} catch (error) {
this.userUpdated = false;
}
this.updateReportDir();
},
};
});

window.app = app;

Expand Down
45 changes: 26 additions & 19 deletions frontend/src/store/store.js → frontend/src/store/store.ts
@@ -1,55 +1,62 @@
import { createStore } from 'vuex';
import { AuthorshipFile, CommitResult, DailyCommit } from '../types/types';
import {
AuthorshipInfo,
StoreState,
SummaryDates,
ZoomInfo,
} from '../types/vuex.d';

export default createStore({
state: {
tabAuthorshipInfo: {},
tabZoomInfo: {},
summaryDates: {},
tabAuthorshipInfo: {} as AuthorshipInfo,
tabZoomInfo: {} as ZoomInfo,
summaryDates: {} as SummaryDates,
mergedGroups: [],
fileTypeColors: {},
loadingOverlayCount: 0,
loadingOverlayMessage: '',
isTabActive: true,
},
} as StoreState,
mutations: {
updateTabZoomInfo(state, info) {
updateTabZoomInfo(state, info: ZoomInfo) {
state.tabZoomInfo = info;
},
updateTabAuthorshipInfo(state, info) {
updateTabAuthorshipInfo(state, info: AuthorshipInfo) {
state.tabAuthorshipInfo = info;
},
updateSummaryDates(state, info) {
updateSummaryDates(state, info: SummaryDates) {
state.summaryDates = info;
},
updateFileTypeColors(state, info) {
updateFileTypeColors(state, info: { [key: string]: string }) {
state.fileTypeColors = info;
},
updateMergedGroup(state, info) {
updateMergedGroup(state, info: string[]) {
state.mergedGroups = info;
},
incrementLoadingOverlayCount(state, increment) {
incrementLoadingOverlayCount(state, increment: number) {
state.loadingOverlayCount += increment;
if (state.loadingOverlayCount === 0) {
state.loadingOverlayMessage = 'Loading. Please wait...';
}
},
updateLoadingOverlayMessage(state, message) {
updateLoadingOverlayMessage(state, message: string) {
state.loadingOverlayMessage = message;
},
updateTabState(state, isTabOpen) {
updateTabState(state, isTabOpen: boolean) {
state.isTabActive = isTabOpen;
window.addHash('tabOpen', isTabOpen);
window.addHash('tabOpen', isTabOpen.toString());
if (!isTabOpen) {
window.removeHash('tabType');
}
window.encodeHash();
},
toggleZoomCommitMessageBody(_, slice) {
toggleZoomCommitMessageBody(_, slice: CommitResult) {
if (slice.isOpen !== undefined) {
slice.isOpen = !slice.isOpen;
}
},
setAllZoomCommitMessageBody(_, { isOpen, commits }) {
setAllZoomCommitMessageBody(_, { isOpen, commits }: { isOpen: boolean; commits: DailyCommit[] }) {
commits.forEach((commit) => {
commit.commitResults.forEach((slice) => {
if (slice.isOpen !== undefined) {
Expand All @@ -58,14 +65,14 @@ export default createStore({
});
});
},
updateTabAuthorshipFiles(state, files) {
updateTabAuthorshipFiles(state, files: AuthorshipFile[]) {
state.tabAuthorshipInfo.files.splice(0, state.tabAuthorshipInfo.files.length, ...files);
},
toggleAuthorshipFileActiveProperty(_, file) {
toggleAuthorshipFileActiveProperty(_, file: AuthorshipFile) {
file.active = !file.active;
file.wasCodeLoaded = file.wasCodeLoaded || file.active;
},
setAllAuthorshipFileActiveProperty(_, { isActive, files }) {
setAllAuthorshipFileActiveProperty(_, { isActive, files }: { isActive: boolean; files: AuthorshipFile[] }) {
files.forEach((file) => {
file.active = isActive;
file.wasCodeLoaded = file.wasCodeLoaded || file.active;
Expand All @@ -75,7 +82,7 @@ export default createStore({
actions: {
// Actions are called with dispatch

async incrementLoadingOverlayCountForceReload({ commit }, increment) {
async incrementLoadingOverlayCountForceReload({ commit }, increment: number) {
commit('incrementLoadingOverlayCount', increment);
await new Promise(window.requestAnimationFrame);
await new Promise(window.requestAnimationFrame);
Expand Down
21 changes: 21 additions & 0 deletions frontend/src/types/types.ts
Expand Up @@ -11,6 +11,7 @@ export interface CommitResult extends CommitResultRaw {
repoId: string;
vvidday marked this conversation as resolved.
Show resolved Hide resolved
insertions: number;
deletions: number;
isOpen?: boolean;
}

// Similar to AuthorDailyContributions, but uses the updated CommitResult with the three new fields
Expand Down Expand Up @@ -45,3 +46,23 @@ export interface Repo extends RepoRaw {
files?: FileResult[];
users?: User[];
}

interface AuthorshipFileSegment {
authored: boolean;
lineNumbers: number[];
lines: string[];
}

export interface AuthorshipFile {
active: boolean;
blankLineCount: number;
charCount: number;
fileSize: number | undefined; // not actually in schema - to verify relevancy when migrating c-authorship.vue
fileType: string;
isBinary: boolean;
isIgnored: boolean;
lineCount: number;
path: string;
segments: AuthorshipFileSegment[];
wasCodeLoaded: boolean;
}
64 changes: 64 additions & 0 deletions frontend/src/types/vuex.d.ts
@@ -0,0 +1,64 @@
import { Store } from 'vuex';
import { AuthorshipFile, User } from './types';

interface AuthorshipInfo {
author: string;
checkedFileTypes?: string[];
files: AuthorshipFile[];
isMergeGroup: boolean;
isRefresh?: boolean;
location: string | undefined;
maxDate: string;
minDate: string;
name: string;
repo: string;
}

interface ZoomInfo {
isRefreshing?: boolean;
zAuthor: string;
zAvgCommitSize: number | string;
zFileTypeColors: { [key: string]: string };
zFilterGroup: string;
zFilterSearch: string;
zFromRamp: boolean;
zIsMerged: boolean;
zLocation: string | undefined;
zRepo: string;
zSince: string;
zTimeFrame: string;
zUntil: string;
zUser: User;
}

interface SummaryDates {
since: string;
until: string;
}

interface StoreState {
tabAuthorshipInfo: AuthorshipInfo;
tabZoomInfo: ZoomInfo;
summaryDates: SummaryDates;
mergedGroups: string[]
fileTypeColors: { [key: string]: string }
loadingOverlayCount: number
loadingOverlayMessage: string
isTabActive: boolean
}

declare module '@vue/runtime-core' {
interface State {
tabAuthorshipInfo: AuthorshipInfo;
tabZoomInfo: ZoomInfo;
summaryDates: SummaryDates;
mergedGroups: string[]
fileTypeColors: { [key: string]: string }
loadingOverlayCount: number
loadingOverlayMessage: string
isTabActive: boolean
}
interface ComponentCustomProperties {
$store: Store<State>;
}
}
2 changes: 2 additions & 0 deletions frontend/src/types/window.ts
Expand Up @@ -68,5 +68,7 @@ declare global {
isSinceDateProvided: boolean;
isUntilDateProvided: boolean;
DOMAIN_URL_MAP: DomainUrlMap;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
app: any;
}
}
2 changes: 2 additions & 0 deletions frontend/src/types/zod/authorship-type.ts
Expand Up @@ -11,6 +11,8 @@ const fileResult = z.object({
fileType: z.string(),
lines: z.array(lineSchema),
authorContributionMap: z.record(z.number()),
isBinary: z.boolean().optional(),
isIgnored: z.boolean().optional(),
});

// Contains the zod validation schema for the authorship.json file
Expand Down