Skip to content

Commit

Permalink
feat(log-table): useful context menus (#169)
Browse files Browse the repository at this point in the history
Co-authored-by: Sam Maddock <smaddock@slack-corp.com>
  • Loading branch information
erickzhao and samuelmaddock authored Jul 23, 2024
1 parent 2e7a38f commit 3654c7c
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 147 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
"date-fns": "^2.16.1",
"debounce": "^1.2.0",
"debug": "4.3.1",
"electron-context-menu": "2.3.0",
"electron-devtools-installer": "3.2.0",
"electron-squirrel-startup": "1.0.0",
"electron-window-state": "5.0.3",
Expand Down
9 changes: 9 additions & 0 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,12 @@ export interface RootState {
releaseChannelOverride: string;
};
}

/**
* Context menu actions that can be taken on a specific log line.
*/
export enum LogLineContextMenuActions {
SHOW_IN_CONTEXT,
COPY_TO_CLIPBOARD,
OPEN_SOURCE,
}
1 change: 1 addition & 0 deletions src/ipc-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ export const enum IpcEvents {
TOGGLE_FILTER = 'TOGGLE_FILTER',
COPY = 'COPY',
RESET = 'RESET',
OPEN_LOG_CONTEXT_MENU = 'OPEN_LOG_CONTEXT_MENU',
}
71 changes: 53 additions & 18 deletions src/main/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ import {
dialog,
systemPreferences,
IpcMainEvent,
Menu,
MenuItemConstructorOptions,
} from 'electron';
import * as path from 'path';

import { settingsFileManager } from './settings';
import { changeIcon } from './app-icon';
import { ICON_NAMES } from '../shared-constants';
import { IpcEvents } from '../ipc-events';
import { LogLineContextMenuActions, LogType } from '../interfaces';

