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

Sorting Functionality #151

Closed
wants to merge 10 commits into from
Binary file modified .DS_Store
Binary file not shown.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,4 @@
"src/*.js": "eslint --cache --fix"
},
"styleModule": "style/index.js"
}
}
2 changes: 2 additions & 0 deletions src/CodeSnippetContentsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export interface ICodeSnippet {
code: string[];
id: number;
tags?: string[];
date_created?: string;
date_modified?: string;
}

/**
Expand Down
17 changes: 11 additions & 6 deletions src/CodeSnippetDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import React from 'react';

import { CodeSnippetWidgetModel } from './CodeSnippetWidgetModel';
import { FilterTools } from './FilterTools';
import { SortTools } from './SortTools';
import { showPreview } from './PreviewSnippet';
import { showMoreOptions } from './MoreOptions';
import {
Expand Down Expand Up @@ -120,6 +121,7 @@ const CODE_SNIPPET_MORE_OTPIONS_INSERT = 'jp-codeSnippet-more-options-insert';
const CODE_SNIPPET_MORE_OTPIONS_EDIT = 'jp-codeSnippet-more-options-edit';
const CODE_SNIPPET_MORE_OTPIONS_DELETE = 'jp-codeSnippet-more-options-delete';
const CODE_SNIPPET_CREATE_NEW_BTN = 'jp-createSnippetBtn';
const CODE_SNIPPET_HEADER_BOX = 'jp-codeSnippet-header-class';

/**
* The threshold in pixels to start a drag event.
Expand Down Expand Up @@ -611,7 +613,7 @@ export class CodeSnippetDisplay extends React.Component<
}

//Set the position of the option to be under to the three dots on snippet.
private _setOptionsPosition(
public static _setOptionsPosition(
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
): void {
const target = event.target as HTMLElement;
Expand Down Expand Up @@ -1140,7 +1142,7 @@ export class CodeSnippetDisplay extends React.Component<
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
): void => {
showMoreOptions({ body: new OptionsHandler(this, codeSnippet) });
this._setOptionsPosition(event);
CodeSnippetDisplay._setOptionsPosition(event);
}
}
];
Expand Down Expand Up @@ -1465,10 +1467,13 @@ export class CodeSnippetDisplay extends React.Component<
<addIcon.react tag="span" right="7px" top="5px" />
</button>
</header>
<FilterTools
tags={this.getActiveTags()}
onFilter={this.filterSnippets}
/>
<div className={CODE_SNIPPET_HEADER_BOX}>
<FilterTools
tags={this.getActiveTags()}
onFilter={this.filterSnippets}
/>
<SortTools />
</div>
<div className={CODE_SNIPPETS_CONTAINER}>
<div>
{this.state.codeSnippets.map((codeSnippet, id) =>
Expand Down
7 changes: 6 additions & 1 deletion src/CodeSnippetEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ export interface ICodeSnippetEditorMetadata {
selectedTags: string[];
allTags: string[];
fromScratch: boolean;
date_created: string;
date_modified: string;
}

export class CodeSnippetEditor extends ReactWidget {
Expand Down Expand Up @@ -406,6 +408,7 @@ export class CodeSnippetEditor extends ReactWidget {
this._codeSnippetEditorMetaData.name = name;
this._codeSnippetEditorMetaData.description = description;
this._codeSnippetEditorMetaData.language = language;
this._codeSnippetEditorMetaData.date_modified = new Date().toLocaleString();

const newPath =
'snippets/' + this._codeSnippetEditorMetaData.name + '.json';
Expand Down Expand Up @@ -461,7 +464,9 @@ export class CodeSnippetEditor extends ReactWidget {
language: this._codeSnippetEditorMetaData.language,
code: this._codeSnippetEditorMetaData.code,
id: this._codeSnippetEditorMetaData.id,
tags: this._codeSnippetEditorMetaData.selectedTags
tags: this._codeSnippetEditorMetaData.selectedTags,
date_created: this._codeSnippetEditorMetaData.date_created,
date_modified: this._codeSnippetEditorMetaData.date_modified
})
});

Expand Down
4 changes: 3 additions & 1 deletion src/CodeSnippetInputDialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ export function CodeSnippetInputDialog(
language: result.value[2],
code: code,
id: idx,
tags: tags
tags: tags,
date_created: new Date().toLocaleString(),
date_modified: new Date().toLocaleString()
};
const contentsService = CodeSnippetContentsService.getInstance();
const currSnippets = codeSnippetWidget.codeSnippetWidgetModel.snippets;
Expand Down
53 changes: 53 additions & 0 deletions src/SortOption.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from 'react';
import { checkIcon } from '@jupyterlab/ui-components';

const CODE_SNIPPET_SORT_OPTION_UNSELECT =
'jp-codeSnippet-sort-option-unselected';
const CODE_SNIPPET_SORT_OPTION_SELECT = 'jp-codeSnippet-sort-option-selected';

interface ISortSnippetOptionProps {
optionSelected: boolean;
optionName: string;
onSelectMulti: (name: string) => void;
onSelectParent: (name: string) => void;
}

const SortOption = ({
optionSelected,
optionName,
onSelectMulti,
onSelectParent
}: ISortSnippetOptionProps): JSX.Element => {
if (optionSelected) {
return (
<div
className={CODE_SNIPPET_SORT_OPTION_SELECT}
onClick={(): void => {
onSelectMulti('');
}}
>
<checkIcon.react
className="jupyterlab-CodeSnippets-sort-selected"
elementPosition="center"
height="16px"
width="16px"
marginLeft="2px"
/>
{optionName}
</div>
);
} else {
return (
<div
className={CODE_SNIPPET_SORT_OPTION_UNSELECT}
onClick={(): void => {
onSelectMulti(optionName);
}}
>
{optionName}
</div>
);
}
};

export default SortOption;
181 changes: 181 additions & 0 deletions src/SortTools.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
import React from 'react';
import { Widget } from '@lumino/widgets';
import { showMoreOptions } from './MoreOptions';

import ReactDOM from 'react-dom';
import SortOption from './SortOption';

const SORT_TOOL = 'jp-codeSnippet-sort-tool';
const SORT_ICON_INACTIVE = 'jp-codeSnippet-sort-icon-inactive';
const SORT_ICON_ACTIVE = 'jp-codeSnippet-sort-icon-active';
const CODE_SNIPPET_SORT_CONTENT = 'jp-codeSnippet-sort-content';
const CODE_SNIPPET_SORT_SORTBY = 'jp-codeSnippet-sort-sortby';
const CODE_SNIPPET_SORT_LINE = 'jp-codeSnippet-sort-line';
// const CODE_SNIPPET_SORT_SELECTED = 'jp-codeSnippet-sort-selected';

/* Add on click to span and then create function to actually do the sorting*/
/* Right now the coloring of the arrows is off, make sure when dialog disappears arrow turns back to gray*/
/* Add innerHTML for the checkmark when something is clicked. When its clicked again remove the checkmark. */

