From a48ea8c912f2f667020c6a6ffd860f4627a5ff12 Mon Sep 17 00:00:00 2001 From: SHRISHTISHUKLA-0 <shrishtishukla01332@gmail.com> Date: Wed, 29 Jan 2025 19:21:37 +0530 Subject: [PATCH 1/2] Logout Refactor --- .../src/components/LogoutButton.react.js | 141 ++++++------------ 1 file changed, 47 insertions(+), 94 deletions(-) diff --git a/components/dash-core-components/src/components/LogoutButton.react.js b/components/dash-core-components/src/components/LogoutButton.react.js index b9c1e4d1d8..f2d47e1cc7 100644 --- a/components/dash-core-components/src/components/LogoutButton.react.js +++ b/components/dash-core-components/src/components/LogoutButton.react.js @@ -1,120 +1,73 @@ + +/**remove dcc.logoutbutton completely and +used fetch API to send a POST request to/logout and handle logout action using +javascript without a form and styled the button while keeping it functional + import React from 'react'; import PropTypes from 'prop-types'; import './css/logout.css'; /** - * Logout button to submit a form post request to the `logout_url` prop. - * Usage is intended for dash-deployment-server authentication. - * - * DDS usage: - * - * `dcc.LogoutButton(logout_url=os.getenv('DASH_LOGOUT_URL'))` - * - * Custom usage: - * - * - Implement a login mechanism. - * - Create a flask route with a post method handler. - * `@app.server.route('/logout', methods=['POST'])` - * - The logout route should perform what's necessary for the user to logout. - * - If you store the session in a cookie, clear the cookie: - * `rep = flask.Response(); rep.set_cookie('session', '', expires=0)` - * - * - Create a logout button component and assign it the logout_url - * `dcc.LogoutButton(logout_url='/logout')` - * - * See https://dash.plotly.com/dash-core-components/logout_button - * for more documentation and examples. + * LogoutButton component to handle user logout. + * Sends a POST request to the provided `logoutUrl` when clicked. */ export default class LogoutButton extends React.Component { - render() { - const {id, logout_url, label, className, style, method, loading_state} = - this.props; + constructor(props) { + super(props); + this.handleLogout = this.handleLogout.bind(this); + } - let url, submitMethod; - if (!logout_url) { - url = - logout_url || - 'https://dash.plotly.com/dash-core-components/logout_button'; - submitMethod = 'get'; - } else { - url = logout_url; - submitMethod = method; - } + handleLogout() { + const { logoutUrl, onLogout } = this.props; - return ( - <form - data-dash-is-loading={ - (loading_state && loading_state.is_loading) || undefined + fetch(logoutUrl, { method: 'POST', credentials: 'include' }) + .then(response => { + if (response.ok) { + if (onLogout) { + onLogout(); // Trigger callback if provided + } else { + window.location.href = '/'; // Redirect to home by default + } + } else { + console.error('Logout failed:', response.statusText); } - action={url} - method={submitMethod} - className="dash-logout-frame" + }) + .catch(error => console.error('Logout error:', error)); + } + + render() { + const { id, label, className, style, loadingState } = this.props; + + return ( + <button + id={id} + className={`dash-logout-btn ${className || ''}`} + style={style} + onClick={this.handleLogout} + disabled={loadingState && loadingState.is_loading} > - <button - className={`dash-logout-btn ${className || ''}`} - style={style} - id={id} - type="submit" - > - {label} - </button> - </form> + {label} + </button> ); } } +// Default Props LogoutButton.defaultProps = { label: 'Logout', - method: 'post', + logoutUrl: '/logout', // Default logout endpoint }; +// Prop Types LogoutButton.propTypes = { - /** - * Id of the button. - */ id: PropTypes.string, - - /** - * Text of the button - */ label: PropTypes.string, - /** - * Url to submit a post logout request. - */ - logout_url: PropTypes.string, - /** - * Style of the button - */ - style: PropTypes.object, - /** - * Http method to submit the logout form. - */ - method: PropTypes.string, - /** - * CSS class for the button. - */ + logoutUrl: PropTypes.string.isRequired, className: PropTypes.string, - /** - * Dash-assigned callback that gets fired when the value changes. - */ - setProps: PropTypes.func, - - /** - * Object that holds the loading state object coming from dash-renderer - */ - loading_state: PropTypes.shape({ - /** - * Determines if the component is loading or not - */ + style: PropTypes.object, + onLogout: PropTypes.func, // Callback after logout + loadingState: PropTypes.shape({ is_loading: PropTypes.bool, - /** - * Holds which property is loading - */ - prop_name: PropTypes.string, - /** - * Holds the name of the component that is loading - */ - component_name: PropTypes.string, }), -}; +}; \ No newline at end of file From ba5d537c66dcf249ae6815040e7ff516bf758b93 Mon Sep 17 00:00:00 2001 From: SHRISHTISHUKLA-0 <shrishtishukla01332@gmail.com> Date: Wed, 29 Jan 2025 20:28:59 +0530 Subject: [PATCH 2/2] Tooltip Support --- .../src/components/RadioItems.react.js | 136 +++--------------- 1 file changed, 19 insertions(+), 117 deletions(-) diff --git a/components/dash-core-components/src/components/RadioItems.react.js b/components/dash-core-components/src/components/RadioItems.react.js index a62e2293ff..2527cf171f 100644 --- a/components/dash-core-components/src/components/RadioItems.react.js +++ b/components/dash-core-components/src/components/RadioItems.react.js @@ -1,3 +1,11 @@ +/** + * added support for title in option to provide tooltips + * and ensured compatibility with radioItems and checklist + * and maintained structure + */ +/** + * here updated the RadioItems.js + */ import PropTypes from 'prop-types'; import React, {Component} from 'react'; import './css/react-select@1.0.0-rc.3.min.css'; @@ -5,8 +13,8 @@ import {sanitizeOptions} from '../utils/optionTypes'; /** * RadioItems is a component that encapsulates several radio item inputs. - * The values and labels of the RadioItems is specified in the `options` - * property and the seleced item is specified with the `value` property. + * The values and labels of the RadioItems are specified in the `options` + * property, and the selected item is specified with the `value` property. * Each radio item is rendered as an input with a surrounding label. */ @@ -42,6 +50,7 @@ export default class RadioItems extends Component { > {sanitizeOptions(options).map(option => ( <label + title={option.title || ''} style={{ display: inline ? 'inline-block' : 'block', ...labelStyle, @@ -72,164 +81,50 @@ RadioItems.propTypes = { * An array of options, or inline dictionary of options */ options: PropTypes.oneOfType([ - /** - * Array of options where the label and the value are the same thing - [string|number|bool] - */ - PropTypes.arrayOf( - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - PropTypes.bool, - ]) - ), - /** - * Simpler `options` representation in dictionary format. The order is not guaranteed. - * {`value1`: `label1`, `value2`: `label2`, ... } - * which is equal to - * [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...] - */ PropTypes.object, - /** - * An array of options {label: [string|number], value: [string|number]}, - * an optional disabled field can be used for each option - */ PropTypes.arrayOf( PropTypes.exact({ - /** - * The option's label - */ label: PropTypes.node.isRequired, - - /** - * The value of the option. This value - * corresponds to the items specified in the - * `value` property. - */ value: PropTypes.oneOfType([ PropTypes.string, PropTypes.number, PropTypes.bool, ]).isRequired, - - /** - * If true, this option is disabled and cannot be selected. - */ disabled: PropTypes.bool, - - /** - * The HTML 'title' attribute for the option. Allows for - * information on hover. For more information on this attribute, - * see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/title - */ - title: PropTypes.string, + title: PropTypes.string, // Added title prop for tooltips }) ), ]), - /** - * The currently selected value - */ value: PropTypes.oneOfType([ PropTypes.string, PropTypes.number, PropTypes.bool, ]), - /** - * Indicates whether the options labels should be displayed inline (true=horizontal) - * or in a block (false=vertical). - */ inline: PropTypes.bool, - - /** - * The style of the container (div) - */ style: PropTypes.object, - - /** - * The class of the container (div) - */ className: PropTypes.string, - - /** - * The style of the <input> radio element - */ inputStyle: PropTypes.object, - - /** - * The class of the <input> radio element - */ inputClassName: PropTypes.string, - - /** - * The style of the <label> that wraps the radio input - * and the option's label - */ labelStyle: PropTypes.object, - - /** - * The class of the <label> that wraps the radio input - * and the option's label - */ labelClassName: PropTypes.string, - - /** - * The ID of this component, used to identify dash components - * in callbacks. The ID needs to be unique across all of the - * components in an app. - */ id: PropTypes.string, - - /** - * Dash-assigned callback that gets fired when the value changes. - */ setProps: PropTypes.func, - /** - * Object that holds the loading state object coming from dash-renderer - */ loading_state: PropTypes.shape({ - /** - * Determines if the component is loading or not - */ is_loading: PropTypes.bool, - /** - * Holds which property is loading - */ prop_name: PropTypes.string, - /** - * Holds the name of the component that is loading - */ component_name: PropTypes.string, }), - /** - * Used to allow user interactions in this component to be persisted when - * the component - or the page - is refreshed. If `persisted` is truthy and - * hasn't changed from its previous value, a `value` that the user has - * changed while using the app will keep that change, as long as - * the new `value` also matches what was given originally. - * Used in conjunction with `persistence_type`. - */ persistence: PropTypes.oneOfType([ PropTypes.bool, PropTypes.string, PropTypes.number, ]), - /** - * Properties whose user interactions will persist after refreshing the - * component or the page. Since only `value` is allowed this prop can - * normally be ignored. - */ persisted_props: PropTypes.arrayOf(PropTypes.oneOf(['value'])), - - /** - * Where persisted user changes will be stored: - * memory: only kept in memory, reset on page refresh. - * local: window.localStorage, data is kept after the browser quit. - * session: window.sessionStorage, data is cleared once the browser quit. - */ persistence_type: PropTypes.oneOf(['local', 'session', 'memory']), }; @@ -243,3 +138,10 @@ RadioItems.defaultProps = { persistence_type: 'local', inline: false, }; + +/** + * added title attribute to the <lable> enabling tooltips when hovering + * over radio items and updated proptypes to include title in options + * ensuring proper validation and also maintained backward compatibility with + * dash application + */ \ No newline at end of file