mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Convert a few widgets to typescript and grainjs.
Summary: No behavior changes. Diff includes an intermediate commit with only renames, for easier review. Test Plan: Existing tests should pass. Reviewers: paulfitz Reviewed By: paulfitz Differential Revision: https://phab.getgrist.com/D2669
This commit is contained in:
71
app/client/widgets/HyperLinkTextBox.ts
Normal file
71
app/client/widgets/HyperLinkTextBox.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import {DataRowModel} from 'app/client/models/DataRowModel';
|
||||
import {ViewFieldRec} from 'app/client/models/entities/ViewFieldRec';
|
||||
import {colors, testId} from 'app/client/ui2018/cssVars';
|
||||
import {icon} from 'app/client/ui2018/icons';
|
||||
import {NTextBox} from 'app/client/widgets/NTextBox';
|
||||
import {dom, styled} from 'grainjs';
|
||||
|
||||
/**
|
||||
* Creates a widget for displaying links. Links can entered directly or following a title.
|
||||
* The last entry following a space is used as the url.
|
||||
* ie 'google https://www.google.com' would apears as 'google' to the user but link to the url.
|
||||
*/
|
||||
export class HyperLinkTextBox extends NTextBox {
|
||||
constructor(field: ViewFieldRec) {
|
||||
super(field);
|
||||
}
|
||||
|
||||
public buildDom(row: DataRowModel) {
|
||||
const value = row.cells[this.field.colId()];
|
||||
return cssFieldClip(
|
||||
dom.style('text-align', this.alignment),
|
||||
dom.cls('text_wrapping', this.wrapping),
|
||||
dom.maybe(value, () =>
|
||||
dom('a',
|
||||
dom.attr('href', (use) => _constructUrl(use(value))),
|
||||
dom.attr('target', '_blank'),
|
||||
// As per Google and Mozilla recommendations to prevent opened links
|
||||
// from running on the same process as Grist:
|
||||
// https://developers.google.com/web/tools/lighthouse/audits/noopener
|
||||
dom.attr('rel', 'noopener noreferrer'),
|
||||
cssLinkIcon('FieldLink'),
|
||||
testId('tb-link')
|
||||
)
|
||||
),
|
||||
dom.text((use) => _formatValue(use(value))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats value like `foo bar baz` by discarding `baz` and returning `foo bar`.
|
||||
*/
|
||||
function _formatValue(value: string|null|undefined): string {
|
||||
if (typeof value !== 'string') { return ''; }
|
||||
const index = value.lastIndexOf(' ');
|
||||
return index >= 0 ? value.slice(0, index) : value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given value like `foo bar baz`, constructs URL by checking if `baz` is a valid URL and,
|
||||
* if not, prepending `http://`.
|
||||
*/
|
||||
function _constructUrl(value: string): string {
|
||||
const url = value.slice(value.lastIndexOf(' ') + 1);
|
||||
try {
|
||||
// Try to construct a valid URL
|
||||
return (new URL(url)).toString();
|
||||
} catch (e) {
|
||||
// Not a valid URL, so try to prefix it with http
|
||||
return 'http://' + url;
|
||||
}
|
||||
}
|
||||
|
||||
const cssFieldClip = styled('div.field_clip', `
|
||||
color: ${colors.lightGreen};
|
||||
`);
|
||||
|
||||
const cssLinkIcon = styled(icon, `
|
||||
background-color: ${colors.lightGreen};
|
||||
margin: -1px 2px 2px 0;
|
||||
`);
|
||||
Reference in New Issue
Block a user