➡️ Migrate core package 'welcome' into ./packages

This commit is contained in:
Jason Rudolph 2019-08-09 16:12:23 -04:00
parent 3663d59043
commit f05db285f8
No known key found for this signature in database
GPG Key ID: B760F197E561DF15
24 changed files with 3442 additions and 6 deletions

3
package-lock.json generated
View File

@ -6969,8 +6969,7 @@
"integrity": "sha1-BNoCcKh6d4VAFzzb8KLbSZqNnik="
},
"welcome": {
"version": "https://www.atom.io/api/packages/welcome/versions/0.36.9/tarball",
"integrity": "sha512-nvDLkdma06bn7DjC4cXvQdm1iTQs0rryNmk6fe44HbqxNyVbmSgNqBjrSllPWPc64C0kAWsgw1PcpVlY/5v4lw==",
"version": "file:packages/welcome",
"requires": {
"etch": "0.9.0"
},

View File

@ -163,7 +163,7 @@
"typescript-simple": "1.0.0",
"update-package-dependencies": "https://www.atom.io/api/packages/update-package-dependencies/versions/0.13.1/tarball",
"vscode-ripgrep": "^1.2.5",
"welcome": "https://www.atom.io/api/packages/welcome/versions/0.36.9/tarball",
"welcome": "file:packages/welcome",
"whitespace": "https://www.atom.io/api/packages/whitespace/versions/0.37.7/tarball",
"winreg": "^1.2.1",
"wrap-guide": "https://www.atom.io/api/packages/wrap-guide/versions/0.41.0/tarball",
@ -226,7 +226,7 @@
"timecop": "0.36.2",
"tree-view": "0.228.0",
"update-package-dependencies": "0.13.1",
"welcome": "0.36.9",
"welcome": "file:./packages/welcome",
"whitespace": "0.37.7",
"wrap-guide": "0.41.0",
"language-c": "0.60.18",

View File

@ -97,7 +97,7 @@ See [RFC 003](https://github.com/atom/atom/blob/master/docs/rfcs/003-consolidate
| **timecop** | [`atom/timecop`][timecop] | [#18272](https://github.com/atom/atom/issues/18272) |
| **tree-view** | [`atom/tree-view`][tree-view] | |
| **update-package-dependencies** | [`atom/update-package-dependencies`][update-package-dependencies] | [#18284](https://github.com/atom/atom/issues/18284) |
| **welcome** | [`atom/welcome`][welcome] | [#18285](https://github.com/atom/atom/issues/18285) |
| **welcome** | [`./welcome`](./welcome) | [#18285](https://github.com/atom/atom/issues/18285) |
| **whitespace** | [`atom/whitespace`][whitespace] | |
| **wrap-guide** | [`atom/wrap-guide`][wrap-guide] | [#18286](https://github.com/atom/atom/issues/18286) |
@ -166,6 +166,5 @@ See [RFC 003](https://github.com/atom/atom/blob/master/docs/rfcs/003-consolidate
[timecop]: https://github.com/atom/timecop
[tree-view]: https://github.com/atom/tree-view
[update-package-dependencies]: https://github.com/atom/update-package-dependencies
[welcome]: https://github.com/atom/welcome
[whitespace]: https://github.com/atom/whitespace
[wrap-guide]: https://github.com/atom/wrap-guide

1
packages/welcome/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
node_modules

View File

@ -0,0 +1,20 @@
Copyright (c) 2014 GitHub Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,3 @@
## Welcome package
Opens a welcome editor with helpful information the very first time Atom is opened and the usage statistics opt-in.

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="160px" height="80px" viewBox="0 0 160 80" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs></defs>
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g>
<rect fill-opacity="0.081861413" fill="#FFFFFF" x="0" y="0" width="160" height="80"></rect>
<rect fill-opacity="0.164600317" fill="#000000" x="40" y="72" width="120" height="8"></rect>
<g>
<rect fill-opacity="0.161882926" fill="#000000" x="0" y="0" width="40" height="80"></rect>
<rect fill-opacity="0.08" fill="#FFFFFF" x="4" y="4" width="24" height="4"></rect>
<rect fill-opacity="0.08" fill="#FFFFFF" x="4" y="12" width="16" height="4"></rect>
<rect fill-opacity="0.08" fill="#FFFFFF" x="4" y="20" width="30" height="4"></rect>
<rect fill-opacity="0.08" fill="#FFFFFF" x="4" y="28" width="21" height="4"></rect>
<rect fill-opacity="0.08" fill="#FFFFFF" x="4" y="36" width="24" height="4"></rect>
</g>
<g transform="translate(40.000000, 0.000000)" fill-opacity="0.164600317" fill="#000000">
<rect x="60" y="0" width="60" height="8"></rect>
<rect x="0" y="0" width="30" height="8"></rect>
</g>
<g transform="translate(44.000000, 12.000000)">
<rect fill="#BB263A" x="0" y="0" width="18" height="4"></rect>
<rect fill="#BB263A" x="0" y="8" width="47" height="4"></rect>
<rect fill="#BB263A" x="0" y="16" width="31" height="4"></rect>
<rect fill="#FF5F74" x="33" y="16" width="2" height="4"></rect>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="160px" height="80px" viewBox="0 0 160 80" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs></defs>
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g>
<rect fill-opacity="0.081861413" fill="#FFFFFF" x="0" y="0" width="160" height="80"></rect>
<rect fill-opacity="0.164600317" fill="#000000" x="40" y="72" width="120" height="8"></rect>
<g>
<rect fill-opacity="0.161882926" fill="#000000" x="0" y="0" width="40" height="80"></rect>
<rect fill-opacity="0.08" fill="#FFFFFF" x="4" y="4" width="24" height="4"></rect>
<rect fill-opacity="0.08" fill="#FFFFFF" x="4" y="12" width="16" height="4"></rect>
<rect fill-opacity="0.08" fill="#FFFFFF" x="4" y="20" width="30" height="4"></rect>
<rect fill-opacity="0.08" fill="#FFFFFF" x="4" y="28" width="21" height="4"></rect>
<rect fill-opacity="0.08" fill="#FFFFFF" x="4" y="36" width="24" height="4"></rect>
</g>
<g transform="translate(40.000000, 0.000000)" fill-opacity="0.164600317" fill="#000000">
<rect x="60" y="0" width="60" height="8"></rect>
<rect x="0" y="0" width="30" height="8"></rect>
</g>
<g transform="translate(142.000000, 8.000000)">
<rect fill="#BB263A" x="0" y="0" width="18" height="64"></rect>
<rect fill="#FF5F74" x="2" y="3" width="12" height="2"></rect>
<rect fill="#FF5F74" x="2" y="7" width="14" height="2"></rect>
<rect fill="#FF5F74" x="2" y="11" width="6" height="2"></rect>
<rect fill="#FF5F74" x="2" y="15" width="10" height="2"></rect>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="160px" height="80px" viewBox="0 0 160 80" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs></defs>
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g>
<rect fill-opacity="0.081861413" fill="#FFFFFF" x="0" y="0" width="160" height="80"></rect>
<rect fill="#BB263A" x="0" y="0" width="40" height="80"></rect>
<rect fill-opacity="0.164600317" fill="#000000" x="100" y="0" width="60" height="8"></rect>
<rect fill-opacity="0.164600317" fill="#000000" x="40" y="0" width="30" height="8"></rect>
<rect fill="#FF5F74" x="4" y="4" width="24" height="4"></rect>
<rect fill="#FF5F74" x="4" y="12" width="16" height="4"></rect>
<rect fill="#FF5F74" x="4" y="20" width="30" height="4"></rect>
<rect fill="#FF5F74" x="4" y="28" width="21" height="4"></rect>
<rect fill="#FF5F74" x="4" y="36" width="24" height="4"></rect>
<rect fill-opacity="0.164600317" fill="#000000" x="40" y="72" width="120" height="8"></rect>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="160px" height="80px" viewBox="0 0 160 80" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs></defs>
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g>
<rect fill-opacity="0.081861413" fill="#FFFFFF" x="0" y="0" width="160" height="80"></rect>
<rect fill-opacity="0.164600317" fill="#000000" x="40" y="72" width="120" height="8"></rect>
<g>
<rect fill-opacity="0.161882926" fill="#000000" x="0" y="0" width="40" height="80"></rect>
<rect fill-opacity="0.08" fill="#FFFFFF" x="4" y="4" width="24" height="4"></rect>
<rect fill-opacity="0.08" fill="#FFFFFF" x="4" y="12" width="16" height="4"></rect>
<rect fill-opacity="0.08" fill="#FFFFFF" x="4" y="20" width="30" height="4"></rect>
<rect fill-opacity="0.08" fill="#FFFFFF" x="4" y="28" width="21" height="4"></rect>
<rect fill-opacity="0.08" fill="#FFFFFF" x="4" y="36" width="24" height="4"></rect>
</g>
<g transform="translate(40.000000, 0.000000)" fill-opacity="0.164600317" fill="#000000">
<rect x="60" y="0" width="60" height="8"></rect>
<rect x="0" y="0" width="30" height="8"></rect>
</g>
<g transform="translate(56.000000, 0.000000)">
<rect fill="#BB263A" x="0" y="0" width="48" height="32"></rect>
<rect fill="#FF5F74" x="4" y="4" width="40" height="4"></rect>
<rect fill="#FF5F74" x="4" y="12" width="22" height="4"></rect>
<rect fill="#FF5F74" x="4" y="18" width="30" height="4"></rect>
<rect fill="#FF5F74" x="4" y="24" width="18" height="4"></rect>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="160px" height="80px" viewBox="0 0 160 80" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs></defs>
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g>
<rect fill-opacity="0.081861413" fill="#FFFFFF" x="0" y="0" width="160" height="80"></rect>
<rect fill-opacity="0.164600317" fill="#000000" x="40" y="72" width="120" height="8"></rect>
<g>
<rect fill-opacity="0.161882926" fill="#000000" x="0" y="0" width="40" height="80"></rect>
<rect fill-opacity="0.08" fill="#FFFFFF" x="4" y="4" width="24" height="4"></rect>
<rect fill-opacity="0.08" fill="#FFFFFF" x="4" y="12" width="16" height="4"></rect>
<rect fill-opacity="0.08" fill="#FFFFFF" x="4" y="20" width="30" height="4"></rect>
<rect fill-opacity="0.08" fill="#FFFFFF" x="4" y="28" width="21" height="4"></rect>
<rect fill-opacity="0.08" fill="#FFFFFF" x="4" y="36" width="24" height="4"></rect>
</g>
<g transform="translate(40.000000, 0.000000)" fill-opacity="0.164600317" fill="#000000">
<rect x="60" y="0" width="60" height="8"></rect>
<rect x="0" y="0" width="30" height="8"></rect>
</g>
<path d="M140,0 L160,0 L160,80 L20,80 L140,0 Z" fill="#BB263A"></path>
<path d="M128,8 L160,8 L160,72 L39.984375,72 L39.984375,66.6474609 L128,8 Z" fill="#FF5F75"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,36 @@
# Events specification
This document specifies all the data (along with the format) which gets sent from the Welcome package to the GitHub analytics pipeline. This document follows the same format and nomenclature as the [Atom Core Events spec](https://github.com/atom/metrics/blob/master/docs/events.md).
## Counters
Currently the Welcome package does not log any counter events.
## Timing events
Currently the Welcome package does not log any timing events.
## Standard events
#### Welcome package shown
* **eventType**: `welcome-v1`
* **metadata**
| field | value |
|-------|-------|
| `ea` | `show-on-initial-load`
#### Click on links
* **eventType**: `welcome-v1`
* **metadata**
| field | value |
|-------|-------|
| `ea` | link that was clicked
(There are many potential values for the `ea` param, e.g: `clicked-welcome-atom-docs-link`,`clicked-welcome-atom-org-link`, `clicked-project-cta`, `clicked-init-script-cta`, ...).

View File

@ -0,0 +1,92 @@
'use babel'
/** @jsx etch.dom */
import etch from 'etch'
export default class ConsentView {
constructor () {
etch.initialize(this)
}
render () {
return (
<div className='welcome'>
<div className='welcome-container'>
<div className='header'>
<a title='atom.io' href='https://atom.io/'>
<svg class='welcome-logo' width='330px' height='68px' viewBox='0 0 330 68' version='1.1'>
<g stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'>
<g transform='translate(2.000000, 1.000000)'>
<g transform='translate(96.000000, 8.000000)' fill='currentColor'>
<path d='M185.498,3.399 C185.498,2.417 186.34,1.573 187.324,1.573 L187.674,1.573 C188.447,1.573 189.01,1.995 189.5,2.628 L208.676,30.862 L227.852,2.628 C228.272,1.995 228.905,1.573 229.676,1.573 L230.028,1.573 C231.01,1.573 231.854,2.417 231.854,3.399 L231.854,49.403 C231.854,50.387 231.01,51.231 230.028,51.231 C229.044,51.231 228.202,50.387 228.202,49.403 L228.202,8.246 L210.151,34.515 C209.729,35.148 209.237,35.428 208.606,35.428 C207.973,35.428 207.481,35.148 207.061,34.515 L189.01,8.246 L189.01,49.475 C189.01,50.457 188.237,51.231 187.254,51.231 C186.27,51.231 185.498,50.458 185.498,49.475 L185.498,3.399 L185.498,3.399 Z' />
<path d='M113.086,26.507 L113.086,26.367 C113.086,12.952 122.99,0.941 137.881,0.941 C152.77,0.941 162.533,12.811 162.533,26.225 L162.533,26.367 C162.533,39.782 152.629,51.792 137.74,51.792 C122.85,51.792 113.086,39.923 113.086,26.507 M158.74,26.507 L158.74,26.367 C158.74,14.216 149.89,4.242 137.74,4.242 C125.588,4.242 116.879,14.075 116.879,26.225 L116.879,26.367 C116.879,38.518 125.729,48.491 137.881,48.491 C150.031,48.491 158.74,38.658 158.74,26.507' />
<path d='M76.705,5.155 L60.972,5.155 C60.06,5.155 59.287,4.384 59.287,3.469 C59.287,2.556 60.059,1.783 60.972,1.783 L96.092,1.783 C97.004,1.783 97.778,2.555 97.778,3.469 C97.778,4.383 97.005,5.155 96.092,5.155 L80.358,5.155 L80.358,49.405 C80.358,50.387 79.516,51.231 78.532,51.231 C77.55,51.231 76.706,50.387 76.706,49.405 L76.706,5.155 L76.705,5.155 Z' />
<path d='M0.291,48.562 L21.291,3.05 C21.783,1.995 22.485,1.292 23.75,1.292 L23.891,1.292 C25.155,1.292 25.858,1.995 26.348,3.05 L47.279,48.421 C47.49,48.843 47.56,49.194 47.56,49.546 C47.56,50.458 46.788,51.231 45.803,51.231 C44.961,51.231 44.329,50.599 43.978,49.826 L38.219,37.183 L9.21,37.183 L3.45,49.897 C3.099,50.739 2.538,51.231 1.694,51.231 C0.781,51.231 0.008,50.529 0.008,49.685 C0.009,49.404 0.08,48.983 0.291,48.562 L0.291,48.562 Z M36.673,33.882 L23.749,5.437 L10.755,33.882 L36.673,33.882 L36.673,33.882 Z' />
</g>
<g>
<path d='M40.363,32.075 C40.874,34.44 39.371,36.77 37.006,37.282 C34.641,37.793 32.311,36.29 31.799,33.925 C31.289,31.56 32.791,29.23 35.156,28.718 C37.521,28.207 39.851,29.71 40.363,32.075' fill='currentColor' />
<path d='M48.578,28.615 C56.851,45.587 58.558,61.581 52.288,64.778 C45.822,68.076 33.326,56.521 24.375,38.969 C15.424,21.418 13.409,4.518 19.874,1.221 C22.689,-0.216 26.648,1.166 30.959,4.629' stroke='currentColor' stroke-width='3.08' stroke-linecap='round' />
<path d='M7.64,39.45 C2.806,36.94 -0.009,33.915 0.154,30.79 C0.531,23.542 16.787,18.497 36.462,19.52 C56.137,20.544 71.781,27.249 71.404,34.497 C71.241,37.622 68.127,40.338 63.06,42.333' stroke='currentColor' stroke-width='3.08' stroke-linecap='round' />
<path d='M28.828,59.354 C23.545,63.168 18.843,64.561 15.902,62.653 C9.814,58.702 13.572,42.102 24.296,25.575 C35.02,9.048 48.649,-1.149 54.736,2.803 C57.566,4.639 58.269,9.208 57.133,15.232' stroke='currentColor' stroke-width='3.08' stroke-linecap='round' />
</g>
</g>
</g>
</svg>
</a>
</div>
<div className='welcome-consent'>
<p>Help improve Atom by sending your anonymous <strong>usage data</strong> to the Atom team. The resulting data plays a key role in deciding what we focus on next.</p>
<div className='welcome-consent-choices'>
<div>
<button className='btn btn-primary' onclick={this.consent.bind(this)}>Yes, send my usage data</button>
<p className='welcome-note'>Including exception and crash reports. See the <a onclick={this.openMetricsPackage.bind(this)}>atom/metrics package</a> for more details.</p>
</div>
<div>
<button className='btn btn-primary' onclick={this.decline.bind(this)}>No, do not send my usage data</button>
<p className='welcome-note'>Note: We only register anonymously that you opted-out.</p>
</div>
</div>
</div>
<div className='welcome-footer'>
<p className='welcome-love'>
<span className='icon icon-code' />
<span className='inline'> with </span>
<span className='icon icon-heart' />
<span className='inline'> by </span>
<a className='icon icon-logo-github' title='GitHub' href='https://github.com' />
</p>
</div>
</div>
</div>
)
}
update () {
return etch.update(this)
}
consent () {
atom.config.set('core.telemetryConsent', 'limited')
atom.workspace.closeActivePaneItemOrEmptyPaneOrWindow()
}
decline () {
atom.config.set('core.telemetryConsent', 'no')
atom.workspace.closeActivePaneItemOrEmptyPaneOrWindow()
}
openMetricsPackage () {
atom.workspace.open('atom://config/packages/metrics')
}
getTitle () {
return 'Telemetry Consent'
}
async destroy () {
await etch.destroy(this)
}
}

View File

@ -0,0 +1,366 @@
/** @babel */
/** @jsx etch.dom **/
import etch from 'etch'
export default class GuideView {
constructor (props) {
this.props = props
this.didClickProjectButton = this.didClickProjectButton.bind(this)
this.didClickGitButton = this.didClickGitButton.bind(this)
this.didClickGitHubButton = this.didClickGitHubButton.bind(this)
this.didClickTeletypeButton = this.didClickTeletypeButton.bind(this)
this.didClickPackagesButton = this.didClickPackagesButton.bind(this)
this.didClickThemesButton = this.didClickThemesButton.bind(this)
this.didClickStylingButton = this.didClickStylingButton.bind(this)
this.didClickInitScriptButton = this.didClickInitScriptButton.bind(this)
this.didClickSnippetsButton = this.didClickSnippetsButton.bind(this)
this.didExpandOrCollapseSection = this.didExpandOrCollapseSection.bind(this)
etch.initialize(this)
}
update () {}
render () {
return (
<div className='welcome is-guide'>
<div className='welcome-container'>
<section className='welcome-panel'>
<h1 className='welcome-title'>
Get to know Atom!
</h1>
<details className='welcome-card' {...this.getSectionProps('project')}>
<summary className='welcome-summary icon icon-repo'>
Open a <span className='welcome-highlight'>Project</span>
</summary>
<div className='welcome-detail'>
<p>
<img className='welcome-img' src='atom://welcome/assets/project.svg' />
</p>
<p>
In Atom you can open individual files or a whole folder as a
project. Opening a folder will add a tree view to the editor
where you can browse all the files.
</p>
<p>
<button ref='projectButton' onclick={this.didClickProjectButton} className='btn btn-primary'>
Open a Project
</button>
</p>
<p className='welcome-note'>
<strong>Next time:</strong> You can also open projects from
the menu, keyboard shortcut or by dragging a folder onto the
Atom dock icon.
</p>
</div>
</details>
<details className='welcome-card' {...this.getSectionProps('git')}>
<summary className='welcome-summary icon icon-mark-github'>
Version control with <span class='welcome-highlight'>Git and GitHub</span>
</summary>
<div className='welcome-detail'>
<p>
<img className='welcome-img' src='atom://welcome/assets/package.svg' />
</p>
<p>
Track changes to your code as you work. Branch, commit, push, and pull without leaving
the comfort of your editor. Collaborate with other developers on GitHub.
</p>
<p>
<button onclick={this.didClickGitButton} className='btn btn-primary inline-block'>
Open the Git panel
</button>
<button onclick={this.didClickGitHubButton} className='btn btn-primary inline-block'>
Open the GitHub panel
</button>
</p>
<p className='welcome-note'>
<strong>Next time:</strong> You can toggle the Git tab by clicking on the
<span className='icon icon-diff' /> button in your status bar.
</p>
</div>
</details>
<details className='welcome-card' {...this.getSectionProps('teletype')}>
<summary className='welcome-summary icon icon-radio-tower'>
Collaborate in real time with <span class='welcome-highlight'>Teletype</span>
</summary>
<div className='welcome-detail'>
<p>
<img className='welcome-img' src='atom://welcome/assets/code.svg' />
</p>
<p>
Share your workspace with team members and collaborate on code in real time.
</p>
<p>
<button onclick={this.didClickTeletypeButton} className='btn btn-primary inline-block'>
Install Teletype for Atom
</button>
</p>
</div>
</details>
<details className='welcome-card' {...this.getSectionProps('packages')}>
<summary className='welcome-summary icon icon-package'>
Install a <span className='welcome-highlight'>Package</span>
</summary>
<div className='welcome-detail'>
<p>
<img className='welcome-img' src='atom://welcome/assets/package.svg' />
</p>
<p>
One of the best things about Atom is the package ecosystem.
Installing packages adds new features and functionality you
can use to make the editor suit your needs. Let's install one.
</p>
<p>
<button ref='packagesButton' onclick={this.didClickPackagesButton} className='btn btn-primary'>
Open Installer
</button>
</p>
<p className='welcome-note'>
<strong>Next time:</strong> You can install new packages from the settings.
</p>
</div>
</details>
<details className='welcome-card' {...this.getSectionProps('themes')}>
<summary className='welcome-summary icon icon-paintcan'>
Choose a <span class='welcome-highlight'>Theme</span>
</summary>
<div className='welcome-detail'>
<p>
<img className='welcome-img' src='atom://welcome/assets/theme.svg' />
</p>
<p>
Atom comes with preinstalled themes. Let's try a few.
</p>
<p>
<button ref='themesButton' onclick={this.didClickThemesButton} className='btn btn-primary'>
Open the theme picker
</button>
</p>
<p>
You can also install themes created by the Atom community. To
install new themes, click on "+ Install" and switch the toggle
to "themes".
</p>
<p className='welcome-note'>
<strong>Next time:</strong> You can switch themes from the settings.
</p>
</div>
</details>
<details className='welcome-card' {...this.getSectionProps('styling')}>
<summary className='welcome-summary icon icon-paintcan'>
Customize the <span class='welcome-highlight'>Styling</span>
</summary>
<div className='welcome-detail'>
<p>
<img className='welcome-img' src='atom://welcome/assets/code.svg' />
</p>
<p>
You can customize almost anything by adding your own CSS/LESS.
</p>
<p>
<button ref='stylingButton' onclick={this.didClickStylingButton} className='btn btn-primary'>
Open your Stylesheet
</button>
</p>
<p>
Now uncomment some of the examples or try your own
</p>
<p className='welcome-note'>
<strong>Next time:</strong> You can open your stylesheet from Menu {this.getApplicationMenuName()}.
</p>
</div>
</details>
<details className='welcome-card' {...this.getSectionProps('init-script')}>
<summary className='welcome-summary icon icon-code'>
Hack on the <span class='welcome-highlight'>Init Script</span>
</summary>
<div className='welcome-detail'>
<p>
<img className='welcome-img' src='atom://welcome/assets/code.svg' />
</p>
<p>
The init script is a bit of JavaScript or CoffeeScript run at
startup. You can use it to quickly change the behaviour of
Atom.
</p>
<p>
<button ref='initScriptButton' onclick={this.didClickInitScriptButton} className='btn btn-primary'>
Open your Init Script
</button>
</p>
<p>
Uncomment some of the examples or try out your own.
</p>
<p className='welcome-note'>
<strong>Next time:</strong> You can open your init script from Menu > {this.getApplicationMenuName()}.
</p>
</div>
</details>
<details className='welcome-card' {...this.getSectionProps('snippets')}>
<summary className='welcome-summary icon icon-code'>
Add a <span class='welcome-highlight'>Snippet</span>
</summary>
<div className='welcome-detail'>
<p>
<img className='welcome-img' src='atom://welcome/assets/code.svg' />
</p>
<p>
Atom snippets allow you to enter a simple prefix in the editor
and hit tab to expand the prefix into a larger code block with
templated values.
</p>
<p>
<button ref='snippetsButton' onclick={this.didClickSnippetsButton} className='btn btn-primary'>
Open your Snippets
</button>
</p>
<p>
In your snippets file, type <code>snip</code> then hit <code>tab</code>.
The <code>snip</code> snippet will expand
to create a snippet!
</p>
<p className='welcome-note'>
<strong>Next time:</strong> You can open your snippets in Menu > {this.getApplicationMenuName()}.
</p>
</div>
</details>
<details className='welcome-card' {...this.getSectionProps('shortcuts')}>
<summary className='welcome-summary icon icon-keyboard'>
Learn <span class='welcome-highlight'>Keyboard Shortcuts</span>
</summary>
<div className='welcome-detail'>
<p>
<img className='welcome-img' src='atom://welcome/assets/shortcut.svg' />
</p>
<p>
If you only remember one keyboard shortcut make
it <kbd className='welcome-key'>{this.getCommandPaletteKeyBinding()}</kbd>.
This keystroke toggles the command palette, which lists every
Atom command. It's a good way to learn more shortcuts. Yes,
you can try it now!
</p>
<p>
If you want to use these guides again use the command
palette <kbd className='welcome-key'>{this.getCommandPaletteKeyBinding()}</kbd> and
search for <span className='text-highlight'>Welcome</span>.
</p>
</div>
</details>
</section>
</div>
</div>
)
}
getSectionProps (sectionName) {
const props = {dataset: {section: sectionName}, onclick: this.didExpandOrCollapseSection}
if (this.props.openSections && this.props.openSections.indexOf(sectionName) !== -1) {
props.open = true
}
return props
}
getCommandPaletteKeyBinding () {
if (process.platform === 'darwin') {
return 'cmd-shift-p'
} else {
return 'ctrl-shift-p'
}
}
getApplicationMenuName () {
if (process.platform === 'darwin') {
return 'Atom'
} else if (process.platform === 'linux') {
return 'Edit'
} else {
return 'File'
}
}
serialize () {
return {
deserializer: this.constructor.name,
openSections: this.getOpenSections(),
uri: this.getURI()
}
}
getURI () {
return this.props.uri
}
getTitle () {
return 'Welcome Guide'
}
isEqual (other) {
return other instanceof GuideView
}
getOpenSections () {
return Array.from(this.element.querySelectorAll('details[open]'))
.map((sectionElement) => sectionElement.dataset.section)
}
didClickProjectButton () {
this.props.reporterProxy.sendEvent('clicked-project-cta')
atom.commands.dispatch(atom.views.getView(atom.workspace), 'application:open')
}
didClickGitButton () {
this.props.reporterProxy.sendEvent('clicked-git-cta')
atom.commands.dispatch(atom.views.getView(atom.workspace), 'github:toggle-git-tab')
}
didClickGitHubButton () {
this.props.reporterProxy.sendEvent('clicked-github-cta')
atom.commands.dispatch(atom.views.getView(atom.workspace), 'github:toggle-github-tab')
}
didClickPackagesButton () {
this.props.reporterProxy.sendEvent('clicked-packages-cta')
atom.workspace.open('atom://config/install', {split: 'left'})
}
didClickThemesButton () {
this.props.reporterProxy.sendEvent('clicked-themes-cta')
atom.workspace.open('atom://config/themes', {split: 'left'})
}
didClickStylingButton () {
this.props.reporterProxy.sendEvent('clicked-styling-cta')
atom.workspace.open('atom://.atom/stylesheet', {split: 'left'})
}
didClickInitScriptButton () {
this.props.reporterProxy.sendEvent('clicked-init-script-cta')
atom.workspace.open('atom://.atom/init-script', {split: 'left'})
}
didClickSnippetsButton () {
this.props.reporterProxy.sendEvent('clicked-snippets-cta')
atom.workspace.open('atom://.atom/snippets', {split: 'left'})
}
didClickTeletypeButton () {
this.props.reporterProxy.sendEvent('clicked-teletype-cta')
atom.workspace.open('atom://config/packages/teletype', {split: 'left'})
}
didExpandOrCollapseSection (event) {
const sectionName = event.currentTarget.closest('details').dataset.section
const action = event.currentTarget.hasAttribute('open') ? 'collapse' : 'expand'
this.props.reporterProxy.sendEvent(`${action}-${sectionName}-section`)
}
}

View File

@ -0,0 +1,5 @@
/** @babel */
import WelcomePackage from './welcome-package'
export default new WelcomePackage()

View File

@ -0,0 +1,27 @@
/** @babel */
export default class ReporterProxy {
constructor () {
this.reporter = null
this.queue = []
this.eventType = 'welcome-v1'
}
setReporter (reporter) {
this.reporter = reporter
let customEvent
while ((customEvent = this.queue.shift())) {
this.reporter.addCustomEvent(this.eventType, customEvent)
}
}
sendEvent (action, label, value) {
const event = { ea: action, el: label, ev: value }
if (this.reporter) {
this.reporter.addCustomEvent(this.eventType, event)
} else {
this.queue.push(event)
}
}
}

View File

@ -0,0 +1,81 @@
/** @babel */
import {CompositeDisposable} from 'atom'
import ReporterProxy from './reporter-proxy'
let WelcomeView, GuideView, ConsentView
const WELCOME_URI = 'atom://welcome/welcome'
const GUIDE_URI = 'atom://welcome/guide'
const CONSENT_URI = 'atom://welcome/consent'
export default class WelcomePackage {
constructor () {
this.reporterProxy = new ReporterProxy()
}
async activate () {
this.subscriptions = new CompositeDisposable()
this.subscriptions.add(atom.workspace.addOpener((filePath) => {
if (filePath === WELCOME_URI) {
return this.createWelcomeView({uri: WELCOME_URI})
}
}))
this.subscriptions.add(atom.workspace.addOpener((filePath) => {
if (filePath === GUIDE_URI) {
return this.createGuideView({uri: GUIDE_URI})
}
}))
this.subscriptions.add(atom.workspace.addOpener((filePath) => {
if (filePath === CONSENT_URI) {
return this.createConsentView({uri: CONSENT_URI})
}
}))
this.subscriptions.add(
atom.commands.add('atom-workspace', 'welcome:show', () => this.show())
)
if (atom.config.get('core.telemetryConsent') === 'undecided') {
await atom.workspace.open(CONSENT_URI)
}
if (atom.config.get('welcome.showOnStartup')) {
await this.show()
this.reporterProxy.sendEvent('show-on-initial-load')
}
}
show () {
return Promise.all([
atom.workspace.open(WELCOME_URI, {split: 'left'}),
atom.workspace.open(GUIDE_URI, {split: 'right'})
])
}
consumeReporter (reporter) {
return this.reporterProxy.setReporter(reporter)
}
deactivate () {
this.subscriptions.dispose()
}
createWelcomeView (state) {
if (WelcomeView == null) WelcomeView = require('./welcome-view')
return new WelcomeView({reporterProxy: this.reporterProxy, ...state})
}
createGuideView (state) {
if (GuideView == null) GuideView = require('./guide-view')
return new GuideView({reporterProxy: this.reporterProxy, ...state})
}
createConsentView (state) {
if (ConsentView == null) ConsentView = require('./consent-view')
return new ConsentView({reporterProxy: this.reporterProxy, ...state})
}
}

View File

@ -0,0 +1,97 @@
/** @babel */
/** @jsx etch.dom **/
import etch from 'etch'
export default class WelcomeView {
constructor (props) {
this.props = props
etch.initialize(this)
this.element.addEventListener('click', (event) => {
const link = event.target.closest('a')
if (link && link.dataset.event) {
this.props.reporterProxy.sendEvent(`clicked-welcome-${link.dataset.event}-link`)
}
})
}
didChangeShowOnStartup () {
atom.config.set('welcome.showOnStartup', this.checked)
}
update () {}
serialize () {
return {
deserializer: 'WelcomeView',
uri: this.props.uri
}
}
render () {
return (
<div className='welcome'>
<div className='welcome-container'>
<header className='welcome-header'>
<a href='https://atom.io/'>
<svg className='welcome-logo' width='330px' height='68px' viewBox='0 0 330 68' version='1.1'>
<g stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'>
<g transform='translate(2.000000, 1.000000)'>
<g transform='translate(96.000000, 8.000000)' fill='currentColor'>
<path d='M185.498,3.399 C185.498,2.417 186.34,1.573 187.324,1.573 L187.674,1.573 C188.447,1.573 189.01,1.995 189.5,2.628 L208.676,30.862 L227.852,2.628 C228.272,1.995 228.905,1.573 229.676,1.573 L230.028,1.573 C231.01,1.573 231.854,2.417 231.854,3.399 L231.854,49.403 C231.854,50.387 231.01,51.231 230.028,51.231 C229.044,51.231 228.202,50.387 228.202,49.403 L228.202,8.246 L210.151,34.515 C209.729,35.148 209.237,35.428 208.606,35.428 C207.973,35.428 207.481,35.148 207.061,34.515 L189.01,8.246 L189.01,49.475 C189.01,50.457 188.237,51.231 187.254,51.231 C186.27,51.231 185.498,50.458 185.498,49.475 L185.498,3.399 L185.498,3.399 Z' />
<path d='M113.086,26.507 L113.086,26.367 C113.086,12.952 122.99,0.941 137.881,0.941 C152.77,0.941 162.533,12.811 162.533,26.225 L162.533,26.367 C162.533,39.782 152.629,51.792 137.74,51.792 C122.85,51.792 113.086,39.923 113.086,26.507 M158.74,26.507 L158.74,26.367 C158.74,14.216 149.89,4.242 137.74,4.242 C125.588,4.242 116.879,14.075 116.879,26.225 L116.879,26.367 C116.879,38.518 125.729,48.491 137.881,48.491 C150.031,48.491 158.74,38.658 158.74,26.507' />
<path d='M76.705,5.155 L60.972,5.155 C60.06,5.155 59.287,4.384 59.287,3.469 C59.287,2.556 60.059,1.783 60.972,1.783 L96.092,1.783 C97.004,1.783 97.778,2.555 97.778,3.469 C97.778,4.383 97.005,5.155 96.092,5.155 L80.358,5.155 L80.358,49.405 C80.358,50.387 79.516,51.231 78.532,51.231 C77.55,51.231 76.706,50.387 76.706,49.405 L76.706,5.155 L76.705,5.155 Z' />
<path d='M0.291,48.562 L21.291,3.05 C21.783,1.995 22.485,1.292 23.75,1.292 L23.891,1.292 C25.155,1.292 25.858,1.995 26.348,3.05 L47.279,48.421 C47.49,48.843 47.56,49.194 47.56,49.546 C47.56,50.458 46.788,51.231 45.803,51.231 C44.961,51.231 44.329,50.599 43.978,49.826 L38.219,37.183 L9.21,37.183 L3.45,49.897 C3.099,50.739 2.538,51.231 1.694,51.231 C0.781,51.231 0.008,50.529 0.008,49.685 C0.009,49.404 0.08,48.983 0.291,48.562 L0.291,48.562 Z M36.673,33.882 L23.749,5.437 L10.755,33.882 L36.673,33.882 L36.673,33.882 Z' />
</g>
<g>
<path d='M40.363,32.075 C40.874,34.44 39.371,36.77 37.006,37.282 C34.641,37.793 32.311,36.29 31.799,33.925 C31.289,31.56 32.791,29.23 35.156,28.718 C37.521,28.207 39.851,29.71 40.363,32.075' fill='currentColor' />
<path d='M48.578,28.615 C56.851,45.587 58.558,61.581 52.288,64.778 C45.822,68.076 33.326,56.521 24.375,38.969 C15.424,21.418 13.409,4.518 19.874,1.221 C22.689,-0.216 26.648,1.166 30.959,4.629' stroke='currentColor' stroke-width='3.08' stroke-linecap='round' />
<path d='M7.64,39.45 C2.806,36.94 -0.009,33.915 0.154,30.79 C0.531,23.542 16.787,18.497 36.462,19.52 C56.137,20.544 71.781,27.249 71.404,34.497 C71.241,37.622 68.127,40.338 63.06,42.333' stroke='currentColor' stroke-width='3.08' stroke-linecap='round' />
<path d='M28.828,59.354 C23.545,63.168 18.843,64.561 15.902,62.653 C9.814,58.702 13.572,42.102 24.296,25.575 C35.02,9.048 48.649,-1.149 54.736,2.803 C57.566,4.639 58.269,9.208 57.133,15.232' stroke='currentColor' stroke-width='3.08' stroke-linecap='round' />
</g>
</g>
</g>
</svg>
<h1 className='welcome-title'>
A hackable text editor for the 21<sup>st</sup> Century
</h1>
</a>
</header>
<section className='welcome-panel'>
<p>For help, please visit</p>
<ul>
<li>The <a href='https://www.atom.io/docs' dataset={{event: 'atom-docs'}}>Atom docs</a> for Guides and the API reference.</li>
<li>The Atom forum at <a href='http://discuss.atom.io' dataset={{event: 'discuss'}}>discuss.atom.io</a></li>
<li>The <a href='https://github.com/atom' dataset={{event: 'atom-org'}}>Atom org</a>. This is where all GitHub-created Atom packages can be found.</li>
</ul>
</section>
<section className='welcome-panel'>
<label>
<input className='input-checkbox' type='checkbox' checked={atom.config.get('welcome.showOnStartup')} onchange={this.didChangeShowOnStartup} />
Show Welcome Guide when opening Atom
</label>
</section>
<footer className='welcome-footer'>
<a href='https://atom.io/' dataset={{event: 'footer-atom-io'}}>atom.io</a> <span className='text-subtle'>×</span> <a className='icon icon-octoface' href='https://github.com/' dataset={{event: 'footer-octocat'}} />
</footer>
</div>
</div>
)
}
getURI () {
return this.props.uri
}
getTitle () {
return 'Welcome'
}
isEqual (other) {
other instanceof WelcomeView
}
}

View File

@ -0,0 +1,6 @@
'menu': [
'label': 'Help'
'submenu': [
{'label': 'Welcome Guide', 'command': 'welcome:show'}
]
]

2170
packages/welcome/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,47 @@
{
"name": "welcome",
"version": "0.36.9",
"description": "Welcome users to Atom with useful information",
"main": "./lib/main",
"atomTestRunner": "atom-mocha-test-runner",
"repository": "https://github.com/atom/atom",
"license": "MIT",
"engines": {
"atom": ">0.50.0"
},
"scripts": {
"lint": "standard",
"test": "atom --test test/*.test.js"
},
"consumedServices": {
"metrics-reporter": {
"versions": {
"^1.1.0": "consumeReporter"
}
}
},
"configSchema": {
"showOnStartup": {
"type": "boolean",
"default": true,
"description": "Show welcome panes with useful information when opening a new Atom window."
}
},
"deserializers": {
"WelcomeView": "createWelcomeView",
"GuideView": "createGuideView",
"ConsentView": "createConsentView"
},
"dependencies": {
"etch": "0.9.0"
},
"devDependencies": {
"atom-mocha-test-runner": "^1.0.0",
"standard": "^8.6.0"
},
"standard": {
"globals": [
"atom"
]
}
}

View File

@ -0,0 +1,196 @@
@import "octicon-mixins";
@import "ui-variables";
.welcome {
display: flex;
font-size: 1.25em;
line-height: 1.4;
color: @text-color;
background-color: @base-background-color;
overflow-x: auto;
// Overrides ----------------------
p {
line-height: inherit;
}
a {
color: @text-color-info;
}
ul {
padding-left: 2em;
}
label {
margin-top: 1em;
font-weight: normal;
}
.input-checkbox {
margin-top: -.2em;
margin-right: .5em;
}
// Components ----------------------
&-container {
width: 100%;
max-width: 580px;
min-width: 300px;
margin: auto;
padding: 3em 2em;
}
&-header {
margin: 0 0 3em 0;
}
&-logo {
display: block;
width: 100%;
max-width: 280px;
margin: 0 auto 2em auto;
color: @text-color-highlight;
}
&-title {
font-size: 1.4em;
text-align: center;
line-height: 1.3;
margin: 1em 0;
}
&-panel {
}
&-card {
margin: 1em 0;
border-radius: @component-border-radius*2;
border: 1px solid @base-border-color;
background-color: lighten(@base-background-color, 3%);
}
&-summary {
padding: 1em 1.5em;
font-size: 1.1em;
font-weight: 300;
line-height: 1.4;
cursor: pointer;
&:hover {
color: lighten(@text-color, 4%);
}
&::-webkit-details-marker {
display: none
}
&:before {
width: 20px;
color: @text-color-subtle;
details[open] & {
color: @text-color-highlight;
}
}
details[open] & {
color: @text-color-highlight;
}
}
&-highlight {
color: @text-color-highlight;
}
&-detail {
border-top: 1px solid @base-border-color;
padding: 1.5em;
.welcome-note {
margin-bottom: 0;
}
.btn {
margin-top: @component-padding/3;
margin-bottom: @component-padding/3;
}
}
&-img {
display: block;
max-width: 100%;
border-radius: 3px;
margin: 0 0 1em 0;
border: 1px solid @base-border-color;
}
&-consent {
margin-top: 3em;
&-choices {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 1em -1em;
button {
width: 100%
}
div {
margin: .5em 1em;
flex: 1;
}
.welcome-note {
margin-top: 1em;
}
}
}
&-key {
display: inline-block;
padding: .3em .4em;
font-size: .8em;
line-height: 1;
border-radius: 3px;
color: @text-color-highlight;
border: 1px solid @text-color-subtle;
background: hsla(0,0%,0%,.1);
}
&-love {
color: @text-color-subtle;
a { color: @text-color-subtle; }
.icon::before {
// Make these octicons look good inlined with text
position: relative;
top: 4px;
width: auto;
margin-right: 0;
font-size: 1.5em;
}
.icon-logo-github::before {
top: 2px;
font-size: 3.6em;
vertical-align: top;
}
}
&-note {
font-size: .86em;
color: @text-color-subtle;
.icon {
margin-left: 5px;
}
.icon::before {
margin-right: 0;
}
}
&-footer {
margin-top: 1em;
text-align: center;
}
}

View File

@ -0,0 +1,9 @@
/** @babel */
export function conditionPromise (predicate) {
return new Promise((resolve) => {
setInterval(() => {
if (predicate()) resolve()
}, 100)
})
}

View File

@ -0,0 +1,154 @@
/** @babel */
/* global beforeEach, afterEach, describe, it */
import WelcomePackage from '../lib/welcome-package'
import assert from 'assert'
import {conditionPromise} from './helpers'
describe('Welcome', () => {
let welcomePackage
beforeEach(() => {
welcomePackage = new WelcomePackage()
atom.config.set('welcome.showOnStartup', true)
})
afterEach(() => {
atom.reset()
})
describe("when `core.telemetryConsent` is 'undecided'", () => {
beforeEach(async () => {
atom.config.set('core.telemetryConsent', 'undecided')
await welcomePackage.activate()
})
it('opens the telemetry consent pane and the welcome panes', () => {
const panes = atom.workspace.getCenter().getPanes()
assert.equal(panes.length, 2)
assert.equal(panes[0].getItems()[0].getTitle(), 'Telemetry Consent')
assert.equal(panes[0].getItems()[1].getTitle(), 'Welcome')
assert.equal(panes[1].getItems()[0].getTitle(), 'Welcome Guide')
})
})
describe('when `core.telemetryConsent` is not `undecided`', () => {
beforeEach(async () => {
atom.config.set('core.telemetryConsent', 'no')
await welcomePackage.activate()
})
describe('when activated for the first time', () =>
it('shows the welcome panes', () => {
const panes = atom.workspace.getCenter().getPanes()
assert.equal(panes.length, 2)
assert.equal(panes[0].getItems()[0].getTitle(), 'Welcome')
assert.equal(panes[1].getItems()[0].getTitle(), 'Welcome Guide')
})
)
describe('the welcome:show command', () => {
it('shows the welcome buffer', async () => {
atom.workspace.getCenter().getPanes().map(pane => pane.destroy())
assert(!atom.workspace.getActivePaneItem())
const workspaceElement = atom.views.getView(atom.workspace)
atom.commands.dispatch(workspaceElement, 'welcome:show')
await conditionPromise(() => atom.workspace.getActivePaneItem())
const panes = atom.workspace.getCenter().getPanes()
assert.equal(panes.length, 2)
assert.equal(panes[0].getItems()[0].getTitle(), 'Welcome')
})
})
describe('deserializing the pane items', () => {
describe('when GuideView is deserialized', () => {
it('remembers open sections', () => {
const panes = atom.workspace.getCenter().getPanes()
const guideView = panes[1].getItems()[0]
guideView.element.querySelector('details[data-section="snippets"]').setAttribute('open', 'open')
guideView.element.querySelector('details[data-section="init-script"]').setAttribute('open', 'open')
const state = guideView.serialize()
assert.deepEqual(state.openSections, ['init-script', 'snippets'])
const newGuideView = welcomePackage.createGuideView(state)
assert(!newGuideView.element.querySelector('details[data-section="packages"]').hasAttribute('open'))
assert(newGuideView.element.querySelector('details[data-section="snippets"]').hasAttribute('open'))
assert(newGuideView.element.querySelector('details[data-section="init-script"]').hasAttribute('open'))
})
})
})
describe('reporting events', () => {
let panes, guideView, reportedEvents
beforeEach(() => {
panes = atom.workspace.getCenter().getPanes()
guideView = panes[1].getItems()[0]
reportedEvents = []
welcomePackage.reporterProxy.sendEvent = (...event) => { reportedEvents.push(event) }
})
describe('GuideView events', () => {
it('captures expand and collapse events', () => {
guideView.element.querySelector('details[data-section="packages"] summary').click()
assert.deepEqual(reportedEvents, [['expand-packages-section']])
guideView.element.querySelector('details[data-section="packages"]').setAttribute('open', 'open')
guideView.element.querySelector('details[data-section="packages"] summary').click()
assert.deepEqual(reportedEvents, [['expand-packages-section'], ['collapse-packages-section']])
})
it('captures button events', () => {
for (const detailElement of Array.from(guideView.element.querySelector('details'))) {
reportedEvents.length = 0
const sectionName = detailElement.dataset.section
const eventName = `clicked-${sectionName}-cta`
const primaryButton = detailElement.querySelector('.btn-primary')
if (primaryButton) {
primaryButton.click()
assert.deepEqual(reportedEvents, [[eventName]])
}
}
})
})
})
describe('when the reporter changes', () =>
it('sends all queued events', () => {
welcomePackage.reporterProxy.queue.length = 0
const reporter1 = {
addCustomEvent (category, event) {
this.reportedEvents.push({ category, ...event })
},
reportedEvents: []
}
const reporter2 = {
addCustomEvent (category, event) {
this.reportedEvents.push({ category, ...event })
},
reportedEvents: []
}
welcomePackage.reporterProxy.sendEvent('foo', 'bar', 10)
welcomePackage.reporterProxy.sendEvent('foo2', 'bar2', 60)
welcomePackage.reporterProxy.setReporter(reporter1)
assert.deepEqual(reporter1.reportedEvents, [
{category: 'welcome-v1', ea: 'foo', el: 'bar', ev: 10},
{category: 'welcome-v1', ea: 'foo2', el: 'bar2', ev: 60}
])
welcomePackage.consumeReporter(reporter2)
assert.deepEqual(reporter2.reportedEvents, [])
})
)
})
})