GridEditModal.jsx 13 KB

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