Skip to content

Commit c5d4ad8

Browse files
authored
feat: add open in colab (#160)
* Add open in Colab feature * test update * Trying VUE_APP_ * test update * Trying smth else * Revert "Trying smth else" This reverts commit e9652e1.
1 parent 7834585 commit c5d4ad8

File tree

4 files changed

+285
-2
lines changed

4 files changed

+285
-2
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"prompts": "^2.4.1",
3333
"semver": "^7.3.5",
3434
"start-server-and-test": "^1.12.3",
35+
"uuid": "^8.3.2",
3536
"vite": "^2.3.3",
3637
"vue": "^3.0.11",
3738
"vue-router": "^4.0.8"

pnpm-lock.yaml

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/NavBar.vue

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<div class="left-side-badges">
1515
<NavHelp />
1616
<NavDownload />
17+
<NavColab />
1718
<NavGitHub />
1819
<NavTwitter />
1920
<NavDiscord />
@@ -33,12 +34,20 @@
3334
import { version } from '../../package.json'
3435
import NavDiscord from './NavDiscord.vue'
3536
import NavDownload from './NavDownload.vue'
37+
import NavColab from './NavColab.vue'
3638
import NavGitHub from './NavGitHub.vue'
3739
import NavTwitter from './NavTwitter.vue'
3840
import NavHelp from './NavHelp.vue'
3941
4042
export default {
41-
components: { NavDiscord, NavDownload, NavGitHub, NavTwitter, NavHelp },
43+
components: {
44+
NavDiscord,
45+
NavDownload,
46+
NavColab,
47+
NavGitHub,
48+
NavTwitter,
49+
NavHelp
50+
},
4251
setup() {
4352
const currentCommit = __COMMIT__ // from vite.config.js
4453

src/components/NavColab.vue

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
<template>
2+
<button
3+
@click="downloadProject"
4+
class="download-button external-links"
5+
title="Open in Colab"
6+
>
7+
<a
8+
class="external-links"
9+
v-bind:href="colabLink"
10+
target="_blank"
11+
rel="noopener noreferrer"
12+
>
13+
<svg
14+
xmlns="http://www.w3.org/2000/svg"
15+
xmlns:xlink="http://www.w3.org/1999/xlink"
16+
width="2.0em"
17+
height="1.4em"
18+
>
19+
<linearGradient id="b" x2="0" y2="100%">
20+
<stop offset="0" stop-color="#bbb" stop-opacity=".1" />
21+
<stop offset="1" stop-opacity=".1" />
22+
</linearGradient>
23+
<clipPath id="a">
24+
<rect width="117" height="20" rx="3" fill="#fff" />
25+
</clipPath>
26+
<g clip-path="url(#a)">
27+
<path fill="#fff" d="M0 0h30v20H0z" />
28+
</g>
29+
<g
30+
fill="#fff"
31+
text-anchor="middle"
32+
font-family="DejaVu Sans,Verdana,Geneva,sans-serif"
33+
font-size="110"
34+
>
35+
<svg
36+
x="4px"
37+
y="0px"
38+
width="23px"
39+
height="21px"
40+
viewBox="0 0 24 24"
41+
style="background-color: #fff; border-radius: 1px"
42+
>
43+
<path
44+
style="fill: #e8710a"
45+
d="M1.977,16.77c-2.667-2.277-2.605-7.079,0-9.357C2.919,8.057,3.522,9.075,4.49,9.691c-1.152,1.6-1.146,3.201-0.004,4.803C3.522,15.111,2.918,16.126,1.977,16.77z"
46+
/>
47+
<path
48+
style="fill: #f9ab00"
49+
d="M12.257,17.114c-1.767-1.633-2.485-3.658-2.118-6.02c0.451-2.91,2.139-4.893,4.946-5.678c2.565-0.718,4.964-0.217,6.878,1.819c-0.884,0.743-1.707,1.547-2.434,2.446C18.488,8.827,17.319,8.435,16,8.856c-2.404,0.767-3.046,3.241-1.494,5.644c-0.241,0.275-0.493,0.541-0.721,0.826C13.295,15.939,12.511,16.3,12.257,17.114z"
50+
/>
51+
<path
52+
style="fill: #e8710a"
53+
d="M19.529,9.682c0.727-0.899,1.55-1.703,2.434-2.446c2.703,2.783,2.701,7.031-0.005,9.764c-2.648,2.674-6.936,2.725-9.701,0.115c0.254-0.814,1.038-1.175,1.528-1.788c0.228-0.285,0.48-0.552,0.721-0.826c1.053,0.916,2.254,1.268,3.6,0.83C20.502,14.551,21.151,11.927,19.529,9.682z"
54+
/>
55+
<path
56+
style="fill: #f9ab00"
57+
d="M4.49,9.691C3.522,9.075,2.919,8.057,1.977,7.413c2.209-2.398,5.721-2.942,8.476-1.355c0.555,0.32,0.719,0.606,0.285,1.128c-0.157,0.188-0.258,0.422-0.391,0.631c-0.299,0.47-0.509,1.067-0.929,1.371C8.933,9.539,8.523,8.847,8.021,8.746C6.673,8.475,5.509,8.787,4.49,9.691z"
58+
/>
59+
<path
60+
style="fill: #f9ab00"
61+
d="M1.977,16.77c0.941-0.644,1.545-1.659,2.509-2.277c1.373,1.152,2.85,1.433,4.45,0.499c0.332-0.194,0.503-0.088,0.673,0.19c0.386,0.635,0.753,1.285,1.181,1.89c0.34,0.48,0.222,0.715-0.253,1.006C7.84,19.73,4.205,19.188,1.977,16.77z"
62+
/>
63+
</svg>
64+
</g>
65+
</svg>
66+
<span class="icon-text">Open in Colab</span>
67+
</a>
68+
</button>
69+
<div
70+
class="download-success"
71+
v-show="showDownloadMsg"
72+
@click="showDownloadMsg = false"
73+
></div>
74+
<div class="msg-wrapper" v-show="showDownloadMsg">
75+
<div class="msg">
76+
<h2>🎉 Your Training Script Has Been Generated! 🎉</h2>
77+
<p>
78+
Thanks for using Code-Generator! Feel free to reach out to us on
79+
<a
80+
class="external-links msg-gh"
81+
href="https://github.com/pytorch-ignite/code-generator"
82+
target="_blank"
83+
rel="noopener noreferrer"
84+
>GitHub</a
85+
>
86+
with any feedback, bug report, and feature request.
87+
</p>
88+
</div>
89+
</div>
90+
</template>
91+
92+
<script>
93+
import { ref } from 'vue'
94+
import { store, msg } from '../store'
95+
import { v4 as uuidv4 } from 'uuid'
96+
import { Octokit } from 'https://cdn.skypack.dev/@octokit/core'
97+
98+
export default {
99+
setup() {
100+
const showDownloadMsg = ref(false)
101+
const colabLink = ref()
102+
const downloadProject = () => {
103+
if (store.code && Object.keys(store.code).length) {
104+
msg.color = 'red'
105+
if (!store.config.output_dir) {
106+
msg.showMsg = true
107+
msg.content = `Output directory is required. Please input in Loggers tab.`
108+
} else if (!store.config.log_every_iters) {
109+
msg.showMsg = true
110+
msg.content = `Logging interval is required. Please input in Loggers tab.`
111+
} else {
112+
// Create notebook placeholder
113+
var nb = {
114+
metadata: {},
115+
cells: [],
116+
nbformat: 4,
117+
nbformat_minor: 2
118+
}
119+
120+
var firstCell // README
121+
var reqCell // !pip install ...
122+
var configCell // %%writefile config.yaml
123+
var lastCell // main()
124+
125+
for (const filename in store.code) {
126+
// Append regular py files
127+
if (filename.includes('.py')) {
128+
var cell = {
129+
cell_type: 'code',
130+
metadata: {},
131+
source: [store.code[filename]],
132+
outputs: [],
133+
execution_count: null
134+
}
135+
// main will be at the end
136+
if (filename.includes('main.py')) {
137+
lastCell = cell
138+
} else if (filename.includes('test_all.py')) {
139+
continue
140+
} else {
141+
nb['cells'].push(cell)
142+
}
143+
// Readme will be at the beginning
144+
} else if (filename.includes('README.md')) {
145+
var firstCell = {
146+
cell_type: 'markdown',
147+
metadata: {},
148+
source: [store.code[filename]]
149+
}
150+
// requirements should be just after the README
151+
} else if (filename.includes('requirements.txt')) {
152+
var cell = {
153+
cell_type: 'code',
154+
metadata: {},
155+
source: [
156+
'!pip install '.concat(
157+
store.code[filename]
158+
.split('\n')
159+
.join(' ')
160+
.replace('pytest', '')
161+
)
162+
],
163+
outputs: [],
164+
execution_count: null
165+
}
166+
reqCell = cell
167+
// config will be after installing requirements
168+
} else if (filename.includes('config.yaml')) {
169+
var cell = {
170+
cell_type: 'code',
171+
metadata: {},
172+
source: ['%%writefile config.yaml\n', store.code[filename]],
173+
outputs: [],
174+
execution_count: null
175+
}
176+
configCell = cell
177+
}
178+
}
179+
180+
// Finalize notebook structure
181+
nb['cells'] = [
182+
firstCell,
183+
reqCell,
184+
{
185+
cell_type: 'markdown',
186+
metadata: {},
187+
source: ['### Create a config file\n']
188+
},
189+
configCell,
190+
...nb['cells'],
191+
lastCell
192+
]
193+
194+
// Conver to json
195+
var nbJSON = JSON.stringify(nb)
196+
197+
var nbUid = uuidv4()
198+
var nbName = 'pytorch-ignite-notebook.ipynb'
199+
var repoOwner = process.env.VUE_APP_GH_USER
200+
var repo = process.env.VUE_APP_GH_REPO
201+
202+
const octokit = new Octokit({
203+
auth: process.env.VUE_APP_GH_TOKEN
204+
})
205+
const response = octokit.request(
206+
'PUT /repos/{owner}/{repo}/contents/{path}',
207+
{
208+
owner: repoOwner,
209+
repo: repo,
210+
path: `nbs/${nbUid}/${nbName}`,
211+
message: `nb: add ${nbUid}`,
212+
content: btoa(unescape(encodeURIComponent(nbJSON)))
213+
}
214+
)
215+
216+
// Getting static link
217+
colabLink.value = `https://colab.research.google.com/github/${repoOwner}/${repo}/blob/main/nbs/${nbUid}/${nbName}`
218+
}
219+
} else {
220+
msg.showMsg = true
221+
msg.content = 'Choose a template to Open.'
222+
}
223+
}
224+
return { downloadProject, showDownloadMsg, colabLink }
225+
}
226+
}
227+
</script>
228+
229+
<style scoped>
230+
@import url('./css/nav-right.css');
231+
232+
.download-button {
233+
display: inline-flex;
234+
align-items: center;
235+
justify-content: center;
236+
background: none;
237+
color: var(--c-text);
238+
cursor: pointer;
239+
font-family: var(--font-family-base);
240+
font-size: 1em;
241+
padding: 0;
242+
}
243+
.download-success {
244+
position: fixed;
245+
top: 0;
246+
left: 0;
247+
background-color: rgba(101, 110, 133, 0.8);
248+
z-index: 10;
249+
width: 100vw;
250+
height: 100vh;
251+
}
252+
.msg-wrapper {
253+
position: absolute;
254+
max-width: 38rem;
255+
padding: 0 1rem;
256+
text-align: center;
257+
margin: 20vh auto 100%;
258+
inset: 0;
259+
z-index: 12;
260+
}
261+
.msg {
262+
padding: 2rem 1rem;
263+
background-color: var(--c-white-light);
264+
color: var(--c-text);
265+
border-radius: 8px;
266+
box-shadow: 0 0 5px 5px rgba(0, 0, 0, 0.33);
267+
}
268+
.msg-gh {
269+
margin: 0;
270+
color: var(--c-brand-red);
271+
}
272+
</style>

0 commit comments

Comments
 (0)