oknosoft / metadata.js

Library for building offline-first browser-based applications :: платформа автономных веб-приложений
MIT License
189 stars 75 forks source link

Поддержать jsx в формулах #445

Open unpete opened 5 years ago

unpete commented 5 years ago

Чтобы модификаторы простым способом с ui взаимодействовали

rnpoddor commented 5 years ago

Вот эта задача мне нравится. Сейчас по работе с интерфейсом из модификаторов нет совсем ничего из коробки, приходится искать разные обходные пути, в том числе опасные.

unpete commented 5 years ago

Спасибо. После oknosoft/windowbuilder@c735a01 и oknosoft/metadata.js@12a9677, начинает работать конструкция:

$p.ui.dialogs.alert({title: '123', html: '<h1>000</h1><b>123</b>', initFullScreen: true})
$p.ui.dialogs.confirm({title: '123', html: '<h1>000</h1><b>123</b>', initFullScreen: true})

Это временная мера, позволяющая оживить вывод информации пользователю

unpete commented 4 years ago

Решил не размазывать задачу на годы. Накидал за два часа два изменения:

Сделал тестовую формулу - работает. image Поддержаны как функциональные, так и class-based компоненты, как stateless, так и со сложным состоянием. В принципе, можно сделать Заказ дилера внутри Заказа дилера.

Для быстрого результата, решил не заморачиваться с автоматической транспиляцией. Добавим её позже в auth-proxy. Там ей самое место. Текст jsx кладём в текстовый реквизит Шаблон справочника Формулы. Поле Формула заполняем руками с помощью https://babeljs.io/repl. Когда сделаем автомат, Формула будет заполняться в фоне при внесении изменений в Шаблон. Пример шаблона:

const {React, withStyles, Grid, FormControl, FormLabel, FormControlLabel, RadioGroup, Radio, Paper} = $p.ui;

const styles = theme => ({
  root: {
    flexGrow: 1,
  },
  demo: {
    height: 240,
  },
  paper: {
    padding: theme.spacing(2),
    height: '100%',
    color: theme.palette.text.secondary,
  },
  control: {
    padding: theme.spacing(2),
  },
});

class InteractiveGrid extends React.Component {
  state = {
    direction: 'row',
    justify: 'center',
    alignItems: 'center',
  };

  handleChange = key => (event, value) => {
    this.setState({
      [key]: value,
    });
  };

  render() {
    const { classes } = this.props;
    const { alignItems, direction, justify } = this.state;

    return (
      <Grid container className={classes.root}>
        <Grid item xs={12}>
          <Grid
            container
            spacing={1}
            className={classes.demo}
            alignItems={alignItems}
            direction={direction}
            justify={justify}
          >
            {[0, 1, 2].map(value => (
              <Grid key={value} item>
                <Paper
                  className={classes.paper}
                  style={{ paddingTop: (value + 1) * 10, paddingBottom: (value + 1) * 10 }}
                >
                  {`Cell ${value + 1}`}
                </Paper>
              </Grid>
            ))}
          </Grid>
        </Grid>
        <Grid item xs={12}>
          <Paper className={classes.control}>
            <Grid container spacing={3}>
              <Grid item xs={12}>
                <FormControl component="fieldset">
                  <FormLabel>direction</FormLabel>
                  <RadioGroup
                    row
                    name="direction"
                    aria-label="Direction"
                    value={direction}
                    onChange={this.handleChange('direction')}
                  >
                    <FormControlLabel value="row" control={<Radio />} label="row" />
                    <FormControlLabel value="row-reverse" control={<Radio />} label="row-reverse" />
                    <FormControlLabel value="column" control={<Radio />} label="column" />
                    <FormControlLabel
                      value="column-reverse"
                      control={<Radio />}
                      label="column-reverse"
                    />
                  </RadioGroup>
                </FormControl>
              </Grid>
              <Grid item xs={12}>
                <FormControl component="fieldset">
                  <FormLabel>justify</FormLabel>
                  <RadioGroup
                    row
                    name="justify"
                    aria-label="Justify"
                    value={justify}
                    onChange={this.handleChange('justify')}
                  >
                    <FormControlLabel value="flex-start" control={<Radio />} label="flex-start" />
                    <FormControlLabel value="center" control={<Radio />} label="center" />
                    <FormControlLabel value="flex-end" control={<Radio />} label="flex-end" />
                    <FormControlLabel
                      value="space-between"
                      control={<Radio />}
                      label="space-between"
                    />
                    <FormControlLabel
                      value="space-around"
                      control={<Radio />}
                      label="space-around"
                    />
                    <FormControlLabel
                      value="space-evenly"
                      control={<Radio />}
                      label="space-evenly"
                    />
                  </RadioGroup>
                </FormControl>
              </Grid>
              <Grid item xs={12}>
                <FormControl component="fieldset">
                  <FormLabel>alignItems</FormLabel>
                  <RadioGroup
                    row
                    name="alignItems"
                    aria-label="Align items"
                    value={alignItems}
                    onChange={this.handleChange('alignItems')}
                  >
                    <FormControlLabel value="flex-start" control={<Radio />} label="flex-start" />
                    <FormControlLabel value="center" control={<Radio />} label="center" />
                    <FormControlLabel value="flex-end" control={<Radio />} label="flex-end" />
                    <FormControlLabel value="stretch" control={<Radio />} label="stretch" />
                    <FormControlLabel value="baseline" control={<Radio />} label="baseline" />
                  </RadioGroup>
                </FormControl>
              </Grid>
            </Grid>
          </Paper>
        </Grid>
      </Grid>
    );
  }
}
return withStyles(styles)(InteractiveGrid);

