widget.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import {
  4. Message
  5. } from 'phosphor/lib/core/messaging';
  6. import {
  7. h, VNode
  8. } from 'phosphor/lib/ui/vdom';
  9. import {
  10. JupyterLab
  11. } from '../application';
  12. import {
  13. VDomModel, VDomWidget
  14. } from '../common/vdom';
  15. /**
  16. * The class name added to the dialog.
  17. */
  18. const LANDING_DIALOG_CLASS = 'jp-Landing-dialog';
  19. /**
  20. * The class name for the JupyterLab icon from default-theme.
  21. */
  22. const JUPYTERLAB_ICON_CLASS = 'jp-ImageJupyterLab';
  23. /**
  24. * The class name added to specify size of the JupyterLab logo.
  25. */
  26. const LANDING_LOGO_CLASS = 'jp-Landing-logo';
  27. /**
  28. * The class name added to the preview message subtitle.
  29. */
  30. const LANDING_SUBTITLE_CLASS = 'jp-Landing-subtitle';
  31. /**
  32. * The class name added for the tour icon from default-theme.
  33. */
  34. const TOUR_ICON_CLASS = 'jp-Landing-tour';
  35. /**
  36. * The class name added to the header text.
  37. */
  38. const LANDING_HEADER_CLASS = 'jp-Landing-header';
  39. /**
  40. * The class name added to the dialog body.
  41. */
  42. const LANDING_BODY_CLASS = 'jp-Landing-body';
  43. /**
  44. * The class name added to the column of the dialog.
  45. */
  46. const LANDING_COLUMN_CLASS = 'jp-Landing-column';
  47. /**
  48. * The class name added to specify size of activity icons.
  49. */
  50. const LANDING_ICON_CLASS = 'jp-Landing-image';
  51. /**
  52. * The class name added to the image text of an activity.
  53. */
  54. const LANDING_TEXT_CLASS = 'jp-Landing-text';
  55. /**
  56. * The class name added to the current working directory.
  57. */
  58. const LANDING_CWD_CLASS = 'jp-Landing-cwd';
  59. /**
  60. * The class name added to Landing folder node.
  61. */
  62. const FOLDER_CLASS = 'jp-Landing-folder';
  63. /**
  64. * The class name added for the folder icon from default-theme.
  65. */
  66. const FOLDER_ICON_CLASS = 'jp-FolderIcon';
  67. /**
  68. * The class name added to the current working directory path.
  69. */
  70. const LANDING_PATH_CLASS = 'jp-Landing-path';
  71. /**
  72. * The list of preview messages.
  73. */
  74. const previewMessages = [
  75. 'super alpha preview',
  76. 'very alpha preview',
  77. 'extremely alpha preview',
  78. 'exceedingly alpha preview',
  79. 'alpha alpha preview'
  80. ];
  81. /**
  82. * LandingModel keeps track of the path to working directory and has text data,
  83. * which the LandingWidget will render.
  84. */
  85. export
  86. class LandingModel extends VDomModel {
  87. /**
  88. * Preview messages.
  89. */
  90. readonly previewMessage: string;
  91. /**
  92. * The `Start a new activity` text.
  93. */
  94. readonly headerText: string;
  95. /**
  96. * The names of activities and their associated commands.
  97. */
  98. readonly activities: string[][];
  99. /**
  100. * Construct a new landing model.
  101. */
  102. constructor(terminalsAvailable = false) {
  103. super();
  104. this.previewMessage = previewMessages[
  105. Math.floor(Math.random() * previewMessages.length)
  106. ];
  107. this.headerText = 'Start a new activity';
  108. this.activities =
  109. [['Notebook', 'file-operations:new-notebook'],
  110. ['Code Console', `console:create`],
  111. ['Text Editor', 'file-operations:new-text-file']];
  112. if (terminalsAvailable) {
  113. this.activities.push(
  114. ['Terminal', 'terminal:create-new']
  115. );
  116. }
  117. this._path = 'home';
  118. }
  119. /**
  120. * Get the path of the current working directory.
  121. */
  122. get path(): string {
  123. return this._path;
  124. }
  125. /**
  126. * Set the path of the current working directory.
  127. */
  128. set path(value: string) {
  129. this._path = value;
  130. this.stateChanged.emit(void 0);
  131. }
  132. private _path: string;
  133. }
  134. /**
  135. * A virtual-DOM-based widget for the Landing plugin.
  136. */
  137. export
  138. class LandingWidget extends VDomWidget<LandingModel> {
  139. /**
  140. * Construct a new landing widget.
  141. */
  142. constructor(app: JupyterLab) {
  143. super();
  144. this._app = app;
  145. }
  146. /**
  147. * Handle `'activate-request'` messages.
  148. */
  149. protected onActivateRequest(msg: Message): void {
  150. this.node.tabIndex = -1;
  151. this.node.focus();
  152. }
  153. /**
  154. * Handle `'close-request'` messages.
  155. */
  156. protected onCloseRequest(msg: Message): void {
  157. super.onCloseRequest(msg);
  158. this.dispose();
  159. }
  160. /**
  161. * Render the landing plugin to virtual DOM nodes.
  162. */
  163. protected render(): VNode {
  164. let activitiesList: VNode[] = [];
  165. let activites = this.model.activities;
  166. for (let activityName of activites) {
  167. let imgName = activityName[0].replace(' ', '');
  168. let column =
  169. h.div({className: LANDING_COLUMN_CLASS},
  170. h.span({className: LANDING_ICON_CLASS + ` jp-Image${imgName}` ,
  171. onclick: () => {
  172. this._app.commands.execute(activityName[1], void 0);
  173. }}
  174. ),
  175. h.span({className: LANDING_TEXT_CLASS}, activityName[0])
  176. );
  177. activitiesList.push(column);
  178. }
  179. let logo = h.span({className: JUPYTERLAB_ICON_CLASS + ' ' + LANDING_LOGO_CLASS});
  180. let subtitle =
  181. h.span({className: LANDING_SUBTITLE_CLASS},
  182. this.model.previewMessage
  183. );
  184. let tour =
  185. h.span({className: TOUR_ICON_CLASS,
  186. onclick: () => {
  187. this._app.commands.execute('about-jupyterlab:show', void 0);
  188. }}
  189. );
  190. let header = h.span({
  191. className: LANDING_HEADER_CLASS
  192. }, this.model.headerText);
  193. let body = h.div({className: LANDING_BODY_CLASS}, activitiesList);
  194. let dialog = h.div({className: LANDING_DIALOG_CLASS},
  195. logo,
  196. subtitle,
  197. tour,
  198. header,
  199. body,
  200. h.div({className: LANDING_CWD_CLASS},
  201. h.span({className: FOLDER_ICON_CLASS + ' ' + FOLDER_CLASS}),
  202. h.span({className: LANDING_PATH_CLASS}, this.model.path
  203. )
  204. )
  205. );
  206. return dialog;
  207. }
  208. private _app: JupyterLab;
  209. }