2021-05-12 14:34:49 +00:00
|
|
|
import {DataRowModel} from 'app/client/models/DataRowModel';
|
2021-07-08 21:35:16 +00:00
|
|
|
import {colors, testId} from 'app/client/ui2018/cssVars';
|
|
|
|
import {
|
|
|
|
ChoiceOptionsByName,
|
|
|
|
ChoiceTextBox,
|
|
|
|
} from 'app/client/widgets/ChoiceTextBox';
|
2021-05-12 21:00:55 +00:00
|
|
|
import {CellValue} from 'app/common/DocActions';
|
2021-05-12 14:34:49 +00:00
|
|
|
import {decodeObject} from 'app/plugin/objtypes';
|
|
|
|
import {Computed, dom, styled} from 'grainjs';
|
2021-07-15 15:50:28 +00:00
|
|
|
import {choiceToken} from 'app/client/widgets/ChoiceToken';
|
2021-05-12 14:34:49 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* ChoiceListCell - A cell that renders a list of choice tokens.
|
|
|
|
*/
|
|
|
|
export class ChoiceListCell extends ChoiceTextBox {
|
|
|
|
private _choiceSet = Computed.create(this, this.getChoiceValues(), (use, values) => new Set(values));
|
|
|
|
|
|
|
|
public buildDom(row: DataRowModel) {
|
|
|
|
const value = row.cells[this.field.colId.peek()];
|
|
|
|
|
|
|
|
return cssChoiceList(
|
|
|
|
dom.cls('field_clip'),
|
|
|
|
cssChoiceList.cls('-wrap', this.wrapping),
|
2021-07-08 21:35:16 +00:00
|
|
|
dom.style('justify-content', use => use(this.alignment) === 'right' ? 'flex-end' : use(this.alignment)),
|
2021-05-12 21:00:55 +00:00
|
|
|
dom.domComputed((use) => {
|
2021-07-08 21:35:16 +00:00
|
|
|
return use(row._isAddRow) ? null :
|
|
|
|
[
|
|
|
|
use(value), use(this._choiceSet),
|
|
|
|
use(this.getChoiceOptions())
|
|
|
|
] as [CellValue, Set<string>, ChoiceOptionsByName];
|
2021-05-12 21:00:55 +00:00
|
|
|
}, (input) => {
|
2021-05-12 14:34:49 +00:00
|
|
|
if (!input) { return null; }
|
2021-07-08 21:35:16 +00:00
|
|
|
const [rawValue, choiceSet, choiceOptionsByName] = input;
|
2021-05-12 14:34:49 +00:00
|
|
|
const val = decodeObject(rawValue);
|
|
|
|
if (!val) { return null; }
|
|
|
|
// Handle any unexpected values we might get (non-array, or array with non-strings).
|
|
|
|
const tokens: unknown[] = Array.isArray(val) ? val : [val];
|
|
|
|
return tokens.map(token =>
|
2021-07-15 15:50:28 +00:00
|
|
|
choiceToken(
|
|
|
|
String(token),
|
|
|
|
choiceOptionsByName.get(String(token)) || {},
|
|
|
|
cssInvalidToken.cls('-invalid', !choiceSet.has(String(token))),
|
|
|
|
dom.cls(cssToken.className),
|
|
|
|
testId('choice-list-cell-token')
|
|
|
|
)
|
2021-05-12 14:34:49 +00:00
|
|
|
);
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-23 15:29:35 +00:00
|
|
|
export const cssChoiceList = styled('div', `
|
2021-05-12 14:34:49 +00:00
|
|
|
display: flex;
|
2022-01-20 02:35:33 +00:00
|
|
|
align-content: start;
|
2021-05-12 14:34:49 +00:00
|
|
|
align-items: start;
|
|
|
|
padding: 0 3px;
|
|
|
|
|
|
|
|
position: relative;
|
|
|
|
min-height: 22px;
|
|
|
|
|
|
|
|
&-wrap {
|
|
|
|
flex-wrap: wrap;
|
|
|
|
}
|
|
|
|
`);
|
|
|
|
|
2021-07-23 15:29:35 +00:00
|
|
|
export const cssToken = styled('div', `
|
2021-05-12 14:34:49 +00:00
|
|
|
flex: 0 1 auto;
|
|
|
|
min-width: 0px;
|
|
|
|
margin: 2px;
|
|
|
|
line-height: 16px;
|
|
|
|
`);
|
|
|
|
|
|
|
|
export const cssInvalidToken = styled('div', `
|
|
|
|
&-invalid {
|
|
|
|
background-color: white !important;
|
|
|
|
box-shadow: inset 0 0 0 1px var(--grist-color-error);
|
|
|
|
color: ${colors.slate};
|
|
|
|
}
|
|
|
|
`);
|