Skip to content

Commit 913a17f

Browse files
Added instantaneous syncing for adding/deleting files and folders for github
1 parent 8bd5a46 commit 913a17f

11 files changed

+306
-81
lines changed

src/commons/fileSystem/FileSystemActions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export const addGithubSaveInfo = createAction(
2828

2929
export const deleteGithubSaveInfo = createAction(
3030
DELETE_GITHUB_SAVE_INFO,
31-
(githubSaveInfo: GitHubSaveInfo) => ({ payload: { githubSaveInfo }})
31+
(persistenceFile : PersistenceFile) => ({ payload: persistenceFile })
3232
);
3333

3434
export const deleteAllGithubSaveInfo = createAction(

src/commons/fileSystem/FileSystemReducer.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,18 @@ export const FileSystemReducer: Reducer<FileSystemState, SourceActionType> = cre
5555
})
5656
.addCase(deleteGithubSaveInfo, (state, action) => { // TODO rewrite - refer to deletePersistenceFile below
5757
const newPersistenceFileArray = state['persistenceFileArray'].filter(e => {
58-
return e.path != action.payload.githubSaveInfo.filePath &&
59-
e.lastSaved != action.payload.githubSaveInfo.lastSaved &&
60-
e.repoName != action.payload.githubSaveInfo.repoName
58+
return e.path != action.payload.path &&
59+
e.lastSaved != action.payload.lastSaved &&
60+
e.repoName != action.payload.repoName
6161
});
62-
state.persistenceFileArray = newPersistenceFileArray;
62+
const isGDriveSyncing = action.payload.id ? true: false;
63+
if (isGDriveSyncing) {
64+
const newPersFile = { id: action.payload.id, path: action.payload.path, repoName: '', name: action.payload.name};
65+
const newPersFileArray = newPersistenceFileArray.concat(newPersFile);
66+
state.persistenceFileArray = newPersFileArray;
67+
} else {
68+
state.persistenceFileArray = newPersistenceFileArray;
69+
}
6370
})
6471
.addCase(deleteAllGithubSaveInfo, (state, action) => {
6572
state.persistenceFileArray = [];

src/commons/fileSystem/FileSystemUtils.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,11 @@ export const getGithubSaveInfo = () => {
277277
if (activeEditorTabIndex !== null) {
278278
currentFilePath = editorTabs[activeEditorTabIndex].filePath || '';
279279
}
280-
const PersistenceFile: PersistenceFile = persistenceFileArray.find(e => e.path === currentFilePath) || {name: '', id: ''};
281-
const githubSaveInfo: GitHubSaveInfo = { filePath: PersistenceFile.path, lastSaved: PersistenceFile.lastSaved, repoName: PersistenceFile.repoName};
280+
const PersistenceFile: PersistenceFile = persistenceFileArray.find(e => e.path === currentFilePath) || {name: '', id: '', repoName: ''};
281+
const githubSaveInfo: GitHubSaveInfo = {
282+
filePath: PersistenceFile.path,
283+
lastSaved: PersistenceFile.lastSaved,
284+
repoName: PersistenceFile.repoName || (persistenceFileArray[0] === undefined ? '' : persistenceFileArray[0].repoName)
285+
};
282286
return githubSaveInfo;
283287
}

src/commons/fileSystemView/FileSystemViewDirectoryNode.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import FileSystemViewIndentationPadding from './FileSystemViewIndentationPadding
1717
import FileSystemViewList from './FileSystemViewList';
1818
import FileSystemViewPlaceholderNode from './FileSystemViewPlaceholderNode';
1919
import { PersistenceFile } from 'src/features/persistence/PersistenceTypes';
20+
import { githubCreateFile, githubDeleteFolder } from 'src/features/github/GitHubActions';
21+
import { enableFileSystemContextMenus } from 'src/features/playground/PlaygroundActions';
2022

2123
type Props = {
2224
workspaceLocation: WorkspaceLocation;
@@ -86,6 +88,7 @@ const FileSystemViewDirectoryNode: React.FC<Props> = ({
8688
return;
8789
}
8890
dispatch(persistenceDeleteFolder(fullPath));
91+
dispatch(githubDeleteFolder(fullPath));
8992
dispatch(removeEditorTabsForDirectory(workspaceLocation, fullPath));
9093
rmdirRecursively(fileSystem, fullPath).then(refreshParentDirectory);
9194
});
@@ -119,6 +122,7 @@ const FileSystemViewDirectoryNode: React.FC<Props> = ({
119122
console.error(err);
120123
}
121124
dispatch(persistenceCreateFile(newFilePath));
125+
dispatch(githubCreateFile(newFilePath));
122126
forceRefreshFileSystemViewList();
123127
});
124128
});
@@ -148,6 +152,22 @@ const FileSystemViewDirectoryNode: React.FC<Props> = ({
148152
}
149153

150154
dispatch(persistenceCreateFolder(newDirectoryPath));
155+
function informUserGithubCannotCreateFolder() {
156+
return showSimpleConfirmDialog({
157+
contents: (
158+
<div>
159+
<p>Warning: Github is unable to create empty directories. When you create your first file in this folder,
160+
Github will automatically sync this folder and the first file.
161+
</p>
162+
<p>Please click 'Confirm' to continue.</p>
163+
</div>
164+
),
165+
positiveIntent: 'primary',
166+
positiveLabel: 'Confirm'
167+
});
168+
}
169+
informUserGithubCannotCreateFolder();
170+
dispatch(enableFileSystemContextMenus());
151171
forceRefreshFileSystemViewList();
152172
});
153173
});