interface ISortSnippetState {
optionName: string;
currSelected: string;
}

class OptionsHandler extends Widget {
constructor(display: SortTools) {
super({ node: display.createOptionsNode() });
}
}
interface ISortMultiState {
currSelected: string;
}

interface ISortMultiProps {
currSelected: string;
handleOptionClick: (name: string) => void;
}

// New component that holds gets re-rendered whenever anything is changed/clicked.
export class SortMultiOption extends React.Component<
ISortMultiProps,
ISortMultiState
> {
constructor(props: ISortMultiProps) {
super(props);
this.state = {
currSelected: this.props.currSelected
};
this.handleClick = this.handleClick.bind(this);
}

handleClick(selectedOption: string): void {
this.props.handleOptionClick(selectedOption);
this.setState({ currSelected: selectedOption });
}

render(): JSX.Element {
return (
<div className={CODE_SNIPPET_SORT_CONTENT} id={CODE_SNIPPET_SORT_CONTENT}>
<div className={CODE_SNIPPET_SORT_SORTBY}>Sort by:</div>
<div className={CODE_SNIPPET_SORT_LINE}></div>
<SortOption
optionSelected={this.state.currSelected === 'Last Modified'}
optionName={'Last Modified'}
onSelectMulti={this.handleClick}
onSelectParent={this.props.handleOptionClick}
></SortOption>
<SortOption
optionSelected={this.state.currSelected === 'Date Created: Newest'}
optionName={'Date Created: Newest'}
onSelectMulti={this.handleClick}
onSelectParent={this.props.handleOptionClick}
></SortOption>
<SortOption
optionSelected={this.state.currSelected === 'Date Created: Oldest'}
optionName={'Date Created: Oldest'}
onSelectMulti={this.handleClick}
onSelectParent={this.props.handleOptionClick}
></SortOption>
</div>
);
}
}

