diff --git a/api/.vscode/launch.json b/api/.vscode/launch.json index 0e5cef4..daf8ebb 100644 --- a/api/.vscode/launch.json +++ b/api/.vscode/launch.json @@ -15,7 +15,8 @@ "args": [ "-p 4900", // 研发 - "-g postgres://FashionAdmin:123456@10.8.30.39:5432/Inspection", + // "-g postgres://FashionAdmin:123456@10.8.30.39:5432/Inspection", + "-g postgres://postgres:123456@10.8.16.184:5432/XunJian", // "-g postgres://FashionAdmin:123456@10.8.30.156:5432/inspection", // 测试 // "--apiEmisUrl http://10.8.30.161:1111", diff --git a/api/app/lib/models/patrol_record_issue_handle.js b/api/app/lib/models/patrol_record_issue_handle.js index 99bb99c..0993169 100644 --- a/api/app/lib/models/patrol_record_issue_handle.js +++ b/api/app/lib/models/patrol_record_issue_handle.js @@ -168,6 +168,33 @@ module.exports = dc => { field: "check_image", autoIncrement: false }, + yanshoushijian: { + type: DataTypes.DATE, + allowNull: true, + defaultValue: null, + comment: null, + primaryKey: false, + field: "yanshoushijian", + autoIncrement: false + }, + yanshoucishu: { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: null, + comment: null, + primaryKey: false, + field: "yanshoucishu", + autoIncrement: false + }, + yujingshijian: { + type: DataTypes.DATE, + allowNull: true, + defaultValue: null, + comment: null, + primaryKey: false, + field: "yujingshijian", + autoIncrement: false + }, }, { tableName: "patrol_record_issue_handle", comment: "", diff --git a/api/log/development.log b/api/log/development.log index 5394c5f..f052f00 100644 --- a/api/log/development.log +++ b/api/log/development.log @@ -4194,3 +4194,129 @@ notNull Violation: PatrolPlan.patrolCount cannot be null 2023-02-21 17:02:47.295 - error: path: /patrolTemplate, error: ReferenceError: createUser is not defined 2023-02-21 17:08:28.472 - error: path: /patrolTemplate, error: ReferenceError: createUser is not defined 2023-02-21 17:08:39.999 - error: path: /patrolTemplate, error: ReferenceError: createUser is not defined +2023-03-03 08:50:15.221 - debug: [FS-LOGGER] Init. +2023-03-03 08:50:16.170 - info: [FS-ATTACHMENT] Inject attachment mw into router. +2023-03-03 08:50:16.171 - debug: init fs.attachment and inject it into app(app.fs.attachment) and runtime ctx(ctx.fs.attachment) +2023-03-03 08:50:16.171 - info: [FS-AUTH] Inject auth and api mv into router. +2023-03-03 08:52:27.130 - error: [FS-ERRHD] +{ + message: 'transaction is not defined', + stack: 'ReferenceError: transaction is not defined\n' + + ' at login (d:\\前端学习\\巡检\\Inspection\\api\\app\\lib\\controllers\\auth\\index.js:78:9)' +} +2023-03-03 08:52:27.133 - error: [FS-ERRHD] +{ + message: 'transaction is not defined', + stack: 'ReferenceError: transaction is not defined\n' + + ' at login (d:\\前端学习\\巡检\\Inspection\\api\\app\\lib\\controllers\\auth\\index.js:78:9)' +} +2023-03-03 08:52:27.133 - error: [FS-ERRHD] +{ + message: 'transaction is not defined', + stack: 'ReferenceError: transaction is not defined\n' + + ' at login (d:\\前端学习\\巡检\\Inspection\\api\\app\\lib\\controllers\\auth\\index.js:78:9)' +} +2023-03-03 08:52:27.134 - error: [FS-ERRHD] +{ + message: 'transaction is not defined', + stack: 'ReferenceError: transaction is not defined\n' + + ' at login (d:\\前端学习\\巡检\\Inspection\\api\\app\\lib\\controllers\\auth\\index.js:78:9)' +} +2023-03-03 08:52:27.134 - error: [FS-ERRHD] +{ + message: 'transaction is not defined', + stack: 'ReferenceError: transaction is not defined\n' + + ' at login (d:\\前端学习\\巡检\\Inspection\\api\\app\\lib\\controllers\\auth\\index.js:78:9)' +} +2023-03-03 08:52:27.135 - error: [FS-ERRHD] +{ + message: 'transaction is not defined', + stack: 'ReferenceError: transaction is not defined\n' + + ' at login (d:\\前端学习\\巡检\\Inspection\\api\\app\\lib\\controllers\\auth\\index.js:78:9)' +} +2023-03-03 08:52:48.235 - error: [FS-ERRHD] +{ + message: 'transaction is not defined', + stack: 'ReferenceError: transaction is not defined\n' + + ' at login (d:\\前端学习\\巡检\\Inspection\\api\\app\\lib\\controllers\\auth\\index.js:78:9)' +} +2023-03-03 08:52:48.236 - error: [FS-ERRHD] +{ + message: 'transaction is not defined', + stack: 'ReferenceError: transaction is not defined\n' + + ' at login (d:\\前端学习\\巡检\\Inspection\\api\\app\\lib\\controllers\\auth\\index.js:78:9)' +} +2023-03-03 08:52:48.237 - error: [FS-ERRHD] +{ + message: 'transaction is not defined', + stack: 'ReferenceError: transaction is not defined\n' + + ' at login (d:\\前端学习\\巡检\\Inspection\\api\\app\\lib\\controllers\\auth\\index.js:78:9)' +} +2023-03-03 08:52:48.238 - error: [FS-ERRHD] +{ + message: 'transaction is not defined', + stack: 'ReferenceError: transaction is not defined\n' + + ' at login (d:\\前端学习\\巡检\\Inspection\\api\\app\\lib\\controllers\\auth\\index.js:78:9)' +} +2023-03-03 08:52:48.238 - error: [FS-ERRHD] +{ + message: 'transaction is not defined', + stack: 'ReferenceError: transaction is not defined\n' + + ' at login (d:\\前端学习\\巡检\\Inspection\\api\\app\\lib\\controllers\\auth\\index.js:78:9)' +} +2023-03-03 08:52:48.239 - error: [FS-ERRHD] +{ + message: 'transaction is not defined', + stack: 'ReferenceError: transaction is not defined\n' + + ' at login (d:\\前端学习\\巡检\\Inspection\\api\\app\\lib\\controllers\\auth\\index.js:78:9)' +} +2023-03-03 08:53:09.296 - error: [FS-ERRHD] +{ + message: 'transaction is not defined', + stack: 'ReferenceError: transaction is not defined\n' + + ' at login (d:\\前端学习\\巡检\\Inspection\\api\\app\\lib\\controllers\\auth\\index.js:78:9)' +} +2023-03-03 08:53:09.296 - error: [FS-ERRHD] +{ + message: 'transaction is not defined', + stack: 'ReferenceError: transaction is not defined\n' + + ' at login (d:\\前端学习\\巡检\\Inspection\\api\\app\\lib\\controllers\\auth\\index.js:78:9)' +} +2023-03-03 08:53:09.296 - error: [FS-ERRHD] +{ + message: 'transaction is not defined', + stack: 'ReferenceError: transaction is not defined\n' + + ' at login (d:\\前端学习\\巡检\\Inspection\\api\\app\\lib\\controllers\\auth\\index.js:78:9)' +} +2023-03-03 08:55:19.376 - debug: [FS-LOGGER] Init. +2023-03-03 08:55:19.504 - info: [FS-ATTACHMENT] Inject attachment mw into router. +2023-03-03 08:55:19.505 - debug: init fs.attachment and inject it into app(app.fs.attachment) and runtime ctx(ctx.fs.attachment) +2023-03-03 08:55:19.505 - info: [FS-AUTH] Inject auth and api mv into router. +2023-03-04 15:30:48.068 - debug: [FS-LOGGER] Init. +2023-03-04 15:30:49.010 - info: [FS-ATTACHMENT] Inject attachment mw into router. +2023-03-04 15:30:49.011 - debug: init fs.attachment and inject it into app(app.fs.attachment) and runtime ctx(ctx.fs.attachment) +2023-03-04 15:30:49.011 - info: [FS-AUTH] Inject auth and api mv into router. +2023-03-04 17:42:25.123 - debug: [FS-LOGGER] Init. +2023-03-04 17:42:25.236 - info: [FS-ATTACHMENT] Inject attachment mw into router. +2023-03-04 17:42:25.236 - debug: init fs.attachment and inject it into app(app.fs.attachment) and runtime ctx(ctx.fs.attachment) +2023-03-04 17:42:25.236 - info: [FS-AUTH] Inject auth and api mv into router. +2023-03-04 18:22:09.556 - debug: [FS-LOGGER] Init. +2023-03-04 18:22:09.675 - info: [FS-ATTACHMENT] Inject attachment mw into router. +2023-03-04 18:22:09.676 - debug: init fs.attachment and inject it into app(app.fs.attachment) and runtime ctx(ctx.fs.attachment) +2023-03-04 18:22:09.676 - info: [FS-AUTH] Inject auth and api mv into router. +2023-03-06 08:51:30.658 - debug: [FS-LOGGER] Init. +2023-03-06 08:51:31.673 - info: [FS-ATTACHMENT] Inject attachment mw into router. +2023-03-06 08:51:31.674 - debug: init fs.attachment and inject it into app(app.fs.attachment) and runtime ctx(ctx.fs.attachment) +2023-03-06 08:51:31.674 - info: [FS-AUTH] Inject auth and api mv into router. +2023-03-06 10:16:04.533 - debug: [FS-LOGGER] Init. +2023-03-06 10:16:04.663 - info: [FS-ATTACHMENT] Inject attachment mw into router. +2023-03-06 10:16:04.663 - debug: init fs.attachment and inject it into app(app.fs.attachment) and runtime ctx(ctx.fs.attachment) +2023-03-06 10:16:04.663 - info: [FS-AUTH] Inject auth and api mv into router. +2023-03-06 14:30:39.123 - debug: [FS-LOGGER] Init. +2023-03-06 14:30:39.248 - info: [FS-ATTACHMENT] Inject attachment mw into router. +2023-03-06 14:30:39.248 - debug: init fs.attachment and inject it into app(app.fs.attachment) and runtime ctx(ctx.fs.attachment) +2023-03-06 14:30:39.248 - info: [FS-AUTH] Inject auth and api mv into router. +2023-03-06 14:32:05.704 - debug: [FS-LOGGER] Init. +2023-03-06 14:32:05.817 - info: [FS-ATTACHMENT] Inject attachment mw into router. +2023-03-06 14:32:05.817 - debug: init fs.attachment and inject it into app(app.fs.attachment) and runtime ctx(ctx.fs.attachment) +2023-03-06 14:32:05.818 - info: [FS-AUTH] Inject auth and api mv into router. diff --git a/script/1.0.4/schema/3.updata_resource.sql b/script/1.0.4/schema/3.updata_resource.sql new file mode 100644 index 0000000..54bc14f --- /dev/null +++ b/script/1.0.4/schema/3.updata_resource.sql @@ -0,0 +1,2 @@ +DELETE FROM public.resource WHERE code = 'REPAIR_MANAGE'; +DELETE FROM public.resource WHERE parent_resource = 'REPAIR_MANAGE'; \ No newline at end of file diff --git a/script/1.0.4/schema/4.updata_patrol_record_issue__handle.sql b/script/1.0.4/schema/4.updata_patrol_record_issue__handle.sql new file mode 100644 index 0000000..9225fcb --- /dev/null +++ b/script/1.0.4/schema/4.updata_patrol_record_issue__handle.sql @@ -0,0 +1,3 @@ +ALTER TABLE patrol_record_issue_handle ADD yanshoushijian timestamp(6); +ALTER TABLE patrol_record_issue_handle ADD yanshoucishu integer; +ALTER TABLE patrol_record_issue_handle ADD yujingshijian timestamp(6); diff --git a/web/client/src/app.js b/web/client/src/app.js index 1597273..e737fac 100644 --- a/web/client/src/app.js +++ b/web/client/src/app.js @@ -8,7 +8,7 @@ import ProjectRegime from './sections/projectRegime'; import Organization from './sections/organization'; import PatrolManage from './sections/patrolManage'; import IssueHandle from './sections/issueHandle' - +import { Func } from '$utils'; const App = props => { const { projectName } = props diff --git a/web/client/src/sections/auth/containers/login.js b/web/client/src/sections/auth/containers/login.js index dcba5df..5ca98ad 100644 --- a/web/client/src/sections/auth/containers/login.js +++ b/web/client/src/sections/auth/containers/login.js @@ -11,7 +11,7 @@ import { login, LOGIN_ERROR } from '../actions/auth'; import { ExclamationCircleOutlined } from '@ant-design/icons'; import { Uploads } from '$components' import { LockOutlined, UserOutlined } from '@ant-design/icons'; - +import { Func } from '$utils'; import '../style.less'; const FormItem = Form.Item; @@ -29,6 +29,43 @@ const Login = props => { const [codCountDown, setCodeCountDown] = useState(60) const codCountDownRef = useRef(0) const [form] = Form.useForm(); + + const tourl = () => { + if (Func.isAuthorized("STRU_INFO_CONFIG")) { + return '/projectRegime/information' + } + if (Func.isAuthorized("QR_CODE_CONFIG")) { + return '/projectRegime/qrCode' + } + if (Func.isAuthorized("USER_CONFIG")) { + return '/organization/user' + } + if (Func.isAuthorized("AUTH_CONFIG")) { + return '/organization/authority' + } + if (Func.isAuthorized("PATROL_PLAN_CONFIG")) { + return '/patrolManage/patrolPlan' + } + if (Func.isAuthorized("PATROL_RECORD_VIEW")) { + return '/patrolManage/patrolRecord' + } + if (Func.isAuthorized("CHECKREPORT")) { + return '/patrolManage/patrolReport' + } + if (Func.isAuthorized("CHECKITEMSET")) { + return '/patrolManage/checkItems' +} +if (Func.isAuthorized("CHECKMOULD")) { + return '/patrolManage/patrolTemplate' +} +if (Func.isAuthorized("WENTICHULI")) { + return '/issueHandle' +} + else { + return message.warn('没有任何模块的查看权限') + } + } + useEffect(() => { }, []) @@ -36,7 +73,7 @@ const Login = props => { useEffect(() => { if (user && user.authorized) { - dispatch(push('/projectRegime/information')); + dispatch(push(tourl())); } }, [user]) diff --git a/web/client/src/sections/patrolManage/components/xiafagaojin.js b/web/client/src/sections/patrolManage/components/xiafagaojin.js new file mode 100644 index 0000000..1d4b1cd --- /dev/null +++ b/web/client/src/sections/patrolManage/components/xiafagaojin.js @@ -0,0 +1,93 @@ +import { Button, Form, Input, Modal, Select, DatePicker,Checkbox } from 'antd'; +import React, { useState, useEffect } from 'react'; +import { connect } from 'react-redux'; +import { createPatrolTemplate, delPatrolTemplate, updatePatrolTemplate, getPatrolTemplate } from '../actions/template'; +import moment from 'moment'; + +const { RangePicker } = DatePicker; +const { TextArea } = Input; + +const PlanModal = ({ visible, onCancel, dispatch, type, curRecord, tableRef, checkItemsGroup }) => { + const [form] = Form.useForm(); + const shigutypes = [{value:1,label: '邮件告警'}, + {value:2,label:'短信告警'}] + return ( + { + form.resetFields(); + onCancel(); + }} + onOk={() => { + form + .validateFields() + .then((values) => { + + const params = { + ...values, + } + + if (type === 'create') { + dispatch(createPatrolTemplate(params)).then(res => { + if (res.success) { + tableRef.current.reload(); + form.resetFields(); + onCancel(); + } + }) + } else { + dispatch(updatePatrolTemplate({ + ...params, + id: curRecord.id + })).then(res => { + if (res.success) { + tableRef.current.reload(); + form.resetFields(); + onCancel(); + } + }) + } + }) + .catch((info) => { + console.log('Validate Failed:', info); + }); + }} + > +
c.id) + }} + labelCol={{ span: 5 }} wrapperCol={{ span: 19 }} offe + > + + + + + + +
+
+ ); +}; + +function mapStateToProps (state) { + const { auth, checkItemsGroup } = state + return { + user: auth.user, + checkItemsGroup: checkItemsGroup.data || [] + } +} +export default connect(mapStateToProps)(PlanModal); \ No newline at end of file diff --git a/web/client/src/sections/patrolManage/containers/index.js b/web/client/src/sections/patrolManage/containers/index.js index 8bcbd53..43a6ba5 100644 --- a/web/client/src/sections/patrolManage/containers/index.js +++ b/web/client/src/sections/patrolManage/containers/index.js @@ -5,5 +5,6 @@ import PatrolReocrd from './patrolRecord'; import PatrolReport from './patrolReport'; import CheckItems from './checkItems'; import PlanTemplate from './patrolTemplate'; +import YujingGuanli from './yujingguanli'; -export { PatrolPlan, PatrolReocrd, PatrolReport, CheckItems, PlanTemplate }; \ No newline at end of file +export { PatrolPlan, PatrolReocrd, PatrolReport, CheckItems, PlanTemplate,YujingGuanli }; \ No newline at end of file diff --git a/web/client/src/sections/patrolManage/containers/yujingguanli.js b/web/client/src/sections/patrolManage/containers/yujingguanli.js new file mode 100644 index 0000000..97e9774 --- /dev/null +++ b/web/client/src/sections/patrolManage/containers/yujingguanli.js @@ -0,0 +1,213 @@ +import React, { useState, useRef, useEffect } from 'react'; +import { connect } from 'react-redux'; +import { Button, Popconfirm, Tag,Tabs } from 'antd'; +import ProTable from '@ant-design/pro-table'; +import Xiafagaojin from '../components/xiafagaojin'; +import { createPatrolTemplate, delPatrolTemplate, updatePatrolTemplate, getPatrolTemplate } from '../actions/template'; +import { getCheckItemsGroup } from '../actions/checkItems'; +import moment from 'moment'; +function YujingGuanli (props) { + const { dispatch, user,actions } = props; + const tableRef = useRef(); + const format = 'YYYY-MM-DD HH:mm:ss' + const { patrolManage } = actions + const [dataSource, setDataSource] = useState([{}]); + const [visible, setVisible] = useState(false); + const [type, setType] = useState(); + const [curRecord, setCurRecord] = useState(); + const [data,setdata]= useState([]) + const [tableList, settableList] = useState([]) + const [name, setName] = useState(''); + const [curState, setCurState] = useState('全部'); + const times = [moment().subtract(70, 'years').format(format), moment().format(format)] + const [search, setSearch] = useState({ name: null, time: [times[0], times[1]], state: 'null' }) + const STATE_TEXT = { 1: '待制定计划', 2: '待审核', 3: '计划驳回', 4: '待维修', 5: '待验收', 6: '验收通过', 7: '验收不通过', } + const onChange = (key) => { + console.log(key); + }; + const renderOptionText = (currentState) => { + let text = '待制定计划' + + return STATE_TEXT[currentState] || text + } + const queryData = () => { + dispatch(patrolManage.records(`patrolRecord/all/${times[0]}/${times[1]}/true/null`)).then(res => { + if (res.success) { + console.log(res,'水平') + let obj = {} + res?.payload?.data?.map(i=>{ + if(obj[i?.points?.project?.id]){ + // if(obj[i?.points?.project?.id.toString()][i.pointId.toString()]){ + // obj[i?.points?.project?.id.toString()][i.pointId.toString()].ponintname=i.points?.itemData?.name + // obj[i?.points?.project?.id.toString()][i.pointId.toString()].num=obj[i?.points?.project?.id.toString()][i.pointId.toString()].num+i?.patrolRecordIssueHandles[0]?.state==6?1:0 + + // }else{ + // obj[i?.points?.project?.id.toString()][i.pointId.toString()].ponintname=i.points?.itemData?.name + // obj[i?.points?.project?.id.toString()][i.pointId.toString()].num=i?.patrolRecordIssueHandles[0]?.state==6?1:0 + // } + obj[i?.points?.project?.id].push({pointId:i.pointId,pointname:i.points.itemData.name}) + // i?patrolRecordIssueHandles[0]?.state==6 + obj[i?.points?.project?.id].num= obj[i?.points?.project?.id].num + i?.patrolRecordIssueHandles[0]?.state==6 ?1:0 + }else{ + obj[i?.points?.project?.id]={name:i?.points?.project?.name,num:i?.patrolRecordIssueHandles[0]?.state==6 ?1:0 } + + } + console.log(obj,'obj') + }) + + } + }) + } + useEffect(() => { + // dispatch(patrolManage.records(`patrolRecord/all/null/null/true/null`)).then(res=>{ + // let obj = {} + // res?.payload?.data?.map(i=>{ + // if(obj[i?.points?.project?.id]){ + // obj[i?.points?.project?.id].name=i?.points?.project?.name; + // obj[i?.points?.project?.id].num=obj[i?.points?.project?.id].num +1 + // }else{ + // obj[i?.points?.project?.id]={name:i?.points?.project?.name,num:1} + + // } + // }) + + // settableList(name != null ? res.payload.data?.filter(v => + // (v.points.user.name.indexOf(name) != -1 || v.points.project.name.indexOf(name) != -1)) + // .filter(x => curState == '全部' || curState == renderOptionText(x?.patrolRecordIssueHandles[0]?.state)) + // .map(v => ({ ...v, key: v.id })) : res.payload.data?.map(v => ({ ...v, key: v.id }))) + // const t1 = Object.keys(obj).map(i=>{ + // return {id:i,name:obj[i].name,num:obj[i].num} + // }) + // console.log(obj,'obj') + // console.log(res,'res') + // }) + + queryData() + dispatch(getCheckItemsGroup()) + }, []) +console.log(tableList,'tablist') + const columns = [{ + title: '结构物名称', + dataIndex: 'name', + key: 'name', + // search: false, + ellipsis: true, + }, { + title: '点位名称', + dataIndex: 'describe', + key: 'describe', + search: false, + ellipsis: true + }, { + title: '异常次数', + dataIndex: 'user.name', + key: 'user.name', + ellipsis: true, + search: false, + render: (t, r, i) => { + return r.user ? r.user.name : '-' + } + }, { + title: '产生时间', + dataIndex: 'checkItems', + key: 'checkItems', + ellipsis: true, + search: false, + render: (_, r) => { + return r?.checkItems ? r?.checkItems.map(c => {c.name}) : '-' + } + }, { + title: '更新时间', + dataIndex: 'checkItems', + key: 'checkItems', + search: false, + ellipsis: true, + render: (_, r) => { + return r?.checkItems ? r?.checkItems.map(c => {c.name}) : '-' + } + }, { + title: '操作', + dataIndex: 'action', + key: 'action', + search: false, + width: 200, + render: (_, record) => { + return <> + + + + }, + }]; + + return ( + <> + { + const res = await dispatch(getPatrolTemplate(params)); + setDataSource(res?.payload.data?.rows); + return { ...res }; + }} + + // toolBarRender={() => [ + // + // ]} + />, + }, + { + label: `已告警`, + key: '2', + children: `Content of Tab Pane 2`, + } + ]} + /> + { + visible ? + { + setVisible(false); + setCurRecord({}) + }} + tableRef={tableRef} + /> : null + } + + ) +} + +function mapStateToProps (state) { + const { auth, global } = state + return { + user: auth.user, + actions: global.actions, + } +} +export default connect(mapStateToProps)(YujingGuanli); diff --git a/web/client/src/sections/patrolManage/nav-item.js b/web/client/src/sections/patrolManage/nav-item.js index 4951534..8dc3592 100644 --- a/web/client/src/sections/patrolManage/nav-item.js +++ b/web/client/src/sections/patrolManage/nav-item.js @@ -26,6 +26,9 @@ export function getNavItem (user, dispatch) { {Func.isAuthorized('CHECKMOULD') && 巡检模板 } + { + 预警管理 + } ); } \ No newline at end of file diff --git a/web/client/src/sections/patrolManage/routes.js b/web/client/src/sections/patrolManage/routes.js index fd8190f..6e4df65 100644 --- a/web/client/src/sections/patrolManage/routes.js +++ b/web/client/src/sections/patrolManage/routes.js @@ -1,5 +1,5 @@ 'use strict'; -import { PatrolPlan, PatrolReocrd, PatrolReport, CheckItems, PlanTemplate } from './containers'; +import { PatrolPlan, PatrolReocrd, PatrolReport, CheckItems, PlanTemplate ,YujingGuanli} from './containers'; export default [{ type: 'inner', @@ -32,6 +32,13 @@ export default [{ key: 'patrolTemplate', component: PlanTemplate, breadcrumb: '巡检模板', - }] + }, + { + path: '/yujingguanli', + key: 'yujingguanli', + component: YujingGuanli, + breadcrumb: '预警管理', + } + ] } }]; \ No newline at end of file