Advertisement
Guest User

Untitled

a guest
Jun 16th, 2019
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.72 KB | None | 0 0
  1. import React from "react";
  2. import _ from "lodash";
  3. import {MuiThemeProvider, withStyles} from "@material-ui/core/styles";
  4. import {theme} from "../saasintegrations/theme.js"; //TODO refactor
  5. import MediaTab from "./tabs/media_tab/MediaTab.jsx";
  6. import HistoryTab from "./tabs/history_tab/HistoryTabWrapper.jsx";
  7. import DialogTitle from "@material-ui/core/DialogTitle";
  8. import Dialog from "@material-ui/core/Dialog";
  9. import Tabs from "@material-ui/core/Tabs";
  10. import Tab from "@material-ui/core/Tab";
  11. import Close from "@material-ui/icons/Close";
  12. import Snackbar from "./componentsUtils/Snackbar.jsx";
  13. import {
  14. onAutocomplete,
  15. getContractDetails,
  16. getContractFromArchive,
  17. getContractFromHistory,
  18. restoreContract,
  19. getContractMeta,
  20. getErrorsModel,
  21. getFieldList,
  22. isMandatoryEmpty,
  23. fieldNotVisible,
  24. getContractMedia,
  25. sendContractMedia,
  26. setAsContractDisplayPhoto,
  27. deleteContractMedia,
  28. shouldShowByRelational,
  29. createContract,
  30. updateContract,
  31. getHistoryList,
  32. wfTriggerCheck,
  33. getInitialContractDetails,
  34. getSaveValue,
  35. pickRelevantData,
  36. hasChangesToSave,
  37. isEditable,
  38. formatBool,
  39. getFieldsConfiguredOnSB,
  40. getInitialVisibleFields
  41. } from "./ContractDetailUtils";
  42. import InfoTab from "./contracts/InfoTab.jsx";
  43. import FieldsList from "./saas/FieldsList.jsx"; //TODO move to common
  44. import UsersTab from "./tabs/contracts_users/UsersTab";
  45. import env from "../util/Environment.js";
  46. import {ARCHIVE, EDIT, NEW, VERSION, VIEW} from "./constants";
  47.  
  48. const maxWidth = 1360;
  49. const maxHeight = 944;
  50.  
  51. const tabs = [
  52. {label: "Information", id: "info"},
  53. {label: "Users", id: "users"},
  54. {label: "Media", id: "media"},
  55. {label: "History", id: "history"}
  56. ];
  57.  
  58. const styles = {
  59. dialogTitle: {
  60. height: 25,
  61. display: "flex",
  62. justifyContent: "space-between",
  63. alignItems: "center",
  64. backgroundColor: "#f5f5f5"
  65. },
  66. dialogSaasName: {
  67. fontSize: 20,
  68. fontWeight: "bold",
  69. color: "#222"
  70. },
  71. closeIcon: {
  72. color: "#8a8a8a",
  73. cursor: "pointer"
  74. },
  75. paper: {
  76. position: "relative",
  77. maxWidth: maxWidth,
  78. maxHeight: maxHeight,
  79. overflow: "hidden",
  80. height: "calc(100% - 40px)",
  81. width: "100%",
  82. "& *": {
  83. fontFamily: "Roboto"
  84. }
  85. },
  86. tabsContainer: {
  87. margin: "0 12px"
  88. },
  89. tabsRoot: {
  90. backgroundColor: "#f5f5f5"
  91. },
  92. selectedTab: {
  93. color: "#1f1f1f"
  94. },
  95. disabledTab: {
  96. color: "#e0e0e0"
  97. },
  98. rootTab: {
  99. minWidth: 0,
  100. fontSize: "14px",
  101. fontWeight: 500,
  102. },
  103. snackBarError: {
  104. marginBottom: 20
  105. }
  106. };
  107.  
  108. class ContractDetailsPopup extends React.Component {
  109. constructor(props) {
  110. super(props);
  111. this.state = {
  112. mode: props.mode,
  113. contract_id: props.contract_id,
  114. error: false,
  115. errorMessage: "",
  116. open: props.open,
  117. showActions: false,
  118. currentTab: "info",
  119. meta: {},
  120. errorModel: {},
  121. data: {},
  122. origData: {},
  123. media: [],
  124. history: [],
  125. contractsMeta: {},
  126. workflowList: [],
  127. dateFormat: "MM/DD/YY",
  128. visibleFields: getInitialVisibleFields()
  129. };
  130.  
  131. this.loadData();
  132. }
  133.  
  134. componentWillReceiveProps(nextProps) {
  135. this.setState({
  136. currentTab: "info",
  137. open: nextProps.open,
  138. media: [],
  139. history: [],
  140. showActions: false
  141. });
  142. }
  143.  
  144. render() {
  145. const {classes} = this.props;
  146. const {currentTab, open, data, error, errorMessage} = this.state;
  147. return (<MuiThemeProvider theme={theme}>
  148. <Dialog
  149. aria-labelledby="simple-dialog-title"
  150. open={open}
  151. classes={{
  152. paper: classes.paper
  153. }}
  154. >
  155. <DialogTitle
  156. id="simple-dialog-title"
  157. disableTypography
  158. classes={{
  159. root: classes.dialogTitle
  160. }}
  161. >
  162. <h2 className={classes.dialogSaasName}>
  163. {data.saas_name}
  164. </h2>
  165. <div>
  166. <Close onClick={this.handleClose} className={classes.closeIcon}/>
  167. </div>
  168. </DialogTitle>
  169. <Tabs
  170. value={currentTab}
  171. indicatorColor="primary"
  172. style={{color: "#09c"}}
  173. onChange={this.changeTab}
  174. classes={{
  175. flexContainer: classes.tabsContainer,
  176. root: classes.tabsRoot
  177. }}
  178. >
  179. {this.getTabs()}
  180. </Tabs>
  181. {this.getTabsContent(currentTab)}
  182. <Snackbar
  183. style={{marginBottom: 20}}
  184. open={error}
  185. message={errorMessage}
  186. handleClose={this.onCloseSnackbar}
  187. />
  188. </Dialog>
  189. </MuiThemeProvider>);
  190. }
  191.  
  192. loadData = () => {
  193. $.when(
  194. getContractMeta(),
  195. this.getDateFormat()
  196. ).then(([meta], dateFormat) => {
  197. return this.getDetails(meta).then((data) => {
  198. const errorModel = getErrorsModel(meta);
  199. this.setState({
  200. meta,
  201. origData: _.cloneDeep(data),
  202. data,
  203. errorModel,
  204. showActions: false,
  205. dateFormat
  206. });
  207. return getFieldsConfiguredOnSB("CONTRACTS", getInitialVisibleFields())
  208. .then(visibleFields => {
  209. this.setState({visibleFields});
  210. });
  211. });
  212. });
  213. };
  214. getDetails = (meta) => {
  215. const {parent_saas_id} = this.props;
  216. const {mode, contract_id} = this.state;
  217. if (mode == NEW) {
  218. let initialData = getInitialContractDetails(meta);
  219. if (parent_saas_id) {
  220. initialData.saas_id = parent_saas_id;
  221. }
  222. return Promise.resolve(initialData);
  223. }
  224. if (mode == ARCHIVE) {
  225. return getContractFromArchive(contract_id);
  226. }
  227. return getContractDetails(contract_id);
  228. };
  229. changeTab = (event, value) => {
  230. this.setState({currentTab: value});
  231. };
  232.  
  233. getTabs = () => {
  234. const {classes: {rootTab: root, selectedTab: selected, disabledTab: disabled}} = this.props;
  235. const {showActions, currentTab, mode} = this.state;
  236.  
  237. return tabs.map(({label, id}) => {
  238. let disableTab = currentTab !== id && showActions;
  239. if (mode == NEW || mode == ARCHIVE || mode == VERSION && id !== "info") {
  240. disableTab = true;
  241. }
  242. return <Tab
  243. key={id}
  244. value={id}
  245. disabled={disableTab}
  246. label={label}
  247. classes={{root, selected, disabled}}
  248. />;
  249. });
  250. };
  251. getTabsContent = (currentTab) => {
  252. const {
  253. showActions, media, data, history, workflowList,
  254. errorModel, mode, contract_id, dateFormat, error
  255. } = this.state;
  256. if (currentTab === "info") {
  257. return <InfoTab
  258. mode={mode}
  259. handleRestore={this.handleRestore}
  260. workflowList={workflowList}
  261. showActions={showActions}
  262. handleCancel={this.handleCancel}
  263. handleSave={this.handleSave}
  264. fieldsList={<FieldsList
  265. mode={mode}
  266. fields={this.getVisibleFields()}
  267. errorModel={errorModel}
  268. handleChange={this.handleChange}
  269. onBlur={this.validateField}
  270. onAutocomplete={onAutocomplete}
  271. onAddValue={this.onAddValue}
  272. width={"240px"}
  273. />}
  274. />;
  275. } else if (currentTab === "media") {
  276. return <MediaTab
  277. getMedia={this.getMedia}
  278. sendMedia={this.sendMedia}
  279. deleteMedia={this.deleteMedia}
  280. setAsDisplayPhoto={this.setAsDisplayPhoto}
  281. mediaList={media}
  282. />;
  283. } else if (currentTab === "history") {
  284. return <HistoryTab
  285. previewVersion={this.previewVersionFromHistory}
  286. getHistoryList={this.getHistoryList}
  287. historyList={history}
  288. />;
  289. } else if (currentTab === "users") {
  290. return <UsersTab
  291. error={error}
  292. data={data}
  293. contract_id={contract_id}
  294. dateFormat={dateFormat}
  295. failCallback={this.onOpenErrorMsg}
  296. />;
  297. }
  298. };
  299.  
  300. getDateFormat = () => {
  301. return env.getDateFormat({moment: true});
  302. };
  303.  
  304. getVisibleFields = () => {
  305. const {meta, data, mode, visibleFields} = this.state;
  306. return getFieldList(meta, data, mode, visibleFields);
  307. };
  308.  
  309. onAddValue = (id, value) => {
  310. this.handleChange({id, value: {value, label: value}});
  311. };
  312.  
  313. handleChange = ({id, value}) => {
  314. const {meta} = this.state;
  315. let updatedData = _.set(_.clone(this.state.data), id, getSaveValue(meta, id, value));
  316. const hasChanges = hasChangesToSave(pickRelevantData(meta, this.state.origData), pickRelevantData(meta, updatedData));
  317. this.setState({data: updatedData, showActions: hasChanges}, () => {
  318. this.validateField(id, "change");
  319. this.wfTriggerCheck();
  320. });
  321. };
  322.  
  323. validateField = (id, event) => {
  324. let {errorModel, meta, data} = this.state;
  325. if (this.shouldValidateEvent(id, event) && isMandatoryEmpty(meta, id, data)) {
  326. errorModel[id] = "This is a mandatory field";
  327. } else {
  328. errorModel[id] = "";
  329. }
  330. this.setState({errorModel});
  331. };
  332. shouldValidateEvent = (id, event) => {
  333. let {errorModel} = this.state;
  334. return event === "blur" || (event === "change" && !!errorModel[id]);
  335. };
  336. validateOnSave = () => {
  337. let {meta, data, mode} = this.state;
  338. let errorModel = {};
  339. _.forEach(data, ((value, id) => {
  340. if (isMandatoryEmpty(meta, id, data)) {
  341. errorModel[id] = "This is a mandatory field";
  342. }
  343. if (fieldNotVisible(meta, id, data)) {
  344. errorModel[id] = "";
  345. }
  346. if (mode == NEW && (id == "contract_type" || !isEditable(formatBool(meta[id].editable), mode))) {
  347. errorModel[id] = ""; //Some fields are populated during creation
  348. }
  349. }));
  350. let stateApplied = $.Deferred();
  351. this.setState({errorModel}, () => stateApplied.resolve());
  352. return stateApplied;
  353. };
  354.  
  355. handleCancel = () => {
  356. this.setState({
  357. data: _.cloneDeep(this.state.origData),
  358. errorModel: {},
  359. showActions: false,
  360. workflowList: []
  361. });
  362. };
  363.  
  364. handleClose = () => {
  365. this.setState({open: false});
  366. };
  367.  
  368. handleSave = () => {
  369. const {contract_id} = this.state;
  370. this.validateOnSave().then(() => {
  371. if (!this.hasErrors()) {
  372. let {meta, data, mode} = this.state;
  373. if (mode == NEW) {
  374. return createContract(pickRelevantData(meta, data))
  375. .then(({contract_id}) => {
  376. this.setState({contract_id, mode: EDIT}, () => {
  377. this.loadData();
  378. });
  379. });
  380. }
  381. return updateContract(contract_id, pickRelevantData(meta, data)).then(() => {
  382. this.setState({showActions: false}, this.loadData);
  383. }).fail(oom.util.failCallback);
  384. }
  385. });
  386. };
  387.  
  388. handleRestore = () => {
  389. const {contract_id} = this.state;
  390. restoreContract(contract_id).then(() => {
  391. this.setState({mode: EDIT})
  392. }).fail(oom.util.failCallback);
  393. };
  394.  
  395. previewVersionFromHistory = (version) => {
  396. const {contract_id} = this.state;
  397. getContractFromHistory(contract_id, version).then((data) => {
  398. this.setState({data, mode: VERSION, currentTab: "info"})
  399. }).fail(oom.util.failCallback);
  400. };
  401.  
  402. hasErrors = () => {
  403. return _.some(this.state.errorModel, (field) => {
  404. return !!field;
  405. });
  406. };
  407.  
  408. wfTriggerCheck = () => {
  409. const {meta, data, mode, contract_id} = this.state;
  410. return wfTriggerCheck(contract_id, pickRelevantData(meta, data), mode)
  411. .then((workflowList) => {
  412. this.setState({workflowList});
  413. });
  414. };
  415.  
  416. getMedia = () => {
  417. const {contract_id} = this.state;
  418. return getContractMedia(contract_id).then((media) => this.setState({media}));
  419. };
  420. sendMedia = (data) => {
  421. const {contract_id} = this.state;
  422. return sendContractMedia(contract_id, data);
  423. };
  424. deleteMedia = (id) => {
  425. const {contract_id} = this.state;
  426. return deleteContractMedia(contract_id, id);
  427. };
  428. setAsDisplayPhoto = (id) => {
  429. const {contract_id} = this.state;
  430.  
  431. return setAsContractDisplayPhoto(contract_id, id);
  432. };
  433. getHistoryList = (skipCount, params) => {
  434. const {contract_id} = this.state;
  435. return getHistoryList(contract_id, skipCount, params)
  436. .then(({data: history, facets}) => {
  437. if (skipCount) {
  438. this.setState({history: this.state.history.concat(history)});
  439. } else {
  440. this.setState({history});
  441. }
  442. return [facets, skipCount];
  443. });
  444. };
  445.  
  446. clearContractsList = () => {
  447. this.setState({contracts: []});
  448. };
  449.  
  450. onOpenErrorMsg = (errorMessage) => {
  451. this.setState({error: true, errorMessage});
  452. };
  453.  
  454. onCloseSnackbar = () => {
  455. this.setState({error: false, errorMessage: ""});
  456. };
  457. }
  458.  
  459. export default withStyles(styles)(ContractDetailsPopup);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement