module_index.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. package modules
  2. import (
  3. "html"
  4. "net/http"
  5. "golang-fave/engine/assets"
  6. "golang-fave/engine/builder"
  7. "golang-fave/engine/consts"
  8. "golang-fave/engine/fetdata"
  9. "golang-fave/engine/utils"
  10. "golang-fave/engine/wrapper"
  11. )
  12. func (this *Modules) index_GetTemplateSelectOptions(wrap *wrapper.Wrapper, template string) string {
  13. result := ``
  14. // index.html
  15. result += `<option title="index.html" value="index"`
  16. if template == "index" {
  17. result += ` selected`
  18. }
  19. result += `>index.html</option>`
  20. // page.html
  21. result += `<option title="page.html" value="page"`
  22. if template == "" || template == "page" {
  23. result += ` selected`
  24. }
  25. result += `>page.html</option>`
  26. return result
  27. }
  28. func (this *Modules) RegisterModule_Index() *Module {
  29. return this.newModule(MInfo{
  30. Mount: "index",
  31. Name: "Pages",
  32. Order: 0,
  33. Icon: assets.SysSvgIconPage,
  34. Sub: &[]MISub{
  35. {Mount: "default", Name: "List of pages", Show: true, Icon: assets.SysSvgIconList},
  36. {Mount: "add", Name: "Add new page", Show: true, Icon: assets.SysSvgIconPlus},
  37. {Mount: "modify", Name: "Modify page", Show: false},
  38. },
  39. }, func(wrap *wrapper.Wrapper) {
  40. // Front-end
  41. row := &utils.MySql_page{}
  42. rou := &utils.MySql_user{}
  43. err := wrap.DB.QueryRow(
  44. wrap.R.Context(),
  45. `SELECT
  46. fave_pages.id,
  47. fave_pages.user,
  48. fave_pages.template,
  49. fave_pages.name,
  50. fave_pages.alias,
  51. fave_pages.content,
  52. fave_pages.meta_title,
  53. fave_pages.meta_keywords,
  54. fave_pages.meta_description,
  55. UNIX_TIMESTAMP(fave_pages.datetime) as datetime,
  56. fave_pages.active,
  57. fave_users.id,
  58. fave_users.first_name,
  59. fave_users.last_name,
  60. fave_users.email,
  61. fave_users.admin,
  62. fave_users.active
  63. FROM
  64. fave_pages
  65. LEFT JOIN fave_users ON fave_users.id = fave_pages.user
  66. WHERE
  67. fave_pages.active = 1 and
  68. fave_pages.alias = ?
  69. LIMIT 1;`,
  70. wrap.R.URL.Path,
  71. ).Scan(
  72. &row.A_id,
  73. &row.A_user,
  74. &row.A_template,
  75. &row.A_name,
  76. &row.A_alias,
  77. &row.A_content,
  78. &row.A_meta_title,
  79. &row.A_meta_keywords,
  80. &row.A_meta_description,
  81. &row.A_datetime,
  82. &row.A_active,
  83. &rou.A_id,
  84. &rou.A_first_name,
  85. &rou.A_last_name,
  86. &rou.A_email,
  87. &rou.A_admin,
  88. &rou.A_active,
  89. )
  90. if err != nil && err != wrapper.ErrNoRows {
  91. // System error 500
  92. wrap.LogCpError(&err)
  93. utils.SystemErrorPageEngine(wrap.W, err)
  94. return
  95. } else if err == wrapper.ErrNoRows {
  96. // User error 404 page
  97. wrap.RenderFrontEnd("404", fetdata.New(wrap, true, nil, nil), http.StatusNotFound)
  98. return
  99. }
  100. // Render template
  101. wrap.RenderFrontEnd(row.A_template, fetdata.New(wrap, false, row, rou), http.StatusOK)
  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(
  110. wrap,
  111. "fave_pages",
  112. "id",
  113. "DESC",
  114. &[]builder.DataTableRow{
  115. {
  116. DBField: "id",
  117. },
  118. {
  119. DBField: "template",
  120. },
  121. {
  122. DBField: "name",
  123. NameInTable: "Page / URL",
  124. CallBack: func(values *[]string) string {
  125. name := `<a href="/cp/` + wrap.CurrModule + `/modify/` + (*values)[0] + `/">` + html.EscapeString((*values)[2]) + `</a>`
  126. alias := html.EscapeString((*values)[3])
  127. template := html.EscapeString((*values)[1]) + ".html"
  128. return `<div>` + name + `</div><div class="template"><small>` + template + `</small></div><div><small>` + alias + `</small></div>`
  129. },
  130. },
  131. {
  132. DBField: "alias",
  133. },
  134. {
  135. DBField: "datetime",
  136. DBExp: "UNIX_TIMESTAMP(`datetime`)",
  137. NameInTable: "Date / Time",
  138. Classes: "d-none d-md-table-cell",
  139. CallBack: func(values *[]string) string {
  140. t := int64(utils.StrToInt((*values)[4]))
  141. return `<div>` + utils.UnixTimestampToFormat(t, "02.01.2006") + `</div>` +
  142. `<div><small>` + utils.UnixTimestampToFormat(t, "15:04:05") + `</small></div>`
  143. },
  144. },
  145. {
  146. DBField: "active",
  147. NameInTable: "Active",
  148. Classes: "d-none d-sm-table-cell",
  149. CallBack: func(values *[]string) string {
  150. return builder.CheckBox(utils.StrToInt((*values)[5]))
  151. },
  152. },
  153. },
  154. func(values *[]string) string {
  155. return builder.DataTableAction(&[]builder.DataTableActionRow{
  156. {
  157. Icon: assets.SysSvgIconView,
  158. Href: (*values)[3],
  159. Hint: "View",
  160. Target: "_blank",
  161. },
  162. {
  163. Icon: assets.SysSvgIconEdit,
  164. Href: "/cp/" + wrap.CurrModule + "/modify/" + (*values)[0] + "/",
  165. Hint: "Edit",
  166. },
  167. {
  168. Icon: assets.SysSvgIconRemove,
  169. Href: "javascript:fave.ActionDataTableDelete(this,'index-delete','" +
  170. (*values)[0] + "','Are you sure want to delete page?');",
  171. Hint: "Delete",
  172. Classes: "delete",
  173. },
  174. })
  175. },
  176. "/cp/"+wrap.CurrModule+"/",
  177. nil,
  178. nil,
  179. true,
  180. )
  181. } else if wrap.CurrSubModule == "add" || wrap.CurrSubModule == "modify" {
  182. if wrap.CurrSubModule == "add" {
  183. content += this.getBreadCrumbs(wrap, &[]consts.BreadCrumb{
  184. {Name: "Add new page"},
  185. })
  186. } else {
  187. content += this.getBreadCrumbs(wrap, &[]consts.BreadCrumb{
  188. {Name: "Modify page"},
  189. })
  190. }
  191. data := utils.MySql_page{
  192. A_id: 0,
  193. A_user: 0,
  194. A_template: "",
  195. A_name: "",
  196. A_alias: "",
  197. A_content: "",
  198. A_meta_title: "",
  199. A_meta_keywords: "",
  200. A_meta_description: "",
  201. A_datetime: 0,
  202. A_active: 0,
  203. }
  204. if wrap.CurrSubModule == "modify" {
  205. if len(wrap.UrlArgs) != 3 {
  206. return "", "", ""
  207. }
  208. if !utils.IsNumeric(wrap.UrlArgs[2]) {
  209. return "", "", ""
  210. }
  211. err := wrap.DB.QueryRow(
  212. wrap.R.Context(),
  213. `SELECT
  214. id,
  215. user,
  216. template,
  217. name,
  218. alias,
  219. content,
  220. meta_title,
  221. meta_keywords,
  222. meta_description,
  223. active
  224. FROM
  225. fave_pages
  226. WHERE
  227. id = ?
  228. LIMIT 1;`,
  229. utils.StrToInt(wrap.UrlArgs[2]),
  230. ).Scan(
  231. &data.A_id,
  232. &data.A_user,
  233. &data.A_template,
  234. &data.A_name,
  235. &data.A_alias,
  236. &data.A_content,
  237. &data.A_meta_title,
  238. &data.A_meta_keywords,
  239. &data.A_meta_description,
  240. &data.A_active,
  241. )
  242. if *wrap.LogCpError(&err) != nil {
  243. return "", "", ""
  244. }
  245. }
  246. btn_caption := "Add"
  247. if wrap.CurrSubModule == "modify" {
  248. btn_caption = "Save"
  249. }
  250. content += builder.DataForm(wrap, []builder.DataFormField{
  251. {
  252. Kind: builder.DFKHidden,
  253. Name: "action",
  254. Value: "index-modify",
  255. },
  256. {
  257. Kind: builder.DFKHidden,
  258. Name: "id",
  259. Value: utils.IntToStr(data.A_id),
  260. },
  261. {
  262. Kind: builder.DFKText,
  263. Caption: "Page name",
  264. Name: "name",
  265. Value: data.A_name,
  266. Required: true,
  267. Min: "1",
  268. Max: "255",
  269. },
  270. {
  271. Kind: builder.DFKText,
  272. Caption: "Page alias",
  273. Name: "alias",
  274. Value: data.A_alias,
  275. Hint: "Example: /about-us/ or /about-us.html",
  276. Max: "255",
  277. },
  278. {
  279. Kind: builder.DFKText,
  280. Caption: "Page template",
  281. Name: "template",
  282. Value: "0",
  283. CallBack: func(field *builder.DataFormField) string {
  284. return `<div class="form-group n2">` +
  285. `<div class="row">` +
  286. `<div class="col-md-3">` +
  287. `<label for="lbl_template">Page template</label>` +
  288. `</div>` +
  289. `<div class="col-md-9">` +
  290. `<div>` +
  291. `<select class="selectpicker form-control" id="lbl_template" name="template" data-live-search="true">` +
  292. this.index_GetTemplateSelectOptions(wrap, data.A_template) +
  293. `</select>` +
  294. `</div>` +
  295. `</div>` +
  296. `</div>` +
  297. `</div>`
  298. },
  299. },
  300. {
  301. Kind: builder.DFKTextArea,
  302. Caption: "Page content",
  303. Name: "content",
  304. Value: data.A_content,
  305. Classes: "wysiwyg",
  306. },
  307. {
  308. Kind: builder.DFKText,
  309. Caption: "Meta title",
  310. Name: "meta_title",
  311. Value: data.A_meta_title,
  312. Max: "255",
  313. },
  314. {
  315. Kind: builder.DFKText,
  316. Caption: "Meta keywords",
  317. Name: "meta_keywords",
  318. Value: data.A_meta_keywords,
  319. Max: "255",
  320. },
  321. {
  322. Kind: builder.DFKTextArea,
  323. Caption: "Meta description",
  324. Name: "meta_description",
  325. Value: data.A_meta_description,
  326. Max: "510",
  327. },
  328. {
  329. Kind: builder.DFKCheckBox,
  330. Caption: "Active",
  331. Name: "active",
  332. Value: utils.IntToStr(data.A_active),
  333. },
  334. {
  335. Kind: builder.DFKSubmit,
  336. Value: btn_caption,
  337. Target: "add-edit-button",
  338. },
  339. })
  340. if wrap.CurrSubModule == "add" {
  341. sidebar += `<button class="btn btn-primary btn-sidebar" id="add-edit-button">Add</button>`
  342. } else {
  343. sidebar += `<button class="btn btn-primary btn-sidebar" id="add-edit-button">Save</button>`
  344. }
  345. }
  346. return this.getSidebarModules(wrap), content, sidebar
  347. })
  348. }