Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Hughes <me@iamphill.com>2019-01-11 13:14:51 +0300
committerPhil Hughes <me@iamphill.com>2019-01-11 13:14:51 +0300
commit8d1683f7b0173040b660a9b61e9a2d5389e1344a (patch)
tree281448892732f68a115f025c04078b7f82d6001e /app/assets/javascripts/notebook
parentb682a6f8981d303e7ee7ecc4273768ee6ed66864 (diff)
Support multiple outputs in Jupyter notebooks
Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/31910, https://gitlab.com/gitlab-org/gitlab-ce/issues/32588
Diffstat (limited to 'app/assets/javascripts/notebook')
-rw-r--r--app/assets/javascripts/notebook/cells/code.vue15
-rw-r--r--app/assets/javascripts/notebook/cells/code/index.vue3
-rw-r--r--app/assets/javascripts/notebook/cells/output/html.vue15
-rw-r--r--app/assets/javascripts/notebook/cells/output/image.vue20
-rw-r--r--app/assets/javascripts/notebook/cells/output/index.vue104
-rw-r--r--app/assets/javascripts/notebook/cells/prompt.vue10
-rw-r--r--app/assets/javascripts/notebook/index.vue4
7 files changed, 103 insertions, 68 deletions
diff --git a/app/assets/javascripts/notebook/cells/code.vue b/app/assets/javascripts/notebook/cells/code.vue
index bd6736152f5..eefc801ed7a 100644
--- a/app/assets/javascripts/notebook/cells/code.vue
+++ b/app/assets/javascripts/notebook/cells/code.vue
@@ -1,11 +1,12 @@
<script>
-import CodeCell from './code/index.vue';
+import CodeOutput from './code/index.vue';
import OutputCell from './output/index.vue';
export default {
+ name: 'CodeCell',
components: {
- 'code-cell': CodeCell,
- 'output-cell': OutputCell,
+ CodeOutput,
+ OutputCell,
},
props: {
cell: {
@@ -29,8 +30,8 @@ export default {
hasOutput() {
return this.cell.outputs.length;
},
- output() {
- return this.cell.outputs[0];
+ outputs() {
+ return this.cell.outputs;
},
},
};
@@ -38,7 +39,7 @@ export default {
<template>
<div class="cell">
- <code-cell
+ <code-output
:raw-code="rawInputCode"
:count="cell.execution_count"
:code-css-class="codeCssClass"
@@ -47,7 +48,7 @@ export default {
<output-cell
v-if="hasOutput"
:count="cell.execution_count"
- :output="output"
+ :outputs="outputs"
:code-css-class="codeCssClass"
/>
</div>
diff --git a/app/assets/javascripts/notebook/cells/code/index.vue b/app/assets/javascripts/notebook/cells/code/index.vue
index 8bf2431c4c6..98b6cdd0944 100644
--- a/app/assets/javascripts/notebook/cells/code/index.vue
+++ b/app/assets/javascripts/notebook/cells/code/index.vue
@@ -3,8 +3,9 @@ import Prism from '../../lib/highlight';
import Prompt from '../prompt.vue';
export default {
+ name: 'CodeOutput',
components: {
- prompt: Prompt,
+ Prompt,
},
props: {
count: {
diff --git a/app/assets/javascripts/notebook/cells/output/html.vue b/app/assets/javascripts/notebook/cells/output/html.vue
index c6fc786fa76..8dc2d73af9b 100644
--- a/app/assets/javascripts/notebook/cells/output/html.vue
+++ b/app/assets/javascripts/notebook/cells/output/html.vue
@@ -4,13 +4,21 @@ import Prompt from '../prompt.vue';
export default {
components: {
- prompt: Prompt,
+ Prompt,
},
props: {
+ count: {
+ type: Number,
+ required: true,
+ },
rawCode: {
type: String,
required: true,
},
+ index: {
+ type: Number,
+ required: true,
+ },
},
computed: {
sanitizedOutput() {
@@ -21,13 +29,16 @@ export default {
},
});
},
+ showOutput() {
+ return this.index === 0;
+ },
},
};
</script>
<template>
<div class="output">
- <prompt />
+ <prompt type="Out" :count="count" :show-output="showOutput" />
<div v-html="sanitizedOutput"></div>
</div>
</template>
diff --git a/app/assets/javascripts/notebook/cells/output/image.vue b/app/assets/javascripts/notebook/cells/output/image.vue
index fe8c81398fb..f1130275525 100644
--- a/app/assets/javascripts/notebook/cells/output/image.vue
+++ b/app/assets/javascripts/notebook/cells/output/image.vue
@@ -6,6 +6,10 @@ export default {
prompt: Prompt,
},
props: {
+ count: {
+ type: Number,
+ required: true,
+ },
outputType: {
type: String,
required: true,
@@ -14,10 +18,24 @@ export default {
type: String,
required: true,
},
+ index: {
+ type: Number,
+ required: true,
+ },
+ },
+ computed: {
+ imgSrc() {
+ return `data:${this.outputType};base64,${this.rawCode}`;
+ },
+ showOutput() {
+ return this.index === 0;
+ },
},
};
</script>
<template>
- <div class="output"><prompt /> <img :src="'data:' + outputType + ';base64,' + rawCode" /></div>
+ <div class="output">
+ <prompt type="out" :count="count" :show-output="showOutput" /> <img :src="imgSrc" />
+ </div>
</template>
diff --git a/app/assets/javascripts/notebook/cells/output/index.vue b/app/assets/javascripts/notebook/cells/output/index.vue
index bd0bcc0d819..c5ae7e7ee10 100644
--- a/app/assets/javascripts/notebook/cells/output/index.vue
+++ b/app/assets/javascripts/notebook/cells/output/index.vue
@@ -1,14 +1,9 @@
<script>
-import CodeCell from '../code/index.vue';
-import Html from './html.vue';
-import Image from './image.vue';
+import CodeOutput from '../code/index.vue';
+import HtmlOutput from './html.vue';
+import ImageOutput from './image.vue';
export default {
- components: {
- 'code-cell': CodeCell,
- 'html-output': Html,
- 'image-output': Image,
- },
props: {
codeCssClass: {
type: String,
@@ -20,68 +15,69 @@ export default {
required: false,
default: 0,
},
- output: {
- type: Object,
+ outputs: {
+ type: Array,
required: true,
- default: () => ({}),
},
},
- computed: {
- componentName() {
- if (this.output.text) {
- return 'code-cell';
- } else if (this.output.data['image/png']) {
- return 'image-output';
- } else if (this.output.data['text/html']) {
- return 'html-output';
- } else if (this.output.data['image/svg+xml']) {
- return 'html-output';
- }
+ data() {
+ return {
+ outputType: '',
+ };
+ },
+ methods: {
+ dataForType(output, type) {
+ let data = output.data[type];
- return 'code-cell';
- },
- rawCode() {
- if (this.output.text) {
- return this.output.text.join('');
+ if (typeof data === 'object') {
+ data = data.join('');
}
- return this.dataForType(this.outputType);
+ return data;
},
- outputType() {
- if (this.output.text) {
- return '';
- } else if (this.output.data['image/png']) {
- return 'image/png';
- } else if (this.output.data['text/html']) {
- return 'text/html';
- } else if (this.output.data['image/svg+xml']) {
- return 'image/svg+xml';
+ getComponent(output) {
+ if (output.text) {
+ return CodeOutput;
+ } else if (output.data['image/png']) {
+ this.outputType = 'image/png';
+
+ return ImageOutput;
+ } else if (output.data['text/html']) {
+ this.outputType = 'text/html';
+
+ return HtmlOutput;
+ } else if (output.data['image/svg+xml']) {
+ this.outputType = 'image/svg+xml';
+
+ return HtmlOutput;
}
- return 'text/plain';
+ this.outputType = 'text/plain';
+ return CodeOutput;
},
- },
- methods: {
- dataForType(type) {
- let data = this.output.data[type];
-
- if (typeof data === 'object') {
- data = data.join('');
+ rawCode(output) {
+ if (output.text) {
+ return output.text.join('');
}
- return data;
+ return this.dataForType(output, this.outputType);
},
},
};
</script>
<template>
- <component
- :is="componentName"
- :output-type="outputType"
- :count="count"
- :raw-code="rawCode"
- :code-css-class="codeCssClass"
- type="output"
- />
+ <div>
+ <component
+ :is="getComponent(output)"
+ v-for="(output, index) in outputs"
+ :key="index"
+ type="output"
+ :output-type="outputType"
+ :count="count"
+ :index="index"
+ :raw-code="rawCode(output)"
+ :code-css-class="codeCssClass"
+ />
+ </div>
</template>
diff --git a/app/assets/javascripts/notebook/cells/prompt.vue b/app/assets/javascripts/notebook/cells/prompt.vue
index 3f1f239a806..1eeb61844a4 100644
--- a/app/assets/javascripts/notebook/cells/prompt.vue
+++ b/app/assets/javascripts/notebook/cells/prompt.vue
@@ -11,18 +11,26 @@ export default {
required: false,
default: 0,
},
+ showOutput: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
},
computed: {
hasKeys() {
return this.type !== '' && this.count;
},
+ showTypeText() {
+ return this.type && this.count && this.showOutput;
+ },
},
};
</script>
<template>
<div class="prompt">
- <span v-if="hasKeys"> {{ type }} [{{ count }}]: </span>
+ <span v-if="showTypeText"> {{ type }} [{{ count }}]: </span>
</div>
</template>
diff --git a/app/assets/javascripts/notebook/index.vue b/app/assets/javascripts/notebook/index.vue
index 6a54d0b3823..e7056c03e4a 100644
--- a/app/assets/javascripts/notebook/index.vue
+++ b/app/assets/javascripts/notebook/index.vue
@@ -3,8 +3,8 @@ import { MarkdownCell, CodeCell } from './cells';
export default {
components: {
- 'code-cell': CodeCell,
- 'markdown-cell': MarkdownCell,
+ CodeCell,
+ MarkdownCell,
},
props: {
notebook: {