|
40 | 40 | <!-- Logs --> |
41 | 41 | <div class="ui tab modal-tab" data-tab="{admin_: submission.admin}logs" hide="{opts.hide_output}"> |
42 | 42 | <div class="ui top attached inverted pointing menu" if="{logTabs.length > 0}"> |
43 | | - <div each="{tab in logTabs}" |
44 | | - class="submission-modal item {active: tab.fullTabId === activeLogTabId}" |
45 | | - data-tab="{tab.fullTabId}" |
46 | | - onclick="{() => { activeLogTabId = tab.fullTabId }}"> |
| 43 | + <div each="{tab, i in logTabs}" |
| 44 | + class="submission-modal item {active: i === 0}" |
| 45 | + data-tab="{tab.fullTabId}"> |
47 | 46 | {tab.label} |
48 | 47 | </div> |
49 | 48 | </div> |
|
52 | 51 | <pre class="empty">No logs available for this submission.</pre> |
53 | 52 | </div> |
54 | 53 | <!-- Dynamic tabs --> |
55 | | - <div each="{tab in logTabs}" |
56 | | - class="ui bottom attached inverted segment tab log {active: tab.fullTabId === activeLogTabId}" |
| 54 | + <div each="{tab, i in logTabs}" |
| 55 | + class="ui bottom attached inverted segment tab log {active: i === 0}" |
57 | 56 | data-tab="{tab.fullTabId}"> |
58 | | - <pre class="{empty: isEmpty(tab.content)}">{ showLog(tab.content) }</pre> |
| 57 | + <pre class="{empty: is_empty(tab.content)}">{ show_log(tab.content) }</pre> |
59 | 58 | </div> |
60 | 59 | </div> |
61 | 60 | <!-- Fact sheet --> |
|
82 | 81 | self.columns = [] |
83 | 82 |
|
84 | 83 | // Logs helpers |
85 | | - self.nonEmpty = (v) => !self.isEmpty(v) |
86 | | - self.showLog = (v) => self.nonEmpty(v) ? self.normalizeLog(v) : "No logs for this tab." |
| 84 | + self.non_empty = (v) => !self.is_empty(v) |
| 85 | + self.show_log = (v) => self.non_empty(v) ? self.normalizeLog(v) : "No logs for this tab." |
87 | 86 | self.normalizeLog = (v) => { |
88 | 87 | if (v == null) return v |
89 | 88 | if (Array.isArray(v)) return v.join('\n') |
|
92 | 91 | } |
93 | 92 | return String(v) |
94 | 93 | } |
95 | | - self.isEmpty = (v) => { |
| 94 | + self.is_empty = (v) => { |
96 | 95 | v = self.normalizeLog(v) |
97 | 96 | return v == null || (typeof v === "string" && v.trim().length === 0) |
98 | 97 | } |
99 | 98 |
|
100 | 99 | // Dynamic tabs state |
101 | 100 | self.logTabs = [] |
102 | | - self.activeLogTabId = null |
103 | 101 |
|
104 | | - self.rebuildLogTabs = () => { |
| 102 | + self.rebuild_log_tabs = () => { |
105 | 103 | const prefix = self.submission && self.submission.admin ? 'admin_' : '' |
106 | 104 | const candidates = [ |
107 | 105 | { key:'p_stdout', label:'Prediction output', content: self.logs.prediction_stdout }, |
|
116 | 114 |
|
117 | 115 | // Keep only non empty tabs |
118 | 116 | self.logTabs = candidates |
119 | | - .filter(t => !self.isEmpty(t.content)) |
| 117 | + .filter(t => !self.is_empty(t.content)) |
120 | 118 | .map(t => ({ |
121 | 119 | ...t, |
122 | 120 | fullTabId: `${prefix}${t.key}` |
123 | 121 | })) |
124 | | - // Select a valid tab as active |
125 | | - const stillValid = self.logTabs.find(t => t.fullTabId === self.activeLogTabId) |
126 | | - if (!stillValid) { |
127 | | - self.activeLogTabId = self.logTabs.length ? self.logTabs[0].fullTabId : null |
128 | | - } |
129 | 122 | } |
130 | 123 |
|
131 | 124 | self.get_score_details = function (column) { |
|
140 | 133 | } |
141 | 134 | self.update_submission_details = () => { |
142 | 135 | self.logs = {} |
143 | | - self.rebuildLogTabs() |
| 136 | + self.rebuild_log_tabs() |
144 | 137 | self.update() |
145 | 138 | CODALAB.api.get_submission_details(self.submission.id) |
146 | 139 | .done(function (data) { |
|
151 | 144 | self.detailed_result = data.detailed_result |
152 | 145 | self.fact_sheet_answers = data.fact_sheet_answers |
153 | 146 |
|
154 | | - _.forEach(data.logs, (item) => { |
155 | | - $.get(item.data_file) |
156 | | - .done(function (content) { |
157 | | - self.logs[item.name] = content |
158 | | - self.rebuildLogTabs() |
159 | | - self.update() |
160 | | - setTimeout(() => { |
161 | | - //$(self.root).find('.ui.top.attached.menu .item').tab() |
162 | | - $('.ui.top.attached.menu .item').tab() |
163 | | - }, 0) |
164 | | - }) |
| 147 | + const requests = data.logs.map(item => |
| 148 | + $.get(item.data_file) |
| 149 | + .done(content => { self.logs[item.name] = content }) |
| 150 | + .fail(() => { self.logs[item.name] = "" }) |
| 151 | + ) |
| 152 | + // When all log files are done loading: |
| 153 | + $.when.apply($, requests).always(() => { |
| 154 | + self.rebuild_log_tabs() |
| 155 | + self.update() |
| 156 | + setTimeout(() => { |
| 157 | + const $items = $(self.root).find('.ui.top.attached.menu .item') |
| 158 | + $items.tab() |
| 159 | + // pick the first tab deterministically |
| 160 | + if (self.logTabs.length) { |
| 161 | + $items.tab('change tab', self.logTabs[0].fullTabId) |
| 162 | + } |
| 163 | + }, 0) |
165 | 164 | }) |
166 | | - self.rebuildLogTabs() |
| 165 | + self.rebuild_log_tabs() |
167 | 166 | self.update() |
168 | 167 | if (self.submission.admin) { |
169 | 168 | _.forEach(data.leaderboards, (leaderboard) => { |
|
0 commit comments