Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
a54b115
Convert Answer view components from JavaScript to TypeScript
claude Nov 15, 2025
b6abade
Convert Answer and User view components from JavaScript to TypeScript
claude Nov 15, 2025
01c5557
Convert Records and SiteMap view components from JavaScript to TypeSc…
claude Nov 15, 2025
758c45e
Convert Record components from JavaScript to TypeScript (batch 4)
claude Nov 15, 2025
8eca020
Fix TypeScript type errors in converted files
claude Nov 15, 2025
9849d16
Convert Favorites, Record, and Reporter components to TypeScript (bat…
claude Nov 15, 2025
a26799c
Convert Core, Reporter, and AttributeFilter components to TypeScript …
claude Nov 15, 2025
7ed0869
Convert AttributeFilter components to TypeScript (batch 7)
claude Nov 15, 2025
6641dd8
Convert AttributeFilter components to TypeScript (batch 8)
claude Nov 15, 2025
edb5e4e
Convert AttributeFilter components to TypeScript (batch 9)
claude Nov 15, 2025
1d5143a
Convert remaining components to TypeScript (batch 10 - final)
claude Nov 15, 2025
9a72e10
Fix TypeScript compilation errors in converted files
claude Nov 15, 2025
1d64f2d
Fix remaining TypeScript compilation errors
claude Nov 15, 2025
aca1ea6
Fix Histogram duplicate identifier errors
claude Nov 15, 2025
b660efe
Fix TypeScript compilation errors in AttributeFilter, Date components…
claude Nov 15, 2025
a662a29
Fix additional Histogram type errors
claude Nov 15, 2025
147dc30
Fix Core/main.ts TypeScript errors
claude Nov 15, 2025
c333af1
Fix AttributeFilter TypeScript errors
claude Nov 15, 2025
2725dd7
Fix RecordUI TypeScript errors
claude Nov 15, 2025
c0a4a11
Fix additional TypeScript errors
claude Nov 15, 2025
2946de7
Fix additional TypeScript errors
claude Nov 15, 2025
c1feb53
Fix TypeScript errors (batch 1 of remaining errors)
claude Nov 15, 2025
53150ee
Fix TypeScript errors (batch 2)
claude Nov 15, 2025
b4a7386
Fix TypeScript errors (batch 3)
claude Nov 15, 2025
d7fcd68
Fix TypeScript errors in FavoritesList (batch 4)
claude Nov 15, 2025
13e860c
Fix TypeScript errors in Answer component (batch 5)
claude Nov 15, 2025
5f15594
Fix TypeScript errors (batch 6)
claude Nov 15, 2025
afd3227
Fix TypeScript errors in RecordMainCategorySection (batch 7)
claude Nov 15, 2025
733397b
Fix TypeScript errors in Answer component (batch 8)
claude Nov 15, 2025
130cd38
Fix TypeScript errors in RecordTable (batch 9)
claude Nov 15, 2025
84a41b1
Fix TypeScript errors in DownloadFormContainer (batch 10)
claude Nov 15, 2025
c412c5c
Fix TypeScript errors in RecordTable and RecordTableSection (batch 11)
claude Nov 15, 2025
1504f85
Fix TypeScript errors in RecordUI and RecordNavigationSection (batch 12)
claude Nov 15, 2025
79906b2
Fix final TypeScript errors - all 64 errors resolved! (batch 13)
claude Nov 15, 2025
37570ed
Convert Mesa component from JavaScript to TypeScript
claude Nov 15, 2025
856a335
Improve RecordTable type safety using Mesa TypeScript types
claude Nov 15, 2025
ee1a421
Reduce 'as any' assertions in RecordTable and Answer components
claude Nov 15, 2025
56d265d
Improve type safety in utility files by replacing 'as' assertions
claude Nov 15, 2025
e20492a
Add comprehensive TypeScript conversion guide
claude Nov 15, 2025
48cfd25
Update compilation verification guidance in TS conversion guide
claude Nov 15, 2025
09aa101
Add git mv guidance to TypeScript conversion guide
claude Nov 15, 2025
df1f97a
Fix initial TypeScript compilation errors in Mesa components
claude Nov 15, 2025
f883287
Fix all TypeScript compilation errors in Mesa components
claude Nov 15, 2025
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
736 changes: 736 additions & 0 deletions CLAUDE-TS-conversion-guide.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,27 @@ import { debounce } from 'lodash';
import MesaTooltip from './MesaTooltip';
import Events from '../Utils/Events';

class AnchoredTooltip extends React.Component {
constructor(props) {
interface Position {
left?: number;
top?: number;
}

interface AnchoredTooltipProps {
className?: string;
children?: React.ReactNode;
content: React.ReactNode;
[key: string]: any;
}

class AnchoredTooltip extends React.Component<AnchoredTooltipProps> {
private childWrapperRef: React.RefObject<HTMLDivElement>;
private listeners: { scroll?: string; resize?: string } = {};
public updatePosition: (() => void) & { cancel: () => void };

constructor(props: AnchoredTooltipProps) {
super(props);
this.getPosition = this.getPosition.bind(this);
this.updatePosition = debounce(this.updatePosition.bind(this), 100);
this.updatePosition = debounce(this._updatePosition.bind(this), 100);
this.componentDidMount = this.componentDidMount.bind(this);
this.componentWillUnmount = this.componentWillUnmount.bind(this);
this.childWrapperRef = React.createRef();
Expand All @@ -22,19 +38,19 @@ class AnchoredTooltip extends React.Component {
}

componentWillUnmount() {
Object.values(this.listeners).forEach((listenerId) =>
Events.remove(listenerId)
);
Object.values(this.listeners).forEach((listenerId) => {
if (listenerId) Events.remove(listenerId);
});
this.updatePosition.cancel();
}

updatePosition() {
_updatePosition() {
this.forceUpdate();
}

getPosition() {
getPosition(): Position {
const element = this.childWrapperRef.current;
if (!element) return undefined;
if (!element) return { left: 0, top: 0 };

const offset = element.getBoundingClientRect();
const { top, left } = offset;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import React from 'react';
import ReactDOM from 'react-dom';

class BodyLayer extends React.Component {
constructor(props) {
interface BodyLayerProps {
[key: string]: any;
}

class BodyLayer extends React.Component<BodyLayerProps> {
private el: HTMLDivElement;

constructor(props: BodyLayerProps) {
super(props);
// XXX This will have to be guarded if we ever use server side rendering
this.el = document.createElement('div');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import React from 'react';
import IndeterminateCheckbox from '../../inputs/checkboxes/IndeterminateCheckbox';

class Checkbox extends React.Component {
constructor(props) {
interface CheckboxProps {
checked: boolean;
onChange?: (checked: boolean) => void;
className?: string;
disabled?: boolean;
indeterminate?: boolean;
}

class Checkbox extends React.Component<CheckboxProps> {
constructor(props: CheckboxProps) {
super(props);
this.handleClick = this.handleClick.bind(this);
}

handleClick(e) {
handleClick(
isCheckedOrEvent: boolean | React.ChangeEvent<HTMLInputElement>
): void {
let { checked, onChange } = this.props;
if (typeof onChange === 'function') onChange(!!checked);
}
Expand All @@ -24,6 +34,8 @@ class Checkbox extends React.Component {
<IndeterminateCheckbox
checked={checked}
indeterminate={indeterminate}
name=""
value=""
onChange={this.handleClick}
/>
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@ import React from 'react';
import Icon from './Icon';
import AnchoredTooltip from './AnchoredTooltip';

class HelpTrigger extends React.Component {
constructor(props) {
interface HelpTriggerProps {
className?: string;
children?: React.ReactNode;
[key: string]: any;
}

class HelpTrigger extends React.Component<HelpTriggerProps> {
constructor(props: HelpTriggerProps) {
super(props);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import React from 'react';

class Icon extends React.PureComponent {
interface IconProps {
fa: string;
className?: string;
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
style?: React.CSSProperties;
}

class Icon extends React.PureComponent<IconProps> {
render() {
let { fa, className, onClick, style } = this.props;
className = `icon fa fa-${fa} ${className || ''}`;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,29 @@
import React from 'react';
import PropTypes from 'prop-types';

import { uid, makeClassifier } from '../Utils/Utils';

const modalBoundaryClass = makeClassifier('ModalBoundary');

class ModalBoundary extends React.Component {
constructor(props) {
interface Modal {
_id?: string;
render: React.ComponentType<any>;
[key: string]: any;
}

interface ModalBoundaryProps {
children?: React.ReactNode;
style?: React.CSSProperties;
}

interface ModalBoundaryState {
modals: Modal[];
}

class ModalBoundary extends React.Component<
ModalBoundaryProps,
ModalBoundaryState
> {
constructor(props: ModalBoundaryProps) {
super(props);

this.state = { modals: [] };
Expand All @@ -28,19 +45,19 @@ class ModalBoundary extends React.Component {
);
}

addModal(modal) {
addModal(modal: Modal): string {
let { modals } = this.state;
modal._id = uid();
modals.push(modal);
this.setState({ modals });
return modal._id;
}

triggerModalRefresh() {
triggerModalRefresh(): void {
this.forceUpdate();
}

removeModal(id) {
removeModal(id: string): void {
let { modals } = this.state;
let index = modals.findIndex((modal) => modal._id === id);
if (index < 0) return;
Expand All @@ -55,7 +72,7 @@ class ModalBoundary extends React.Component {

renderModalWrapper() {
const { modals } = this.state;
const style = {
const style: React.CSSProperties = {
top: 0,
left: 0,
width: '100vw',
Expand All @@ -76,10 +93,17 @@ class ModalBoundary extends React.Component {
render() {
const { children, style } = this.props;
const ModalWrapper = this.renderModalWrapper;
const fullStyle = Object.assign({}, style ? style : {}, {
const fullStyle: React.CSSProperties = Object.assign(
{},
style ? style : {},
{
position: 'relative',
}
);
const zIndex = (z: number): React.CSSProperties => ({
position: 'relative',
zIndex: z,
});
const zIndex = (z) => ({ position: 'relative', zIndex: z });

return (
<div
Expand All @@ -95,15 +119,4 @@ class ModalBoundary extends React.Component {
}
}

ModalBoundary.childContextTypes = {
addModal: PropTypes.func,
removeModal: PropTypes.func,
triggerModalRefresh: PropTypes.func,
};

ModalBoundary.propTypes = {
children: PropTypes.oneOfType([PropTypes.node, PropTypes.element]),
style: PropTypes.object,
};

export default ModalBoundary;
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import React from 'react';

class OverScroll extends React.Component {
constructor(props) {
interface OverScrollProps {
className?: string;
height?: number;
children?: React.ReactNode;
}

class OverScroll extends React.Component<OverScrollProps> {
constructor(props: OverScrollProps) {
super(props);
}

render() {
let { className, height } = this.props;
className = 'OverScroll' + (className ? ' ' + className : '');
height = typeof height === 'number' ? height + 'px' : 'none';
const heightValue = typeof height === 'number' ? height + 'px' : 'none';

const style = {
maxHeight: height,
const style: React.CSSProperties = {
maxHeight: heightValue,
overflowY: 'auto',
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,39 @@
import React from 'react';

class SelectBox extends React.PureComponent {
constructor(props) {
interface SelectOption {
name: string;
value: string | number;
}

interface SelectBoxProps {
name?: string;
className?: string;
selected?: string | number;
options?: (SelectOption | string | number)[];
onChange?: (value: string) => void;
}

class SelectBox extends React.PureComponent<SelectBoxProps> {
constructor(props: SelectBoxProps) {
super(props);
this.handleChange = this.handleChange.bind(this);
}

handleChange(e) {
handleChange(e: React.ChangeEvent<HTMLSelectElement>): void {
const { onChange } = this.props;
const value = e.target.value;
if (onChange) onChange(value);
}

getOptions() {
getOptions(): SelectOption[] {
let { options } = this.props;
if (!Array.isArray(options)) return [];
options = options.map((option) => {
return typeof option === 'object' && 'name' in option && 'value' in option
? option
: { name: option.toString(), value: option };
});
return options;
return options as SelectOption[];
}

render() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import React from 'react';

import Icon from '../../../Components/Mesa/Components/Icon';
import Icon from './Icon';

class Toggle extends React.Component {
constructor(props) {
interface ToggleProps {
enabled: boolean;
onChange?: (enabled: boolean) => void;
className?: string;
disabled?: boolean;
style?: React.CSSProperties;
}

class Toggle extends React.Component<ToggleProps> {
constructor(props: ToggleProps) {
super(props);
this.handleClick = this.handleClick.bind(this);
}

handleClick(e) {
handleClick(e: React.MouseEvent): void {
let { enabled, onChange } = this.props;
if (typeof onChange === 'function') onChange(!!enabled);
}
Expand All @@ -18,19 +26,19 @@ class Toggle extends React.Component {
className = 'Toggle' + (className ? ' ' + className : '');
className += ' ' + (enabled ? 'Toggle-On' : 'Toggle-Off');
className += disabled ? ' Toggle-Disabled' : '';
let offStyle = {
let offStyle: React.CSSProperties = {
fontSize: '1.2rem',
color: '#989898',
};
let onStyle = Object.assign({}, offStyle, {
let onStyle: React.CSSProperties = Object.assign({}, offStyle, {
color: '#198835',
});

return (
<span
style={style}
className={className}
onClick={disabled ? null : this.handleClick}
onClick={disabled ? undefined : this.handleClick}
>
<Icon
fa={enabled ? 'toggle-on' : 'toggle-off'}
Expand Down
Loading