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

WIP: Implement comment notifications #4

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
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
90 changes: 78 additions & 12 deletions src/background/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,18 @@ import { browser } from 'webextension-polyfill-ts';
import { Gitlab } from 'gitlab'; // All Resources
import { getSettings } from './utils/getSettings';
import { fetchMRExtraInfo } from './utils/fetchMRExtraInfo';
import { MergeRequests, GetSettingsResponse, MergeRequestsDetails } from './types';
import { MergeRequests, GetSettingsResponse, ReviewRequests, ReviewGiven, StoredData, ReviewChanges } from './types';

let ERROR_TRACKER: Error | null;

const pollMR = (cb: Callback<boolean>) => {
interface ReviewRequests {
mrAssigned: MergeRequestsDetails[];
mrToReview: number;
}

interface ReviewGiven {
mrGiven: MergeRequestsDetails[];
mrReviewed: number;
}

interface AsyncResults {
getSettings: GetSettingsResponse;
gitlabApi: Gitlab;
reviewRequests: ReviewRequests;
givenRequests: ReviewGiven;
getStoredData: StoredData;
computeChanges: ReviewChanges;
saveLocalStorage: void;
}

Expand Down Expand Up @@ -142,12 +134,78 @@ const pollMR = (cb: Callback<boolean>) => {
});
}
],
getStoredData: [
'reviewRequests',
'givenRequests',
(_results, cb) => {
browser.storage.local
.get(['mrAssigned', 'mrGiven', 'mrToReview', 'mrReviewed', 'reviewChanges'])
.then((data) => cb(null, data as StoredData))
.catch((error) => cb(error));
}
],
computeChanges: [
'reviewRequests',
'givenRequests',
'getStoredData',
(results, cb) => {
/** Get all comments (stored and received) */
const storedData = results.getStoredData;

const storedCommentsAssigned = storedData.mrAssigned?.flatMap((mr) => mr.comments) || [];
const storedCommentsGiven = storedData.mrGiven?.flatMap((mr) => mr.comments) || [];

const receivedCommentsAssigned = results.reviewRequests.mrAssigned.flatMap((mr) => mr.comments);
const receivedCommentsGiven = results.givenRequests.mrGiven.flatMap((mr) => mr.comments);

/** Filter only new comments */
const newCommentsAssigned = receivedCommentsAssigned
.filter((comment) => !storedCommentsAssigned.some((y) => comment.id === y.id))
.concat(
storedData.reviewChanges?.newCommentsAssigned
? storedData.reviewChanges.newCommentsAssigned
: []
);

const newCommentsGiven = receivedCommentsGiven
.filter((comment) => !storedCommentsGiven.some((y) => comment.id === y.id))
.concat(
storedData.reviewChanges?.newCommentsGiven ? storedData.reviewChanges.newCommentsGiven : []
);

/** Filter only new comments tagging user */
const ownerName = 'username'; // to be changed
const PATTERN = new RegExp(`@${ownerName}`);
const newCommentsAssignedTagged = newCommentsAssigned.filter((comment) =>
PATTERN.test(comment.body)
);
const newCommentsGivenTagged = newCommentsGiven.filter((comment) => PATTERN.test(comment.body));

console.log(newCommentsAssignedTagged, newCommentsGivenTagged);

/** Prepare notification (?) */
// TBD

/** Send result */
const computedChanges = {
newCommentsAssigned,
newCommentsGiven,
notifications: []
};

// console.log(computedChanges);

return cb(null, computedChanges);
}
],
saveLocalStorage: [
'reviewRequests',
'givenRequests',
'computeChanges',
(results, cb) => {
const { mrAssigned, mrToReview } = results.reviewRequests;
const { mrGiven, mrReviewed } = results.givenRequests;
const reviewChanges = results.computeChanges;
const lastUpdateDateUnix = new Date().getTime();

browser.storage.local
Expand All @@ -156,6 +214,7 @@ const pollMR = (cb: Callback<boolean>) => {
mrToReview,
mrGiven,
mrReviewed,
reviewChanges,
lastUpdateDateUnix
})
.then(() => cb())
Expand Down Expand Up @@ -189,7 +248,14 @@ browser.runtime.onMessage.addListener((message) => {
}

return Promise.resolve(
browser.storage.local.get(['mrAssigned', 'mrGiven', 'mrToReview', 'mrReviewed', 'lastUpdateDateUnix'])
browser.storage.local.get([
'mrAssigned',
'mrGiven',
'mrToReview',
'mrReviewed',
'reviewChanges',
'lastUpdateDateUnix'
])
);
}

Expand Down
34 changes: 33 additions & 1 deletion src/background/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export interface MergeRequests {
title: string;
description: string;
project_id: number;
created_at: number;
created_at: string;
source_branch: string;
merge_status: string;
web_url: string;
Expand Down Expand Up @@ -37,10 +37,42 @@ export interface User {
}

export interface Comment {
id: number;
created_at: string;
updated_at: string;
system: boolean;
author: User;
body: string;
noteable_id: number;
noteable_idd: number;
// missing types here
}

export interface Notification {
content: string;
}

export interface GetSettingsResponse {
token: string;
address: string;
}

export interface ReviewRequests {
mrAssigned: MergeRequestsDetails[];
mrToReview: number;
}

export interface ReviewGiven {
mrGiven: MergeRequestsDetails[];
mrReviewed: number;
}

export interface ReviewChanges {
newCommentsAssigned: Comment[];
newCommentsGiven: Comment[];
notifications: Notification[];
}

export interface StoredData extends ReviewRequests, ReviewGiven {
reviewChanges: ReviewChanges;
}
16 changes: 8 additions & 8 deletions src/popup/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import Octicon, { Sync, Gear } from '@primer/octicons-react';
import { MergeRequest } from './components/MergeRequest';
import emptyInbox from './assets/empty_inbox.svg';
import './style.css';
import { MergeRequestsDetails } from '../background/types';
import { MergeRequestsDetails, StoredData, Comment } from '../background/types';
import { getHumanReadableDate } from './helpers';

const App = () => {
Expand All @@ -35,11 +35,7 @@ const App = () => {

let type = 'getMRs';

interface SendMsgResponse {
mrAssigned: MergeRequestsDetails[];
mrToReview: number;
mrGiven: MergeRequestsDetails[];
mrReviewed: number;
interface SendMsgResponse extends StoredData {
lastUpdateDateUnix: number;
}
interface SendMsgError {
Expand Down Expand Up @@ -68,18 +64,22 @@ const App = () => {
}

let mrNewList: MergeRequestsDetails[];
let commentsNewList: Comment[];
if (type === 'getMRs') {
mrNewList = response.mrAssigned;
commentsNewList = response.reviewChanges.newCommentsAssigned;
} else {
mrNewList = response.mrGiven;
commentsNewList = response.reviewChanges.newCommentsGiven;
}
console.log('Displayed list', mrNewList);
console.log('Displayed list', mrNewList, commentsNewList);

if (mrNewList.length === 0) {
updateList(<img src={emptyInbox} className={'emptyInbox'} />);
} else {
const listItems = mrNewList.map((mr) => {
return <MergeRequest mr={mr} key={mr.id} />;
const comments = commentsNewList.filter((comment) => comment.noteable_id === mr.id);
return <MergeRequest mr={mr} comments={comments} key={mr.id} />;
});

updateList(<FilterList className={'mrList'}>{listItems}</FilterList>);
Expand Down
8 changes: 6 additions & 2 deletions src/popup/components/MergeRequest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ import { BranchName, FilterList, Flex, Box, Link, Label } from '@primer/componen
import Octicon, { GitMerge, IssueClosed, IssueOpened, Clock, CommentDiscussion } from '@primer/octicons-react';
import { Avatars } from './Avatars';
import { calculateTimeElapsed } from '../helpers';
import { MergeRequestsDetails } from '../../background/types';
import { MergeRequestsDetails, Comment } from '../../background/types';

interface Props {
mr: MergeRequestsDetails;
comments: Comment[];
}

export const MergeRequest = (props: Props) => {
const mr = props.mr;
const newCommentsCount = props.comments.length;
const hasNewComments = newCommentsCount > 0;

let mrApproved = false;
if (mr.approvals.user_has_approved) {
Expand Down Expand Up @@ -50,7 +53,8 @@ export const MergeRequest = (props: Props) => {
</Label>
)}
<Label variant="medium" bg="white" color="black" className={'mrLabel'}>
<Octicon icon={CommentDiscussion} /> {mr.comments.length}
<Octicon icon={CommentDiscussion} /> {mr.comments.length}{' '}
{hasNewComments ? '(+' + newCommentsCount + ')' : null}
</Label>
<Label variant="medium" bg="white" color="#8e8e8e" className={'mrLabel'}>
<Octicon icon={Clock} /> {timeElapsed}
Expand Down
2 changes: 1 addition & 1 deletion src/popup/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const calculateTimeElapsed = (timestamp: number) => {
export const calculateTimeElapsed = (timestamp: string | number) => {
const startStamp = new Date(timestamp).getTime();
const newDate = new Date();
const newStamp = newDate.getTime();
Expand Down