export class SortTools extends React.Component<{}, ISortSnippetState> {
constructor(props: {}) {
super(props);
this.state = {
optionName: '',
currSelected: ''
};
this.handleClick = this.handleClick.bind(this);
this.handleOptionClick = this.handleOptionClick.bind(this);
}

private _setSortToolPosition(
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
): void {
const target = event.target as HTMLElement;
const top = target.getBoundingClientRect().top + 30;
const leftAsString =
(target.getBoundingClientRect().left - 164).toString(10) + 'px';
const topAsString = top.toString(10) + 'px';
document.documentElement.style.setProperty(
'--more-options-top',
topAsString
);
document.documentElement.style.setProperty(
'--more-options-left',
leftAsString
);
}

public createOptionsNode(): HTMLElement {
const body = document.createElement('div');
body.className = 'jp-codeSnippet-sort-test-container';
ReactDOM.render(
<SortMultiOption
currSelected={this.state.currSelected}
handleOptionClick={this.handleOptionClick}
/>,
body
);
return body;
}

// Converge the three sortoptions into a classful component that gets re-rendered when
// an option gets clicked.
// public createOptionsNodeHelper(): JSX.Element {
// return (
// <div className={CODE_SNIPPET_SORT_CONTENT} id={CODE_SNIPPET_SORT_CONTENT}>
// <div className={CODE_SNIPPET_SORT_SORTBY}>Sort by:</div>
// <div className={CODE_SNIPPET_SORT_LINE}></div>
// <SortOption
// optionSelected={this.state.currSelected === 'Last Modified'}
// optionName={'Last Modified'}
// onSelect={this.handleOptionClick}
// ></SortOption>
// <SortOption
// optionSelected={this.state.currSelected === 'Date Created : Newest'}
// optionName={'Date Created: Newest'}
// onSelect={this.handleOptionClick}
// ></SortOption>
// <SortOption
// optionSelected={this.state.currSelected === 'Date Created: Oldest'}
// optionName={'Date Created: Oldest'}
// onSelect={this.handleOptionClick}
// ></SortOption>
// </div>
// );
// }

handleOptionClick(selectedOption: string): void {
this.setState({ currSelected: selectedOption });
}

handleClick(event: React.MouseEvent<HTMLButtonElement, MouseEvent>): void {
const target = event.target as HTMLElement;
// const clickedTag = target.innerText;
// const parent = target.parentElement;
this.handleClickHelper(target);
showMoreOptions({ body: new OptionsHandler(this) });
this._setSortToolPosition(event);
}

handleClickHelper(parent: HTMLElement): void {
if (parent.classList.contains(SORT_ICON_INACTIVE)) {
parent.classList.replace(SORT_ICON_INACTIVE, SORT_ICON_ACTIVE);
} else if (parent.classList.contains(SORT_ICON_ACTIVE)) {
parent.classList.replace(SORT_ICON_ACTIVE, SORT_ICON_INACTIVE);
}
}

render(): JSX.Element {
return (
<div className={SORT_TOOL}>
<span className={SORT_ICON_INACTIVE} onClick={this.handleClick}></span>
</div>
);
}
}
10 changes: 9 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ import {
CodeSnippetEditor,
ICodeSnippetEditorMetadata
} from './CodeSnippetEditor';
// import {
// SettingManager,
// ServerConnection,
// ServiceManager
// } from '@jupyterlab/services';
// import { URLExt } from '@jupyterlab/coreutils';
// import { BaseManager } from '@jupyterlab/services/lib/basemanager';

const CODE_SNIPPET_EXTENSION_ID = 'code-snippet-extension';

Expand Down Expand Up @@ -73,7 +80,8 @@ function activateCodeSnippet(
app: JupyterFrontEnd,
palette: ICommandPalette,
restorer: ILayoutRestorer,
editorServices: IEditorServices
editorServices: IEditorServices,
settingRegistry: ISettingRegistry
): void {
console.log('JupyterLab extension code-snippets is activated!');

Expand Down
Loading