То же самое, после транспиляции:

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

const {
  React,
  withStyles,
  Grid,
  FormControl,
  FormLabel,
  FormControlLabel,
  RadioGroup,
  Radio,
  Paper
} = $p.ui;

const styles = theme => ({
  root: {
    flexGrow: 1
  },
  demo: {
    height: 240
  },
  paper: {
    padding: theme.spacing(2),
    height: '100%',
    color: theme.palette.text.secondary
  },
  control: {
    padding: theme.spacing(2)
  }
});

class InteractiveGrid extends React.Component {
  constructor(...args) {
    super(...args);

    _defineProperty(this, "state", {
      direction: 'row',
      justify: 'center',
      alignItems: 'center'
    });

    _defineProperty(this, "handleChange", key => (event, value) => {
      this.setState({
        [key]: value
      });
    });
  }

  render() {
    const {
      classes
    } = this.props;
    const {
      alignItems,
      direction,
      justify
    } = this.state;
    return React.createElement(Grid, {
      container: true,
      className: classes.root
    }, React.createElement(Grid, {
      item: true,
      xs: 12
    }, React.createElement(Grid, {
      container: true,
      spacing: 1,
      className: classes.demo,
      alignItems: alignItems,
      direction: direction,
      justify: justify
    }, [0, 1, 2].map(value => React.createElement(Grid, {
      key: value,
      item: true
    }, React.createElement(Paper, {
      className: classes.paper,
      style: {
        paddingTop: (value + 1) * 10,
        paddingBottom: (value + 1) * 10
      }
    }, `Cell ${value + 1}`))))), React.createElement(Grid, {
      item: true,
      xs: 12
    }, React.createElement(Paper, {
      className: classes.control
    }, React.createElement(Grid, {
      container: true,
      spacing: 3
    }, React.createElement(Grid, {
      item: true,
      xs: 12
    }, React.createElement(FormControl, {
      component: "fieldset"
    }, React.createElement(FormLabel, null, "direction"), React.createElement(RadioGroup, {
      row: true,
      name: "direction",
      "aria-label": "Direction",
      value: direction,
      onChange: this.handleChange('direction')
    }, React.createElement(FormControlLabel, {
      value: "row",
      control: React.createElement(Radio, null),
      label: "row"
    }), React.createElement(FormControlLabel, {
      value: "row-reverse",
      control: React.createElement(Radio, null),
      label: "row-reverse"
    }), React.createElement(FormControlLabel, {
      value: "column",
      control: React.createElement(Radio, null),
      label: "column"
    }), React.createElement(FormControlLabel, {
      value: "column-reverse",
      control: React.createElement(Radio, null),
      label: "column-reverse"
    })))), React.createElement(Grid, {
      item: true,
      xs: 12
    }, React.createElement(FormControl, {
      component: "fieldset"
    }, React.createElement(FormLabel, null, "justify"), React.createElement(RadioGroup, {
      row: true,
      name: "justify",
      "aria-label": "Justify",
      value: justify,
      onChange: this.handleChange('justify')
    }, React.createElement(FormControlLabel, {
      value: "flex-start",
      control: React.createElement(Radio, null),
      label: "flex-start"
    }), React.createElement(FormControlLabel, {
      value: "center",
      control: React.createElement(Radio, null),
      label: "center"
    }), React.createElement(FormControlLabel, {
      value: "flex-end",
      control: React.createElement(Radio, null),
      label: "flex-end"
    }), React.createElement(FormControlLabel, {
      value: "space-between",
      control: React.createElement(Radio, null),
      label: "space-between"
    }), React.createElement(FormControlLabel, {
      value: "space-around",
      control: React.createElement(Radio, null),
      label: "space-around"
    }), React.createElement(FormControlLabel, {
      value: "space-evenly",
      control: React.createElement(Radio, null),
      label: "space-evenly"
    })))), React.createElement(Grid, {
      item: true,
      xs: 12
    }, React.createElement(FormControl, {
      component: "fieldset"
    }, React.createElement(FormLabel, null, "alignItems"), React.createElement(RadioGroup, {
      row: true,
      name: "alignItems",
      "aria-label": "Align items",
      value: alignItems,
      onChange: this.handleChange('alignItems')
    }, React.createElement(FormControlLabel, {
      value: "flex-start",
      control: React.createElement(Radio, null),
      label: "flex-start"
    }), React.createElement(FormControlLabel, {
      value: "center",
      control: React.createElement(Radio, null),
      label: "center"
    }), React.createElement(FormControlLabel, {
      value: "flex-end",
      control: React.createElement(Radio, null),
      label: "flex-end"
    }), React.createElement(FormControlLabel, {
      value: "stretch",
      control: React.createElement(Radio, null),
      label: "stretch"
    }), React.createElement(FormControlLabel, {
      value: "baseline",
      control: React.createElement(Radio, null),
      label: "baseline"
    }))))))));
  }
}
return withStyles(styles)(InteractiveGrid);

Важно: внутри формулы нельзя использовать import, export. Конструкторы основных React-компонентов поместил в $p.ui. Базовый список можно расширить, если попросите. Пользовательские компоненты можно грузить из CDN, со своего или нашего сервера или блоба, который можем организовать под эту задачу. Надо попробовать решать реальную задачу и станет понятнее, какие доработки требуются этому механизму.

unpete commented 4 years ago

Добавлена возможность рендерить в новое окно 096d099cd4a0bed6681e6859e514f9be9ce6574e