@@ -168,6 +168,7 @@ export class CodeSnippetDisplay extends React.Component<
168168 this . _dragData = null ;
169169 this . handleDragMove = this . handleDragMove . bind ( this ) ;
170170 this . _evtMouseUp = this . _evtMouseUp . bind ( this ) ;
171+ this . handleRenameSnippet = this . handleRenameSnippet . bind ( this ) ;
171172 }
172173
173174 // Handle code snippet insert into an editor
@@ -321,9 +322,85 @@ export class CodeSnippetDisplay extends React.Component<
321322 ) ;
322323 }
323324 }
324- return < span > { name } </ span > ;
325+ return < span onDoubleClick = { this . handleRenameSnippet } > { name } </ span > ;
325326 } ;
326327
328+ // rename snippet on double click
329+ // TODO: duplicate name check!
330+ private async handleRenameSnippet (
331+ event : React . MouseEvent < HTMLSpanElement , MouseEvent >
332+ ) : Promise < void > {
333+ const contentsService = CodeSnippetContentsService . getInstance ( ) ;
334+ console . log ( event . currentTarget ) ;
335+ console . log ( event . target ) ;
336+ const target = event . target as HTMLElement ;
337+ const oldPath = 'snippets/' + target . innerHTML + '.json' ;
338+
339+ const new_element = document . createElement ( 'input' ) ;
340+ new_element . setAttribute ( 'type' , 'text' ) ;
341+ new_element . id = 'jp-codeSnippet-rename' ;
342+ new_element . innerHTML = target . innerHTML ;
343+
344+ target . replaceWith ( new_element ) ;
345+ new_element . value = target . innerHTML ;
346+
347+ new_element . focus ( ) ;
348+ new_element . setSelectionRange ( 0 , new_element . value . length ) ;
349+
350+ new_element . onblur = async ( ) : Promise < void > => {
351+ console . log ( target . innerHTML ) ;
352+ console . log ( new_element . value ) ;
353+ if ( target . innerHTML !== new_element . value ) {
354+ const newPath = 'snippets/' + new_element . value + '.json' ;
355+ try {
356+ await contentsService . rename ( oldPath , newPath ) ;
357+ } catch ( error ) {
358+ new_element . replaceWith ( target ) ;
359+
360+ await showDialog ( {
361+ title : 'Duplicate Name of Code Snippet' ,
362+ body : < p > { `"${ newPath } " already exists.` } </ p > ,
363+ buttons : [ Dialog . okButton ( { label : 'Dismiss' } ) ]
364+ } ) ;
365+ return ;
366+ }
367+ this . props . _codeSnippetWidgetModel . renameSnippet (
368+ target . innerHTML ,
369+ new_element . value
370+ ) ;
371+ target . innerHTML = new_element . value ;
372+ }
373+ new_element . replaceWith ( target ) ;
374+ } ;
375+ new_element . onkeydown = ( event : KeyboardEvent ) : void => {
376+ switch ( event . code ) {
377+ case 'Enter' || 'NumpadEnter' : // Enter
378+ event . stopPropagation ( ) ;
379+ event . preventDefault ( ) ;
380+ new_element . blur ( ) ;
381+ break ;
382+ case 'Escape' : // Escape
383+ event . stopPropagation ( ) ;
384+ event . preventDefault ( ) ;
385+ new_element . blur ( ) ;
386+ break ;
387+ case 'ArrowUp' : // Up arrow
388+ event . stopPropagation ( ) ;
389+ event . preventDefault ( ) ;
390+ new_element . selectionStart = new_element . selectionEnd = 0 ;
391+ break ;
392+ case 'ArrowDown' : // Down arrow
393+ event . stopPropagation ( ) ;
394+ event . preventDefault ( ) ;
395+ new_element . selectionStart = new_element . selectionEnd =
396+ new_element . value . length ;
397+ break ;
398+ default :
399+ break ;
400+ }
401+ } ;
402+ }
403+
327404 private handleDragSnippet (
328405 event : React . MouseEvent < HTMLDivElement , MouseEvent >
329406 ) : void {
0 commit comments