Skip to content

Commit

Permalink
Improve git
Browse files Browse the repository at this point in the history
  • Loading branch information
ggodlewski committed Sep 14, 2023
1 parent 22be85f commit d448632
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 52 deletions.
25 changes: 22 additions & 3 deletions apps/ui/src/components/GitCommit.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@

<template v-slot:sidebar="{ collapse }">
<GitSideBar
ref="git_sidebar"
:selectedPath="selectedPath"
:gitChanges="gitChanges"
:checked="checked"
@toggle="toggle"
@toggleAll="toggleAll"
@setCurrentDiff="setCurrentDiff"
@collapse="collapse"
/>
Expand All @@ -21,7 +23,6 @@
<form>
<div class="container d-flex flex-column order-0 w-vh-toolbar w-100">
<GitToolBar :active-tab="activeTab" :selected-file="selectedFile" />

<div v-if="file_deleted" class="flex-grow-1">
<div class="alert-warning p-3 mb-3">
File deleted
Expand Down Expand Up @@ -88,7 +89,8 @@ export default {
contentDir: {
type: String
},
selectedFile: Object
selectedFile: Object,
selectedFolder: Object
},
data() {
return {
Expand All @@ -103,7 +105,8 @@ export default {
},
computed: {
file_deleted() {
return !this.selectedFile.id && !['/toc.md'].includes(this.selectedFile.path);
return false;
// return !this.selectedFile.id && !this.selectedFolder?.path && !['/toc.md'].includes(this.selectedFile.path);
},
git_remote_url() {
return this.user_config.remote_url || '';
Expand Down Expand Up @@ -178,6 +181,13 @@ export default {
const responseConfig = await this.authenticatedClient.fetchApi(`/api/config/${this.driveId}`);
this.user_config = await responseConfig.json();
this.$nextTick(() => {
const el = this.$el.querySelector('[data-path="' + this.selectedPath + '"]');
if (el) {
el.scrollIntoView();
}
});
},
open(url) {
window.open(url, '_blank');
Expand Down Expand Up @@ -270,6 +280,15 @@ export default {
}
});
},
toggleAll() {
if (Object.keys(this.checked).length === this.gitChanges.length) {
this.checked = {};
} else {
for (const change of this.gitChanges) {
this.checked[change.path] = true;
}
}
},
toggle(path) {
if (this.checked[path]) {
delete this.checked[path];
Expand Down
59 changes: 48 additions & 11 deletions apps/ui/src/components/GitSideBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,46 @@
<ul class="nav files-list border-bottom dark">
<li class="nav-item fs-4">
<div class="files-list__item">
<i class="fa-brands fa-github"></i>&nbsp; Files to commit
<input name="filePath" type="checkbox" value="/" @click="$emit('toggleAll')" :checked="isCheckedAll" />
&nbsp; Files to commit ({{checkedCount}})
</div>
</li>
</ul>

<GitSideBarLeaf
v-if="gitChanges && gitChanges.length > 0"
:tree="tree"
<ul class="nav nav-pills flex-column order-0 files-list" v-if="filteredGitChanges.length > 0">
<GitSideBarRow
v-for="filteredGitChange in filteredGitChanges"
:checked="checked"
:checkedDirs="checkedDirs"
:selectedPath="selectedPath"
@toggleDir="toggleDir"
:change="filteredGitChange"
:key="filteredGitChange.path"
:selectedPath="selectedPathWithoutSlash"
:data-path="filteredGitChange.path"
@toggle="$emit('toggle', $event)"
@selected="$emit('setCurrentDiff', $event)"
/>
@contextmenu.prevent.stop="showContextMenu($event, filteredGitChange)"
/>
</ul>
<div v-else-if="gitChanges === null"><i class="fa-solid fa-rotate fa-spin"></i> Loading...</div>
<div v-else>No changes to commit</div>

<ContextMenu ref="contextMenu">
<template v-slot="slotProps">
<div class="dropdown" v-if="slotProps.ctx">
<ul class="dropdown-menu show">
<li><button class="dropdown-item" type="button" @click="removeFile(slotProps.ctx)"><i class="fa-solid fa-trash"></i> Remove</button></li>
</ul>
</div>
</template>
</ContextMenu>
</template>
<script>
import GitSideBarLeaf from './GitSideBarLeaf.vue';
import GitSideBarRow from './GitSideBarRow.vue';
import ContextMenu from './ContextMenu.vue';
export default {
components: {
GitSideBarLeaf
ContextMenu,
GitSideBarRow
},
props: {
gitChanges: Array,
Expand All @@ -38,7 +54,7 @@ export default {
checkedDirs: {}
};
},
emits: ['toggle', 'collapse', 'setCurrentDiff'],
emits: ['toggle', 'toggleAll', 'collapse', 'setCurrentDiff'],
watch: {
gitChanges() {
const retVal = [];
Expand Down Expand Up @@ -94,6 +110,18 @@ export default {
}
},
methods: {
async removeFile(file) {
if (!window.confirm('Are you sure?')) {
this.$refs.contextMenu.close();
return;
}
const path = file.path;
await this.FileClientService.removeFile('/' + this.driveId + (path.startsWith('/') ? path : '/' + path));
this.$refs.contextMenu.close();
},
showContextMenu(event, ctx) {
this.$refs.contextMenu.open(event, ctx);
},
addCheckedDirs(tree) {
for (const item of tree) {
if (item.children.length > 0) {
Expand Down Expand Up @@ -130,11 +158,20 @@ export default {
}
},
computed: {
selectedPathWithoutSlash() {
return this.selectedPath.replace(/^\//, '');
},
filteredGitChanges() {
if (null === this.gitChanges) {
return [];
}
return this.gitChanges.filter(change => {
return (change.path.indexOf('.assets/') === -1);
});
},
checkedCount() {
return Object.keys(this.checked).length;
},
isCheckedAll() {
return Object.keys(this.checked).length === this.gitChanges?.length;
}
Expand Down
64 changes: 64 additions & 0 deletions apps/ui/src/components/GitSideBarRow.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<template>
<li :title="change.path">
<div class="nav-item files-list__item"
:class="{'active': change.path === selectedPath, 'text-git-del': changeStatus === 'D', 'text-git-new': changeStatus === 'N', 'text-git-mod': changeStatus === 'M'}"
>
<span>
<input name="filePath" type="checkbox" :value="change.path" @click="$emit('toggle', change.path)" :checked="checked[change.path]" />
</span>
<span class="file-name m-1" @click="$emit('selected', change)">{{ fileName }} <small v-if="change.attachments > 0">(<i class="fa-solid fa-paperclip"></i>{{ change.attachments }})</small></span>
</div>
</li>
</template>
<script>
import {UtilsMixin} from './UtilsMixin.ts';
export default {
name: 'GitSideBarRow',
mixins: [ UtilsMixin ],
props: {
selectedPath: String,
change: Object,
checked: Object
},
computed: {
fileName() {
const idx = this.change.path.lastIndexOf('/');
if (idx > -1) {
return this.change.path.substring(idx + 1);
}
return this.change.path;
},
changeStatus() {
if (this.change.state.isDeleted) {
return 'D';
}
if (this.change.state.isNew) {
return 'N';
}
if (this.change.state.isModified) {
return 'M';
}
if (this.change.state.isRenamed) {
return 'R';
}
return '';
}
},
methods: {
async openExternal(file) {
if (!file) {
return;
}
if (!file.path) {
return;
}
const response = await this.FileClientService.getFile(`/${this.driveId}/${file.path}`);
if (response.googleId) {
this.openWindow(`https://drive.google.com/open?id=${response.googleId}`, '_blank');
}
}
}
};
</script>
2 changes: 1 addition & 1 deletion apps/ui/src/pages/FolderView.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<GitCommit v-if="activeTab === 'git_commit'" :folderPath="folderPath" :contentDir="contentDir" :selectedFile="selectedFile" :active-tab="activeTab" :sidebar="sidebar" :shareEmail="shareEmail" />
<GitCommit v-if="activeTab === 'git_commit'" :folderPath="folderPath" :contentDir="contentDir" :selectedFile="selectedFile" :selectedFolder="selectedFolder" :active-tab="activeTab" :sidebar="sidebar" :shareEmail="shareEmail" />
<GitInfo v-else-if="activeTab === 'git_info'" :folderPath="folderPath" :contentDir="contentDir" :selectedFile="selectedFile" :active-tab="activeTab" :sidebar="sidebar" :shareEmail="shareEmail" />
<BaseLayout v-else :share-email="shareEmail" :sidebar="sidebar">
<template v-slot:navbar="{ collapsed, collapse }">
Expand Down
88 changes: 51 additions & 37 deletions src/git/GitScanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,44 +87,44 @@ export class GitScanner {
}

async changes(): Promise<GitChange[]> {
const retVal = [];
const retVal = {};

const skipOthers = false;

function addEntry(path, state, attachments = 0) {
if (!retVal[path]) {
retVal[path] = {
path,
state: {
isNew: false,
isDeleted: false,
isModified: false
}
};
}
retVal[path].cnt++;
for (const k in state) {
retVal[path].state[k] = state[k];
}
if (attachments > 0) {
retVal[path].attachments = (retVal[path].attachments || 0) + attachments;
}
}

try {
const result = await this.exec('git --no-pager diff HEAD --name-status -- \':!**/*.assets/*.png\'', { skipLogger: true });
for (const line of result.stdout.split('\n')) {
const parts = line.split(/\s/);
const path = parts[parts.length - 1];

if (line.match(/^A\s/)) {
retVal.push({
path,
state: {
isNew: true,
isDeleted: false,
isModified: false
}
});
addEntry(path, { isNew: true });
}
if (line.match(/^M\s/)) {
retVal.push({
path,
state: {
isNew: false,
isDeleted: false,
isModified: true
}
});
addEntry(path, { isModified: true });
}
if (line.match(/^D\s/)) {
retVal.push({
path,
state: {
isNew: false,
isDeleted: true,
isModified: false
}
});
addEntry(path, { true: true });
}
}
} catch (err) {
Expand All @@ -142,20 +142,26 @@ export class GitScanner {
if (!line.trim()) {
continue;
}
retVal.push({
path: line
.trim()
.replace(/^"/, '')
.replace(/"$/, ''),
state: {
isNew: true,
isDeleted: false,
isModified: false
}
});
const path = line
.trim()
.replace(/^"/, '')
.replace(/"$/, '');

if (path.indexOf('.assets/') > -1) {
const idx = path.indexOf('.assets/');
const mdPath = path.substring(0, idx) + '.md';
addEntry(mdPath, { isModified: true }, 1);
continue;
}

addEntry(path, { isNew: true });
}

return retVal;
const retValArr: GitChange[] = Object.values(retVal);
retValArr.sort((a, b) => {
return a.path.localeCompare(b.path);
});
return retValArr;
}

async commit(message: string, addedFiles: string[], removedFiles: string[], committer): Promise<string> {
Expand Down Expand Up @@ -357,6 +363,10 @@ export class GitScanner {
}


if (fileName.endsWith('.md')) {
fileName = fileName.substring(0, fileName.length - '.md'.length) + '.*' + ' ' + fileName.substring(0, fileName.length - '.md'.length) + '.*/*';
}

const result = await this.exec(`git diff --minimal ${sanitize(fileName)}`, { skipLogger: true });

const retVal = [];
Expand Down Expand Up @@ -441,6 +451,10 @@ export class GitScanner {
retVal.push(current);
}

retVal.sort((a, b) => {
return -a.newFile.localeCompare(b.newFile);
});

return retVal;
} catch (err) {
if (err.message.indexOf('fatal: bad revision') > -1) {
Expand Down

0 comments on commit d448632

Please sign in to comment.