diff --git a/src/widgets/bulb_service.ts b/src/widgets/bulb_service.ts index a5c7107..df5bd28 100644 --- a/src/widgets/bulb_service.ts +++ b/src/widgets/bulb_service.ts @@ -155,29 +155,59 @@ export class BulbService { // const dataState: BulbService['statuses'] = {}; const rawCells: BulbService['statuses'] = {}; - for (const cell of cellInfo) { + + const keylist = ['cell_id', 'proofreading']; + const mappedResponse: any = {}; + for (let i = 0; i < cellInfo.length; i++) { + const cell = cellInfo[i]; if (cell.status === 'fulfilled') { - const raw = - await (<{status: string; value: any;}>cell).value.text(); - const data = JSONBS.parse(raw); - if (data.pt_root_id) { - const indicies = Object.keys(data.pt_root_id); - indicies.map((key: any) => { - const sid = data.pt_root_id[key]; - if (!rawCells[sid]) rawCells[sid] = this.statuses[sid]; - rawCells[sid].state = - Object.keys(data).reduce((prev: any, curr: string) => { - prev[curr] = data[curr][key]; - return prev; - }, rawCells[sid].state || {}); - const {tag, proofread} = rawCells[sid].state; - rawCells[sid].status = proofread === 't' ? - (tag ? 'complete' : 'unlabeled') : - 'incomplete'; - }); - } + mappedResponse[keylist[i]] = JSONBS.parse( + await (<{status: string; value: any;}>cell).value.text()); } } + + Object.entries(mappedResponse).forEach((pkvp: any) => { + const key = pkvp[0]; + const data = pkvp[1]; + + if (data.pt_root_id) { + const states: any = {}; + const props = Object.keys(data); + Object.entries(data.pt_root_id).forEach((kvp: any) => { + const obj: any = {}; + const sid = kvp[1]; + props.forEach((prop: string) => { + obj[prop] = data[prop][kvp[0]]; + }); + if (states[sid]) { + states[sid][key].push(obj); + } else { + states[sid] = {[key]: [obj]}; + } + }); + Object.entries(states).forEach((kvp: any) => { + const sid = kvp[0]; + const state: any = kvp[1]; + if (!rawCells[sid]) rawCells[sid] = this.statuses[sid]; + rawCells[sid].state = {...rawCells[sid].state, ...state}; + let tag = rawCells[sid].state.cell_id; + let proofread = rawCells[sid].state.proofreading; + if (tag && tag.length) { + tag = tag[tag.length - 1].tag; + } + if (proofread && proofread.length) { + proofread = proofread[proofread.length - 1].proofread; + } + + rawCells[sid].status = proofread === 't' ? + (tag ? 'complete' : 'unlabeled') : + 'incomplete'; + }); + } + }); + + + this.statuses = {...this.statuses, ...rawCells}; const values = Object.keys(rawCells); @@ -404,8 +434,8 @@ export class BulbService { handleDialogOpen, host, segmentIDString, currentTimeStamp, {...state, paramStr, linkTS}); - const {tag} = (state || {}); - let cellIDButtons = tag ? + const {cell_id} = (state || {}); + let cellIDButtons = cell_id && cell_id.length ? [ ['Details', 'blue', details[2]], ['Add New Identification', 'purple', identify[2]] diff --git a/src/widgets/cell_detail.ts b/src/widgets/cell_detail.ts index 3ef8605..b1ba4ce 100644 --- a/src/widgets/cell_detail.ts +++ b/src/widgets/cell_detail.ts @@ -102,7 +102,8 @@ export class CellDetailDialog extends Overlay { `No existing identification can be found for this cell.`, cancel); return; } - const {tag, paramStr, linkTS} = (this.stateInfo || {}); + const {cell_id, paramStr, linkTS} = (this.stateInfo || {}); + const tags = cell_id.sort((a: any, b: any) => b.created - a.created); const br = () => document.createElement('br'); const apiURL = `${this.host}/neurons/api/v1/cell_identification`; const sub = this.makeButton({ @@ -116,13 +117,35 @@ export class CellDetailDialog extends Overlay { } }); - if (tag) { + if (tags && tags.length > 0) { this.title.innerText = 'Cell Identification'; - this.infoField = - this.insertField({content: tag, type: 'textarea', disabled: true}); - this.infoField.classList.add('rounded-input', 'large'); + + this.description = document.createElement('table'); + /*let rows = + [{user_name: 'Marked by', tag: 'Cell Identification'}, ...tags];*/ + let rows = + [{created: 'Created', tag: 'Label', user_name: 'Marked by'}, ...tags]; + let thead = document.createElement('thead'); + let tbody = document.createElement('tbody'); + rows.forEach((tag: any, i: number) => { + const row = document.createElement('tr'); + const created = document.createElement(`${i ? 'td' : 'th'}`); + const user = document.createElement(`${i ? 'td' : 'th'}`); + const tagTD = document.createElement(`${i ? 'td' : 'th'}`); + created.innerText = i ? + (new Date(tag.created)).toLocaleString('en-US', {hour12: false}) : + tag.created; + user.innerText = tag.user_name; + tagTD.innerText = tag.tag; + row.append(created, tagTD, user); + (i ? tbody : thead).append(row); + }); + this.description.append(thead, tbody); + + this.description.classList.add( + 'rounded-input', 'large', 'cell_identification'); this.form.append( - this.title, this.infoField, br(), br(), sub, ' ', cancel); + this.title, this.description, br(), br(), sub, ' ', cancel); let modal = document.createElement('div'); this.content.appendChild(modal); diff --git a/src/widgets/cell_identification.css b/src/widgets/cell_identification.css index 1e30b8c..7be5b56 100644 --- a/src/widgets/cell_identification.css +++ b/src/widgets/cell_identification.css @@ -11,4 +11,23 @@ outline: none; background-color: transparent; color: white; -} \ No newline at end of file +} + +table.cell_identification.rounded-input.large { + border-collapse: collapse; + width: 600px; + height: 150px; + max-width: 600px; + max-height: 450px; +} + +.cell_identification td, .cell_identification th { + padding-left: 120px; +} +.cell_identification td:first-child, .cell_identification th:first-child { + padding-left: 0px; +} + +.cell_identification tbody tr{ + border-top: 1px solid #eeeeee77; +}