Esempio n. 1
0
// The confirmation code will be passed in the GET parameter "code"
func EmailConfirmationView(profileURL view.URL) view.View {
	return view.DynamicView(
		func(context *view.Context) (view.View, error) {
			confirmationCode, ok := context.Params["code"]
			if !ok {
				return view.DIV("error", view.HTML("Invalid email confirmation code!")), nil
			}

			doc, email, confirmed, err := ConfirmEmail(confirmationCode)
			if !confirmed {
				return view.DIV("error", view.HTML("Invalid email confirmation code!")), err
			}

			Login(context, doc)

			return view.Views{
				view.DIV("success", view.Printf("Email address %s confirmed!", email)),
				&view.If{
					Condition: profileURL != nil,
					Content: view.P(
						view.HTML("Continue to your "),
						view.A(profileURL, "profile..."),
					),
				},
			}, nil
		},
	)
}
Esempio n. 2
0
func ImagesAdmin() view.View {
	return view.Views{
		UploadImageButton(Config.ImagesAdmin.ThumbnailSize, "function(){window.location.reload()}"),
		&view.ModelIteratorView{
			GetModelIterator: func(ctx *view.Context) model.Iterator {
				return Config.Backend.ImageIterator()
			},
			GetModelIteratorView: func(ctx *view.Context, m interface{}) (view.View, error) {
				image := m.(*Image)
				thumbnail, err := image.Thumbnail(Config.ImagesAdmin.ThumbnailSize)
				if err != nil {
					return nil, err
				}
				editor := view.DIV(Config.ImagesAdmin.ImageEditorClass,
					view.H3(image.TitleOrFilename()),
					view.DIV(Config.ImagesAdmin.ThumbnailFrameClass,
						thumbnail.ViewImage(""),
					),
					view.HTML("Image URL: "),
					view.A_blank(image.URL(), image.URL().URL(ctx)),
					&view.Form{
						FormID:            "edit" + image.ID.Get(),
						SubmitButtonClass: Config.ImagesAdmin.ButtonClass,
						GetModel: func(form *view.Form, ctx *view.Context) (model interface{}, err error) {
							return &imageData{
								Title:    image.Title,
								Filename: image.Versions[0].Filename,
								Link:     image.Link,
							}, nil
						},
						OnSubmit: func(form *view.Form, formModel interface{}, ctx *view.Context) (message string, redirect view.URL, err error) {
							model := formModel.(*imageData)
							image.Title = model.Title
							image.Link = model.Link
							for i := range image.Versions {
								image.Versions[i].Filename = model.Filename
							}
							err = image.Save()
							return "", view.StringURL("."), err
						},
					},
					&view.Form{
						SubmitButtonText:    "Delete",
						SubmitButtonConfirm: "Are you sure you want to delete the image " + image.TitleOrFilename() + "?",
						SubmitButtonClass:   Config.ImagesAdmin.ButtonClass,
						FormID:              "delete" + image.ID.Get(),
						OnSubmit: func(form *view.Form, formModel interface{}, ctx *view.Context) (message string, redirect view.URL, err error) {
							return "", view.StringURL("."), image.Delete()
						},
					},
					view.DivClearBoth(),
				)
				return editor, nil
			},
		},
	}
}
Esempio n. 3
0
func (self BlobRefController) NewInput(withLabel bool, metaData *model.MetaData, form *view.Form) (input view.View, err error) {
	blobRef := metaData.Value.Addr().Interface().(*BlobRef)

	hiddenInput := &view.HiddenInput{Name: metaData.Selector(), Value: blobRef.String()}

	uploadList := &view.List{Class: "qq-upload-list"}

	removeButton := &view.Div{
		Class:   "qq-upload-button",
		Content: view.HTML("Remove"),
		OnClick: fmt.Sprintf(
			`jQuery("#%s").attr("value", "");
			jQuery("#%s").empty();`,
			hiddenInput.ID(),
			uploadList.ID(),
		),
	}

	chooseList := view.Views{
		view.JQueryUIAutocompleteFromURL(".gostart-select-blob", API.AllBlobs, 2),
	}

	uploadButton := UploadBlobButton(
		"",
		"#"+uploadList.ID(),
		fmt.Sprintf(
			`function(id, fileName, responseJSON) {
				jQuery("#%s").attr("value", responseJSON.blobID);
			}`,
			hiddenInput.ID(),
		),
	)

	editor := view.DIV(Config.BlobRefController.Class,
		view.RequireScriptURL("/media/media.js", 0),
		view.RequireStyle(
			`.qq-upload-button {
				margin: 0 0 5px 10px;
				cursor: pointer;
			}
			.qq-upload-button:hover {
				background-color: #cc0000;
			}`,
			10,
		),
		hiddenInput,
		view.DIV(Config.BlobRefController.ActionsClass, chooseList, removeButton, uploadButton),
		uploadList,
		view.DivClearBoth(),
	)

	if withLabel {
		return view.AddStandardLabel(form, editor, metaData), nil
	}
	return editor, nil
}
Esempio n. 4
0
func (self *FormFieldFactory) NewInput(withLabel bool, metaData *model.MetaData, form *view.Form) (view.View, error) {
	if imageRef, ok := metaData.Value.Addr().Interface().(*ImageRef); ok {
		thumbnailFrame := &view.Div{
			Class: "thumbnail-frame",
			Style: fmt.Sprintf("width:%dpx;height:%dpx;", self.ThumbnailSize, self.ThumbnailSize),
		}
		if !imageRef.IsEmpty() {
			image, err := imageRef.Image()
			if err != nil {
				return nil, err
			}
			version, err := image.Thumbnail(self.ThumbnailSize)
			if err != nil {
				return nil, err
			}
			thumbnailFrame.Content = version.ViewImage("")
		}
		result := view.DIV(self.ImageWidgetClass,
			thumbnailFrame,
			&view.Button{Content: view.HTML("Change")},
			&view.Button{Content: view.HTML("Remove")},
			// description
			// link
			view.DivClearBoth(),
		)
		if withLabel {
			return view.AddStandardLabel(form, result, metaData), nil
		}
		return result, nil
	}
	return self.FormFieldFactoryWrapper.Wrapped.NewInput(withLabel, metaData, form)
}
Esempio n. 5
0
// Uses https://github.com/valums/file-uploader
func UploadImageButton(thumbnailSize int, onComplete string) view.View {
	if onComplete == "" {
		onComplete = "function(){}"
	}

	const registerUploaderScript = `jQuery(function() {
		var uploader = new qq.FileUploader({
			debug: true,
		    element: jQuery("#%s")[0],
		    action: "%s",
		    allowedExtensions: ["png", "jpg", "jpeg", "gif", "bmp", "tif", "tiff"],
		    acceptFiles: ["image/png", "image/jpeg", "image/gif", "image/bmp", "image/tiff"],
		    multiple: false,
		    onComplete: %s
		});
	});`

	uploader := view.DIV("uploader")
	uploaderID := uploader.ID()
	uploaderScript := view.RenderView(
		func(ctx *view.Context) error {
			uploadURL := UploadImage.URL(ctx.ForURLArgsConvert(thumbnailSize))
			script := fmt.Sprintf(registerUploaderScript, uploaderID, uploadURL, onComplete)
			ctx.Response.RequireScript(script, 20)
			return nil
		},
	)
	return view.Views{
		&view.If{
			Condition: !Config.NoDynamicStyleAndScript,
			Content: view.Views{
				view.RequireStyleURL("/media/fileuploader.css", 0),
				view.RequireScriptURL("/media/fileuploader.js", 0),
				// view.RequireScriptURL("/media/media.js", 10),
			},
		},
		uploader,
		uploaderScript,
	}
}
Esempio n. 6
0
func BlobsAdmin() view.View {
	return view.Views{
		UploadBlobButton("", "", "function(){window.location.reload()}"),
		&view.ModelIteratorView{
			GetModelIterator: func(ctx *view.Context) model.Iterator {
				// debug.Dump(Config.Backend.Blobs.Count())
				return Config.Backend.BlobIterator()
			},
			GetModel: func(ctx *view.Context) (interface{}, error) {
				return new(Blob), nil
			},
			GetModelView: func(ctx *view.Context, m interface{}) (view.View, error) {
				blob := *m.(*Blob) // copy by value because it will be used in a closure later on
				refCount, err := blob.CountRefs()
				if err != nil {
					return nil, err
				}
				deleteConfirmation := fmt.Sprintf("Are you sure you want to delete the blob %s?", blob.Title)
				if refCount > 0 {
					deleteConfirmation += fmt.Sprintf(" It is used %d times!", refCount)
				}
				editor := view.DIV(Config.Admin.ImageEditorClass,
					view.H3(blob.Title.Get()),
					view.P("Link to file: ", view.A_blank(blob.FileURL()) /*, view.Printf(" | Used %d times", refCount)*/),
					view.P(view.Printf("Size: %d kb", blob.Size.Get()/1024.0)),
					&view.Form{
						FormID:            "edit" + blob.ID.Get(),
						SubmitButtonClass: Config.Admin.ButtonClass,
						GetModel: func(form *view.Form, ctx *view.Context) (interface{}, error) {
							return &blobData{
								Title:    blob.Title,
								Filename: blob.Filename,
								Link:     blob.Link,
							}, nil
						},
						OnSubmit: func(form *view.Form, formModel interface{}, ctx *view.Context) (message string, redirect view.URL, err error) {
							model := formModel.(*blobData)
							blob.Title = model.Title
							blob.Filename = model.Filename
							blob.Link = model.Link
							err = blob.Save()
							return "", view.StringURL("."), err
						},
					},
					&view.Form{
						SubmitButtonText:    "Delete",
						SubmitButtonConfirm: deleteConfirmation,
						SubmitButtonClass:   Config.Admin.ButtonClass,
						FormID:              "delete" + blob.ID.Get(),
						OnSubmit: func(form *view.Form, formModel interface{}, ctx *view.Context) (message string, redirect view.URL, err error) {
							_, err = blob.RemoveAllRefs()
							if err != nil {
								return "", nil, err
							}
							return "", view.StringURL("."), blob.Delete()
						},
					},
					view.DivClearBoth(),
				)
				return editor, nil
			},
		},
	}
}
Esempio n. 7
0
func ImagesAdmin() view.View {
	uploader := view.DIV("")
	uploaderID := uploader.ID()
	uploader.Content = UploadImageButton("#"+uploaderID, "", "", Config.ImagesAdmin.ThumbnailSize, "function(){window.location.reload()}")
	return view.Views{
		uploader,
		&view.ModelIteratorView{
			GetModelIterator: func(ctx *view.Context) model.Iterator {
				return Config.Backend.ImageIterator()
			},
			GetModelIteratorView: func(ctx *view.Context, m interface{}) (view.View, error) {
				image := m.(*Image)
				refCount, err := image.CountRefs()
				if err != nil {
					return nil, err
				}
				thumbnail, err := image.Thumbnail(Config.ImagesAdmin.ThumbnailSize)
				if err != nil {
					return nil, err
				}
				deleteConfirmation := fmt.Sprintf("Are you sure you want to delete the image %s?", image.TitleOrFilename())
				if refCount > 0 {
					deleteConfirmation += fmt.Sprintf(" It is used %d times!", refCount)
				}
				editor := view.DIV(Config.ImagesAdmin.ImageEditorClass,
					view.H3(image.TitleOrFilename()),
					view.P(
						view.A_blank(image.GetURL(), "Link to original"),
						view.Printf(" | Used %d times", refCount),
					),
					view.DIV(Config.ImagesAdmin.ThumbnailFrameClass,
						thumbnail.View(""),
					),
					&view.Form{
						FormID:            "edit" + image.ID.Get(),
						SubmitButtonClass: Config.ImagesAdmin.ButtonClass,
						GetModel: func(form *view.Form, ctx *view.Context) (interface{}, error) {
							return &imageData{
								Title:    image.Title,
								Filename: model.String(image.Filename()),
								Link:     image.Link,
							}, nil
						},
						OnSubmit: func(form *view.Form, formModel interface{}, ctx *view.Context) (message string, redirect view.URL, err error) {
							model := formModel.(*imageData)
							image.Title = model.Title
							image.Link = model.Link
							for i := range image.Versions {
								image.Versions[i].Filename = model.Filename
							}
							err = image.Save()
							return "", view.StringURL("."), err
						},
					},
					&view.Form{
						SubmitButtonText:    "Delete",
						SubmitButtonConfirm: deleteConfirmation,
						SubmitButtonClass:   Config.ImagesAdmin.ButtonClass,
						FormID:              "delete" + image.ID.Get(),
						OnSubmit: func(form *view.Form, formModel interface{}, ctx *view.Context) (message string, redirect view.URL, err error) {
							err = image.RemoveAllRefs()
							if err != nil {
								return "", nil, err
							}
							return "", view.StringURL("."), image.Delete()
						},
					},
					view.DivClearBoth(),
				)
				return editor, nil
			},
		},
	}
}
Esempio n. 8
0
func (self BlobRefController) NewInput(withLabel bool, metaData *model.MetaData, form *view.Form) (input view.View, err error) {
	blobRef := metaData.Value.Addr().Interface().(*BlobRef)
	// _, _, err = blobRef.TryGet()
	// if err != nil {
	// 	return nil, err
	// }

	selectModel := &view.ValueLabelSelectModel{
		ValuesAndLabels: []string{"", ""},
		SelectedValue:   blobRef.String(),
	}
	var b Blob
	for i := BlobIterator(); i.Next(&b); {
		label := fmt.Sprintf("%s (%d kb)", b.Title, b.Size.Get()/1024)
		selectModel.ValuesAndLabels = append(selectModel.ValuesAndLabels, b.ID.Get(), label)
	}
	selector := &view.Select{
		Name:  metaData.Selector(),
		Model: selectModel,
		Size:  1,
	}

	uploadList := &view.List{Class: "qq-upload-list"}

	removeButton := &view.Div{
		Class:   "qq-upload-button",
		Content: view.HTML("Remove"),
		OnClick: fmt.Sprintf(
			`jQuery("#%s").attr("value", "");
			jQuery("#%s").empty();`,
			selector.ID(),
			uploadList.ID(),
		),
	}

	uploadButton := UploadBlobButton(
		"",
		"#"+uploadList.ID(),
		fmt.Sprintf(
			`function(id, fileName, responseJSON) {
				var select = jQuery("#%s");
				select.append("<option value='"+ responseJSON.blobID +"'>" + fileName + " (" + Math.floor(responseJSON.blobSize / 1024) + " kb)</option>");
				select.attr("value", responseJSON.blobID);
			}`,
			selector.ID(),
		),
	)

	editor := view.DIV(Config.BlobRefController.Class,
		view.RequireScriptURL("/media/media.js", 0),
		view.RequireStyle(
			`.qq-upload-button {
				margin: 0 0 5px 10px;
				cursor: pointer;
			}
			.qq-upload-button:hover {
				background-color: #cc0000;
			}`,
			10,
		),
		view.DIV(
			Config.BlobRefController.ActionsClass,
			selector,
			removeButton,
			uploadButton),
		uploadList,
		view.DivClearBoth(),
	)

	if withLabel {
		return view.AddStandardLabel(form, editor, metaData), nil
	}
	return editor, nil
}
Esempio n. 9
0
func (self *FormFieldFactory) NewInput(withLabel bool, metaData *model.MetaData, form *view.Form) (view.View, error) {
	if imageRef, ok := metaData.Value.Addr().Interface().(*ImageRef); ok {
		thumbnailSize := Config.ImageRefEditor.ThumbnailSize
		removeButton := &view.Button{Content: view.HTML("Remove"), OnClick: ""}

		var img view.View
		if imageRef.IsEmpty() {
			removeButton.Disabled = true
			img = view.IMG(Config.dummyImageURL, thumbnailSize, thumbnailSize)
		} else {
			image, err := imageRef.GetImage()
			if err != nil {
				return nil, err
			}
			version, err := image.Thumbnail(thumbnailSize)
			if err != nil {
				return nil, err
			}
			img = version.ViewImage("")
		}

		hiddenInput := &view.HiddenInput{Name: metaData.Selector(), Value: imageRef.String()}

		thumbnailFrame := &view.Div{
			Class:   Config.ImageRefEditor.ThumbnailFrameClass,
			Style:   fmt.Sprintf("width:%dpx;height:%dpx;", thumbnailSize, thumbnailSize),
			Content: img,
		}

		const onCompleteSrc = `function(id, fileName, responseJSON) {
			alert(JSON.stringify(responseJSON));
			var img = "<img src='" + responseJSON.thumbnailURL + "' width='%d' height='%d'/>";
			jQuery("#%s").empty().html(img);
			jQuery("#%s").attr("value", responseJSON.imageID);
		}`
		onComplete := fmt.Sprintf(
			onCompleteSrc,
			thumbnailSize,
			thumbnailSize,
			thumbnailFrame.ID(),
			hiddenInput.ID(),
		)
		// onComplete = ""

		editor := view.DIV(Config.ImageRefEditor.Class,
			hiddenInput,
			thumbnailFrame,
			view.DIV(Config.ImageRefEditor.ActionsClass,
				view.HTML("&larr; drag &amp; drop files here"),
				removeButton,
				UploadImageButton(thumbnailSize, onComplete),
			),
			view.DivClearBoth(),
		)

		if withLabel {
			return view.AddStandardLabel(form, editor, metaData), nil
		}
		return editor, nil
	}

	return self.FormFieldFactoryWrapper.Wrapped.NewInput(withLabel, metaData, form)
}
Esempio n. 10
0
func (self ImageRefController) NewInput(withLabel bool, metaData *model.MetaData, form *view.Form) (input view.View, err error) {
	imageRef := metaData.Value.Addr().Interface().(*ImageRef)
	thumbnailSize := Config.ImageRefController.ThumbnailSize

	var img view.View
	if imageRef.IsEmpty() {
		img = view.IMG(Config.dummyImageURL, thumbnailSize, thumbnailSize)
	} else {
		image, found, err := imageRef.TryGet()
		if err != nil {
			return nil, err
		}
		if found {
			version, err := image.Thumbnail(thumbnailSize)
			if err != nil {
				return nil, err
			}
			img = version.View("")
		} else {
			imageRef.Set(nil)
			img = view.IMG(Config.dummyImageURL, thumbnailSize, thumbnailSize)
		}
	}

	hiddenInput := &view.HiddenInput{Name: metaData.Selector(), Value: imageRef.String()}

	thumbnailFrame := &view.Div{
		Class:   Config.ImageRefController.ThumbnailFrameClass,
		Style:   fmt.Sprintf("width:%dpx;height:%dpx;", thumbnailSize, thumbnailSize),
		Content: img,
	}

	uploadList := &view.List{Class: "qq-upload-list"}

	removeButton := &view.Div{
		Class:   "qq-upload-button",
		Content: view.HTML("Remove"),
		OnClick: fmt.Sprintf(
			`jQuery("#%s").attr("value", "");
			jQuery("#%s").empty().append("<img src='%s' width='%d' height='%d'/>");
			jQuery("#%s").empty();`,
			hiddenInput.ID(),
			thumbnailFrame.ID(),
			Config.dummyImageURL,
			thumbnailSize,
			thumbnailSize,
			uploadList.ID(),
		),
	}

	chooseDialogThumbnails := view.DIV("")
	chooseDialogThumbnailsID := chooseDialogThumbnails.ID()
	chooseDialog := &view.ModalDialog{
		Style: "width:600px;height:400px;",
		Content: view.Views{
			view.H3("Choose Image:"),
			chooseDialogThumbnails,
			view.ModalDialogCloseButton("Close"),
		},
	}

	chooseButton := view.DynamicView(
		func(ctx *view.Context) (view.View, error) {
			return &view.Div{
				Class:   "qq-upload-button",
				Content: view.HTML("Choose existing"),
				OnClick: fmt.Sprintf(
					`gostart_media.fillChooseDialog('#%s', '%s', function(value){
						jQuery('#%s').attr('value', value.id);
						var img = '<img src=\"'+value.url+'\" alt=\"'+value.title+'\"/>';
						jQuery('#%s').empty().append(img);
						%s
					});
					%s;`,
					chooseDialogThumbnailsID,
					AllThumbnailsAPI.URL(ctx.ForURLArgsConvert(Config.ImageRefController.ThumbnailSize)),
					hiddenInput.ID(),
					thumbnailFrame.ID(),
					view.ModalDialogCloseScript,
					chooseDialog.OpenScript(),
				),
			}, nil
		},
	)

	uploadButton := view.DIV("")
	uploadButtonID := uploadButton.ID()
	uploadButton.Content = UploadImageButton(
		"#"+uploadButtonID,
		"#"+thumbnailFrame.ID(),
		"#"+uploadList.ID(),
		thumbnailSize,
		fmt.Sprintf(
			`function(id, fileName, responseJSON) {
				var img = "<img src='" + responseJSON.thumbnailURL + "' width='%d' height='%d'/>";
				jQuery("#%s").empty().html(img);
				jQuery("#%s").attr("value", responseJSON.imageID);
			}`,
			thumbnailSize,
			thumbnailSize,
			thumbnailFrame.ID(),
			hiddenInput.ID(),
		),
	)

	editor := view.DIV(Config.ImageRefController.Class,
		view.RequireScriptURL("/media/media.js", 0),
		view.RequireStyle(
			`.qq-upload-button {
				margin: 0 0 5px 10px;
				cursor: pointer;
			}
			.qq-upload-button:hover {
				background-color: #cc0000;
			}`,
			10,
		),
		chooseDialog,
		hiddenInput,
		thumbnailFrame,
		&view.Div{
			Class: Config.ImageRefController.ActionsClass,
			Style: fmt.Sprintf("margin-left: %dpx", thumbnailSize+10),
			Content: view.Views{
				removeButton,
				chooseButton,
				uploadButton,
			},
		},
		uploadList,
	)

	if withLabel {
		return view.AddStandardLabel(form, editor, metaData), nil
	}
	return editor, nil
}
Esempio n. 11
0
func ImagesAdmin() view.View {
	return view.Views{
		UploadImageButton("", "", Config.Admin.ThumbnailSize, "function(){window.location.reload()}"),
		view.HR(),
		&view.Form{
			SubmitButtonText:  "Delete smaller image versions (they will be regenerated)",
			SubmitButtonClass: Config.Admin.ButtonClass,
			FormID:            "deleteVersions",
			OnSubmit: func(form *view.Form, formModel interface{}, ctx *view.Context) (message string, redirect view.URL, err error) {
				var image Image

				for i := ImageIterator(); i.Next(&image); {
					err = image.DeleteVersions()
					if err != nil {
						return "", nil, err
					}
					err = image.Save()
					if err != nil {
						return "", nil, err
					}
				}
				return "", view.StringURL("."), nil
			},
		},
		&view.ModelIteratorView{
			GetModelIterator: func(ctx *view.Context) model.Iterator {
				return Config.Backend.ImageIterator()
			},
			GetModel: func(ctx *view.Context) (interface{}, error) {
				return new(Image), nil
			},
			GetModelView: func(ctx *view.Context, m interface{}) (view.View, error) {
				image := *m.(*Image) // copy by value because it will be used in a closure later on
				refCount, err := image.CountRefs()
				if err != nil {
					return nil, err
				}
				thumbnail, err := image.Thumbnail(Config.Admin.ThumbnailSize)
				if err != nil {
					return nil, err
				}
				deleteConfirmation := fmt.Sprintf("Are you sure you want to delete the image %s?", image.Title)
				if refCount > 0 {
					deleteConfirmation += fmt.Sprintf(" It is used %d times!", refCount)
				}
				editor := view.DIV(Config.Admin.ImageEditorClass,
					view.H3(image.Title.Get()),
					view.P(view.A_blank(image.FileURL(), "Link to original") /*, view.Printf(" | Used %d times", refCount)*/),
					view.P("Size in MB: ", view.Printf("%f", (float32)(image.Size.Get())/(1024.0*1024.0))),
					view.DIV(Config.Admin.ThumbnailFrameClass,
						thumbnail.View(""),
					),
					&view.Form{
						FormID:            "edit" + image.ID.Get(),
						SubmitButtonClass: Config.Admin.ButtonClass,
						GetModel: func(form *view.Form, ctx *view.Context) (interface{}, error) {
							return &imageData{
								Title:    image.Title,
								Filename: model.String(image.Filename()),
								Link:     image.Link,
							}, nil
						},
						OnSubmit: func(form *view.Form, formModel interface{}, ctx *view.Context) (message string, redirect view.URL, err error) {
							model := formModel.(*imageData)
							image.Title = model.Title
							image.Link = model.Link
							for i := range image.Versions {
								image.Versions[i].Filename = model.Filename
							}
							err = image.Save()
							return "", view.StringURL("."), err
						},
					},
					&view.Form{
						SubmitButtonText:    "Delete",
						SubmitButtonConfirm: deleteConfirmation,
						SubmitButtonClass:   Config.Admin.ButtonClass,
						FormID:              "delete" + image.ID.Get(),
						OnSubmit: func(form *view.Form, formModel interface{}, ctx *view.Context) (message string, redirect view.URL, err error) {
							_, err = image.RemoveAllRefs()
							if err != nil {
								return "", nil, err
							}
							return "", view.StringURL("."), image.Delete()
						},
					},
					view.DivClearBoth(),
				)
				return editor, nil
			},
		},
	}
}