GridEditModal.jsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import {
  4. Modal, ModalHeader, ModalBody, ModalFooter,
  5. } from 'reactstrap';
  6. import { withTranslation } from 'react-i18next';
  7. import geu from './GridEditorUtil';
  8. import BootstrapGrid from '../../models/BootstrapGrid';
  9. const resSizes = BootstrapGrid.ResponsiveSize;
  10. const resSizeObj = {
  11. [resSizes.XS_SIZE]: { iconClass: 'icon-screen-smartphone', displayText: 'grid_edit.smart_no' },
  12. [resSizes.SM_SIZE]: { iconClass: 'icon-screen-tablet', displayText: 'tablet' },
  13. [resSizes.MD_SIZE]: { iconClass: 'icon-screen-desktop', displayText: 'desktop' },
  14. };
  15. class GridEditModal extends React.Component {
  16. constructor(props) {
  17. super(props);
  18. this.state = {
  19. colsRatios: [6, 6],
  20. responsiveSize: BootstrapGrid.ResponsiveSize.XS_SIZE,
  21. show: false,
  22. // use when re-edit grid
  23. // gridHtml: '',
  24. };
  25. this.checkResposiveSize = this.checkResposiveSize.bind(this);
  26. this.checkColsRatios = this.checkColsRatios.bind(this);
  27. // use when re-edit grid
  28. // this.init = this.init.bind(this);
  29. this.show = this.show.bind(this);
  30. this.hide = this.hide.bind(this);
  31. this.cancel = this.cancel.bind(this);
  32. this.pasteCodedGrid = this.pasteCodedGrid.bind(this);
  33. this.renderSelectedGridPattern = this.renderSelectedGridPattern.bind(this);
  34. this.renderBreakPointSetting = this.renderBreakPointSetting.bind(this);
  35. }
  36. async checkResposiveSize(rs) {
  37. await this.setState({ responsiveSize: rs });
  38. }
  39. async checkColsRatios(cr) {
  40. await this.setState({ colsRatios: cr });
  41. }
  42. // use when re-edit grid
  43. // init(gridHtml) {
  44. // const initGridHtml = gridHtml;
  45. // this.setState({ gridHtml: initGridHtml });
  46. // }
  47. show(gridHtml) {
  48. // use when re-edit grid
  49. // this.init(gridHtml);
  50. this.setState({ show: true });
  51. }
  52. hide() {
  53. this.setState({ show: false });
  54. }
  55. cancel() {
  56. this.hide();
  57. }
  58. pasteCodedGrid() {
  59. const { colsRatios, responsiveSize } = this.state;
  60. const convertedHTML = geu.convertRatiosAndSizeToHTML(colsRatios, responsiveSize);
  61. const pastedGridData = `::: editable-row\n<div class="container">\n <div class="row">\n${convertedHTML}\n\t</div>\n</div>\n:::`;
  62. if (this.props.onSave != null) {
  63. this.props.onSave(pastedGridData);
  64. }
  65. this.cancel();
  66. }
  67. renderSelectedGridPattern() {
  68. const colsRatios = this.state.colsRatios;
  69. return colsRatios.join(' - ');
  70. }
  71. renderBreakPointSetting() {
  72. const { t } = this.props;
  73. const output = Object.entries(resSizeObj).map((responsiveSizeForMap) => {
  74. return (
  75. <div className="custom-control custom-radio custom-control-inline">
  76. <input
  77. type="radio"
  78. className="custom-control-input"
  79. id={responsiveSizeForMap[1].displayText}
  80. value={responsiveSizeForMap[1].displayText}
  81. checked={this.state.responsiveSize === responsiveSizeForMap[0]}
  82. onChange={e => this.checkResposiveSize(responsiveSizeForMap[0])}
  83. />
  84. <label className="custom-control-label" htmlFor={responsiveSizeForMap[1].displayText}>
  85. <i className={`pr-1 ${responsiveSizeForMap[1].iconClass}`} />
  86. {t(responsiveSizeForMap[1].displayText)}
  87. </label>
  88. </div>
  89. );
  90. });
  91. return output;
  92. }
  93. renderGridDivisionMenu() {
  94. const gridDivisions = geu.mappingAllGridDivisionPatterns;
  95. const { t } = this.props;
  96. return (
  97. <div className="container">
  98. <div className="row">
  99. {gridDivisions.map((gridDivion, i) => {
  100. return (
  101. <div className="col-md-4 text-center">
  102. <h6 className="dropdown-header">{gridDivion.numberOfGridDivisions} {t('grid_edit.division')}</h6>
  103. {gridDivion.mapping.map((gridOneDivision) => {
  104. return (
  105. <button className="dropdown-item" type="button" onClick={() => { this.checkColsRatios(gridOneDivision) }}>
  106. <div className="row">
  107. {gridOneDivision.map((god) => {
  108. const className = `bg-info col-${god} border`;
  109. return <span className={className}>{god}</span>;
  110. })}
  111. </div>
  112. </button>
  113. );
  114. })}
  115. </div>
  116. );
  117. })}
  118. </div>
  119. </div>
  120. );
  121. }
  122. renderPreview() {
  123. // TODO GW-3721 make objects and simplify all loops
  124. /* const prevSize = BootstrapGrid.ResponsiveSize;
  125. const prevSizeObj = {
  126. [prevSize.MD_SIZE]: {
  127. [prevSize.MD_SIZE]: {
  128. iconClass: 'icon-screen-desktop', prevClass: 'desktop-preview', prevText: 'Desktop', prevRender: this.renderNoBreakPreview(),
  129. },
  130. [prevSize.SM_SIZE]: {
  131. iconClass: 'icon-screen-tablet', prevClass: 'tablet-preview', prevText: 'Tablet', prevRender: this.renderBreakPreview(),
  132. },
  133. [prevSize.XS_SIZE]: {
  134. iconClass: 'icon-screen-smartphone', prevClass: 'mobile-preview', prevText: 'Smartphone', prevRender: this.renderBreakPreview(),
  135. },
  136. },
  137. [prevSize.SM_SIZE]: {
  138. [prevSize.MD_SIZE]: {
  139. iconClass: 'icon-screen-desktop', prevClass: 'desktop-preview', prevText: 'Desktop', prevRender: this.renderNoBreakPreview(),
  140. },
  141. [prevSize.SM_SIZE]: {
  142. iconClass: 'icon-screen-tablet', prevClass: 'tablet-preview', prevText: 'Tablet', prevRender: this.renderNoBreakPreview(),
  143. },
  144. [prevSize.XS_SIZE]: {
  145. iconClass: 'icon-screen-smartphone', prevClass: 'mobile-preview', prevText: 'Smartphone', prevRender: this.renderBreakPreview(),
  146. },
  147. },
  148. [prevSize.MD_SIZE]: {
  149. [prevSize.MD_SIZE]: {
  150. iconClass: 'icon-screen-desktop', prevClass: 'desktop-preview', prevText: 'Desktop', prevRender: this.renderNoBreakPreview(),
  151. },
  152. [prevSize.SM_SIZE]: {
  153. iconClass: 'icon-screen-tablet', prevClass: 'tablet-preview', prevText: 'Tablet', prevRender: this.renderNoBreakPreview(),
  154. },
  155. [prevSize.XS_SIZE]: {
  156. iconClass: 'icon-screen-smartphone', prevClass: 'mobile-preview', prevText: 'Smartphone', prevRender: this.renderNoBreakPreview(),
  157. },
  158. },
  159. }; */
  160. const { t } = this.props;
  161. if (this.state.responsiveSize === BootstrapGrid.ResponsiveSize.MD_SIZE) {
  162. return (
  163. <div className="row">
  164. <div className="col-lg-6">
  165. <label className="d-block mt-2"><i className="pr-2 icon-screen-desktop"></i>{t('desktop')}</label>
  166. <div className="desktop-preview d-block">
  167. {this.renderNoBreakPreview()}
  168. </div>
  169. </div>
  170. <div className="col-lg-3">
  171. <label className="d-block mt-2"><i className="pr-2 icon-screen-tablet"></i>{t('tablet')}</label>
  172. <div className="tablet-preview d-block">
  173. {this.renderBreakPreview()}
  174. </div>
  175. </div>
  176. <div className="col-lg-3">
  177. <label className="d-block mt-2"><i className="pr-2 icon-screen-smartphone"></i>{t('phone')}</label>
  178. <div className="mobile-preview d-block">
  179. {this.renderBreakPreview()}
  180. </div>
  181. </div>
  182. </div>
  183. );
  184. }
  185. if (this.state.responsiveSize === BootstrapGrid.ResponsiveSize.SM_SIZE) {
  186. return (
  187. <div className="row">
  188. <div className="col-lg-6">
  189. <label className="d-block mt-2"><i className="pr-2 icon-screen-desktop"></i>{t('desktop')}</label>
  190. <div className="desktop-preview d-block">
  191. {this.renderNoBreakPreview()}
  192. </div>
  193. </div>
  194. <div className="col-lg-3">
  195. <label className="d-block mt-2"><i className="pr-2 icon-screen-tablet"></i>{t('tablet')}</label>
  196. <div className="tablet-preview d-block">
  197. {this.renderNoBreakPreview()}
  198. </div>
  199. </div>
  200. <div className="col-lg-3">
  201. <label className="d-block mt-2"><i className="pr-2 icon-screen-smartphone"></i>{t('phone')}</label>
  202. <div className="mobile-preview d-block">
  203. {this.renderBreakPreview()}
  204. </div>
  205. </div>
  206. </div>
  207. );
  208. }
  209. if (this.state.responsiveSize === BootstrapGrid.ResponsiveSize.XS_SIZE) {
  210. return (
  211. <div className="row">
  212. <div className="col-lg-6">
  213. <label className="d-block mt-2"><i className="pr-2 icon-screen-desktop"></i>{t('desktop')}</label>
  214. <div className="desktop-preview d-block">
  215. {this.renderNoBreakPreview()}
  216. </div>
  217. </div>
  218. <div className="col-lg-3">
  219. <label className="d-block mt-2"><i className="pr-2 icon-screen-tablet"></i>{t('tablet')}</label>
  220. <div className="tablet-preview d-block">
  221. {this.renderNoBreakPreview()}
  222. </div>
  223. </div>
  224. <div className="col-lg-3">
  225. <label className="d-block mt-2"><i className="pr-2 icon-screen-smartphone"></i>{t('phone')}</label>
  226. <div className="mobile-preview d-block">
  227. {this.renderNoBreakPreview()}
  228. </div>
  229. </div>
  230. </div>
  231. );
  232. }
  233. }
  234. renderNoBreakPreview() {
  235. const { colsRatios } = this.state;
  236. const convertedHTML = colsRatios.map((colsRatios) => {
  237. const className = `col-${colsRatios} border`;
  238. return (
  239. <div className={className}></div>
  240. );
  241. });
  242. return (
  243. <div className="row">{convertedHTML}</div>
  244. );
  245. }
  246. renderBreakPreview() {
  247. const { colsRatios } = this.state;
  248. const convertedHTML = colsRatios.map(() => {
  249. const className = 'col-12 border';
  250. return (
  251. <div className={className}></div>
  252. );
  253. });
  254. return (
  255. <div className="row">{convertedHTML}</div>
  256. );
  257. }
  258. render() {
  259. const { t } = this.props;
  260. return (
  261. <Modal isOpen={this.state.show} toggle={this.cancel} size="xl" className="grw-grid-edit-modal">
  262. <ModalHeader tag="h4" toggle={this.cancel} className="bg-primary text-light">
  263. {t('grid_edit.create_bootstrap_4_grid')}
  264. </ModalHeader>
  265. <ModalBody className="container">
  266. <div className="row">
  267. <div className="col-12">
  268. <h3 className="grw-modal-head">{t('grid_edit.grid_settings')}</h3>
  269. <form className="form-group mb-0">
  270. <div className="form-group row my-3">
  271. <label className="col-sm-3" htmlFor="gridPattern">
  272. {t('grid_edit.grid_pattern')}
  273. </label>
  274. <div className="col-sm-9">
  275. <button
  276. className="btn btn-outline-secondary dropdown-toggle"
  277. type="button"
  278. id="dropdownMenuButton"
  279. data-toggle="dropdown"
  280. aria-haspopup="true"
  281. aria-expanded="false"
  282. >
  283. {this.renderSelectedGridPattern()}
  284. </button>
  285. <div className="dropdown-menu grid-division-menu" aria-labelledby="dropdownMenuButton">
  286. {this.renderGridDivisionMenu()}
  287. </div>
  288. </div>
  289. </div>
  290. <div className="form-group row">
  291. <label className="col-sm-3" htmlFor="breakPoint">
  292. {t('grid_edit.break_point')}
  293. </label>
  294. <div className="col-sm-9">
  295. {this.renderBreakPointSetting()}
  296. </div>
  297. </div>
  298. </form>
  299. </div>
  300. </div>
  301. <h3 className="grw-modal-head">{t('preview')}</h3>
  302. {this.renderPreview()}
  303. </ModalBody>
  304. <ModalFooter className="grw-modal-footer">
  305. <div className="ml-auto">
  306. <button type="button" className="mr-2 btn btn-secondary" onClick={this.cancel}>
  307. Cancel
  308. </button>
  309. <button type="button" className="btn btn-primary" onClick={this.pasteCodedGrid}>
  310. Done
  311. </button>
  312. </div>
  313. </ModalFooter>
  314. </Modal>
  315. );
  316. }
  317. }
  318. GridEditModal.propTypes = {
  319. onSave: PropTypes.func,
  320. t: PropTypes.func.isRequired,
  321. };
  322. export default withTranslation('translation', { withRef: true })(GridEditModal);