Skip to content
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

lab: open log files in Jupyter Lab #2092

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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
5 changes: 4 additions & 1 deletion src/components/Markdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@
<script>
import MarkdownIt from 'markdown-it'

const md = new MarkdownIt()
const md = new MarkdownIt({
// allow HTML syntax
html: true,
})

export default {
name: 'Markdown',
Expand Down
16 changes: 15 additions & 1 deletion src/components/core/Alert.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,35 @@
<v-icon>{{ $options.icons.mdiClose }}</v-icon>
</v-btn>
</template>
{{ alert.text }}
<Markdown v-if="alert.text" :markdown="String(alert.text)" />
</v-snackbar>
</template>

<script>
import { mdiClose } from '@mdi/js'
import { mapActions, mapState } from 'vuex'
import Markdown from '@/components/Markdown.vue'

export default {
name: 'Alert',

components: {
Markdown,
},

computed: {
...mapState(['alert'])
},

watch: {
async alert (val, old) {
if (val && val !== old) {
await new Promise(resolve => setTimeout(resolve, val.timeout))
this.closeAlert()

Check warning on line 61 in src/components/core/Alert.vue

View check run for this annotation

Codecov / codecov/patch

src/components/core/Alert.vue#L61

Added line #L61 was not covered by tests
}
}
},

methods: {
...mapActions(['setAlert']),
/**
Expand Down
93 changes: 93 additions & 0 deletions src/components/cylc/JupyterLauncher.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<!--
Copyright (C) NIWA & British Crown (Met Office) & Contributors.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->

<template class="c-jupyter-launcher">
<v-chip
variant="outlined"
class="flex-shrink-0"
@click="open"
v-if="user.extensions?.lab"
>
<v-icon style="margin-right: 0.5em">{{ $options.icons.jupyterLogo }}</v-icon>
Open in Jupyter Lab
</v-chip>
</template>

<script>
import axios from 'axios'
import { store } from '@/store/index'
import { Alert as AlertModel } from '@/model/Alert.model'
import { mapState } from 'vuex'
import { createUrl, getCylcHeaders } from '@/utils/urls'
import { jupyterLogo } from '@/utils/icons'

const LAB_ENDPOINT = 'lab-bridge/open/'

export default {
name: 'JupyterLauncher',

components: {},

props: {
path: {
type: String,
required: true,
}
},

icons: {
jupyterLogo,
},

computed: {
...mapState('user', ['user']),

openInExistingSession () {
return `${LAB_ENDPOINT}/${this.path}`

Check warning on line 60 in src/components/cylc/JupyterLauncher.vue

View check run for this annotation

Codecov / codecov/patch

src/components/cylc/JupyterLauncher.vue#L60

Added line #L60 was not covered by tests
},

openInNewSession () {
// TODO: Strip $HOME from the path and add it onto the URL like so:
// return `${this.user.extensions?.lab}/tree/${this.path}`
return this.user.extensions?.lab

Check warning on line 66 in src/components/cylc/JupyterLauncher.vue

View check run for this annotation

Codecov / codecov/patch

src/components/cylc/JupyterLauncher.vue#L66

Added line #L66 was not covered by tests
}
},

methods: {
async open () {
await axios.get(

Check warning on line 72 in src/components/cylc/JupyterLauncher.vue

View check run for this annotation

Codecov / codecov/patch

src/components/cylc/JupyterLauncher.vue#L72

Added line #L72 was not covered by tests
createUrl(this.openInExistingSession),
{ headers: getCylcHeaders() }
)
store.dispatch(

Check warning on line 76 in src/components/cylc/JupyterLauncher.vue

View check run for this annotation

Codecov / codecov/patch

src/components/cylc/JupyterLauncher.vue#L76

Added line #L76 was not covered by tests
'setAlert',
new AlertModel(
// `Opened file in any existing Lab session\n\n[Open a new Jupyter Lab session!](${this.openInNewSession}){:target="_blank"}`,
'Sent request to open file in any active Jupyter Lab sessions.',
'success',
(
'Sent request to open file in any active Jupyter Lab sessions.' +
'<br /><br />' +
`<a href="${this.openInNewSession}" target="_blank">Open a new Jupyter Lab session</a>`
),
4000,
)
)
},
},
}
</script>
3 changes: 2 additions & 1 deletion src/model/Alert.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ export class Alert {
* @param {string} color - color of the displayed alert.
* @param {?string} msg - a custom message to display in the alert instead of err.
*/
constructor (err, color, msg = null) {
constructor (err, color, msg = null, timeout = 10000) {
this.err = err
this.text = msg || err
this.color = color
this.timeout = timeout
}
}
8 changes: 8 additions & 0 deletions src/views/Log.vue
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
>
{{ results.connected ? 'Connected' : 'Reconnect' }}
</v-chip>
<JupyterLauncher :path="urlSafePath" style="margin-left: 0.5em" />
<div
data-cy="log-path"
class="ml-2 mr-1 d-flex text-medium-emphasis text-pre overflow-x-hidden"
Expand Down Expand Up @@ -205,6 +206,7 @@ import ViewToolbar from '@/components/cylc/ViewToolbar.vue'
import DeltasCallback from '@/services/callbacks'
import { debounce } from 'lodash-es'
import CopyBtn from '@/components/core/CopyBtn.vue'
import JupyterLauncher from '@/components/cylc/JupyterLauncher.vue'

/**
* Query used to retrieve data for the Log view.
Expand Down Expand Up @@ -324,6 +326,7 @@ export default {

components: {
CopyBtn,
JupyterLauncher,
LogComponent,
ViewToolbar,
},
Expand Down Expand Up @@ -370,6 +373,10 @@ export default {
() => results.value.path?.substring(0, results.value.path.length - file.value.length - 1)
)

const urlSafePath = computed(
() => encodeURIComponent(`${parentPath.value}/${file.value}`)
)

whenever(
() => store.state.offline,
() => { results.value.connected = false }
Expand Down Expand Up @@ -406,6 +413,7 @@ export default {
debouncedUpdateRelativeID,
toolbarBtnSize,
toolbarBtnProps: btnProps(toolbarBtnSize),
urlSafePath,
}
},

Expand Down