src/commons/fileSystemView/FileSystemViewFileNode.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import FileSystemViewContextMenu from './FileSystemViewContextMenu';
1414
import FileSystemViewFileName from './FileSystemViewFileName';
1515
import FileSystemViewIndentationPadding from './FileSystemViewIndentationPadding';
1616
import { PersistenceFile } from 'src/features/persistence/PersistenceTypes';
17+
import { githubDeleteFile } from 'src/features/github/GitHubActions';
1718

1819
type Props = {
1920
workspaceLocation: WorkspaceLocation;
@@ -50,7 +51,7 @@ const FileSystemViewFileNode: React.FC<Props> = ({
5051
? Colors.ORANGE4
5152
: Colors.BLUE4
5253
: Colors.BLUE4
53-
: Colors.ORANGE4
54+
: Colors.BLUE4
5455
: undefined;
5556
setCurrColor(checkColor(myFileMetadata));
5657
}, [lastEditedFilePath]);
@@ -107,6 +108,7 @@ const FileSystemViewFileNode: React.FC<Props> = ({
107108
console.error(err);
108109
}
109110
dispatch(persistenceDeleteFile(fullPath));
111+
dispatch(githubDeleteFile(fullPath));
110112
dispatch(removeEditorTabForFile(workspaceLocation, fullPath));
111113
refreshDirectory();
112114
});

src/commons/fileSystemView/FileSystemViewList.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ type Props = {
2020
isContextMenuDisabled: boolean;
2121
};
2222

