Skip to content
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

Typescriptize reports files #5079

Merged
merged 16 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
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
29 changes: 28 additions & 1 deletion jsapp/js/actions.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,30 @@ interface SetAssetPublicCompletedDefinition extends Function {
listen: (callback: (assetUid: string, shouldSetAnonPerms: boolean) => void) => Function;
}

interface ReportsSetStyleDefinition extends Function {
(assetId: string, details: AssetResponseReportStyles): void;
listen: (callback: (assetId: string, details: AssetResponseReportStyles) => void) => Function;
completed: ReportsSetStyleCompletedDefinition;
failed: GenericFailedDefinition;
}

interface ReportsSetStyleCompletedDefinition extends Function {
(response: AssetResponse): void;
listen: (callback: (response: AssetResponse) => void) => Function;
}

interface ReportsSetCustomDefinition extends Function {
(assetId: string, details: {[crid: string]: CustomReport}, crid: string): void;
listen: (callback: (assetId: string, details: {[crid: string]: CustomReport}, crid: string) => void) => Function;
completed: ReportsSetCustomCompletedDefinition;
failed: GenericFailedDefinition;
}

interface ReportsSetCustomCompletedDefinition extends Function {
(response: AssetResponse): void;
listen: (callback: (response: AssetResponse, crid: string) => void) => Function;
}

