PageRenderTime 52ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/cms/app/controllers/cms/organization/CMS.scala

https://github.com/delving/culture-hub
Scala | 216 lines | 182 code | 26 blank | 8 comment | 12 complexity | 5bc75069a970e9e0dcfe923e473a7018 MD5 | raw file
  1. package controllers.cms.organization
  2. import play.api.mvc._
  3. import play.api.i18n._
  4. import play.api.data.Form
  5. import play.api.data.Forms._
  6. import play.api.data.format.Formats._
  7. import play.api.data.validation.Constraints._
  8. import extensions.Formatters._
  9. import controllers.OrganizationController
  10. import extensions.{ MissingLibs, JJson }
  11. import models._
  12. import cms.{ MenuEntry, CMSPage }
  13. import com.mongodb.casbah.Imports._
  14. import plugins.CMSPlugin
  15. import scala.collection.JavaConverters._
  16. import core.storage.{ FileUploadResponse, FileStorage }
  17. import controllers.dos.FileUpload
  18. import com.escalatesoft.subcut.inject.BindingModule
  19. /**
  20. *
  21. * @author Manuel Bernhardt <bernhardt.manuel@gmail.com>
  22. */
  23. class CMS(implicit val bindingModule: BindingModule) extends OrganizationController {
  24. def CMSAction[A](action: Action[A]): Action[A] = {
  25. OrganizationMember {
  26. MultitenantAction(action.parser) {
  27. implicit request =>
  28. {
  29. if (organizationServiceLocator.byDomain.isAdmin(configuration.orgId, connectedUser) || Group.dao.count(MongoDBObject("users" -> connectedUser, "grantType" -> CMSPlugin.ROLE_CMS_ADMIN.key)) > 0) {
  30. action(request)
  31. } else {
  32. Forbidden(Messages("hub.YouDoNotHaveAccess"))
  33. }
  34. }
  35. }
  36. }
  37. }
  38. def list(language: Option[String], menu: Option[String]) = CMSAction {
  39. MultitenantAction {
  40. implicit request =>
  41. val lang = if (language.isDefined) Lang.get(language.get).getOrElse(getLang) else getLang
  42. val entries = CMSPage.dao.entryList(lang, menu)
  43. Ok(Template(
  44. 'data -> JJson.generate(Map("entries" -> entries)),
  45. 'languages -> getLanguages,
  46. 'currentLanguage -> lang.code,
  47. 'menuKey -> menu.getOrElse("")
  48. ))
  49. }
  50. }
  51. def upload = CMSAction {
  52. MultitenantAction {
  53. implicit request =>
  54. val files = FileStorage.listFiles(configuration.orgId).map(f => FileUploadResponse(f))
  55. Ok(Template('uid -> MissingLibs.UUID, 'files -> JJson.generate(files)))
  56. }
  57. }
  58. def uploadSubmit(uid: String) = CMSAction {
  59. MultitenantAction {
  60. implicit request =>
  61. FileUpload.markFilesAttached(uid, configuration.orgId)
  62. Redirect(routes.CMS.upload())
  63. }
  64. }
  65. def listImages = CMSAction {
  66. MultitenantAction {
  67. implicit request =>
  68. val images = FileStorage.listFiles(configuration.orgId).filter(_.contentType.contains("image"))
  69. // tinyMCE stoopidity
  70. val javascript = "var tinyMCEImageList = new Array(" + images.map(i => """["%s","%s"]""".format(i.name, "/file/image/%s".format(i.id))).mkString(", ") + ");"
  71. Ok(javascript).as("text/html")
  72. }
  73. }
  74. def page(language: String, page: Option[String], menu: String): Action[AnyContent] = CMSAction {
  75. MultitenantAction {
  76. implicit request =>
  77. def menuEntries = MenuEntry.dao.findEntries(menu)
  78. val (viewModel: Option[CMSPageViewModel], versions: List[CMSPageViewModel]) = page match {
  79. case None =>
  80. (Some(CMSPageViewModel(System.currentTimeMillis(), "", language, "", connectedUser, "", false, false, menuEntries.length + 1, menu)), List.empty)
  81. case Some(key) =>
  82. val versions = CMSPage.dao.findByKeyAndLanguage(key, language)
  83. if (versions.isEmpty) {
  84. (None, Seq.empty)
  85. } else {
  86. (Some(CMSPageViewModel(versions.head, menu)), versions.map(CMSPageViewModel(_, menu)))
  87. }
  88. }
  89. val menuDefinitions: Seq[java.util.Map[String, String]] = CMSPlugin.getConfiguration.map { config =>
  90. config.menuDefinitions.map { definition =>
  91. Map(
  92. "key" -> definition.key,
  93. "value" -> definition.title.get(getLang.language).getOrElse(definition.key)
  94. ).asJava
  95. }
  96. }.getOrElse {
  97. Seq.empty
  98. }
  99. val activeMenuKey = if (viewModel.isDefined) {
  100. viewModel.get.menu
  101. } else {
  102. menu
  103. }
  104. if (page.isDefined && versions.isEmpty) {
  105. NotFound(page.get)
  106. } else {
  107. Ok(
  108. Template(
  109. 'page -> JJson.generate(viewModel),
  110. 'versions -> JJson.generate(Map("versions" -> versions)),
  111. 'languages -> getLanguages,
  112. 'currentLanguage -> language,
  113. 'isNew -> (versions.isEmpty),
  114. 'menuKey -> activeMenuKey,
  115. 'menuDefinitions -> menuDefinitions
  116. )
  117. )
  118. }
  119. }
  120. }
  121. def pageSubmit = CMSAction {
  122. MultitenantAction {
  123. implicit request =>
  124. CMSPageViewModel.pageForm.bind(request.body.asJson.get).fold(
  125. formWithErrors => handleValidationError(formWithErrors),
  126. pageModel => {
  127. // create / update the entry before we create / update the page since in the implicit conversion above we'll query for that page's position.
  128. MenuEntry.dao.savePage(pageModel.menu, pageModel.key, pageModel.position, pageModel.title, pageModel.lang, pageModel.published)
  129. val page: CMSPageViewModel = CMSPageViewModel(CMSPage.dao.create(pageModel.key, pageModel.lang, connectedUser, pageModel.title, pageModel.content, pageModel.published), pageModel.menu)
  130. CMSPage.dao.removeOldVersions(pageModel.key, pageModel.lang)
  131. Json(page)
  132. }
  133. )
  134. }
  135. }
  136. def pageDelete(key: String, language: String) = CMSAction {
  137. MultitenantAction {
  138. implicit request =>
  139. CMSPage.dao.delete(key, language)
  140. // also delete menu entries that refer to that page
  141. log.info(s"[$connectedUser@${configuration.orgId}] Removed CMS page '$key' in '$language")
  142. MenuEntry.dao.removePage(key, language)
  143. Ok
  144. }
  145. }
  146. def pagePreview(key: String, language: String) = CMSAction {
  147. MultitenantAction {
  148. implicit request =>
  149. CMSPage.dao.find(MongoDBObject("key" -> key, "lang" -> language)).$orderby(MongoDBObject("_id" -> -1)).limit(1).toList.headOption match {
  150. case None => NotFound(key)
  151. case Some(pagePreview) => Ok(Template('page -> pagePreview))
  152. }
  153. }
  154. }
  155. }
  156. case class CMSPageViewModel(dateCreated: Long,
  157. key: String, // the key of this page (unique across all version sets of pages)
  158. lang: String, // 2-letters ISO code of the page language
  159. title: String, // title of the page in this language
  160. userName: String, // creator / editor
  161. content: String, // actual page content (text)
  162. isSnippet: Boolean = false, // is this a snippet in the welcome page or not
  163. published: Boolean,
  164. position: Int,
  165. menu: String)
  166. object CMSPageViewModel {
  167. def apply(cmsPage: CMSPage, menu: String)(implicit configuration: OrganizationConfiguration): CMSPageViewModel = {
  168. // we only allow linking once to a CMSPage so we can be sure that we will only ever find at most one MenuEntry for it
  169. val (menuEntryPosition, menuKey) = MenuEntry.dao.findOneByTargetPageKey(cmsPage.key).map { e =>
  170. (e.position, e.menuKey)
  171. }.getOrElse {
  172. (MenuEntry.dao.findEntries(menu).length + 1, CMSPlugin.MAIN_MENU)
  173. }
  174. CMSPageViewModel(cmsPage._id.getTime, cmsPage.key, cmsPage.lang, cmsPage.title, cmsPage.userName, cmsPage.content, cmsPage.isSnippet, cmsPage.published, menuEntryPosition, menuKey)
  175. }
  176. val pageForm = Form(
  177. mapping(
  178. "dateCreated" -> of[Long],
  179. "key" -> text.verifying(pattern("^[-a-z0-9]{3,35}$".r, error = Messages("cms.InvalidKeyValue"))),
  180. "lang" -> nonEmptyText,
  181. "title" -> nonEmptyText,
  182. "userName" -> text,
  183. "content" -> text,
  184. "isSnippet" -> boolean,
  185. "published" -> boolean,
  186. "position" -> number,
  187. "menu" -> text
  188. )(CMSPageViewModel.apply)(CMSPageViewModel.unapply)
  189. )
  190. }