2019-12-26 22:10:19 +05:30
|
|
|
<script>
|
2020-05-24 23:13:21 +05:30
|
|
|
import { escape } from 'lodash';
|
2019-12-26 22:10:19 +05:30
|
|
|
import { GlTooltip } from '@gitlab/ui';
|
2020-01-01 13:55:28 +05:30
|
|
|
import { __, sprintf } from '~/locale';
|
2019-12-26 22:10:19 +05:30
|
|
|
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
|
|
|
|
import FileIcon from '~/vue_shared/components/file_icon.vue';
|
|
|
|
import Icon from '~/vue_shared/components/icon.vue';
|
|
|
|
|
|
|
|
export default {
|
|
|
|
components: {
|
|
|
|
ClipboardButton,
|
|
|
|
FileIcon,
|
|
|
|
Icon,
|
|
|
|
},
|
|
|
|
directives: {
|
|
|
|
GlTooltip,
|
|
|
|
},
|
|
|
|
props: {
|
|
|
|
lines: {
|
|
|
|
type: Array,
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
filePath: {
|
|
|
|
type: String,
|
|
|
|
required: true,
|
|
|
|
},
|
2020-01-01 13:55:28 +05:30
|
|
|
errorFn: {
|
|
|
|
type: String,
|
|
|
|
required: false,
|
|
|
|
default: '',
|
|
|
|
},
|
2019-12-26 22:10:19 +05:30
|
|
|
errorLine: {
|
|
|
|
type: Number,
|
2020-01-01 13:55:28 +05:30
|
|
|
required: false,
|
|
|
|
default: 0,
|
|
|
|
},
|
|
|
|
errorColumn: {
|
|
|
|
type: Number,
|
|
|
|
required: false,
|
|
|
|
default: 0,
|
2019-12-26 22:10:19 +05:30
|
|
|
},
|
|
|
|
expanded: {
|
|
|
|
type: Boolean,
|
|
|
|
required: false,
|
|
|
|
default: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
isExpanded: this.expanded,
|
|
|
|
};
|
|
|
|
},
|
|
|
|
computed: {
|
2020-01-01 13:55:28 +05:30
|
|
|
hasCode() {
|
|
|
|
return Boolean(this.lines.length);
|
2019-12-26 22:10:19 +05:30
|
|
|
},
|
|
|
|
collapseIcon() {
|
|
|
|
return this.isExpanded ? 'chevron-down' : 'chevron-right';
|
|
|
|
},
|
2020-03-13 15:44:24 +05:30
|
|
|
errorFnText() {
|
|
|
|
return this.errorFn
|
|
|
|
? sprintf(
|
|
|
|
__(`%{spanStart}in%{spanEnd} %{errorFn}`),
|
|
|
|
{
|
2020-05-24 23:13:21 +05:30
|
|
|
errorFn: `<strong>${escape(this.errorFn)}</strong>`,
|
2020-03-13 15:44:24 +05:30
|
|
|
spanStart: `<span class="text-tertiary">`,
|
|
|
|
spanEnd: `</span>`,
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
)
|
|
|
|
: '';
|
2020-01-01 13:55:28 +05:30
|
|
|
},
|
2020-03-13 15:44:24 +05:30
|
|
|
errorPositionText() {
|
2020-01-01 13:55:28 +05:30
|
|
|
return this.errorLine
|
2020-03-13 15:44:24 +05:30
|
|
|
? sprintf(
|
|
|
|
__(`%{spanStart}at line%{spanEnd} %{errorLine}%{errorColumn}`),
|
|
|
|
{
|
|
|
|
errorLine: `<strong>${this.errorLine}</strong>`,
|
|
|
|
errorColumn: this.errorColumn ? `:<strong>${this.errorColumn}</strong>` : ``,
|
|
|
|
spanStart: `<span class="text-tertiary">`,
|
|
|
|
spanEnd: `</span>`,
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
)
|
2020-01-01 13:55:28 +05:30
|
|
|
: '';
|
|
|
|
},
|
2020-03-13 15:44:24 +05:30
|
|
|
errorInfo() {
|
|
|
|
return `${this.errorFnText} ${this.errorPositionText}`;
|
|
|
|
},
|
2019-12-26 22:10:19 +05:30
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
isHighlighted(lineNum) {
|
|
|
|
return lineNum === this.errorLine;
|
|
|
|
},
|
|
|
|
toggle() {
|
|
|
|
this.isExpanded = !this.isExpanded;
|
|
|
|
},
|
|
|
|
lineNum(line) {
|
|
|
|
return line[0];
|
|
|
|
},
|
|
|
|
lineCode(line) {
|
|
|
|
return line[1];
|
|
|
|
},
|
|
|
|
},
|
|
|
|
userColorScheme: window.gon.user_color_scheme,
|
|
|
|
};
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
|
|
|
<div class="file-holder">
|
|
|
|
<div ref="header" class="file-title file-title-flex-parent">
|
2020-01-01 13:55:28 +05:30
|
|
|
<div class="file-header-content d-flex align-content-center">
|
|
|
|
<div v-if="hasCode" class="d-inline-block cursor-pointer" @click="toggle()">
|
2019-12-26 22:10:19 +05:30
|
|
|
<icon :name="collapseIcon" :size="16" aria-hidden="true" class="append-right-5" />
|
|
|
|
</div>
|
2020-01-01 13:55:28 +05:30
|
|
|
<file-icon
|
|
|
|
:file-name="filePath"
|
|
|
|
:size="18"
|
|
|
|
aria-hidden="true"
|
|
|
|
css-classes="append-right-5"
|
|
|
|
/>
|
|
|
|
<strong
|
|
|
|
v-gl-tooltip
|
|
|
|
:title="filePath"
|
2020-03-13 15:44:24 +05:30
|
|
|
class="file-title-name d-inline-block overflow-hidden text-truncate limited-width"
|
2020-01-01 13:55:28 +05:30
|
|
|
data-container="body"
|
|
|
|
>
|
|
|
|
{{ filePath }}
|
|
|
|
</strong>
|
2019-12-26 22:10:19 +05:30
|
|
|
<clipboard-button
|
|
|
|
:title="__('Copy file path')"
|
|
|
|
:text="filePath"
|
2020-01-01 13:55:28 +05:30
|
|
|
css-class="btn-default btn-transparent btn-clipboard position-static"
|
2019-12-26 22:10:19 +05:30
|
|
|
/>
|
2020-03-13 15:44:24 +05:30
|
|
|
<span v-html="errorInfo"></span>
|
2019-12-26 22:10:19 +05:30
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<table v-if="isExpanded" :class="$options.userColorScheme" class="code js-syntax-highlight">
|
|
|
|
<tbody>
|
|
|
|
<template v-for="(line, index) in lines">
|
|
|
|
<tr :key="`stacktrace-line-${index}`" class="line_holder">
|
|
|
|
<td class="diff-line-num" :class="{ old: isHighlighted(lineNum(line)) }">
|
|
|
|
{{ lineNum(line) }}
|
|
|
|
</td>
|
|
|
|
<td
|
|
|
|
class="line_content"
|
|
|
|
:class="{ old: isHighlighted(lineNum(line)) }"
|
|
|
|
v-html="lineCode(line)"
|
|
|
|
></td>
|
|
|
|
</tr>
|
|
|
|
</template>
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
</template>
|