Skip to content

Master 2.15.0 #2739

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 53 commits into from
Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
3532997
Added triggered_id to clientside callbacks
AnnMarieW Nov 18, 2023
250e1b5
added changelog for 2695
AnnMarieW Nov 18, 2023
2521ee8
lint
AnnMarieW Nov 18, 2023
e53291b
fix for tests
AnnMarieW Nov 18, 2023
81da7bf
rerun tests
AnnMarieW Nov 18, 2023
09fb52b
Update callbacks.ts
AnnMarieW Nov 22, 2023
a846f53
Merge branch 'dev' into clientside-triggered_id
AnnMarieW Dec 1, 2023
81fd848
rerun tests
AnnMarieW Dec 1, 2023
2153a68
Merge pull request #2695 from AnnMarieW/clientside-triggered_id
alexcjohnson Dec 1, 2023
b9c9270
Allow Clipboard to respond to new content directly
Lxstr Sep 29, 2023
73747c8
Test clipboard to respond to new content directly
Lxstr Oct 3, 2023
2ccde16
Clipboard support for text/html MIME type
Lxstr Oct 3, 2023
2ffada3
Copy of n_clicks change
Lxstr Dec 10, 2023
44639eb
Tests update
Lxstr Dec 14, 2023
7e1b45d
Fix test
Lxstr Dec 16, 2023
9469c58
Changelog
Lxstr Dec 16, 2023
7527383
Merge pull request #2652 from Lxstr/feature/clipboard-html
alexcjohnson Dec 16, 2023
7bbd493
Remove ansi2html.
T4rk1n Jan 8, 2024
70a651b
Lock mimesis<=11.1.0
T4rk1n Jan 8, 2024
cc62bb8
Update changelog
T4rk1n Jan 9, 2024
baa9a6d
Use NoColor Ipython formatted stacktrace.
T4rk1n Jan 9, 2024
0ebc553
build
T4rk1n Jan 9, 2024
000ec18
Merge pull request #2721 from plotly/remove-ansi2html
T4rk1n Jan 9, 2024
0ca1b94
Add Slider/RangeSlider tooltip.format and tooltip.style.
T4rk1n Jan 10, 2024
45e8aa8
Update changelog.
T4rk1n Jan 11, 2024
073775c
Update changelog.
T4rk1n Jan 12, 2024
936bde3
Sanitize html props with xss vulnerability.
T4rk1n Jan 24, 2024
66b3b7e
Lint fix.
T4rk1n Jan 24, 2024
98c7aae
Allow img src
T4rk1n Jan 24, 2024
5bd2c70
Put back html react 16 in dev deps.
T4rk1n Jan 24, 2024
33b79b5
Remove href from omitted props.
T4rk1n Jan 25, 2024
d3e2d18
destructure newProps to get _dash_error.
T4rk1n Jan 25, 2024
0fcdd41
Audit fix.
T4rk1n Jan 25, 2024
0d63b0b
Update components deps.
T4rk1n Jan 25, 2024
6bdd256
Fix dash-table typescript errors.
T4rk1n Jan 25, 2024
714ff86
Update changelog.
T4rk1n Jan 25, 2024
86bd8a3
chokidar fix.
T4rk1n Jan 25, 2024
70948c0
Remove old Link comment.
T4rk1n Jan 30, 2024
737cfd9
build
T4rk1n Jan 30, 2024
f4ea5e4
Update components/dash-core-components/src/components/RangeSlider.rea…
T4rk1n Jan 30, 2024
cd9c523
Rename format -> template.
T4rk1n Jan 30, 2024
f1fc2e0
build
T4rk1n Jan 30, 2024
9920073
Merge pull request #2732 from plotly/fix/xss-props
T4rk1n Jan 30, 2024
638abf1
Merge branch 'dev' into slider-tips
T4rk1n Jan 30, 2024
06fb03a
docstring typos
alexcjohnson Jan 30, 2024
49ac14f
Merge pull request #2723 from plotly/slider-tips
T4rk1n Jan 31, 2024
27751a8
Version 2.15.0
T4rk1n Jan 31, 2024
da4261e
Fix changelog.
T4rk1n Jan 31, 2024
7cb6f07
build
T4rk1n Jan 31, 2024
6a8da52
Merge pull request #2737 from plotly/version-2.15.0
T4rk1n Jan 31, 2024
78d07c4
Merge branch 'dev' into master-2.15.0
T4rk1n Jan 31, 2024
83c5422
Version 2.15.0 build artifacts
T4rk1n Jan 31, 2024
9243f93
build
T4rk1n Jan 31, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@
All notable changes to `dash` will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/).

