1515 * See the License for the specific language governing permissions a* limitations under the License.
1616 */
1717
18- import { Clipboard , Dialog , showDialog } from '@jupyterlab/apputils' ;
18+ import {
19+ Clipboard ,
20+ Dialog ,
21+ InputDialog ,
22+ showDialog ,
23+ } from '@jupyterlab/apputils' ;
1924import { PathExt } from '@jupyterlab/coreutils' ;
2025import { DocumentWidget } from '@jupyterlab/docregistry' ;
2126import { FileEditor } from '@jupyterlab/fileeditor' ;
@@ -50,10 +55,9 @@ import { CodeSnippetService, ICodeSnippet } from './CodeSnippetService';
5055import { FilterTools } from './FilterTools' ;
5156import { showPreview } from './PreviewSnippet' ;
5257import { showMoreOptions } from './CodeSnippetMenu' ;
53- // import {
54- // ICodeSnippet,
55- // CodeSnippetContentsService
56- // } from './CodeSnippetContentsService';
58+ // import { showCodeSnippetForm, CodeSnippetForm } from './CodeSnippetForm';
59+
60+ import { CodeSnippetContentsService } from './CodeSnippetContentsService' ;
5761
5862import moreSVGstr from '../style/icon/jupyter_moreicon.svg' ;
5963import {
@@ -96,6 +100,7 @@ import {
96100 sasIcon ,
97101} from './CodeSnippetLanguages' ;
98102import { ICodeSnippetEditorMetadata } from './CodeSnippetEditor' ;
103+ // import { CodeSnippetContentsService } from './CodeSnippetContentsService';
99104
100105/**
101106 * The CSS class added to code snippet widget.
@@ -121,6 +126,8 @@ const CODE_SNIPPET_MORE_OTPIONS_COPY = 'jp-codeSnippet-more-options-copy';
121126const CODE_SNIPPET_MORE_OTPIONS_INSERT = 'jp-codeSnippet-more-options-insert' ;
122127const CODE_SNIPPET_MORE_OTPIONS_EDIT = 'jp-codeSnippet-more-options-edit' ;
123128const CODE_SNIPPET_MORE_OTPIONS_DELETE = 'jp-codeSnippet-more-options-delete' ;
129+ const CODE_SNIPPET_MORE_OTPIONS_DOWNLOAD =
130+ 'jp-codeSnippet-more-options-download' ;
124131const CODE_SNIPPET_CREATE_NEW_BTN = 'jp-createSnippetBtn' ;
125132const CODE_SNIPPET_NAME = 'jp-codeSnippet-name' ;
126133
@@ -195,7 +202,7 @@ export class CodeSnippetDisplay extends React.Component<
195202 this . handleRenameSnippet = this . handleRenameSnippet . bind ( this ) ;
196203 }
197204
198- // Handle code snippet insert into an editor
205+ // Handle code snippet insert into a notebook or document
199206 private insertCodeSnippet = async ( snippet : ICodeSnippet ) : Promise < void > => {
200207 const widget : Widget = this . props . getCurrentWidget ( ) ;
201208 const snippetStr : string = snippet . code . join ( '\n' ) ;
@@ -1415,6 +1422,38 @@ export class CodeSnippetDisplay extends React.Component<
14151422 } ) ;
14161423 }
14171424
1425+ private downloadCommand ( codeSnippet : ICodeSnippet ) : void {
1426+ // Request a text
1427+ InputDialog . getText ( {
1428+ title : 'Download Snippet?' ,
1429+ label : 'Directory to Download: ' ,
1430+ placeholder : 'share/snippet' ,
1431+ okLabel : 'Download' ,
1432+ } ) . then ( ( value : Dialog . IResult < string > ) => {
1433+ if ( value . button . accept ) {
1434+ const dirs = value . value . split ( '/' ) ;
1435+
1436+ const codeSnippetDownloader = CodeSnippetContentsService . getInstance ( ) ;
1437+
1438+ let path = '' ;
1439+ for ( let i = 0 ; i < dirs . length ; i ++ ) {
1440+ path += dirs [ i ] + '/' ;
1441+ codeSnippetDownloader . save ( path , { type : 'directory' } ) . catch ( ( _ ) => {
1442+ alert ( 'Path should be a relative path' ) ;
1443+ } ) ;
1444+ }
1445+
1446+ path += codeSnippet . name + '.json' ;
1447+
1448+ codeSnippetDownloader . save ( path , {
1449+ type : 'file' ,
1450+ format : 'text' ,
1451+ content : JSON . stringify ( codeSnippet ) ,
1452+ } ) ;
1453+ }
1454+ } ) ;
1455+ }
1456+
14181457 // remove dropdown menu
14191458 private removeOptionsNode ( ) : void {
14201459 const temp = document . getElementsByClassName ( CODE_SNIPPET_MORE_OPTIONS ) [ 0 ] ;
@@ -1468,9 +1507,19 @@ export class CodeSnippetDisplay extends React.Component<
14681507 this . deleteCommand ( codeSnippet ) ;
14691508 this . removeOptionsNode ( ) ;
14701509 } ;
1510+
1511+ const downloadSnip = document . createElement ( 'div' ) ;
1512+ downloadSnip . className = CODE_SNIPPET_MORE_OTPIONS_DOWNLOAD ;
1513+ downloadSnip . textContent = 'Download snippet' ;
1514+ downloadSnip . onclick = ( ) : void => {
1515+ this . downloadCommand ( codeSnippet ) ;
1516+ this . removeOptionsNode ( ) ;
1517+ } ;
1518+
14711519 optionsContainer . appendChild ( insertSnip ) ;
14721520 optionsContainer . appendChild ( copySnip ) ;
14731521 optionsContainer . appendChild ( editSnip ) ;
1522+ optionsContainer . appendChild ( downloadSnip ) ;
14741523 optionsContainer . appendChild ( deleteSnip ) ;
14751524 body . append ( optionsContainer ) ;
14761525 return body ;
0 commit comments