Skip to content

Adds analytics to the playground, and nightly, and keyboard shortcuts #223

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions packages/playground/src/createUI.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
export interface UI {
showModal: (message: string, subtitle?: string, buttons?: any) => void
flashInfo: (message: string) => void
}

export const createUI = (): UI => {
return {
flashInfo: (message: string) => {
let flashBG = document.getElementById('flash-bg')
if (flashBG) {
flashBG.parentElement?.removeChild(flashBG)
}

flashBG = document.createElement('div')
flashBG.id = 'flash-bg'

const p = document.createElement('p')
p.textContent = message
flashBG.appendChild(p)
document.body.appendChild(flashBG)

setTimeout(() => {
flashBG?.parentElement?.removeChild(flashBG)
}, 1000)
},

showModal: (code: string, subtitle?: string, links?: any) => {
document.querySelectorAll('.navbar-sub li.open').forEach(i => i.classList.remove('open'))

Expand Down
3 changes: 3 additions & 0 deletions packages/playground/src/getExample.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ export const getExampleSourceCode = async (prefix: string, lang: string, example
.trim()
}

// @ts-ignore
window.appInsights.trackEvent({ name: 'Read Playground Example', properties: { id: exampleID, lang } })

return {
example,
code,
Expand Down
56 changes: 51 additions & 5 deletions packages/playground/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ export const setupPlayground = (
return plugins[tabs.indexOf(selectedTab)]
}

console.log(i)
const initialPlugins = defaultPluginFactories.map(f => f(i))
initialPlugins.forEach(p => registerPlugin(p))

Expand Down Expand Up @@ -143,6 +142,8 @@ export const setupPlayground = (
// When any compiler flags are changed, trigger a potential change to the URL
sandbox.setDidUpdateCompilerSettings(() => {
playgroundDebouncedMainFunction()
// @ts-ignore
window.appInsights.trackEvent({ name: 'Compiler Settings changed' })

const model = sandbox.editor.getModel()
const plugin = currentPlugin()
Expand All @@ -159,7 +160,7 @@ export const setupPlayground = (

// Add the versions to the dropdown
const versionsMenu = document.querySelectorAll('#versions > ul').item(0)
const allVersions = ['3.8.0-beta', ...sandbox.supportedVersions]
const allVersions = ['3.8.0-beta', ...sandbox.supportedVersions, 'Nightly']
allVersions.forEach((v: string) => {
const li = document.createElement('li')
const a = document.createElement('a')
Expand All @@ -169,7 +170,9 @@ export const setupPlayground = (
li.onclick = () => {
const currentURL = sandbox.getURLQueryWithCompilerOptions(sandbox)
const params = new URLSearchParams(currentURL.split('#')[0])
params.set('ts', v)
const version = v === 'Nightly' ? 'next' : v
params.set('ts', version)

const hash = document.location.hash.length ? document.location.hash : ''
const newURL = `${document.location.protocol}//${document.location.host}${document.location.pathname}?${params}${hash}`

Expand All @@ -196,7 +199,7 @@ export const setupPlayground = (
.getElementsByTagName('ul')
.item(0)!

// SEt exact height and widths for the popovers for the main playground navigation
// Set exact height and widths for the popovers for the main playground navigation
const isPlaygroundSubmenu = !!a.closest('nav')
if (isPlaygroundSubmenu) {
const playgroundContainer = document.getElementById('playground-container')!
Expand All @@ -209,12 +212,43 @@ export const setupPlayground = (
}
})

window.addEventListener(
'keydown',
(event: KeyboardEvent) => {
const S_KEY = 83
if (event.keyCode == S_KEY && (event.metaKey || event.ctrlKey)) {
event.preventDefault()

window.navigator.clipboard.writeText(location.href.toString()).then(
() => ui.flashInfo(i('play_export_clipboard')),
(e: any) => alert(e)
)
}

if (
event.keyCode === 13 &&
(event.metaKey || event.ctrlKey) &&
event.target instanceof Node &&
event.target === document.body
) {
event.preventDefault()
const runButton = document.getElementById('run-button')!
runButton.onclick && runButton.onclick({} as any)
}
},
false
)

const runButton = document.getElementById('run-button')!
runButton.onclick = () => {
const run = sandbox.getRunnableJS()
const runPlugin = plugins.find(p => p.id === 'logs')!
activatePlugin(runPlugin, currentPlugin(), sandbox, tabBar, container)
runWithCustomLogs(run)

runWithCustomLogs(run, i)

const isJS = sandbox.config.useJavaScript
ui.flashInfo(i(isJS ? 'play_run_js' : 'play_run_ts'))
}

// Handle the close buttons on the examples
Expand Down Expand Up @@ -348,6 +382,18 @@ export const setupPlayground = (
}
})

if (location.hash.startsWith('#show-examples')) {
setTimeout(() => {
document.getElementById('examples-button')?.click()
}, 100)
}

if (location.hash.startsWith('#show-whatisnew')) {
setTimeout(() => {
document.getElementById('whatisnew-button')?.click()
}, 100)
}

return playground
}

Expand Down
11 changes: 8 additions & 3 deletions packages/playground/src/sidebar/options.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
// import React from "react"
// import { withPrefix } from "gatsby"

import { PlaygroundPlugin, PluginFactory } from '..'

const pluginRegistry = [
Expand Down Expand Up @@ -35,6 +32,10 @@ const addCustomPlugin = (mod: string) => {
const newPlugins = customPlugins()
newPlugins.push(mod)
localStorage.setItem('custom-plugins-playground', JSON.stringify(newPlugins))
// @ts-ignore
window.appInsights &&
// @ts-ignore
window.appInsights.trackEvent({ name: 'Added Custom Module', properties: { id: mod } })
}

const customPlugins = (): string[] => {
Expand Down Expand Up @@ -178,6 +179,10 @@ const createPlugin = (plugin: typeof pluginRegistry[0]) => {
input.onchange = () => {
announceWeNeedARestart()
if (input.checked) {
// @ts-ignore
window.appInsights &&
// @ts-ignore
window.appInsights.trackEvent({ name: 'Added Registry Plugin', properties: { id: key } })
localStorage.setItem(key, 'true')
} else {
localStorage.removeItem(key)
Expand Down
15 changes: 11 additions & 4 deletions packages/playground/src/sidebar/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const runPlugin: PluginFactory = i => {
return plugin
}

export const runWithCustomLogs = (closure: Promise<string>) => {
export const runWithCustomLogs = (closure: Promise<string>, i: Function) => {
const noLogs = document.getElementById('empty-message-container')
if (noLogs) {
noLogs.style.display = 'none'
Expand All @@ -43,7 +43,8 @@ export const runWithCustomLogs = (closure: Promise<string>) => {
() => document.getElementById('log')!,
() => document.getElementById('log-container')!,
closure,
true
true,
i
)
}

Expand All @@ -53,7 +54,8 @@ function rewireLoggingToElement(
eleLocator: () => Element,
eleOverflowLocator: () => Element,
closure: Promise<string>,
autoScroll: boolean
autoScroll: boolean,
i: Function
) {
fixLoggingFunc('log', 'LOG')
fixLoggingFunc('debug', 'DBG')
Expand All @@ -62,7 +64,12 @@ function rewireLoggingToElement(
fixLoggingFunc('info', 'INF')

closure.then(js => {
eval(js)
try {
eval(js)
} catch (error) {
console.error(i('play_run_js_fail'))
console.error(error)
}

allLogs = allLogs + '<hr />'

Expand Down
6 changes: 6 additions & 0 deletions packages/sandbox/src/compilerOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export const getURLQueryWithCompilerOptions = (sandbox: any, paramOverrides?: an

// Support sending the selection
const s = sandbox.editor.getSelection()
// TODO: when it's full
if (
(s && s.selectionStartLineNumber !== s.positionLineNumber) ||
(s && s.selectionStartColumn !== s.positionColumn)
Expand All @@ -118,6 +119,11 @@ export const getURLQueryWithCompilerOptions = (sandbox: any, paramOverrides?: an
urlParams['ssc'] = s.selectionStartColumn
urlParams['pln'] = s.positionLineNumber
urlParams['pc'] = s.positionColumn
} else {
urlParams['ssl'] = undefined
urlParams['ssc'] = undefined
urlParams['pln'] = undefined
urlParams['pc'] = undefined
}

if (sandbox.config.useJavaScript) urlParams['useJavaScript'] = true
Expand Down
34 changes: 34 additions & 0 deletions packages/typescriptlang-org/src/components/AppInsights.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React, { useEffect } from "react"

/**
* Sets up the App Insights analytics, docs: https://github.com/Microsoft/ApplicationInsights-JS
* Mutates window to add window.appInsights
*/
export const AppInsights = () => {
useEffect(() => {
var sdkInstance = "appInsightsSDK";
window[sdkInstance] = "appInsights";
const config = {
instrumentationKey: "78a8fb52-a225-4c66-ac08-92fad1c1ade1",
// loggingLevelConsole: 1
}

// @ts-ignore
var aiName = window[sdkInstance], aisdk = window[aiName] || function (e) { function n(e) { t[e] = function () { var n = arguments; t.queue.push(function () { t[e].apply(t, n) }) } } var t = { config: e }; t.initialize = !0; var i = document, a = window; setTimeout(function () { var n = i.createElement("script"); n.async = true; n.src = e.url || "https://az416426.vo.msecnd.net/scripts/b/ai.2.min.js", i.getElementsByTagName("script")[0].parentNode.appendChild(n) }); try { t.cookie = i.cookie } catch (e) { } t.queue = [], t.version = 2; for (var r = ["Event", "PageView", "Exception", "Trace", "DependencyData", "Metric", "PageViewPerformance"]; r.length;)n("track" + r.pop()); n("startTrackPage"), n("stopTrackPage"); var s = "Track" + r[0]; if (n("start" + s), n("stop" + s), n("setAuthenticatedUserContext"), n("clearAuthenticatedUserContext"), n("flush"), !(!0 === e.disableExceptionTracking || e.extensionConfig && e.extensionConfig.ApplicationInsightsAnalytics && !0 === e.extensionConfig.ApplicationInsightsAnalytics.disableExceptionTracking)) { n("_" + (r = "onerror")); var o = a[r]; a[r] = function (e, n, i, a, s) { var c = o && o(e, n, i, a, s); return !0 !== c && t["_" + r]({ message: e, url: n, lineNumber: i, columnNumber: a, error: s }), c }, e.autoExceptionInstrumented = !0 } return t }(config);
window[aiName] = aisdk

// @ts-ignore
if (aisdk.queue && 0 === aisdk.queue.length) {
const locationWithoutPlaygroundCode = document.location.href.split("#code")[0].split("#src")[0]
const referrerWithoutPlaygroundCode = document.referrer && document.referrer.split("#code")[0].split("#src")[0]
// @ts-ignore
aisdk.trackPageView({ uri: locationWithoutPlaygroundCode, refUri: referrerWithoutPlaygroundCode });
}
})

return (
<>
<div />
</>
)
}
2 changes: 2 additions & 0 deletions packages/typescriptlang-org/src/components/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { SiteNav, Props } from "./layout/TopNav"
import { SiteFooter } from "./layout/SiteFooter"
import { SeoProps, HeadSEO } from "./HeadSEO";
import "./layout/main.scss"
import { AppInsights } from "./AppInsights";

type LayoutProps = SeoProps & Props & {
children: any
Expand All @@ -18,6 +19,7 @@ export const Layout = (props: LayoutProps) => {
<main>{props.children}</main>
<SiteFooter />
</div>
<AppInsights />
</>
)
}
4 changes: 4 additions & 0 deletions packages/typescriptlang-org/src/copy/en/playground.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ export const playCopy = {
play_export_tsast: "Open in TypeScript AST Viewer",
play_export_sandbox: "Open in CodeSandbox",
play_export_stackblitz: "Open in StackBlitz",
play_export_clipboard: "URL copied to clipboard",
play_run_js: "Executed JavaScript",
play_run_ts: "Executed transpiled TypeScript",
play_run_js_fail: "Executed JavaScript Failed:",
play_default_code_sample: `// Welcome to the TypeScript Playground, this is a website
// which gives you a chance to write, share and learn TypeScript.

Expand Down
29 changes: 29 additions & 0 deletions packages/typescriptlang-org/src/templates/play.scss
Original file line number Diff line number Diff line change
Expand Up @@ -667,3 +667,32 @@ input.good {
opacity: 0.5;
}
}

#flash-bg {
top: 0;
left: 0;
right: 0;
bottom: 0;
position: fixed;
z-index: 42;
display: flex;
justify-content: center;
align-items: center;
pointer-events: none;

p {
background-color: rgba(0, 0, 0, 0.8);
color: white;
padding: 20px;
font-size: 1.5rem;

border-radius: 1em;
padding: 0.5em 1.5em;

color: white;
transition: opacity 0.1s ease-in-out;

/* help Safari with blurred text */
transform: translateZ(0);
}
}
4 changes: 2 additions & 2 deletions packages/typescriptlang-org/src/templates/play.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,15 +137,15 @@ const Play = (props: Props) => {
</li>

<li className="dropdown">
<a href="#" className="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{i("play_subnav_examples")} <span className="caret"></span></a>
<a href="#" id="whatisnew-button" className="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{i("play_subnav_examples")} <span className="caret"></span></a>
<ul className="examples-dropdown" id="examples" >
<button className="examples-close">{i("play_subnav_examples_close")}</button>
<RenderExamples defaultSection="JavaScript" sections={["JavaScript", "TypeScript"]} examples={props.pageContext.examplesTOC} locale={props.pageContext.lang} />
</ul>
</li>

<li className="dropdown">
<a href="#" className="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{i("play_subnav_whatsnew")} <span className="caret"></span></a>
<a href="#" id="examples-button" className="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{i("play_subnav_whatsnew")} <span className="caret"></span></a>
<ul className="examples-dropdown" id="whatisnew">
<button className="examples-close">{i("play_subnav_examples_close")}</button>
<RenderExamples defaultSection="3.8" sections={["3.8", "3.7", "Playground"]} examples={props.pageContext.examplesTOC} locale={props.pageContext.lang} />
Expand Down