From 378d611aa7b3e0128cfc6aa2248299f2b7e45d10 Mon Sep 17 00:00:00 2001 From: krassowski Date: Thu, 25 Feb 2021 18:32:27 +0000 Subject: [PATCH] Add colours for files in browser --- src/browserDecorations.ts | 60 ++++++++++++++++++++++ src/components/FileItem.tsx | 11 ++-- src/index.ts | 3 ++ src/style/BrowserFile.ts | 100 ++++++++++++++++++++++++++++++++++++ src/tokens.ts | 20 +++++++- 5 files changed, 187 insertions(+), 7 deletions(-) create mode 100644 src/browserDecorations.ts create mode 100644 src/style/BrowserFile.ts diff --git a/src/browserDecorations.ts b/src/browserDecorations.ts new file mode 100644 index 000000000..92c2d3614 --- /dev/null +++ b/src/browserDecorations.ts @@ -0,0 +1,60 @@ +import { Git, IGitExtension } from './tokens'; +import * as fileStyle from './style/BrowserFile'; +import { DirListing, FileBrowser } from '@jupyterlab/filebrowser'; +import { Contents } from '@jupyterlab/services'; +import { DocumentRegistry } from '@jupyterlab/docregistry'; +import { ITranslator } from '@jupyterlab/translation'; + +const statusStyles: Map = new Map([ + // note: the classes cannot repeat, + // otherwise the assignments will be overwritten + ['M', fileStyle.modified], + ['A', fileStyle.added], + ['D', fileStyle.deleted], + ['R', fileStyle.renamed], + ['C', fileStyle.copied], + ['U', fileStyle.updated], + ['?', fileStyle.untracked], + ['!', fileStyle.ignored] +]); + +class GitListingRenderer extends DirListing.Renderer { + constructor(private gitExtension: IGitExtension) { + super(); + } + + updateItemNode( + node: HTMLElement, + model: Contents.IModel, + fileType?: DocumentRegistry.IFileType, + translator?: ITranslator + ) { + super.updateItemNode(node, model, fileType, translator); + const file = this.gitExtension.getFile(model.path); + let status_code: Git.StatusCode = null; + if (file) { + status_code = file.status === 'staged' ? file.x : file.y; + } + + for (const [otherStatus, className] of statusStyles.entries()) { + if (status_code === otherStatus) { + node.classList.add(className); + } else { + node.classList.remove(className); + } + } + } +} + +export function substituteListingRenderer( + extension: IGitExtension, + fileBrowser: FileBrowser +): void { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + const listing: DirListing = fileBrowser._listing; + const renderer = new GitListingRenderer(extension); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + listing._renderer = renderer; +} diff --git a/src/components/FileItem.tsx b/src/components/FileItem.tsx index 8756ff2be..39c2fcd5f 100644 --- a/src/components/FileItem.tsx +++ b/src/components/FileItem.tsx @@ -13,8 +13,7 @@ import { import { Git } from '../tokens'; import { FilePath } from './FilePath'; -// Git status codes https://git-scm.com/docs/git-status -export const STATUS_CODES = { +export const STATUS_CODES: Record = { M: 'Modified', A: 'Added', D: 'Deleted', @@ -22,7 +21,9 @@ export const STATUS_CODES = { C: 'Copied', U: 'Updated', '?': 'Untracked', - '!': 'Ignored' + '!': 'Ignored', + ' ': 'Unchanged', + '': 'Unchanged' }; /** @@ -124,7 +125,7 @@ export interface IFileItemProps { } export class FileItem extends React.PureComponent { - protected _getFileChangedLabel(change: keyof typeof STATUS_CODES): string { + protected _getFileChangedLabel(change: Git.StatusCode): string { return STATUS_CODES[change]; } @@ -157,7 +158,7 @@ export class FileItem extends React.PureComponent { render(): JSX.Element { const { file } = this.props; const status_code = file.status === 'staged' ? file.x : file.y; - const status = this._getFileChangedLabel(status_code as any); + const status = this._getFileChangedLabel(status_code); return (