Example #1
0
func getBlogContext(reqId uint, embed *service.EmbedNode,
	s *service.Session, settings *settings, renderer *mtemplate.Renderer) (
	map[string][]byte, *service.CacheMods, error) {
	req, err := s.Monsti().GetRequest(reqId)
	if err != nil {
		return nil, nil, fmt.Errorf("Could not get request: %v", err)
	}
	query := req.Query
	blogPath := req.NodePath
	if embed != nil {
		embedUrl, err := url.Parse(embed.URI)
		if err != nil {
			return nil, nil, fmt.Errorf("Could not parse embed URI")
		}
		query = embedUrl.Query()
		blogPath = embedUrl.Path
	}
	limit := -1
	if limitParam, err := strconv.Atoi(query.Get("limit")); err == nil {
		limit = limitParam
		if limit < 1 {
			limit = 1
		}
	}
	context := mtemplate.Context{}
	context["Embedded"] = embed
	context["Posts"], err = getBlogPosts(req, blogPath, s, limit)
	if err != nil {
		return nil, nil, fmt.Errorf("Could not retrieve blog posts: %v", err)
	}
	rendered, err := renderer.Render("core/blogpost-list", context,
		req.Session.Locale, settings.Monsti.GetSiteTemplatesPath(req.Site))
	if err != nil {
		return nil, nil, fmt.Errorf("Could not render template: %v", err)
	}
	mods := &service.CacheMods{
		Deps: []service.CacheDep{{Node: req.NodePath, Descend: 1}},
	}
	return map[string][]byte{"BlogPosts": rendered}, mods, nil
}
Example #2
0
func getBlogPosts(req *service.Request, blogPath string, s *service.Session,
	limit int) ([]*service.Node, error) {
	var posts []*service.Node
	years, err := s.Monsti().GetChildren(req.Site, blogPath)
	if err != nil {
		return nil, fmt.Errorf("Could not fetch year children: %v", err)
	}
	for _, year := range years {
		months, err := s.Monsti().GetChildren(req.Site, year.Path)
		if err != nil {
			return nil, fmt.Errorf("Could not fetch month children: %v", err)
		}
		for _, month := range months {
			monthPosts, err := s.Monsti().GetChildren(req.Site, month.Path)
			if err != nil {
				return nil, fmt.Errorf("Could not fetch month children: %v", err)
			}
			posts = append(posts, monthPosts...)
		}
	}
	order := func(left, right *service.Node) bool {
		return left.PublishTime.Before(right.PublishTime)
	}
	sort.Sort(sort.Reverse(&nodes.Sorter{posts, order}))
	return posts, nil
}
Example #3
0
func initBlog(settings *settings, session *service.Session,
	sessions *service.SessionPool, logger *log.Logger,
	renderer *mtemplate.Renderer) error {
	G := func(in string) string { return in }

	nodeType := service.NodeType{
		Id:        "core.Blog",
		AddableTo: []string{"."},
		Name:      i18n.GenLanguageMap(G("Blog"), availableLocales),
		Fields: []*service.FieldConfig{
			{Id: "core.Title"},
		},
	}
	if err := session.Monsti().RegisterNodeType(&nodeType); err != nil {
		return fmt.Errorf("Could not register blog node type: %v", err)
	}

	nodeType = service.NodeType{
		Id:        "core.BlogPost",
		AddableTo: []string{"core.Blog"},
		Name:      i18n.GenLanguageMap(G("Blog Post"), availableLocales),
		Fields: []*service.FieldConfig{
			{Id: "core.Title"},
			{Id: "core.Body"},
		},
		Hide:       true,
		PathPrefix: "$year/$month",
	}
	if err := session.Monsti().RegisterNodeType(&nodeType); err != nil {
		return fmt.Errorf("Could not register blog post node type: %v", err)
	}

	// Add a signal handler
	handler := service.NewNodeContextHandler(sessions,
		func(req uint, session *service.Session, nodeType string,
			embedNode *service.EmbedNode) (
			map[string][]byte, *service.CacheMods, error) {
			switch nodeType {
			case "core.Blog":
				ctx, mods, err := getBlogContext(req, embedNode, session, settings, renderer)
				if err != nil {
					return nil, nil, fmt.Errorf("Could not get blog context: %v", err)
				}
				return ctx, mods, nil
			default:
				return nil, nil, nil
			}
		})
	if err := session.Monsti().AddSignalHandler(handler); err != nil {
		logger.Fatalf("Could not add signal handler: %v", err)
	}
	return nil
}
Example #4
0
func initNodeTypes(settings *settings, session *service.Session, logger *log.Logger) error {
	G := func(in string) string { return in }
	pathType := service.NodeType{
		Id:   "core.Path",
		Hide: true,
		Name: util.GenLanguageMap(G("Path"), availableLocales),
	}
	if err := session.Monsti().RegisterNodeType(&pathType); err != nil {
		return fmt.Errorf("Could not register path node type: %v", err)
	}

	documentType := service.NodeType{
		Id:        "core.Document",
		AddableTo: []string{"."},
		Name:      util.GenLanguageMap(G("Document"), availableLocales),
		Fields: []*service.NodeField{
			{
				Id:       "core.Title",
				Required: true,
				Name:     util.GenLanguageMap(G("Title"), availableLocales),
				Type:     "Text",
			},
			{
				Id:       "core.Body",
				Required: true,
				Name:     util.GenLanguageMap(G("Body"), availableLocales),
				Type:     "HTMLArea",
			},
		},
	}
	if err := session.Monsti().RegisterNodeType(&documentType); err != nil {
		return fmt.Errorf("Could not register document node type: %v", err)
	}

	fileType := service.NodeType{
		Id:        "core.File",
		AddableTo: []string{"."},
		Name:      util.GenLanguageMap(G("File"), availableLocales),
		Fields: []*service.NodeField{
			{Id: "core.Title"},
			{Id: "core.Body"},
			{
				Id:       "core.File",
				Required: true,
				Name:     util.GenLanguageMap(G("File"), availableLocales),
				Type:     "File",
			},
		},
	}
	if err := session.Monsti().RegisterNodeType(&fileType); err != nil {
		return fmt.Errorf("Could not register file node type: %v", err)
	}

	imageType := service.NodeType{
		Id:        "core.Image",
		AddableTo: []string{"."},
		Name:      util.GenLanguageMap(G("Image"), availableLocales),
		Fields: []*service.NodeField{
			{Id: "core.Title"},
			{Id: "core.File"},
		},
	}
	if err := session.Monsti().RegisterNodeType(&imageType); err != nil {
		return fmt.Errorf("Could not register image node type: %v", err)
	}

	contactFormType := service.NodeType{
		Id:        "core.ContactForm",
		AddableTo: []string{"."},
		Name:      util.GenLanguageMap(G("Contact form"), availableLocales),
		Fields: []*service.NodeField{
			{Id: "core.Title"},
			{Id: "core.Body"},
		},
	}
	if err := session.Monsti().RegisterNodeType(&contactFormType); err != nil {
		return fmt.Errorf("Could not register contactform node type: %v", err)
	}
	return nil
}
Example #5
0
// renderInMaster renders the content in the master template.
func renderInMaster(r template.Renderer, content []byte, env masterTmplEnv,
	settings *settings, site string, siteSettings *service.Settings,
	userLocale string,
	s *service.Session) ([]byte, *service.CacheMods) {
	mods := &service.CacheMods{Deps: []service.CacheDep{{Node: "/", Descend: -1}}}
	if env.Flags&EDIT_VIEW != 0 {
		ret, err := r.Render("admin/master", template.Context{
			"Site":         site,
			"SiteSettings": siteSettings,
			"Page": template.Context{
				"Title":    env.Title,
				"Node":     env.Node,
				"EditView": true,
				"SlimView": env.Flags&SLIM_VIEW != 0,
				"Content":  htmlT.HTML(content),
			},
			"Session": env.Session}, userLocale,
			settings.Monsti.GetSiteTemplatesPath(site))
		if err != nil {
			panic("Can't render admin template: " + err.Error())
		}
		return ret, nil
	}
	firstDir := splitFirstDir(env.Node.Path)
	getNodeFn := func(path string) (*service.Node, error) {
		node, err := s.Monsti().GetNode(site, path)
		return node, err
	}
	getChildrenFn := func(path string) ([]*service.Node, error) {
		return s.Monsti().GetChildren(site, path)
	}

	priNavDepth := 1
	if nav, ok := siteSettings.Fields["core.Navigations"].(*service.MapField).
		Fields["core.Main"]; ok {
		priNavDepth = nav.(*service.CombinedField).
			Fields["depth"].Value().(int)
	}
	prinav, err := getNav("/", path.Join("/", firstDir), env.Session.User == nil,
		getNodeFn, getChildrenFn, priNavDepth)
	if err != nil {
		panic(fmt.Sprint("Could not get primary navigation: ", err))
	}
	prinav.MakeAbsolute("/")

	var secnav navigation = nil
	if env.Node.Path != "/" {
		secnav, err = getNav(env.Node.Path, env.Node.Path, env.Session.User == nil,
			getNodeFn, getChildrenFn, 1)
		if err != nil {
			panic(fmt.Sprint("Could not get secondary navigation: ", err))
		}
		secnav.MakeAbsolute(env.Node.Path)
	}

	blocks := make(map[string][]renderedBlock)

	// EXPERIMENTAL Render blocks
	if _, ok := siteSettings.Fields["core.RegionBlocks"].(*service.MapField).
		Fields["core.PrimaryNavigation"].(*service.ListField); ok {
		renderedNav, err := r.Render("blocks/core/Navigation", template.Context{
			"Id":    "core.PrimaryNavigation",
			"Links": prinav,
		}, userLocale, settings.Monsti.GetSiteTemplatesPath(site))
		if err != nil {
			panic(fmt.Sprintf("Could not render navigation: %v", err))
		}
		blocks["core.PrimaryNavigation"] = append(blocks["core.PrimaryNavigation"],
			renderedBlock{
				Rendered: htmlT.HTML(renderedNav),
			})
	}

	title := getNodeTitle(env.Node)
	ret, err := r.Render("master", template.Context{
		"Site":         site,
		"SiteSettings": siteSettings,
		"Page": template.Context{
			"Node":             env.Node,
			"PrimaryNav":       prinav, // TODO DEPRECATED
			"SecondaryNav":     secnav, // TODO DEPRECATED
			"EditView":         env.Flags&EDIT_VIEW != 0,
			"Title":            title,
			"Content":          htmlT.HTML(content),
			"ShowSecondaryNav": len(secnav) > 0, // TODO DEPRECATED
			"Blocks":           blocks,
		},
		"Session": env.Session}, userLocale,
		settings.Monsti.GetSiteTemplatesPath(site))
	if err != nil {
		panic(fmt.Sprintf(
			"Can't render master template for site %v: %v",
			site, err))
	}
	return ret, mods
}
Example #6
0
// renderInMaster renders the content in the master template.
func renderInMaster(r template.Renderer, content []byte, env masterTmplEnv,
	settings *settings, site util.SiteSettings, locale string,
	s *service.Session) string {
	if env.Flags&EDIT_VIEW != 0 {
		ret, err := r.Render("admin/master", template.Context{
			"Site": site,
			"Page": template.Context{
				"Title":    env.Title,
				"Node":     env.Node,
				"EditView": env.Flags&EDIT_VIEW != 0,
				"Content":  htmlT.HTML(content),
			},
			"Session": env.Session}, locale,
			settings.Monsti.GetSiteTemplatesPath(site.Name))
		if err != nil {
			panic("Can't render: " + err.Error())
		}
		return ret
	}
	firstDir := splitFirstDir(env.Node.Path)
	getNodeFn := func(path string) (*service.Node, error) {
		node, err := s.Monsti().GetNode(site.Name, path)
		return node, err
	}
	getChildrenFn := func(path string) ([]*service.Node, error) {
		return s.Monsti().GetChildren(site.Name, path)
	}
	prinav, err := getNav("/", path.Join("/", firstDir), env.Session.User == nil,
		getNodeFn, getChildrenFn)
	if err != nil {
		panic(fmt.Sprint("Could not get primary navigation: ", err))
	}
	prinav.MakeAbsolute("/")
	var secnav navigation = nil
	if env.Node.Path != "/" {
		secnav, err = getNav(env.Node.Path, env.Node.Path, env.Session.User == nil,
			getNodeFn, getChildrenFn)
		if err != nil {
			panic(fmt.Sprint("Could not get secondary navigation: ", err))
		}
		secnav.MakeAbsolute(env.Node.Path)
	}

	title := getNodeTitle(env.Node)
	ret, err := r.Render("master", template.Context{
		"Site": site,
		"Page": template.Context{
			"Node":             env.Node,
			"PrimaryNav":       prinav,
			"SecondaryNav":     secnav,
			"EditView":         env.Flags&EDIT_VIEW != 0,
			"Title":            title,
			"Content":          htmlT.HTML(content),
			"ShowSecondaryNav": len(secnav) > 0},
		"Session": env.Session}, locale,
		settings.Monsti.GetSiteTemplatesPath(site.Name))
	if err != nil {
		panic("Can't render: " + err.Error())
	}
	return ret
}
Example #7
0
func renderContactForm(req *service.Request, session *service.Session) (
	*service.RenderNodeRet, error) {

	m := session.Monsti()
	siteSettings, err := m.LoadSiteSettings(req.Site)
	if err != nil {
		return nil, fmt.Errorf("Could not get site settings: %v", err)
	}
	G, _, _, _ := gettext.DefaultLocales.Use("",
		siteSettings.Fields["core.Locale"].Value().(string))

	node, err := m.GetNode(req.Site, req.NodePath)
	if err != nil {
		return nil, fmt.Errorf("Could not get contact form node: %v", err)
	}

	data := make(service.NestedMap)
	var dataFields []dataField
	form := htmlwidgets.NewForm(data)

	formFields := node.Fields["core.ContactFormFields"].(*service.ListField)

	for i, field := range formFields.Fields {
		combinedField := field.(*service.CombinedField)
		name := combinedField.Fields["Name"].Value().(string)
		required := combinedField.Fields["Required"].Value().(bool)
		fieldId := fmt.Sprintf("field_%d", i)
		dataFields = append(dataFields, dataField{fieldId, name})
		data[fieldId] = ""
		innerFieldType := combinedField.Fields["Field"].(*service.DynamicTypeField).DynamicType
		var widget htmlwidgets.Widget
		switch innerFieldType {
		case "text":
			textWidget := &htmlwidgets.TextWidget{ValidationError: G("Required.")}
			if required {
				textWidget.MinLength = 1
			}
			widget = textWidget
		case "textarea":
			areaWidget := &htmlwidgets.TextAreaWidget{ValidationError: G("Required.")}
			if required {
				areaWidget.MinLength = 1
			}
			widget = areaWidget
		default:
			panic(fmt.Sprintf("Unknow inner field type <%v>", innerFieldType))
		}
		form.AddWidget(widget, fieldId, name, "")
	}

	if len(formFields.Fields) == 0 {
		// Add default fields for backward compatibility
		data["Name"] = ""
		data["Email"] = ""
		data["Subject"] = ""
		data["Message"] = ""
		dataFields = []dataField{
			{"Name", G("Name")},
			{"Email", G("Email")},
			{"Subject", G("Subject")},
			{"Message", G("Message")},
		}
		form.AddWidget(&htmlwidgets.TextWidget{MinLength: 1,
			ValidationError: G("Required.")}, "Name", G("Name"), "")
		form.AddWidget(&htmlwidgets.TextWidget{MinLength: 1,
			ValidationError: G("Required.")}, "Email", G("Email"), "")
		form.AddWidget(&htmlwidgets.TextWidget{MinLength: 1,
			ValidationError: G("Required.")}, "Subject", G("Subject"), "")
		form.AddWidget(&htmlwidgets.TextAreaWidget{MinLength: 1,
			ValidationError: G("Required.")}, "Message", G("Message"), "")
	}

	context := make(map[string]interface{})
	switch req.Method {
	case "GET":
		if _, submitted := req.Form["submitted"]; submitted {
			context["Submitted"] = 1
		}
	case "POST":
		if form.Fill(req.PostForm) {
			mail := gomail.NewMessage()
			mail.SetAddressHeader("From",
				siteSettings.StringValue("core.EmailAddress"),
				siteSettings.StringValue("core.EmailName"))
			mail.SetAddressHeader("To",
				siteSettings.StringValue("core.OwnerEmail"),
				siteSettings.StringValue("core.OwnerName"))
			// mail.SetAddressHeader("Reply-To", data.Email, data.Name)
			mail.SetHeader("Subject", "Contact form submission")
			var fieldValues string
			for _, v := range dataFields {
				fieldValues += fmt.Sprintf("%v: %v\n", v.Name, data[v.Id])
			}
			body := fmt.Sprintf("%v\n\n%v",
				fmt.Sprintf(G("Received from contact form at %v"),
					siteSettings.StringValue("core.Title")), fieldValues)
			mail.SetBody("text/plain", body)
			mailer := gomail.NewCustomMailer("", nil, gomail.SetSendMail(
				m.SendMailFunc()))
			err := mailer.Send(mail)
			if err != nil {
				return nil, fmt.Errorf("Could not send mail: %v", err)
			}
			return &service.RenderNodeRet{
				Redirect: &service.Redirect{
					path.Dir(node.Path) + "/?submitted", http.StatusSeeOther}}, nil
		}
	default:
		return nil, fmt.Errorf("Request method not supported: %v", req.Method)
	}
	context["Form"] = form.RenderData()
	return &service.RenderNodeRet{Context: context}, err
}
Example #8
0
func initNodeTypes(settings *settings, session *service.Session, logger *log.Logger) error {
	G := func(in string) string { return in }
	pathType := service.NodeType{
		Id:   "core.Path",
		Hide: true,
		Name: i18n.GenLanguageMap(G("Path"), availableLocales),
	}
	if err := session.Monsti().RegisterNodeType(&pathType); err != nil {
		return fmt.Errorf("Could not register path node type: %v", err)
	}

	documentType := service.NodeType{
		Id:        "core.Document",
		AddableTo: []string{"."},
		Name:      i18n.GenLanguageMap(G("Document"), availableLocales),
		Fields: []*service.FieldConfig{
			{
				Id:       "core.Title",
				Required: true,
				Name:     i18n.GenLanguageMap(G("Title"), availableLocales),
				Type:     new(service.TextFieldType),
			},
			{
				Id:   "core.Description",
				Name: i18n.GenLanguageMap(G("Description"), availableLocales),
				Type: new(service.TextFieldType),
			},
			{
				Id:   "core.Thumbnail",
				Name: i18n.GenLanguageMap(G("Thumbnail"), availableLocales),
				Type: new(service.RefFieldType),
			},
			{
				Id:       "core.Body",
				Required: true,
				Name:     i18n.GenLanguageMap(G("Body"), availableLocales),
				Type:     new(service.HTMLFieldType),
			},
		},
	}
	if err := session.Monsti().RegisterNodeType(&documentType); err != nil {
		return fmt.Errorf("Could not register document node type: %v", err)
	}

	fileType := service.NodeType{
		Id:        "core.File",
		AddableTo: []string{"."},
		Name:      i18n.GenLanguageMap(G("File"), availableLocales),
		Fields: []*service.FieldConfig{
			{Id: "core.Title"},
			{
				Id:       "core.File",
				Required: true,
				Name:     i18n.GenLanguageMap(G("File"), availableLocales),
				Type:     new(service.FileFieldType),
			},
		},
	}
	if err := session.Monsti().RegisterNodeType(&fileType); err != nil {
		return fmt.Errorf("Could not register file node type: %v", err)
	}

	imageType := service.NodeType{
		Id:        "core.Image",
		Hide:      true,
		AddableTo: []string{"."},
		Name:      i18n.GenLanguageMap(G("Image"), availableLocales),
		Fields: []*service.FieldConfig{
			{Id: "core.Title"},
			{Id: "core.File"},
		},
	}
	if err := session.Monsti().RegisterNodeType(&imageType); err != nil {
		return fmt.Errorf("Could not register image node type: %v", err)
	}

	return nil
}