nilsbu / lastfm

Last.FM tools in Go
1 stars 0 forks source link

is the closure here needed? #31

Open github-actions[bot] opened 1 year ago

github-actions[bot] commented 1 year ago

https://github.com/nilsbu/lastfm/blob/560f22746a1bbe855eda17fefece55aeebdf9846/static/react/script.js#L122


    switch (props.page) {
    case "main":
        return (
            <div className="row row-body" style={{display: "block"}}>
                <Charts func={CMD["year"]} param={YEAR}/>
                <Charts func={CMD["fade"]} param="365"/>
                <Charts func={CMD["fade"]} param="3653"/>
            </div>
        );
    case "buffet":
        return (
            <div className="row row-body" style={{display: "block"}}>
                <Buffet />
            </div>
        );
    default:
        return (
            // <div className="row row-body table-responsive">
                <ChosenCharts options={OPTS[props.page]} func={CMD[props.page]} key={props.page} init={INITIAL_IDX[props.page]} /> 
            // </div>
        );
    }
}

class Buffet extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            base: "total",
            params: {},
            filters: "all",
            jsxParams: null,
        };

        this.chooseBase = (page) => {
            this.setState(Object.assign({}, this.state, {
                base: page,
                params: {},
            }));
        };

        this.setParams = (params) => {
            this.setState(Object.assign({}, this.state, {
                params: params,
            })); 
        }

        this.setFilters = (filters) => {
            this.setState(Object.assign({}, this.state, {
            filters: filters,
        })); 
    }
    }

    getFunc() {
        // TODO: is the closure here needed?
        var str = "/json/print/" + this.state.base;
        var params = {...this.state.params};

        switch (this.state.base) {
        case "fade":
        case "period":
            str += `/${params.p0}`;
            break;
        case "interval":
            str += `/${params.p0}/${params.p1}`;
            break;
        }
        delete params.p0;
        delete params.p1;

        if (this.state.filters != null) {
            params.by = this.state.filters;
        }

        var first = true;
        for (const [key, value] of Object.entries(params)) {
            if (first) {
                str += "?";
                first = false;
            } else {
                str += "&";
            }
            str += `${key}=${value}`;
        }

        return function () {return str;}
    }

    render() {
        var func = this.getFunc();
        return (
            <div key={`buffet-${func()}`}>
                <div className="row">
                    <Choices onSubmit={this.chooseBase} type={["total", "fade", "period", "interval"]} page={this.state.base}/>
                </div>
                <Params base={this.state.base} cb={this.setParams} />
                <Filter name="all" cb={this.setFilters} />
                <Filter name="super" cb={this.setFilters} />
                <Filter name="country" cb={this.setFilters} />
                <Filter name="year" cb={this.setFilters} />
                <Filter name="groups" cb={this.setFilters} />
                <Charts func={func} param="" />
            </div>
        );
    }
}

class Params extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            params: {},
            lastBase: props.base,
        };

        this.set = (name, value) => {
            this.setState(Object.assign({}, this.state, {
                params: Object.assign({}, this.state.params, {
                    [name]: value,
                }),
            }));
        }; 
    }

    componentDidUpdate(prevProps) {
        if (prevProps.base !== this.props.base) {
            this.setState(Object.assign({}, this.state, {
                params: {},
            }));
            this.props.cb(this.state.params);
        }
    }

    render() {
        var titles = [];

        switch (this.props.base) {
        case "total":
            break;
        case "fade":
            titles = ["half-life"];
            break;
        case "period":
            titles = ["period"];
            break;
        case "interval":
            titles = ["begin", "end"];
            break;
        }

        if (titles.length == 0) {
            return (<div/>);
        } else {
            return (
                <div className="input-group bg-dark">
                    {
                        titles.map((opt, i) => [
                            (<span className="input-group-text bg-dark" key={"p-span-" + opt} >{opt}</span>), 
                            (<input type="text" key={"p-input-" + opt} className="form-control bg-dark" placeholder="" aria-label={opt} aria-describedby="basic-addon1" onChange={(v) => this.set(`p${i}`, v.target.value)} />)]
                        )
                    }
                    <button type="button" className="btn btn-outline-secondary bg-dark" onClick={() => this.props.cb(this.state.params)} >Confirm</button>
                </div>
            );
        }
    }
}

class Filter extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            value: "",
        };

        this.set = () => {
            this.props.cb(this.props.name);
        };
    }

    render() {
        return (
            <div className="form-check form-check-inline" key={"filter-" + this.props.name}>
                <input className="form-check-input" type="radio"
                    id={this.props.name}
                    name="filter-radio"
                    value={this.props.name}
                    onClick={this.set}
                    />
                <label className="form-check-label text-white" htmlFor={this.props.name}>{this.props.name}</label>
            </div>
        );
    }