index.ts 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  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. VDomModel, VDomWidget
  11. } from '../common/vdom';
  12. /**
  13. * The class name added to each page in the About plugin.
  14. */
  15. const SECTION_CLASS = 'jp-About-section';
  16. /**
  17. * The class name added to center content.
  18. */
  19. const SECTION_CENTER_CLASS = 'jp-About-sectioncenter';
  20. /**
  21. * The class name added to group elements on the initial page.
  22. */
  23. const CONTAINER_CLASS = 'jp-About-container';
  24. /**
  25. * The class name added to elements in a row.
  26. */
  27. const ROW_CLASS = 'jp-About-row';
  28. /**
  29. * The class name added to elements in a column.
  30. */
  31. const COLUMN_CLASS = 'jp-About-column';
  32. /**
  33. * The class name used specify postion of elements.
  34. */
  35. const HALF_CLASS = 'jp-About-one-half';
  36. /**
  37. * The class name added to the About plugin description on the intial page.
  38. */
  39. const DESC_ONE_CLASS = 'jp-About-desc-one';
  40. /**
  41. * The class name added to other plugin descriptions on the intial page.
  42. */
  43. const DESC_TWO_CLASS = 'jp-About-desc-two';
  44. /**
  45. * The class name added to headers of other plugins on the intial page.
  46. */
  47. const DESC_TWO_HEADER_CLASS = 'jp-About-desc-two-header';
  48. /**
  49. * The class name added to headers.
  50. */
  51. const HEADER_CLASS = 'jp-About-header';
  52. /**
  53. * The class name added to plugin pages.
  54. */
  55. const CONTENT_CLASS = 'jp-About-content';
  56. /**
  57. * The class name added to descriptions on plugin pages.
  58. */
  59. const CONTENT_DESC_CLASS = 'jp-About-content-desc';
  60. /**
  61. * The class name added to the navigation down button.
  62. */
  63. const NAV_CLASS = 'jp-About-nav-button';
  64. /**
  65. * The class name added to all images and icons.
  66. */
  67. const IMAGE_CLASS = 'jp-img';
  68. /**
  69. * The class name added to the JupyterLab logo.
  70. */
  71. const LOGO_CLASS = 'jp-About-logo';
  72. /**
  73. * The class name added to the main area icon.
  74. */
  75. const MAIN_AREA_ICON_CLASS = 'jp-About-hero-mainarea';
  76. /**
  77. * The class name added the command palette icon.
  78. */
  79. const COMMAND_ICON_CLASS = 'jp-About-hero-command';
  80. /**
  81. * The class name added to the filebrowser icon.
  82. */
  83. const FILEBROWSER_ICON_CLASS = 'jp-About-hero-filebrowser';
  84. /**
  85. * The class name added for the notebook icon.
  86. */
  87. const NOTEBOOK_ICON_CLASS = 'jp-About-hero-notebook';
  88. /**
  89. * The class name added to the main area image.
  90. */
  91. const MAIN_AREA_IMAGE_CLASS = 'jp-About-mainarea';
  92. /**
  93. * The class name added to the command palette image.
  94. */
  95. const COMMAND_IMAGE_CLASS = 'jp-About-command';
  96. /**
  97. * The class name added to the filebrowser image.
  98. */
  99. const FILEBROWSER_IMAGE_CLASS = 'jp-About-fb';
  100. /**
  101. * The class name added to the notebook image.
  102. */
  103. const NOTEBOOK_IMAGE_CLASS = 'jp-About-nb';
  104. /**
  105. * Title of About page.
  106. */
  107. const TITLE = 'Welcome to the JupyterLab Alpha preview';
  108. /**
  109. * Text on the first page that gives a high level overview of JupyterLab.
  110. */
  111. const HEADER_TEXT = [
  112. 'Click on the Launcher tab for the initial JupyterLab screen.',
  113. 'This demo gives an alpha developer preview of the JupyterLab environment.',
  114. 'It is not ready for general usage yet.',
  115. 'We are developing JupyterLab at ',
  116. 'https://github.com/jupyterlab/jupyterlab',
  117. '. Pull requests are welcome!',
  118. `Here is a brief description of some of the things you'll find in this demo.`
  119. ];
  120. /**
  121. * Contains the plugin names.
  122. */
  123. const PLUGIN_HEADERS = [
  124. 'Main Area',
  125. 'Command Palette',
  126. 'File Browser',
  127. 'Notebook'
  128. ];
  129. /**
  130. * Description of the main area and its functionality.
  131. */
  132. const MAIN_AREA_DESC = [
  133. 'Open tabs and drag and drop them to rearrange them.',
  134. `The main area is divided into panels of tabs. Drag a tab around the area
  135. to split the main area in different ways. Drag a tab to the center of a
  136. panel to move a tab without splitting the panel (in this case, the whole
  137. panel will highlight instead of just a portion).`,
  138. `Resize panels by dragging their borders (be aware that panels and sidebars
  139. also have a minimum width). A file that contains changes to be saved has
  140. a circle for a close icon.`
  141. ];
  142. /**
  143. * Description of the file browser and its functionality.
  144. */
  145. const FILE_BROWSER_DESC = [
  146. 'Navigate and organize your files.',
  147. `Clicking the "Files" tab, located on the left, will toggle the file browser.
  148. Navigate into directories by double-clicking, and use the breadcrumbs at the
  149. top to navigate out. Create a new file/directory by clicking the plus icon at
  150. the top. Click the middle icon to upload files, and click the last icon to
  151. reload the file listing. Drag and drop files to move them to subdirectories.
  152. Click on a selected file to rename it. Sort the list by clicking on a column
  153. header.
  154. Open a file by double-clicking it or dragging it into the main area.
  155. Opening an image displays the image. Opening a code file opens a code editor.
  156. Opening a notebook opens a very preliminary notebook component.`
  157. ];
  158. /**
  159. * Description of the command palette and its functionality.
  160. */
  161. const COMMAND_PALETTE_DESC = [
  162. 'View list of commands and keyboard shortcuts.',
  163. `Clicking the "Commands" tab, located on the left, will toggle the command
  164. palette. Execute a command by clicking, or navigating with your arrow keys
  165. and pressing Enter. Filter commands by typing in the text box at the top of
  166. the palette. The palette is organized into categories, and you can filter on
  167. a single category by clicking on the category header or by typing the header
  168. surrounded by colons in the search input (e.g., :file:).`,
  169. 'You can try these things from the command palette:',
  170. 'Open a new terminal (requires macOS or Linux)',
  171. 'Open an IPython console',
  172. 'Open a new file',
  173. 'Save a file',
  174. 'Open a help panel on the right'
  175. ];
  176. /**
  177. * Description of the notebook and its functionality.
  178. */
  179. const NOTEBOOK_DESC = [
  180. 'Dedicate a tab to running a class notebook.',
  181. `Opening a notebook will open a minimally-featured notebook.
  182. Code execution, Markdown rendering, and basic cell toolbar actions are
  183. supported.
  184. Future versions will add more features from the existing Jupyter notebook.`
  185. ];
  186. /**
  187. * AboutModel holds data which the AboutWidgetwill render.
  188. */
  189. export
  190. class AboutModel extends VDomModel {
  191. /**
  192. * Title of About page.
  193. */
  194. readonly title = TITLE;
  195. /**
  196. * Text on the first page that gives a high level overview of JupyterLab.
  197. */
  198. readonly headerText = HEADER_TEXT;
  199. /**
  200. * Contains the plugin names.
  201. */
  202. readonly pluginHeaders = PLUGIN_HEADERS;
  203. /**
  204. * Description of the main area and its functionality.
  205. */
  206. readonly mainAreaDesc = MAIN_AREA_DESC;
  207. /**
  208. * Description of the file browser and its functionality.
  209. */
  210. readonly filebrowserDesc = FILE_BROWSER_DESC;
  211. /**
  212. * Description of the command palette and its functionality.
  213. */
  214. readonly commandPaletteDesc = COMMAND_PALETTE_DESC;
  215. /**
  216. * Description of the notebook and its functionality.
  217. */
  218. readonly notebookDesc = NOTEBOOK_DESC;
  219. }
  220. /**
  221. * A virtual-DOM-based widget for the About plugin.
  222. */
  223. export
  224. class AboutWidget extends VDomWidget<AboutModel> {
  225. /**
  226. * Handle `'activate-request'` messages.
  227. */
  228. protected onActivateRequest(msg: Message): void {
  229. this.node.tabIndex = -1;
  230. this.node.focus();
  231. }
  232. /**
  233. * Handle `'close-request'` messages.
  234. */
  235. protected onCloseRequest(msg: Message): void {
  236. super.onCloseRequest(msg);
  237. this.dispose();
  238. }
  239. /**
  240. * Render the about plugin to virtual DOM nodes.
  241. */
  242. protected render(): VNode {
  243. let title = this.model.title;
  244. let headerText = this.model.headerText;
  245. let pluginHeaders = this.model.pluginHeaders;
  246. let mainAreaDesc = this.model.mainAreaDesc;
  247. let filebrowserDesc = this.model.filebrowserDesc;
  248. let commandPaletteDesc = this.model.commandPaletteDesc;
  249. let notebookDesc = this.model.notebookDesc;
  250. let headerRow = h.div({ className: ROW_CLASS },
  251. h.div({ className: COLUMN_CLASS },
  252. h.span({ className: IMAGE_CLASS + ' ' + LOGO_CLASS }),
  253. h.p({ className: HEADER_CLASS }, title),
  254. h.div({ className: DESC_ONE_CLASS },
  255. h.p(headerText[0]),
  256. h.p(headerText[1], ' ', h.strong(headerText[2])),
  257. h.p(headerText[3],
  258. h.a({ href: headerText[4], target: '_blank' }, headerText[4]),
  259. headerText[5]
  260. ),
  261. h.p(headerText[6])
  262. )
  263. )
  264. );
  265. let mainAreaCommandPaletteRow = h.div({ className: ROW_CLASS },
  266. h.div({ className: HALF_CLASS + ' ' + COLUMN_CLASS },
  267. h.p({ className: DESC_TWO_HEADER_CLASS },
  268. h.a({ href: '#about-main-area' },
  269. h.span({ className: IMAGE_CLASS + ' ' + MAIN_AREA_ICON_CLASS }),
  270. pluginHeaders[0]
  271. )
  272. ),
  273. h.p({ className: DESC_TWO_CLASS }, mainAreaDesc[0])
  274. ),
  275. h.div({ className: HALF_CLASS + ' ' + COLUMN_CLASS },
  276. h.p({ className: DESC_TWO_HEADER_CLASS },
  277. h.a({ href: '#about-command' },
  278. h.span({ className: IMAGE_CLASS + ' ' + COMMAND_ICON_CLASS }),
  279. pluginHeaders[1]
  280. )
  281. ),
  282. h.p({ className: DESC_TWO_CLASS }, commandPaletteDesc[0])
  283. )
  284. );
  285. let filebrowserNotebookRow = h.div({ className: ROW_CLASS },
  286. h.div({ className: HALF_CLASS + ' ' + COLUMN_CLASS },
  287. h.p({ className: DESC_TWO_HEADER_CLASS },
  288. h.a({ href: '#about-filebrowser' },
  289. h.span({ className: IMAGE_CLASS + ' ' + FILEBROWSER_ICON_CLASS }),
  290. pluginHeaders[2]
  291. )
  292. ),
  293. h.p({ className: DESC_TWO_CLASS }, filebrowserDesc[0]),
  294. ),
  295. h.div({ className: HALF_CLASS + ' ' + COLUMN_CLASS },
  296. h.p({ className: DESC_TWO_HEADER_CLASS },
  297. h.a({ href: '#about-notebook' },
  298. h.span({ className: IMAGE_CLASS + ' ' + NOTEBOOK_ICON_CLASS }),
  299. pluginHeaders[3]
  300. )
  301. ),
  302. h.p({ className: DESC_TWO_CLASS }, notebookDesc[0])
  303. )
  304. );
  305. let mainAreaPage = h.div({ className: SECTION_CLASS },
  306. h.a({ id: 'about-main-area' }),
  307. h.div({ className: SECTION_CENTER_CLASS },
  308. h.p({ className: HEADER_CLASS + ' ' + CONTENT_CLASS },
  309. h.span({ className: IMAGE_CLASS + ' ' + MAIN_AREA_ICON_CLASS }),
  310. pluginHeaders[0]
  311. ),
  312. h.span({ className: IMAGE_CLASS + ' ' + MAIN_AREA_IMAGE_CLASS }),
  313. h.p({ className: CONTENT_DESC_CLASS }, mainAreaDesc[1]),
  314. h.p({ className: CONTENT_DESC_CLASS }, mainAreaDesc[2]),
  315. h.a({ href: '#about-command' }, h.span({ className: NAV_CLASS }))
  316. )
  317. );
  318. let commandPalettePage = h.div({ className: SECTION_CLASS },
  319. h.a({ id: 'about-command' }),
  320. h.div({ className: SECTION_CENTER_CLASS },
  321. h.p({ className: HEADER_CLASS + ' ' + CONTENT_CLASS },
  322. h.span({ className: IMAGE_CLASS + ' ' + COMMAND_ICON_CLASS }),
  323. pluginHeaders[1]
  324. ),
  325. h.span({ className: IMAGE_CLASS + ' ' + COMMAND_IMAGE_CLASS }),
  326. h.p({ className: CONTENT_DESC_CLASS }, commandPaletteDesc[1]),
  327. h.div({ className: CONTENT_DESC_CLASS },
  328. h.p(commandPaletteDesc[2]),
  329. h.ul(
  330. h.li(commandPaletteDesc[3]),
  331. h.li(commandPaletteDesc[4]),
  332. h.li(commandPaletteDesc[5]),
  333. h.li(commandPaletteDesc[6]),
  334. h.li(commandPaletteDesc[7])
  335. )
  336. ),
  337. h.a({ href: '#about-filebrowser' }, h.span({ className: NAV_CLASS }))
  338. )
  339. );
  340. let filebrowserPage = h.div({ className: SECTION_CLASS },
  341. h.a({ id: 'about-filebrowser' }),
  342. h.div({ className: SECTION_CENTER_CLASS },
  343. h.p({ className: HEADER_CLASS + ' ' + CONTENT_CLASS },
  344. h.span({ className: IMAGE_CLASS + ' ' + FILEBROWSER_ICON_CLASS }),
  345. pluginHeaders[2]
  346. ),
  347. h.span({ className: IMAGE_CLASS + ' ' + FILEBROWSER_IMAGE_CLASS }),
  348. h.p({ className: CONTENT_DESC_CLASS }, filebrowserDesc[1]),
  349. h.a({ href: '#about-notebook' }, h.span({ className: NAV_CLASS }))
  350. )
  351. );
  352. let notebookPage = h.div({ className: SECTION_CLASS },
  353. h.a({ id: 'about-notebook' }),
  354. h.div({ className: SECTION_CENTER_CLASS },
  355. h.p({ className: HEADER_CLASS + ' ' + CONTENT_CLASS },
  356. h.span({ className: IMAGE_CLASS + ' ' + NOTEBOOK_ICON_CLASS }),
  357. pluginHeaders[3]
  358. ),
  359. h.span({ className: IMAGE_CLASS + ' ' + NOTEBOOK_IMAGE_CLASS }),
  360. h.p({ className: CONTENT_DESC_CLASS }, notebookDesc[1])
  361. )
  362. );
  363. return h.div({id: 'about' },
  364. h.div({ className: SECTION_CLASS },
  365. h.div({ className: SECTION_CENTER_CLASS },
  366. h.div({ className: CONTAINER_CLASS },
  367. headerRow,
  368. mainAreaCommandPaletteRow,
  369. filebrowserNotebookRow
  370. ),
  371. h.a({ href: '#about-main-area' }, h.span({ className: NAV_CLASS }))
  372. )
  373. ),
  374. mainAreaPage,
  375. commandPalettePage,
  376. filebrowserPage,
  377. notebookPage
  378. );
  379. }
  380. }