module_index.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  1. package modules
  2. import (
  3. "database/sql"
  4. _ "github.com/go-sql-driver/mysql"
  5. "fmt"
  6. "html"
  7. "html/template"
  8. "os"
  9. "strconv"
  10. "golang-fave/assets"
  11. "golang-fave/consts"
  12. "golang-fave/engine/builder"
  13. "golang-fave/engine/wrapper"
  14. "golang-fave/utils"
  15. )
  16. func (this *Modules) RegisterModule_Index() *Module {
  17. return this.newModule(MInfo{
  18. WantDB: true,
  19. Mount: "index",
  20. Name: "Pages",
  21. Order: 0,
  22. Icon: assets.SysSvgIconPage,
  23. Sub: &[]MISub{
  24. {Mount: "default", Name: "List of Pages", Show: true, Icon: assets.SysSvgIconList},
  25. {Mount: "add", Name: "Add New Page", Show: true, Icon: assets.SysSvgIconPlus},
  26. {Mount: "modify", Name: "Modify Page", Show: false},
  27. },
  28. }, func(wrap *wrapper.Wrapper) {
  29. // Front-end
  30. /*
  31. wrap.RenderFrontEnd("index", consts.TmplDataModIndex{
  32. MetaTitle: "Meta Title",
  33. MetaKeywords: "Meta Keywords",
  34. MetaDescription: "Meta Description",
  35. MainMenuItems: []consts.TmplDataMainMenuItem{
  36. {Name: "Home", Link: "/", Active: true},
  37. {Name: "Item 1", Link: "/#1", Active: false},
  38. {Name: "Item 2", Link: "/#2", Active: false},
  39. {Name: "Item 3", Link: "/#3", Active: false},
  40. },
  41. })
  42. */
  43. row := &utils.MySql_page{}
  44. err := wrap.DB.QueryRow(`
  45. SELECT
  46. id,
  47. user,
  48. name,
  49. alias,
  50. content,
  51. meta_title,
  52. meta_keywords,
  53. meta_description,
  54. UNIX_TIMESTAMP(datetime) as datetime,
  55. active
  56. FROM
  57. pages
  58. WHERE
  59. active = 1 and
  60. alias = ?
  61. LIMIT 1;`,
  62. wrap.R.URL.Path,
  63. ).Scan(
  64. &row.A_id,
  65. &row.A_user,
  66. &row.A_name,
  67. &row.A_alias,
  68. &row.A_content,
  69. &row.A_meta_title,
  70. &row.A_meta_keywords,
  71. &row.A_meta_description,
  72. &row.A_datetime,
  73. &row.A_active,
  74. )
  75. if err != nil && err != sql.ErrNoRows {
  76. // Error 500
  77. utils.SystemErrorPageEngine(wrap.W, err)
  78. return
  79. } else if err == sql.ErrNoRows {
  80. // Error 404
  81. utils.SystemErrorPage404(wrap.W)
  82. return
  83. }
  84. // Replace title with page name
  85. if row.A_meta_title == "" {
  86. row.A_meta_title = row.A_name
  87. }
  88. // Which template
  89. tmpl_name := "index"
  90. if wrap.R.URL.Path != "/" {
  91. tmpl_name = "page"
  92. }
  93. // Render template
  94. wrap.RenderFrontEnd(tmpl_name, consts.TmplDataModIndex{
  95. Name: row.A_name,
  96. Alias: row.A_alias,
  97. Content: template.HTML(row.A_content),
  98. MetaTitle: row.A_meta_title,
  99. MetaKeywords: row.A_meta_keywords,
  100. MetaDescription: row.A_meta_description,
  101. })
  102. }, func(wrap *wrapper.Wrapper) (string, string, string) {
  103. content := ""
  104. sidebar := ""
  105. if wrap.CurrSubModule == "" || wrap.CurrSubModule == "default" {
  106. content += this.getBreadCrumbs(wrap, &[]consts.BreadCrumb{
  107. {Name: "List of Pages"},
  108. })
  109. content += builder.DataTable(wrap, "pages", "id", "DESC", &[]builder.DataTableRow{
  110. {
  111. DBField: "id",
  112. },
  113. {
  114. DBField: "name",
  115. NameInTable: "Page / Alias",
  116. CallBack: func(values *[]string) string {
  117. name := `<a href="/cp/` + wrap.CurrModule + `/modify/` + (*values)[0] + `/">` + html.EscapeString((*values)[1]) + `</a>`
  118. alias := html.EscapeString((*values)[2])
  119. return `<div>` + name + `</div><div><small>` + alias + `</small></div>`
  120. },
  121. },
  122. {
  123. DBField: "alias",
  124. },
  125. {
  126. DBField: "datetime",
  127. DBExp: "UNIX_TIMESTAMP(`datetime`)",
  128. NameInTable: "Date / Time",
  129. CallBack: func(values *[]string) string {
  130. t := int64(utils.StrToInt((*values)[3]))
  131. return `<div>` + utils.UnixTimestampToFormat(t, "02.01.2006") + `</div>` +
  132. `<div><small>` + utils.UnixTimestampToFormat(t, "15:04:05") + `</small></div>`
  133. },
  134. },
  135. {
  136. DBField: "active",
  137. NameInTable: "Active",
  138. CallBack: func(values *[]string) string {
  139. return builder.CheckBox(utils.StrToInt((*values)[4]))
  140. },
  141. },
  142. }, func(values *[]string) string {
  143. return builder.DataTableAction(&[]builder.DataTableActionRow{
  144. {
  145. Icon: assets.SysSvgIconView,
  146. Href: (*values)[2],
  147. Hint: "View",
  148. Target: "_blank",
  149. },
  150. {
  151. Icon: assets.SysSvgIconEdit,
  152. Href: "/cp/" + wrap.CurrModule + "/modify/" + (*values)[0] + "/",
  153. Hint: "Edit",
  154. },
  155. {
  156. Icon: assets.SysSvgIconRemove,
  157. Href: "javascript:fave.ActionDataTableDelete(this,'index-delete','" +
  158. (*values)[0] + "','Are you sure want to delete page?');",
  159. Hint: "Delete",
  160. },
  161. })
  162. }, "/cp/"+wrap.CurrModule+"/")
  163. } else if wrap.CurrSubModule == "add" || wrap.CurrSubModule == "modify" {
  164. if wrap.CurrSubModule == "add" {
  165. content += this.getBreadCrumbs(wrap, &[]consts.BreadCrumb{
  166. {Name: "Add New Page"},
  167. })
  168. } else {
  169. content += this.getBreadCrumbs(wrap, &[]consts.BreadCrumb{
  170. {Name: "Modify Page"},
  171. })
  172. }
  173. data := utils.MySql_page{
  174. A_id: 0,
  175. A_user: 0,
  176. A_name: "",
  177. A_alias: "",
  178. A_content: "",
  179. A_meta_title: "",
  180. A_meta_keywords: "",
  181. A_meta_description: "",
  182. A_datetime: 0,
  183. A_active: 0,
  184. }
  185. if wrap.CurrSubModule == "modify" {
  186. if len(wrap.UrlArgs) != 3 {
  187. return "", "", ""
  188. }
  189. if !utils.IsNumeric(wrap.UrlArgs[2]) {
  190. return "", "", ""
  191. }
  192. err := wrap.DB.QueryRow(`
  193. SELECT
  194. id,
  195. user,
  196. name,
  197. alias,
  198. content,
  199. meta_title,
  200. meta_keywords,
  201. meta_description,
  202. active
  203. FROM
  204. pages
  205. WHERE
  206. id = ?
  207. LIMIT 1;`,
  208. utils.StrToInt(wrap.UrlArgs[2]),
  209. ).Scan(
  210. &data.A_id,
  211. &data.A_user,
  212. &data.A_name,
  213. &data.A_alias,
  214. &data.A_content,
  215. &data.A_meta_title,
  216. &data.A_meta_keywords,
  217. &data.A_meta_description,
  218. &data.A_active,
  219. )
  220. if err != nil {
  221. return "", "", ""
  222. }
  223. }
  224. content += builder.DataForm(wrap, []builder.DataFormField{
  225. {
  226. Kind: builder.DFKHidden,
  227. Name: "action",
  228. Value: "index-modify",
  229. },
  230. {
  231. Kind: builder.DFKHidden,
  232. Name: "id",
  233. Value: utils.IntToStr(data.A_id),
  234. },
  235. {
  236. Kind: builder.DFKText,
  237. Caption: "Page Name",
  238. Name: "name",
  239. Value: data.A_name,
  240. },
  241. {
  242. Kind: builder.DFKText,
  243. Caption: "Page Alias",
  244. Name: "alias",
  245. Value: data.A_alias,
  246. Hint: "Example: /about-us/ or /about-us.html or /about/team.html",
  247. },
  248. {
  249. Kind: builder.DFKTextArea,
  250. Caption: "Page Content",
  251. Name: "content",
  252. Value: data.A_content,
  253. },
  254. {
  255. Kind: builder.DFKText,
  256. Caption: "Meta Title",
  257. Name: "meta_title",
  258. Value: data.A_meta_title,
  259. },
  260. {
  261. Kind: builder.DFKText,
  262. Caption: "Meta Keywords",
  263. Name: "meta_keywords",
  264. Value: data.A_meta_keywords,
  265. },
  266. {
  267. Kind: builder.DFKTextArea,
  268. Caption: "Meta Description",
  269. Name: "meta_description",
  270. Value: data.A_meta_description,
  271. },
  272. {
  273. Kind: builder.DFKCheckBox,
  274. Caption: "Active",
  275. Name: "active",
  276. Value: utils.IntToStr(data.A_active),
  277. },
  278. {
  279. Kind: builder.DFKMessage,
  280. },
  281. {
  282. Kind: builder.DFKSubmit,
  283. Value: "Add",
  284. Target: "add-edit-button",
  285. },
  286. })
  287. if wrap.CurrSubModule == "add" {
  288. sidebar += `<button class="btn btn-primary btn-sidebar" id="add-edit-button">Add</button>`
  289. } else {
  290. sidebar += `<button class="btn btn-primary btn-sidebar" id="add-edit-button">Save</button>`
  291. }
  292. }
  293. return this.getSidebarModules(wrap), content, sidebar
  294. })
  295. }
  296. func (this *Modules) RegisterAction_IndexModify() *Action {
  297. return this.newAction(AInfo{
  298. WantDB: true,
  299. Mount: "index-modify",
  300. WantAdmin: true,
  301. }, func(wrap *wrapper.Wrapper) {
  302. pf_id := wrap.R.FormValue("id")
  303. pf_name := wrap.R.FormValue("name")
  304. pf_alias := wrap.R.FormValue("alias")
  305. pf_content := wrap.R.FormValue("content")
  306. pf_meta_title := wrap.R.FormValue("meta_title")
  307. pf_meta_keywords := wrap.R.FormValue("meta_keywords")
  308. pf_meta_description := wrap.R.FormValue("meta_description")
  309. pf_active := wrap.R.FormValue("active")
  310. if pf_active == "" {
  311. pf_active = "0"
  312. }
  313. if !utils.IsNumeric(pf_id) {
  314. wrap.MsgError(`Inner system error`)
  315. return
  316. }
  317. if pf_name == "" {
  318. wrap.MsgError(`Please specify page name`)
  319. return
  320. }
  321. if pf_alias == "" {
  322. pf_alias = utils.GenerateAlias(pf_name)
  323. }
  324. if !utils.IsValidAlias(pf_alias) {
  325. wrap.MsgError(`Please specify correct page alias`)
  326. return
  327. }
  328. if pf_id == "0" {
  329. // Add new page
  330. _, err := wrap.DB.Query(
  331. `INSERT INTO pages SET
  332. user = ?,
  333. name = ?,
  334. alias = ?,
  335. content = ?,
  336. meta_title = ?,
  337. meta_keywords = ?,
  338. meta_description = ?,
  339. datetime = ?,
  340. active = ?
  341. ;`,
  342. wrap.User.A_id,
  343. pf_name,
  344. pf_alias,
  345. pf_content,
  346. pf_meta_title,
  347. pf_meta_keywords,
  348. pf_meta_description,
  349. utils.UnixTimestampToMySqlDateTime(utils.GetCurrentUnixTimestamp()),
  350. pf_active,
  351. )
  352. if err != nil {
  353. wrap.MsgError(err.Error())
  354. return
  355. }
  356. wrap.Write(`window.location='/cp/';`)
  357. } else {
  358. // Update page
  359. _, err := wrap.DB.Query(
  360. `UPDATE pages SET
  361. name = ?,
  362. alias = ?,
  363. content = ?,
  364. meta_title = ?,
  365. meta_keywords = ?,
  366. meta_description = ?,
  367. active = ?
  368. WHERE
  369. id = ?
  370. ;`,
  371. pf_name,
  372. pf_alias,
  373. pf_content,
  374. pf_meta_title,
  375. pf_meta_keywords,
  376. pf_meta_description,
  377. pf_active,
  378. utils.StrToInt(pf_id),
  379. )
  380. if err != nil {
  381. wrap.MsgError(err.Error())
  382. return
  383. }
  384. wrap.Write(`window.location='/cp/index/modify/` + pf_id + `/';`)
  385. }
  386. })
  387. }
  388. func (this *Modules) RegisterAction_IndexDelete() *Action {
  389. return this.newAction(AInfo{
  390. WantDB: true,
  391. Mount: "index-delete",
  392. WantAdmin: true,
  393. }, func(wrap *wrapper.Wrapper) {
  394. pf_id := wrap.R.FormValue("id")
  395. if !utils.IsNumeric(pf_id) {
  396. wrap.MsgError(`Inner system error`)
  397. return
  398. }
  399. // Delete page
  400. _, err := wrap.DB.Query(
  401. `DELETE FROM pages WHERE id = ?;`,
  402. utils.StrToInt(pf_id),
  403. )
  404. if err != nil {
  405. wrap.MsgError(err.Error())
  406. return
  407. }
  408. // Reload current page
  409. wrap.Write(`window.location.reload(false);`)
  410. })
  411. }
  412. func (this *Modules) RegisterAction_IndexMysqlSetup() *Action {
  413. return this.newAction(AInfo{
  414. WantDB: false,
  415. Mount: "index-mysql-setup",
  416. }, func(wrap *wrapper.Wrapper) {
  417. pf_host := wrap.R.FormValue("host")
  418. pf_port := wrap.R.FormValue("port")
  419. pf_name := wrap.R.FormValue("name")
  420. pf_user := wrap.R.FormValue("user")
  421. pf_password := wrap.R.FormValue("password")
  422. if pf_host == "" {
  423. wrap.MsgError(`Please specify host for MySQL connection`)
  424. return
  425. }
  426. if pf_port == "" {
  427. wrap.MsgError(`Please specify host port for MySQL connection`)
  428. return
  429. }
  430. if _, err := strconv.Atoi(pf_port); err != nil {
  431. wrap.MsgError(`MySQL host port must be integer number`)
  432. return
  433. }
  434. if pf_name == "" {
  435. wrap.MsgError(`Please specify MySQL database name`)
  436. return
  437. }
  438. if pf_user == "" {
  439. wrap.MsgError(`Please specify MySQL user`)
  440. return
  441. }
  442. // Try connect to mysql
  443. db, err := sql.Open("mysql", pf_user+":"+pf_password+"@tcp("+pf_host+":"+pf_port+")/"+pf_name)
  444. if err != nil {
  445. wrap.MsgError(err.Error())
  446. return
  447. }
  448. defer db.Close()
  449. err = db.Ping()
  450. if err != nil {
  451. wrap.MsgError(err.Error())
  452. return
  453. }
  454. // Try to install all tables
  455. _, err = db.Query(fmt.Sprintf(
  456. `CREATE TABLE %s.users (
  457. id int(11) NOT NULL AUTO_INCREMENT COMMENT 'AI',
  458. first_name VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'User first name',
  459. last_name VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'User last name',
  460. email VARCHAR(64) NOT NULL COMMENT 'User email',
  461. password VARCHAR(32) NOT NULL COMMENT 'User password (MD5)',
  462. admin int(1) NOT NULL COMMENT 'Is admin user or not',
  463. active int(1) NOT NULL COMMENT 'Is active user or not',
  464. PRIMARY KEY (id)
  465. ) ENGINE = InnoDB;`,
  466. pf_name))
  467. if err != nil {
  468. wrap.MsgError(err.Error())
  469. return
  470. }
  471. _, err = db.Query(fmt.Sprintf(
  472. `CREATE TABLE %s.pages (
  473. id int(11) NOT NULL AUTO_INCREMENT COMMENT 'AI',
  474. user int(11) NOT NULL COMMENT 'User id',
  475. name varchar(255) NOT NULL COMMENT 'Page name',
  476. alias varchar(255) NOT NULL COMMENT 'Page url part',
  477. content text NOT NULL COMMENT 'Page content',
  478. meta_title varchar(255) NOT NULL DEFAULT '' COMMENT 'Page meta title',
  479. meta_keywords varchar(255) NOT NULL DEFAULT '' COMMENT 'Page meta keywords',
  480. meta_description varchar(510) NOT NULL DEFAULT '' COMMENT 'Page meta description',
  481. datetime datetime NOT NULL COMMENT 'Creation date/time',
  482. active int(1) NOT NULL COMMENT 'Is active page or not',
  483. PRIMARY KEY (id)
  484. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;`,
  485. pf_name))
  486. if err != nil {
  487. wrap.MsgError(err.Error())
  488. return
  489. }
  490. _, err = db.Query(fmt.Sprintf(
  491. `ALTER TABLE %s.pages ADD UNIQUE KEY alias (alias);`,
  492. pf_name))
  493. if err != nil {
  494. wrap.MsgError(err.Error())
  495. return
  496. }
  497. // Save mysql config file
  498. err = utils.MySqlConfigWrite(wrap.DConfig+string(os.PathSeparator)+"mysql.json", pf_host, pf_port, pf_name, pf_user, pf_password)
  499. if err != nil {
  500. wrap.MsgError(err.Error())
  501. return
  502. }
  503. // Reload current page
  504. wrap.Write(`window.location.reload(false);`)
  505. })
  506. }
  507. func (this *Modules) RegisterAction_IndexFirstUser() *Action {
  508. return this.newAction(AInfo{
  509. WantDB: true,
  510. Mount: "index-first-user",
  511. }, func(wrap *wrapper.Wrapper) {
  512. pf_first_name := wrap.R.FormValue("first_name")
  513. pf_last_name := wrap.R.FormValue("last_name")
  514. pf_email := wrap.R.FormValue("email")
  515. pf_password := wrap.R.FormValue("password")
  516. if pf_email == "" {
  517. wrap.MsgError(`Please specify user email`)
  518. return
  519. }
  520. if !utils.IsValidEmail(pf_email) {
  521. wrap.MsgError(`Please specify correct user email`)
  522. return
  523. }
  524. if pf_password == "" {
  525. wrap.MsgError(`Please specify user password`)
  526. return
  527. }
  528. _, err := wrap.DB.Query(
  529. `INSERT INTO users SET
  530. first_name = ?,
  531. last_name = ?,
  532. email = ?,
  533. password = MD5(?),
  534. admin = 1,
  535. active = 1
  536. ;`,
  537. pf_first_name,
  538. pf_last_name,
  539. pf_email,
  540. pf_password,
  541. )
  542. if err != nil {
  543. wrap.MsgError(err.Error())
  544. return
  545. }
  546. // Reload current page
  547. wrap.Write(`window.location.reload(false);`)
  548. })
  549. }
  550. func (this *Modules) RegisterAction_IndexUserSignIn() *Action {
  551. return this.newAction(AInfo{
  552. WantDB: true,
  553. Mount: "index-user-sign-in",
  554. }, func(wrap *wrapper.Wrapper) {
  555. pf_email := wrap.R.FormValue("email")
  556. pf_password := wrap.R.FormValue("password")
  557. if pf_email == "" {
  558. wrap.MsgError(`Please specify user email`)
  559. return
  560. }
  561. if !utils.IsValidEmail(pf_email) {
  562. wrap.MsgError(`Please specify correct user email`)
  563. return
  564. }
  565. if pf_password == "" {
  566. wrap.MsgError(`Please specify user password`)
  567. return
  568. }
  569. if wrap.S.GetInt("UserId", 0) > 0 {
  570. wrap.MsgError(`You already logined`)
  571. return
  572. }
  573. var user_id int
  574. err := wrap.DB.QueryRow(
  575. `SELECT
  576. id
  577. FROM
  578. users
  579. WHERE
  580. email = ? and
  581. password = MD5(?) and
  582. admin = 1 and
  583. active = 1
  584. LIMIT 1;`,
  585. pf_email,
  586. pf_password,
  587. ).Scan(
  588. &user_id,
  589. )
  590. if err != nil && err != sql.ErrNoRows {
  591. wrap.MsgError(err.Error())
  592. return
  593. }
  594. if err == sql.ErrNoRows {
  595. wrap.MsgError(`Incorrect email or password`)
  596. return
  597. }
  598. // Save to current session
  599. wrap.S.SetInt("UserId", user_id)
  600. // Reload current page
  601. wrap.Write(`window.location.reload(false);`)
  602. })
  603. }
  604. func (this *Modules) RegisterAction_IndexUserLogout() *Action {
  605. return this.newAction(AInfo{
  606. WantDB: true,
  607. Mount: "index-user-logout",
  608. WantUser: true,
  609. }, func(wrap *wrapper.Wrapper) {
  610. // Reset session var
  611. wrap.S.SetInt("UserId", 0)
  612. // Reload current page
  613. wrap.Write(`window.location.reload(false);`)
  614. })
  615. }
  616. func (this *Modules) RegisterAction_IndexUserUpdateProfile() *Action {
  617. return this.newAction(AInfo{
  618. WantDB: true,
  619. Mount: "index-user-update-profile",
  620. WantUser: true,
  621. }, func(wrap *wrapper.Wrapper) {
  622. pf_first_name := wrap.R.FormValue("first_name")
  623. pf_last_name := wrap.R.FormValue("last_name")
  624. pf_email := wrap.R.FormValue("email")
  625. pf_password := wrap.R.FormValue("password")
  626. if pf_email == "" {
  627. wrap.MsgError(`Please specify user email`)
  628. return
  629. }
  630. if !utils.IsValidEmail(pf_email) {
  631. wrap.MsgError(`Please specify correct user email`)
  632. return
  633. }
  634. if pf_password != "" {
  635. // Update with password if set
  636. _, err := wrap.DB.Query(
  637. `UPDATE users SET
  638. first_name = ?,
  639. last_name = ?,
  640. email = ?,
  641. password = MD5(?)
  642. WHERE
  643. id = ?
  644. ;`,
  645. pf_first_name,
  646. pf_last_name,
  647. pf_email,
  648. pf_password,
  649. wrap.User.A_id,
  650. )
  651. if err != nil {
  652. wrap.MsgError(err.Error())
  653. return
  654. }
  655. } else {
  656. // Update without password if not set
  657. _, err := wrap.DB.Query(
  658. `UPDATE users SET
  659. first_name = ?,
  660. last_name = ?,
  661. email = ?
  662. WHERE
  663. id = ?
  664. ;`,
  665. pf_first_name,
  666. pf_last_name,
  667. pf_email,
  668. wrap.User.A_id,
  669. )
  670. if err != nil {
  671. wrap.MsgError(err.Error())
  672. return
  673. }
  674. }
  675. // Reload current page
  676. wrap.Write(`window.location.reload(false);`)
  677. })
  678. }