export class IpcManager {
constructor() {
Expand All @@ -27,6 +30,7 @@ export class IpcManager {
this.setupQuit();
this.setupOpenRecent();
this.setupTitleBarClickMac();
this.setupContextMenus();
}

public openFile(pathName: string) {
Expand Down Expand Up @@ -123,24 +127,12 @@ export class IpcManager {
}

private setupGetPath() {
type name =
| 'home'
| 'appData'
| 'userData'
| 'temp'
| 'exe'
| 'module'
| 'desktop'
| 'documents'
| 'downloads'
| 'music'
| 'pictures'
| 'videos'
| 'logs';

ipcMain.handle(IpcEvents.GET_PATH, (_event, pathName: name) => {
return app.getPath(pathName);
});
ipcMain.handle(
IpcEvents.GET_PATH,
(_event, pathName: Parameters<typeof app.getPath>[0]) => {
return app.getPath(pathName);
},
);
}

private setupGetUserAgent() {
Expand Down Expand Up @@ -202,6 +194,49 @@ export class IpcManager {
app.addRecentDocument(filename);
});
}

private setupContextMenus() {
ipcMain.handle(IpcEvents.OPEN_LOG_CONTEXT_MENU, (event, type: LogType) => {
return new Promise((resolve) => {
const maybeShowInContext: MenuItemConstructorOptions[] =
type === LogType.BROWSER || type === LogType.WEBAPP
? [
{
type: 'separator',
},
{
label: 'Show in "All Desktop Logs"',
click: () => {
resolve(LogLineContextMenuActions.SHOW_IN_CONTEXT);
},
},
]
: [];

const menu = Menu.buildFromTemplate([
{
label: 'Copy Line',
click: () => {
resolve(LogLineContextMenuActions.COPY_TO_CLIPBOARD);
},
},
{
label: 'Show Line in Source',
click: () => {
resolve(LogLineContextMenuActions.OPEN_SOURCE);
},
},
...maybeShowInContext,
]);
menu.popup({
window: BrowserWindow.fromWebContents(event.sender) || undefined,
callback: () => {
resolve(undefined);
},
});
});
});
}
}

export const ipcManager = new IpcManager();
3 changes: 0 additions & 3 deletions src/main/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,6 @@ export class AppMenu {
* Actually creates the menu.
*/
public setupMenu() {
// eslint-disable-next-line @typescript-eslint/no-var-requires
require('electron-context-menu')();

this.menu = getMenuTemplate({
openItems: this.getOpenItems(),
pruneItems: this.getPruneItems(),
Expand Down
23 changes: 4 additions & 19 deletions src/renderer/components/log-line-details/details.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
import { observer } from 'mobx-react';
import { exec } from 'child_process';
import { SleuthState } from '../../state/sleuth';
import React from 'react';
import classNames from 'classnames';
import { Card, Button, ButtonGroup, Tag, Elevation } from '@blueprintjs/core';
import debug from 'debug';

import { LogEntry } from '../../../interfaces';
import { LogLineData } from './data';
import { Timestamp } from './timestamp';
import { shell } from 'electron';
import { getIsBookmark, toggleBookmark } from '../../state/bookmarks';
import { capitalize } from '../../../utils/capitalize';

const d = debug('sleuth:details');
import { openLineInSource } from '../../../utils/open-line-in-source';

export interface LogLineDetailsProps {
state: SleuthState;
Expand Down Expand Up @@ -52,20 +48,9 @@ export class LogLineDetails extends React.Component<
if (selectedEntry && selectedEntry.sourceFile) {
const { sourceFile, line } = selectedEntry;

if (defaultEditor) {
const cmd = defaultEditor
.replace('{filepath}', `"${sourceFile}"`)
.replace('{line}', line.toString(10));

d(`Executing ${cmd}`);
exec(cmd, (error: Error) => {
if (!error) return;
d(`Tried to open source file, but failed`, error);
shell.showItemInFolder(sourceFile);
});
} else {
shell.showItemInFolder(sourceFile);
}
openLineInSource(line, sourceFile, {
defaultEditor,
});
}
}

Expand Down
41 changes: 41 additions & 0 deletions src/renderer/components/log-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import {
DateRange,
LogType,
ProcessableLogType,
LogLineContextMenuActions,
LogFile,
} from '../../interfaces';
import { didFilterChange } from '../../utils/did-filter-change';
import { isReduxAction } from '../../utils/is-redux-action';
Expand All @@ -38,6 +40,10 @@ import { RepeatedLevels } from '../../shared-constants';
import { reaction } from 'mobx';
import { Tag } from 'antd';
import { observer } from 'mobx-react';
import { showLogLineContextMenu } from '../ipc';
import { clipboard } from 'electron';
import { openLineInSource } from '../../utils/open-line-in-source';
import { getCopyText } from '../state/copy';

const d = debug('sleuth:logtable');

Expand Down Expand Up @@ -268,6 +274,40 @@ export class LogTable extends React.Component<LogTableProps, LogTableState> {
});
}

/**
* Show a context menu for the individual log lines in the table
*/
private async onRowRightClick(params: RowMouseEventHandlerParams) {
const rowData: LogEntry = params.rowData;
// type assertion because this component should only appear when you have a LogFile showing
const logType = (this.props.state.selectedLogFile as LogFile).logType;
const response = await showLogLineContextMenu(logType);

switch (response) {
case LogLineContextMenuActions.COPY_TO_CLIPBOARD: {
const copyText = getCopyText(rowData);
clipboard.writeText(copyText);
break;
}
case LogLineContextMenuActions.OPEN_SOURCE: {
const { line, sourceFile } = rowData;
openLineInSource(line, sourceFile, {
defaultEditor: this.props.state.defaultEditor,
});
break;
}
case LogLineContextMenuActions.SHOW_IN_CONTEXT:
{
this.props.state.selectLogFile(null, LogType.ALL);
const matchingIndex = this.state.sortedList.findIndex(
(row) => row.momentValue === rowData.momentValue,
);
this.changeSelection(matchingIndex);
}
break;
}
}

/**
* Handles the change of sorting direction. This method is passed to the LogTableHeaderCell
* components, who call it once the user changes sorting.
Expand Down Expand Up @@ -639,6 +679,7 @@ export class LogTable extends React.Component<LogTableProps, LogTableState> {
rowGetter: this.rowGetter,
rowCount: sortedList.length,
onRowClick: this.onRowClick,
onRowRightClick: this.onRowRightClick,
rowClassName: this.rowClassNameGetter,
headerHeight: 30,
sort: this.onSortChange,
Expand Down
28 changes: 11 additions & 17 deletions src/renderer/ipc.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,14 @@
import { ipcRenderer } from 'electron';
import { ipcRenderer, app } from 'electron';
import { ICON_NAMES } from '../shared-constants';
import { IpcEvents } from '../ipc-events';
import { LogLineContextMenuActions, LogType } from '../interfaces';

// This file handles sending IPC events. Other classes might
// listen to IPC events.

type name =
| 'home'
| 'appData'
| 'userData'
| 'cache'
| 'temp'
| 'exe'
| 'module'
| 'desktop'
| 'documents'
| 'downloads'
| 'music'
| 'pictures'
| 'videos'
| 'logs';
export function getPath(path: name): Promise<string> {
export function getPath(
path: Parameters<typeof app.getPath>[0],
): Promise<string> {
return ipcRenderer.invoke(IpcEvents.GET_PATH, path);
}

Expand Down Expand Up @@ -55,3 +43,9 @@ export function showMessageBox(
export function changeIcon(iconName: ICON_NAMES) {
return ipcRenderer.invoke(IpcEvents.CHANGE_ICON, iconName);
}

export function showLogLineContextMenu(
type: LogType,
): Promise<LogLineContextMenuActions> {
return ipcRenderer.invoke(IpcEvents.OPEN_LOG_CONTEXT_MENU, type);
}
2 changes: 1 addition & 1 deletion src/renderer/state/copy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function copy(state: SleuthState): boolean {
return false;
}

function getCopyText(entry: LogEntry) {
export function getCopyText(entry: LogEntry) {
const { message, meta } = entry;
let { timestamp } = entry;

Expand Down
30 changes: 30 additions & 0 deletions src/utils/open-line-in-source.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { shell } from 'electron';
import { exec } from 'child_process';
import debug from 'debug';

const d = debug('sleuth:open-line-in-source');

interface OpenSourceOptions {
defaultEditor: string;
}

export function openLineInSource(
line: number,
sourceFile: string,
options: OpenSourceOptions,
) {
if (options.defaultEditor) {
const cmd = options.defaultEditor
.replace('{filepath}', `"${sourceFile}"`)
.replace('{line}', line.toString(10));

d(`Executing ${cmd}`);
exec(cmd, (error: Error) => {
if (!error) return;
d(`Tried to open source file, but failed`, error);
shell.showItemInFolder(sourceFile);
});
} else {
shell.showItemInFolder(sourceFile);
}
}
Loading

0 comments on commit 3654c7c

Please sign in to comment.