23-
export let refreshFileView: () => any; // TODO jank
24-
2523
const FileSystemViewList: React.FC<Props> = ({
2624
workspaceLocation,
2725
fileSystem,

src/commons/sagas/GitHubPersistenceSaga.ts

Lines changed: 141 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ import {
1010
GITHUB_OPEN_FILE,
1111
GITHUB_SAVE_ALL,
1212
GITHUB_SAVE_FILE,
13-
GITHUB_SAVE_FILE_AS
13+
GITHUB_SAVE_FILE_AS,
14+
GITHUB_CREATE_FILE,
15+
GITHUB_DELETE_FILE,
16+
GITHUB_DELETE_FOLDER
1417
} from '../../features/github/GitHubTypes';
1518
import * as GitHubUtils from '../../features/github/GitHubUtils';
1619
import { getGitHubOctokitInstance } from '../../features/github/GitHubUtils';
@@ -34,6 +37,9 @@ export function* GitHubPersistenceSaga(): SagaIterator {
3437
yield takeLatest(GITHUB_SAVE_FILE, githubSaveFile);
3538
yield takeLatest(GITHUB_SAVE_FILE_AS, githubSaveFileAs);
3639
yield takeLatest(GITHUB_SAVE_ALL, githubSaveAll);
40+
yield takeLatest(GITHUB_CREATE_FILE, githubCreateFile);
41+
yield takeLatest(GITHUB_DELETE_FILE, githubDeleteFile);
42+
yield takeLatest(GITHUB_DELETE_FOLDER, githubDeleteFolder);
3743
}
3844

3945
function* githubLoginSaga() {
@@ -138,15 +144,14 @@ function* githubSaveFile(): any {
138144
octokit,
139145
githubLoginId,
140146
repoName || '',
141-
filePath,
147+
filePath.slice(12),
142148
githubEmail,
143149
githubName,
144150
commitMessage,
145151
content
146152
);
147153

148-
// forces lasteditedfilepath in filesystem to be updated which causes the colors to be updated
149-
store.dispatch(actions.updateLastEditedFilePath(''));
154+
store.dispatch(actions.updateRefreshFileViewKey());
150155
}
151156

152157
function* githubSaveFileAs(): any {
@@ -241,8 +246,138 @@ function* githubSaveAll(): any {
241246
githubName,
242247
{ commitMessage: commitMessage, files: modifiedcurrFiles});
243248

244-
// forces lasteditedfilepath in filesystem to be updated which causes the colors to be updated
245-
store.dispatch(actions.updateLastEditedFilePath(''));
249+
store.dispatch(actions.updateRefreshFileViewKey());
250+
}
251+
252+
function* githubCreateFile({ payload }: ReturnType<typeof actions.githubCreateFile>): any {
253+
yield call(store.dispatch, actions.disableFileSystemContextMenus());
254+
255+
const filePath = payload;
256+
257+
const octokit = getGitHubOctokitInstance();
258+
if (octokit === undefined) return;
259+
260+
type GetAuthenticatedResponse = GetResponseTypeFromEndpointMethod<
261+
typeof octokit.users.getAuthenticated
262+
>;
263+
const authUser: GetAuthenticatedResponse = yield call(octokit.users.getAuthenticated);
264+
265+
const githubLoginId = authUser.data.login;
266+
const repoName = getGithubSaveInfo().repoName;
267+
const githubEmail = authUser.data.email;
268+
const githubName = authUser.data.name;
269+
const commitMessage = 'Changes made from Source Academy';
270+
const content = ''
271+
272+
if (repoName === '') {
273+
yield call(console.log, "not synced to github");
274+
return;
275+
}
276+
277+
GitHubUtils.performCreatingSave(
278+
octokit,
279+
githubLoginId,
280+
repoName || '',
281+
filePath.slice(12),
282+
githubEmail,
283+
githubName,
284+
commitMessage,
285+
content
286+
);
287+
288+
yield call(store.dispatch, actions.addGithubSaveInfo({
289+
repoName: repoName,
290+
filePath: filePath,
291+
lastSaved: new Date()
292+
}))
293+
yield call(store.dispatch, actions.enableFileSystemContextMenus());
294+
yield call(store.dispatch, actions.updateRefreshFileViewKey());
295+
}
296+
297+
function* githubDeleteFile({ payload }: ReturnType<typeof actions.githubDeleteFile>): any {
298+
yield call(store.dispatch, actions.disableFileSystemContextMenus());
299+
300+
const filePath = payload;
301+
302+
const octokit = getGitHubOctokitInstance();
303+
if (octokit === undefined) return;
304+
305+
type GetAuthenticatedResponse = GetResponseTypeFromEndpointMethod<
306+
typeof octokit.users.getAuthenticated
307+
>;
308+
const authUser: GetAuthenticatedResponse = yield call(octokit.users.getAuthenticated);
309+
310+
const githubLoginId = authUser.data.login;
311+
const githubSaveInfo = getGithubSaveInfo();
312+
const repoName = githubSaveInfo.repoName;
313+
const lastSaved = githubSaveInfo.lastSaved;
314+
const githubEmail = authUser.data.email;
315+
const githubName = authUser.data.name;
316+
const commitMessage = 'Changes made from Source Academy';
317+
318+
if (repoName === '') {
319+
yield call(console.log, "not synced to github");
320+
return;
321+
}
322+
323+
GitHubUtils.performFileDeletion(
324+
octokit,
325+
githubLoginId,
326+
repoName || '',
327+
filePath.slice(12),
328+
githubEmail,
329+
githubName,
330+
commitMessage,
331+
);
332+
333+
const persistenceFileArray = store.getState().fileSystem.persistenceFileArray;
334+
const persistenceFile = persistenceFileArray.find(e =>
335+
e.repoName === repoName &&
336+
e.path === filePath &&
337+
e.lastSaved === lastSaved) || {id: '', name: ''};
338+
store.dispatch(actions.deleteGithubSaveInfo(persistenceFile));
339+
340+
341+
yield call(store.dispatch, actions.enableFileSystemContextMenus());
342+
yield call(store.dispatch, actions.updateRefreshFileViewKey());
343+
}
344+
345+
function* githubDeleteFolder({ payload }: ReturnType<typeof actions.githubDeleteFolder>): any {
346+
yield call(store.dispatch, actions.disableFileSystemContextMenus());
347+
348+
const filePath = payload;
349+
350+
const octokit = getGitHubOctokitInstance();
351+
if (octokit === undefined) return;
352+
353+
type GetAuthenticatedResponse = GetResponseTypeFromEndpointMethod<
354+
typeof octokit.users.getAuthenticated
355+
>;
356+
const authUser: GetAuthenticatedResponse = yield call(octokit.users.getAuthenticated);
357+
358+
const githubLoginId = authUser.data.login;
359+
const repoName = getGithubSaveInfo().repoName;
360+
const githubEmail = authUser.data.email;
361+
const githubName = authUser.data.name;
362+
const commitMessage = 'Changes made from Source Academy';
363+
364+
if (repoName === '') {
365+
yield call(console.log, "not synced to github");
366+
return;
367+
}
368+
369+
GitHubUtils.performFolderDeletion(
370+
octokit,
371+
githubLoginId,
372+
repoName || '',
373+
filePath.slice(12),
374+
githubEmail,
375+
githubName,
376+
commitMessage
377+
);
378+
379+
yield call(store.dispatch, actions.enableFileSystemContextMenus());
380+
yield call(store.dispatch, actions.updateRefreshFileViewKey());
246381
}
247382

248383
export default GitHubPersistenceSaga;

src/commons/sagas/PersistenceSaga.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,8 @@ export function* persistenceSaga(): SagaIterator {
171171
}
172172
yield put(actions.addPersistenceFile({ id: currFile.id, parentId: currFile.parentId, name: currFile.name, path: "/playground" + currFile.path, lastSaved: new Date() }));
173173
const contents = yield call([gapi.client.drive.files, 'get'], { fileId: currFile.id, alt: 'media' });
174+
console.log(currFile.path);
175+
console.log(contents.body === "");
174176
yield call(writeFileRecursively, fileSystem, "/playground" + currFile.path, contents.body);
175177
yield call(showSuccessMessage, `Loaded file ${currFile.path}.`, 1000);
176178
}
@@ -724,7 +726,7 @@ export function* persistenceSaga(): SagaIterator {
724726
// look for file
725727
const persistenceFileArray: PersistenceFile[] = yield select((state: OverallState) => state.fileSystem.persistenceFileArray);
726728
const persistenceFile = persistenceFileArray.find(e => e.path === filePath);
727-
if (!persistenceFile) {
729+
if (!persistenceFile || persistenceFile.id === '') {
728730
yield call(console.log, "cannot find pers file for ", filePath);
729731
return;
730732
}
@@ -751,7 +753,7 @@ export function* persistenceSaga(): SagaIterator {
751753
// identical to delete file
752754
const persistenceFileArray: PersistenceFile[] = yield select((state: OverallState) => state.fileSystem.persistenceFileArray);
753755
const persistenceFile = persistenceFileArray.find(e => e.path === folderPath);
754-
if (!persistenceFile) {
756+
if (!persistenceFile || persistenceFile.id === '') {
755757
yield call(console.log, "cannot find pers file for ", folderPath);
756758
return;
757759
}

src/features/github/GitHubActions.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import { createAction } from '@reduxjs/toolkit';
22

3-
import { GITHUB_OPEN_FILE, GITHUB_SAVE_ALL,GITHUB_SAVE_FILE, GITHUB_SAVE_FILE_AS } from './GitHubTypes';
3+
import {
4+
GITHUB_CREATE_FILE,
5+
GITHUB_OPEN_FILE,
6+
GITHUB_SAVE_ALL,
7+
GITHUB_SAVE_FILE,
8+
GITHUB_SAVE_FILE_AS,
9+
GITHUB_DELETE_FILE,
10+
GITHUB_DELETE_FOLDER} from './GitHubTypes';
411

512
export const githubOpenFile = createAction(GITHUB_OPEN_FILE, () => ({ payload: {} }));
613

@@ -9,3 +16,9 @@ export const githubSaveFile = createAction(GITHUB_SAVE_FILE, () => ({ payload: {
916
export const githubSaveFileAs = createAction(GITHUB_SAVE_FILE_AS, () => ({ payload: {} }));
1017

1118
export const githubSaveAll = createAction(GITHUB_SAVE_ALL, () => ({ payload: {} }));
19+
20+
export const githubCreateFile = createAction(GITHUB_CREATE_FILE, (filePath: string) => ({ payload: filePath }));
21+
22+
export const githubDeleteFile = createAction(GITHUB_DELETE_FILE, (filePath: string) => ({ payload: filePath }));
23+
24+
export const githubDeleteFolder = createAction(GITHUB_DELETE_FOLDER, (filePath: string) => ({ payload: filePath}));

src/features/github/GitHubTypes.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ export const GITHUB_OPEN_FILE = 'GITHUB_OPEN_FILE';
22
export const GITHUB_SAVE_FILE = 'GITHUB_SAVE_FILE';
33
export const GITHUB_SAVE_FILE_AS = 'GITHUB_SAVE_FILE_AS';
44
export const GITHUB_SAVE_ALL = 'GITHUB_SAVE_ALL';
5+
export const GITHUB_CREATE_FILE = 'GITHUB_CREATE_FILE';
6+
export const GITHUB_DELETE_FILE = 'GITHUB_DELETE_FILE';
7+
export const GITHUB_DELETE_FOLDER = 'GITHUB_DELETE_FOLDER';
58

69
export type GitHubSaveInfo = {
710
repoName?: string;

0 commit comments

Comments
 (0)