// NOTE: as you use more actions in your ts files, please extend this namespace,
// for now we are defining only the ones we need.
export namespace actions {
Expand Down Expand Up @@ -196,7 +220,10 @@ export namespace actions {
const misc: {
getUser: GetUserDefinition;
};
const reports: object;
const reports: {
setStyle: ReportsSetStyleDefinition;
setCustom: ReportsSetCustomDefinition;
};
const table: {
updateSettings: TableUpdateSettingsDefinition;
};
Expand Down
6 changes: 3 additions & 3 deletions jsapp/js/actions.es6
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ actions.reports = Reflux.createActions({
}
});

actions.reports.setStyle.listen(function(assetId, details){
actions.reports.setStyle.listen((assetId, details) => {
dataInterface.patchAsset(assetId, {report_styles: details})
.done((asset) => {
actions.reports.setStyle.completed(asset);
Expand All @@ -268,10 +268,10 @@ actions.reports.setStyle.listen(function(assetId, details){
.fail(actions.reports.setStyle.failed);
});

actions.reports.setCustom.listen(function(assetId, details){
actions.reports.setCustom.listen((assetId, details, crid) => {
dataInterface.patchAsset(assetId, {report_custom: details})
.done((asset) => {
actions.reports.setCustom.completed(asset);
actions.reports.setCustom.completed(asset, crid);
actions.resources.updateAsset.completed(asset);
})
.fail(actions.reports.setCustom.failed);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,45 +1,74 @@
import React from 'react';
import autoBind from 'react-autobind';
import {KEY_CODES} from 'js/constants';
import bem from 'js/bem';
import classNames from 'classnames';
import Button from 'js/components/common/button';
import './modal.scss';

interface ModalPartialProps {
children?: React.ReactNode;
}

class Footer extends React.Component<ModalPartialProps> {
render() {
return (<bem.Modal__footer>{this.props.children}</bem.Modal__footer>);
}
}

class Body extends React.Component<ModalPartialProps> {
render() {
return (<bem.Modal__body>{this.props.children}</bem.Modal__body>);
}
}

class Tabs extends React.Component<ModalPartialProps> {
render() {
return <bem.Modal__tabs>{this.props.children}</bem.Modal__tabs>;
}
}

interface ModalProps {
onClose: () => void;
open: boolean;
children: React.ReactNode;
title: string;
icon?: string;
small?: boolean;
large?: boolean;
isDuplicated?: boolean;
disableEscClose?: boolean;
disableBackdropClose?: boolean;
customModalHeader?: React.ReactNode;
className?: string;
}

/**
* A generic modal component.
* DEPRECATED: please use `KoboModal`
*
* @prop {function} onClose
* @prop {string} title
* @prop {boolean} small
* @prop {boolean} isDuplicated
* @prop {string} className
* @prop {boolean} open
* @prop {boolean} large
* @prop {string} icon
* @prop {node} children
* A generic modal component.
*/
export default class Modal extends React.Component {
constructor(props) {
super(props);
autoBind(this);
}
export default class Modal extends React.Component<ModalProps> {
static Footer = Footer;
static Body = Body;
static Tabs = Tabs;

escFunctionBound = this.escFunction.bind(this);

componentDidMount() {
document.addEventListener('keydown', this.escFunction);
document.addEventListener('keydown', this.escFunctionBound);
}

componentWillUnmount() {
document.removeEventListener('keydown', this.escFunction);
document.removeEventListener('keydown', this.escFunctionBound);
}

escFunction(evt) {
escFunction(evt: KeyboardEvent) {
if (!this.props.disableEscClose && (evt.keyCode === KEY_CODES.ESC || evt.key === 'Escape')) {
this.props.onClose.call(evt);
}
}

backdropClick(evt) {
backdropClick(evt: TouchEvent) {
duvld marked this conversation as resolved.
Show resolved Hide resolved
if (evt.currentTarget === evt.target && !this.props.disableBackdropClose) {
this.props.onClose.call(evt);
}
Expand All @@ -64,7 +93,7 @@ export default class Modal extends React.Component {

renderClose() {
if (this.props.isDuplicated) {
return(
return (
<Button
type='text'
size='l'
Expand All @@ -73,7 +102,7 @@ export default class Modal extends React.Component {
/>
);
} else {
return(
return (
<a className='modal__x' type='button' onClick={this.props.onClose}>
<i className='k-icon k-icon-close'/>
</a>
Expand Down Expand Up @@ -109,44 +138,3 @@ export default class Modal extends React.Component {
);
}
}

/**
* @prop {node} children
*/
class Footer extends React.Component {
constructor(props) {
super(props);
}
render() {
return (<bem.Modal__footer>{this.props.children}</bem.Modal__footer>);
}
}
Modal.Footer = Footer;

/**
* @prop {node} children
*/
class Body extends React.Component {
constructor(props) {
super(props);
}

render() {
return (<bem.Modal__body>{this.props.children}</bem.Modal__body>);
}
}
Modal.Body = Body;

/**
* @prop {node} children
*/
class Tabs extends React.Component {
constructor(props) {
super(props);
}

render() {
return <bem.Modal__tabs>{this.props.children}</bem.Modal__tabs>;
}
}
Modal.Tabs = Tabs;
56 changes: 56 additions & 0 deletions jsapp/js/components/reports/chartColorsPicker.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react';
import bem from 'js/bem';
import {REPORT_COLOR_SETS} from './reportsConstants';
import type {ReportStyle, ReportColorSet} from './reportsConstants';

interface ChartColorsPickerProps {
onChange: (params: {default: boolean}, value: {report_colors: string[]}) => void;
defaultStyle: ReportStyle;
}

export default function ChartColorsPicker(props: ChartColorsPickerProps) {
duvld marked this conversation as resolved.
Show resolved Hide resolved
function defaultReportColorsChange(value: number) {
let newColors = REPORT_COLOR_SETS[0].colors;
if (REPORT_COLOR_SETS[value]?.colors) {
newColors = REPORT_COLOR_SETS[value].colors;
}

props.onChange({default: true}, {report_colors: newColors});
}

// Not sure why this is called "is default", and not simply "is active". This
// needs some more investigation.
duvld marked this conversation as resolved.
Show resolved Hide resolved
function isDefaultValue(set: ReportColorSet, index: number) {
if (props.defaultStyle.report_colors === undefined && index === 0) {
return true;
}

return (
JSON.stringify(props.defaultStyle.report_colors) ===
JSON.stringify(set.colors)
);
}

return (
<bem.GraphSettings__colors>
{REPORT_COLOR_SETS.map((set, index) => (
<bem.GraphSettings__radio key={index}>
<input
type='radio'
name='chart_colors'
value={index}
checked={isDefaultValue(set, index)}
onChange={() => defaultReportColorsChange(index)}
id={'type-' + set.label}
/>

<label htmlFor={'type-' + set.label}>
{REPORT_COLOR_SETS[index].colors.map((color, i) => (
<div style={{backgroundColor: color}} key={i} />
))}
</label>
</bem.GraphSettings__radio>
))}
</bem.GraphSettings__colors>
);
}
64 changes: 0 additions & 64 deletions jsapp/js/components/reports/chartColorsPicker.es6

This file was deleted.

11 changes: 3 additions & 8 deletions jsapp/js/components/reports/chartTypePicker.component.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
import React from 'react';
import {REPORT_STYLES} from './reportsConstants';
import type {ReportStyleName} from './reportsConstants';
import type {ReportStyle, ReportStyleName} from './reportsConstants';
import styles from './chartTypePicker.module.scss';

interface ChartTypePickerProps {
onChange: (
params: {default: boolean},
value: {report_type: ReportStyleName}
) => void;
defaultStyle: {
report_type: ReportStyleName;
};
onChange: (params: {default: boolean}, value: {report_type: ReportStyleName}) => void;
defaultStyle: ReportStyle;
}

export default function ChartTypePicker(props: ChartTypePickerProps) {
Expand Down
Loading
Loading