## [2.15.0] - 2024-01-31

## Added
- [#2695](https://github.com/plotly/dash/pull/2695) Adds `triggered_id` to `dash_clientside.callback_context`. Fixes [#2692](https://github.com/plotly/dash/issues/2692)
- [#2723](https://github.com/plotly/dash/pull/2723) Improve dcc Slider/RangeSlider tooltips. Fixes [#1846](https://github.com/plotly/dash/issues/1846)
- Add `tooltip.template` a string for the format template, {value} will be formatted with the actual value.
- Add `tooltip.style` a style object to give to the div of the tooltip.
- Add `tooltip.transform` a reference to a function in the `window.dccFunctions` namespace.
- [#2732](https://github.com/plotly/dash/pull/2732) Add special key `_dash_error` to `setProps`, allowing component developers to send error without throwing in render. Usage `props.setProps({_dash_error: new Error("custom error")})`

## Fixed

- [#2732](https://github.com/plotly/dash/pull/2732) Sanitize html props that are vulnerable to xss vulnerability if user data is inserted. Fix Validate url to prevent XSS attacks [#2729](https://github.com/plotly/dash/issues/2729)

## Changed
- [#2652](https://github.com/plotly/dash/pull/2652) dcc.Clipboard supports htm_content and triggers a copy to clipboard when n_clicks are changed
- [#2721](https://github.com/plotly/dash/pull/2721) Remove ansi2html, fixes [#2613](https://github.com/plotly/dash/issues/2713)

## [2.14.2] - 2023-11-27

## Fixed
Expand Down
5,101 changes: 2,953 additions & 2,148 deletions components/dash-core-components/package-lock.json

Large diffs are not rendered by default.

16 changes: 9 additions & 7 deletions components/dash-core-components/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dash-core-components",
"version": "2.12.1",
"version": "2.13.0",
"description": "Core component suite for Dash",
"repository": {
"type": "git",
Expand Down Expand Up @@ -35,6 +35,7 @@
"maintainer": "Alex Johnson <[email protected]>",
"license": "MIT",
"dependencies": {
"@braintree/sanitize-url": "^7.0.0",
"@fortawesome/fontawesome-svg-core": "1.2.36",
"@fortawesome/free-regular-svg-icons": "^5.15.4",
"@fortawesome/free-solid-svg-icons": "^5.15.4",
Expand All @@ -49,7 +50,7 @@
"moment": "^2.29.4",
"node-polyfill-webpack-plugin": "^2.0.1",
"prop-types": "^15.8.1",
"ramda": "^0.29.0",
"ramda": "^0.29.1",
"rc-slider": "^9.7.5",
"react-addons-shallow-compare": "^15.6.3",
"react-dates": "^21.8.0",
Expand All @@ -64,11 +65,11 @@
"uniqid": "^5.4.0"
},
"devDependencies": {
"@babel/cli": "^7.23.0",
"@babel/core": "^7.23.0",
"@babel/cli": "^7.23.4",
"@babel/core": "^7.23.7",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/preset-env": "^7.22.20",
"@babel/preset-react": "^7.22.15",
"@babel/preset-env": "^7.23.8",
"@babel/preset-react": "^7.23.3",
"@plotly/dash-component-plugins": "^1.2.3",
"@plotly/webpack-dash-dynamic-import": "^1.3.0",
"babel-loader": "^9.1.3",
Expand All @@ -88,9 +89,10 @@
"react-jsx-parser": "1.21.0",
"style-loader": "^3.3.3",
"styled-jsx": "^3.4.4",
"webpack": "^5.88.2",
"webpack": "^5.90.0",
"webpack-cli": "^5.1.4"
},
"optionalDependencies": { "fsevents": "*" },
"files": [
"/dash_core_components/*{.js,.map}",
"/lib/"
Expand Down
55 changes: 45 additions & 10 deletions components/dash-core-components/src/components/Clipboard.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export default class Clipboard extends React.Component {
constructor(props) {
super(props);
this.copyToClipboard = this.copyToClipboard.bind(this);
this.onClickHandler = this.onClickHandler.bind(this);
this.copySuccess = this.copySuccess.bind(this);
this.getTargetText = this.getTargetText.bind(this);
this.loading = this.loading.bind(this);
Expand All @@ -26,6 +27,22 @@ export default class Clipboard extends React.Component {
};
}

onClickHandler() {
this.props.setProps({n_clicks: this.props.n_clicks + 1});
}

componentDidUpdate(prevProps) {
// If the clicks has not changed, do nothing
if (
!this.props.n_clicks ||
this.props.n_clicks === prevProps.n_clicks
) {
return;
}
// If the clicks has changed, copy to clipboard
this.copyToClipboard();
}

// stringifies object ids used in pattern matching callbacks
stringifyId(id) {
if (typeof id !== 'object') {
Expand All @@ -38,9 +55,23 @@ export default class Clipboard extends React.Component {
return '{' + parts.join(',') + '}';
}

async copySuccess(content) {
async copySuccess(content, htmlContent) {
const showCopiedIcon = 1000;
await clipboardAPI.writeText(content);
if (htmlContent) {
const blobHtml = new Blob([htmlContent], {type: 'text/html'});
const blobText = new Blob([content ?? htmlContent], {
type: 'text/plain',
});
const data = [
new ClipboardItem({
['text/plain']: blobText,
['text/html']: blobHtml,
}),
];
await navigator.clipboard.write(data);
} else {
await clipboardAPI.writeText(content);
}
this.setState({copied: true});
await wait(showCopiedIcon);
this.setState({copied: false});
Expand Down Expand Up @@ -71,20 +102,18 @@ export default class Clipboard extends React.Component {
}

async copyToClipboard() {
this.props.setProps({
n_clicks: this.props.n_clicks + 1,
});

let content;
let htmlContent;
if (this.props.target_id) {
content = this.getTargetText();
} else {
await wait(100); // gives time for callback to start
await this.loading();
content = this.props.content;
htmlContent = this.props.html_content;
}
if (content) {
this.copySuccess(content);
if (content || htmlContent) {
this.copySuccess(content, htmlContent);
}
}

Expand All @@ -106,7 +135,7 @@ export default class Clipboard extends React.Component {
title={title}
style={style}
className={className}
onClick={this.copyToClipboard}
onClick={this.onClickHandler}
data-dash-is-loading={
(loading_state && loading_state.is_loading) || undefined
}
Expand All @@ -119,6 +148,7 @@ export default class Clipboard extends React.Component {

Clipboard.defaultProps = {
content: null,
html_content: null,
target_id: null,
n_clicks: 0,
};
Expand All @@ -137,7 +167,7 @@ Clipboard.propTypes = {
target_id: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),

/**
* The text to be copied to the clipboard if the `target_id` is None.
* The text to be copied to the clipboard if the `target_id` is None.
*/
content: PropTypes.string,

Expand All @@ -146,6 +176,11 @@ Clipboard.propTypes = {
*/
n_clicks: PropTypes.number,

/**
* The clipboard html text be copied to the clipboard if the `target_id` is None.
*/
html_content: PropTypes.string,

/**
* The text shown as a tooltip when hovering over the copy icon.
*/
Expand Down
93 changes: 47 additions & 46 deletions components/dash-core-components/src/components/Link.react.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import PropTypes from 'prop-types';

import React, {Component} from 'react';

import React, {useEffect, useMemo} from 'react';
import {sanitizeUrl} from '@braintree/sanitize-url';
import {isNil} from 'ramda';

/*
Expand Down Expand Up @@ -33,15 +33,23 @@ CustomEvent.prototype = window.Event.prototype;
* For links with destinations outside the current app, `html.A` is a better
* component to use.
*/
export default class Link extends Component {
constructor(props) {
super(props);
this.updateLocation = this.updateLocation.bind(this);
}
const Link = props => {
const {
className,
style,
id,
href,
loading_state,
children,
title,
target,
refresh,
setProps,
} = props;
const sanitizedUrl = useMemo(() => sanitizeUrl(href), [href]);

updateLocation(e) {
const updateLocation = e => {
const hasModifiers = e.metaKey || e.shiftKey || e.altKey || e.ctrlKey;
const {href, refresh, target} = this.props;

if (hasModifiers) {
return;
Expand All @@ -52,49 +60,40 @@ export default class Link extends Component {
// prevent anchor from updating location
e.preventDefault();
if (refresh) {
window.location = href;
window.location = sanitizedUrl;
} else {
window.history.pushState({}, '', href);
window.history.pushState({}, '', sanitizedUrl);
window.dispatchEvent(new CustomEvent('_dashprivate_pushstate'));
}
// scroll back to top
window.scrollTo(0, 0);
}
};

render() {
const {
className,
style,
id,
href,
loading_state,
children,
title,
target,
} = this.props;
/*
* ideally, we would use cloneElement however
* that doesn't work with dash's recursive
* renderTree implementation for some reason
*/
return (
<a
data-dash-is-loading={
(loading_state && loading_state.is_loading) || undefined
}
id={id}
className={className}
style={style}
href={href}
onClick={e => this.updateLocation(e)}
title={title}
target={target}
>
{isNil(children) ? href : children}
</a>
);
}
}
useEffect(() => {
if (sanitizedUrl !== href) {
setProps({
_dash_error: new Error(`Dangerous link detected:: ${href}`),
});
}
}, [href, sanitizedUrl]);

return (
<a
data-dash-is-loading={
(loading_state && loading_state.is_loading) || undefined
}
id={id}
className={className}
style={style}
href={sanitizedUrl}
onClick={updateLocation}
title={title}
target={target}
>
{isNil(children) ? sanitizedUrl : children}
</a>
);
};

Link.propTypes = {
/**
Expand Down Expand Up @@ -151,8 +150,10 @@ Link.propTypes = {
*/
component_name: PropTypes.string,
}),
setProps: PropTypes.func,
};

Link.defaultProps = {
refresh: false,
};
export default Link;
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,31 @@ RangeSlider.propTypes = {
'bottomLeft',
'bottomRight',
]),
/**
* Template string to display the tooltip in.
* Must contain `{value}`, which will be replaced with either
* the default string representation of the value or the result of the
* transform function if there is one.
*/
template: PropTypes.string,
/**
* Custom style for the tooltip.
*/
style: PropTypes.object,
/**
* Reference to a function in the `window.dccFunctions` namespace.
* This can be added in a script in the asset folder.
*
* For example, in `assets/tooltip.js`:
* ```
* window.dccFunctions = window.dccFunctions || {};
* window.dccFunctions.multByTen = function(value) {
* return value * 10;
* }
* ```
* Then in the component `tooltip={'transform': 'multByTen'}`
*/
transform: PropTypes.string,
}),

/**
Expand Down
Loading