2

私はGrailsサイトで作業していますが、CMSのような機能を多く含める必要がありますが、実際のCMSインストールの一部として(さまざまな理由で)まだ構築されていません。ユーザーに許可する必要があることの1つは、HTMLレイアウト(GrailsアプリケーションではGSPファイルにレイアウトされている)と、異なるページの他の通常は静的な要素を編集することです。特定のドメインオブジェクトも、ドメインオブジェクトを処理するCRUDページのいずれかの一部を形成することもありません。

は、viewsディレクトリを指定できることと、アプリ内のどこかから実行中のアプリの実際のファイルに書き込むことができることの両方を知っています。さらに、ユーザーがページのレイアウトとコンテンツ全体をひどく破壊しないようにするために、これを行う場合は非常に細心の注意が必要になる可能性があることを知っており、それに対処する準備ができています。しかし、Grailsページの作成に使用されるレイアウトやその他のGSPファイルをユーザーが編集できるようにすることは可能ですか?もしそうなら、私はそれについてどうやって行くことができますか?

4

5 に答える 5

3

テンプレート/レイアウトをデータベースに保存する場合(上記で提案されているように)、GroovyPagesTemplateEngineを使用してレンダリングできます。

package com.mycompany

import groovy.text.Template;
import org.codehaus.groovy.grails.web.pages.GroovyPagesTemplateEngine 

class TemplatingService {
  GroovyPagesTemplateEngine groovyPagesTemplateEngine

  def render(String templateString, Map model) {
    ByteArrayInputStream bais = new ByteArrayInputStream(templateString.getBytes());
    Template template = groovyPagesTemplateEngine.createTemplate(bais)

    try {
      def writer = new StringWriter()
      template.make(model).writeTo(writer)
      return writer.toString()
    } catch (Exception e) {
      // handle exception
      return ""    // or "[an error occurred]" or rethrow the exception
    }
  }
}

さて、これを行うことはできますが、その影響を必ず考えてください。gspで実行できるものはすべて、このコンテキストで実行できます。ファイルへの書き込みやファイルの削除、コマンドの実行など。

SecurityManagerを利用してテンプレートで実行できることを制限する方法がわからなかったため、私の解決策は、ユーザーがデータベースにテンプレートを入力できないようにすることでした。新しいテンプレートが必要な場合は、セキュリティへの影響を確認した後、自分でテンプレートを配置します。

createTemplate()の結果をキャッシュして、毎回再コンパイルしないようにすることで、パフォーマンスを向上させることもできます。

于 2013-01-25T15:53:18.863 に答える
2

これを行う簡単な方法は、HTMLのチャンクをドメインオブジェクトとしてデータベースに保存することです。その後、ビューは自動的にhtmlをプルします。ユーザーがHTMLを編集できるように、シンプルなインターフェイスを作成できます。これに関する詳細については、このスレッドを参照してください。別の可能なオプションは、Weceemプラグインを使用することです。

于 2013-01-22T20:41:12.333 に答える
1

cmsのような機能をGrailsアプリケーションに統合する代わりに、可能ではありますが、さまざまなアプローチを見てきました。

1つの方法は、CMSを脇に置いて、次のことができることを確認することです。

  • 変換プロセス、通常は自動化またはスケジュールされたジョブの後にgspを読み取ります

  • Grailsアプリケーションによって消費されるgspファイルを生成します。この場合、あなたが述べたように、ビューの場所を上書きすることができます。

私が説明しているアプローチで深刻なUIの問題やCMSの制限を回避するために、レイアウトは使用しません。CMSベンダーは、GSPファイルをインポート/エクスポートするためのモジュールを提供しています。そうでない場合は、そのレイヤーを自分で作成します。

それがお役に立てば幸いです。

于 2013-01-23T03:57:21.640 に答える
1

レイアウトはgspビューでもあり、定義上、動的ビューのコンテンツを処理します。

ただし、gspファイルを直接編集して、実行時にコンパイルすることはお勧めできません。

代わりに、カスタマイズされたコンテンツが永続化され、事前定義されたgspレイアウトからロードされるドメインクラスを定義できます。

具体的には、次のドメインクラスのようなものを定義して、カスタムWeb要素を保存できます。

class Module {
    Integer positionLeft
    Integer positionTop
    Integer width
    Integer height
    String  className   //CSS class
    String  border      
    String  borderColor 
    Integer borderSize  
    Integer seq
    String  content
    String  type
    static  hasMany = [components: Component]        //inner elements within a module
    Module  parentModule                    //support nested module structure to ensure flexibility
    User    owner
}

class Component {
    String title
    String content
    String methodName
    String url
    String type     //I-image,A-attachment,L-external link,T-text,G-graph report,D-data table,R RSS FEED...
    String font
    String fontFamily
    String fontBold
    String fontUnderline
    String color    
    String textAlign
    String source      //uri -- enables ajax call to some method to get dynamic data
    Integer seq
}

クライアント側のJavaScriptを使用すると、ユーザーはドラッグ、サイズ変更、一部のメニューからさまざまな要素タイプの選択、これらの要素のCRUD操作を実行するバックエンドコントローラーへの送信によって、カスタマイズされたビューを簡単に生成できます。

次に、レイアウトで、これらのカスタマイズされた要素を1つずつレンダリングします。

<%@ page import="com.app.Module" %>
<g:each in="${Module.findAllByOwnerAndParentModuleIsNull(session.user,[fetch:[components:'join']]).collect {[
            id:it.id,
            posLeft:it.posLeft,
            posTop:it. posTop,
            width:it.width,
            height:it.height,
            className:it.className,
            border:it.border,
            borderColor:it.borderColor,
            borderSize:it.borderSize,
            seq:it.seq,
            content:it.content,
            type:it.type,
            components:it.components,
            innerModules:Module.findAllByParentModule(it)
        ]}}" var="module" status="i">
    <div class="${module.className?module.className:''}" style="position: absolute; left: ${module.posLeft}px; top: ${module.posTop}px; width: ${module.width}px; height: ${module.height}px; border: ${module.borderColor} ${module.borderSize?(module.borderSize+'px'):''} ${module.border};">
        <g:each in="${module.innerModules}" var="inner">  
             <div class="${inner.className?inner.className:''}"  style="position: absolute; left: ${inner.posLeft-module.posLeft}px; top: ${inner.posTop-module.posTop}px; width: ${inner.width}px; height: ${inner.height}px; border: blue 1px solid;">
                  <g:render template="/home/module" model="[
                      module: inner
                  ]"/>
            </div>
        </g:each> 
        <g:render template="/home/module" model="[
             module: module
        ]"/>
    </div>
</g:each>

このようにして、各ユーザーはパーソナライズされたレイアウトを管理できます。

于 2013-01-23T06:14:00.693 に答える
1

GrailsでGSPファイルをレンダリングする適切な方法は、GrailsのGSPBeanを使用することです。これにより、すべてのタグライブラリ機能にアクセスできます。以下は、GSPファイルを処理するGrailsプラグインのスニペットです。

GroovyPagesTemplateEngine gsp = (GroovyPagesTemplateEngine)appCtx.getBean(GROOVY_PAGES_TEMPLATE_ENGINE);
Template template = gsp.createTemplate(new ByteArrayResource(bufferStr.getBytes(encoding)), false);
Writable w = template.make();
StringWriter sw = new StringWriter();
w.writeTo(new PrintWriter(sw));
于 2013-01-30T17:06:32.993 に答える