@Override
    protected TextField<String> newTextField(
        String id, IModel<String> valueModel, final ImportableRemoteRepo rowObject) {
      TextField<String> textField = super.newTextField(id, valueModel, rowObject);
      textField.setLabel(Model.of("Key"));
      textField.setOutputMarkupId(true);
      textField.setRequired(true);
      textField.add(new NameValidator("Invalid repository key '%s'."));
      textField.add(new XsdNCNameValidator("Invalid repository key '%s'."));
      textField.add(
          new AjaxFormComponentUpdatingBehavior("onkeyup") {
            @Override
            protected void onUpdate(AjaxRequestTarget target) {
              validateRepoKey(rowObject);
              // On each update, refresh import button to customize the warning messages of the call
              // decorator
              target.add(importButton);
            }

            @Override
            protected void onError(AjaxRequestTarget target, RuntimeException e) {
              super.onError(target, e);
              AjaxUtils.refreshFeedback();
            }

            @Override
            protected IAjaxCallDecorator getAjaxCallDecorator() {
              return new NoAjaxIndicatorDecorator();
            }
          });
      return textField;
    }
Beispiel #2
0
  /** @see Form#Form(String) */
  public UploadForm(String id) {
    super(id);

    // multipart always needed for uploads
    setMultiPart(true);

    // input field for identifier text
    identifier = new TextField<String>("identifier", new Model<String>());
    // pattern validator
    identifier.add(new PatternValidator("[A-Za-z0-9 _\\-]+"));
    // validator that checks if the project name is already taken
    identifier.add(
        new IValidator<String>() {

          private static final long serialVersionUID = 275885544279441469L;

          @Override
          public void validate(IValidatable<String> validatable) {
            String name = validatable.getValue();
            for (String project : projects.getResources()) {
              // ignore case to avoid confusion
              if (name.equalsIgnoreCase(project)) {
                validatable.error(new ValidationError().setMessage("Identifier already in use"));
                break;
              }
            }
          }
        });
    FieldMessage identifierMessage =
        new FieldMessage(
            "identifierMessage",
            new Model<String>("Unique identifier for the project"),
            identifier);
    identifier.add(new FieldValidatingBehavior("onblur", identifierMessage));
    identifier.setOutputMarkupId(true);
    identifier.setRequired(true);
    //		identifier.add(new DefaultFocus()); XXX not working well with ajax
    add(identifier);
    add(identifierMessage);

    // Add one file input field
    add(file = new FileUploadField("file"));
    add(new FeedbackPanel("feedback"));

    addAllowedContentType("application/zip");
    addAllowedContentType("application/x-zip");
    addAllowedContentType("application/x-zip-compressed");
    addAllowedContentType("application/octet-stream");

    //		setCustomTypeErrorMessage("Only ZIP archives are supported for upload");

    setMaxSize(Bytes.megabytes(20));
  }
  public SpatialFilePanel(String id) {
    super(id);

    add(dialog = new GeoServerDialog("dialog"));

    Form form = new Form("form", new CompoundPropertyModel(this));
    add(form);

    fileField = new TextField("file");
    fileField.setRequired(true);
    fileField.setOutputMarkupId(true);
    form.add(fileField);
    form.add(chooserButton(form));
  }
Beispiel #4
0
  public UserPanel(String id, CompoundPropertyModel userModel) {
    super(id, new Model());
    setOutputMarkupId(true);

    form = new Form("userForm", userModel);

    if (userModel == null) {
      User user = new User();
      user.setRoles(new ArrayList<Role>());
      form.setModel(new CompoundPropertyModel(user));
    }
    add(form);

    name = new TextField("name");
    password = new TextField("password");
    name.setOutputMarkupId(true);
    form.add(name);
    form.add(password);

    Roles roles = settings.getUserManagement().getAllRoles();
    Palette role =
        new Palette("roles", new Model(roles), new ChoiceRenderer("label", "label"), 6, false);
    form.add(role);

    CheckBox admin = new CheckBox("admin");
    form.add(admin);

    form.add(
        new AjaxButton("save", form) {

          @Override
          protected void onSubmit(AjaxRequestTarget target, Form form) {
            User user = (User) form.getModelObject();
            settings.getUserManagement().addUser(user);
            onSave(target);
          }
        });
  }
  /**
   * @param id
   * @param paramsMap
   * @param paramName
   * @param paramLabelModel
   * @param required
   * @param validators any extra validator that should be added to the input field, or {@code null}
   */
  public FileParamPanel(
      final String id,
      final IModel paramValue,
      final IModel paramLabelModel,
      final boolean required,
      IValidator... validators) {
    // make the value of the text field the model of this panel, for easy value retrieval
    super(id, paramValue);

    // add the dialog for the file chooser
    add(dialog = new ModalWindow("dialog"));

    // the label
    String requiredMark = required ? " *" : "";
    Label label = new Label("paramName", paramLabelModel.getObject() + requiredMark);
    add(label);

    // the text field, with a decorator for validations
    textField = new TextField("paramValue", new FileModel(paramValue));
    textField.setRequired(required);
    textField.setOutputMarkupId(true);
    // set the label to be the paramLabelModel otherwise a validation error would look like
    // "Parameter 'paramValue' is required"
    textField.setLabel(paramLabelModel);

    if (validators != null) {
      for (IValidator validator : validators) {
        textField.add(validator);
      }
    }

    FormComponentFeedbackBorder feedback = new FormComponentFeedbackBorder("border");
    feedback.add(textField);
    feedback.add(chooserButton((String) paramLabelModel.getObject()));
    add(feedback);
  }
  public ComposeNewMessage(String id) {
    super(id);

    // current user
    final String userId = sakaiProxy.getCurrentUserId();

    // setup model
    NewMessageModel newMessage = new NewMessageModel();
    newMessage.setFrom(userId);

    // feedback for form submit action
    formFeedback = new Label("formFeedback");
    formFeedback.setOutputMarkupPlaceholderTag(true);
    add(formFeedback);

    // setup form
    final Form<NewMessageModel> form =
        new Form<NewMessageModel>("form", new Model<NewMessageModel>(newMessage));

    // close button
    /*
    WebMarkupContainer closeButton = new WebMarkupContainer("closeButton");
    closeButton.add(new AjaxFallbackLink<Void>("link") {
    	private static final long serialVersionUID = 1L;

    	public void onClick(AjaxRequestTarget target) {
    		if(target != null) {
    			target.prependJavascript("$('#" + thisPanel.getMarkupId() + "').slideUp();");
    			target.appendJavascript("setMainFrameHeight(window.name);");
    		}
    	}
    }.add(new ContextImage("img",new Model<String>(ProfileConstants.CLOSE_IMAGE))));
    form.add(closeButton);
    */

    // to label
    form.add(new Label("toLabel", new ResourceModel("message.to")));

    // get connections
    final List<Person> connections = connectionsLogic.getConnectionsForUser(userId);
    Collections.sort(connections);

    // list provider
    AutoCompletionChoicesProvider<Person> provider =
        new AutoCompletionChoicesProvider<Person>() {
          private static final long serialVersionUID = 1L;

          public Iterator<Person> getChoices(String input) {
            return connectionsLogic
                .getConnectionsSubsetForSearch(connections, input, true)
                .iterator();
          }
        };

    // renderer
    ObjectAutoCompleteRenderer<Person> renderer =
        new ObjectAutoCompleteRenderer<Person>() {
          private static final long serialVersionUID = 1L;

          protected String getIdValue(Person p) {
            return p.getUuid();
          }

          protected String getTextValue(Person p) {
            return p.getDisplayName();
          }
        };

    // autocompletefield builder
    ObjectAutoCompleteBuilder<Person, String> builder =
        new ObjectAutoCompleteBuilder<Person, String>(provider);
    builder.autoCompleteRenderer(renderer);
    builder.searchLinkImage(ResourceReferences.CROSS_IMG_LOCAL);
    builder.preselect();

    // autocompletefield
    final ObjectAutoCompleteField<Person, String> autocompleteField =
        builder.build("toField", new PropertyModel<String>(newMessage, "to"));
    toField = autocompleteField.getSearchTextField();
    toField.setMarkupId("messagerecipientinput");
    toField.setOutputMarkupId(true);
    toField.add(new AttributeModifier("class", true, new Model<String>("formInputField")));
    toField.setRequired(true);
    form.add(autocompleteField);

    // subject
    form.add(new Label("subjectLabel", new ResourceModel("message.subject")));
    final TextField<String> subjectField =
        new TextField<String>("subjectField", new PropertyModel<String>(newMessage, "subject"));
    subjectField.setMarkupId("messagesubjectinput");
    subjectField.setOutputMarkupId(true);
    subjectField.add(new RecipientEventBehavior("onfocus"));
    form.add(subjectField);

    // body
    form.add(new Label("messageLabel", new ResourceModel("message.message")));
    final TextArea<String> messageField =
        new TextArea<String>("messageField", new PropertyModel<String>(newMessage, "message"));
    messageField.setMarkupId("messagebodyinput");
    messageField.setOutputMarkupId(true);
    messageField.setRequired(true);
    messageField.add(new RecipientEventBehavior("onfocus"));
    form.add(messageField);

    // send button
    IndicatingAjaxButton sendButton =
        new IndicatingAjaxButton("sendButton", form) {
          private static final long serialVersionUID = 1L;

          protected void onSubmit(AjaxRequestTarget target, Form form) {

            // get the backing model
            NewMessageModel newMessage = (NewMessageModel) form.getModelObject();

            // generate the thread id
            String threadId = ProfileUtils.generateUuid();

            // save it, it will be abstracted into its proper parts and email notifications sent
            if (messagingLogic.sendNewMessage(
                newMessage.getTo(),
                newMessage.getFrom(),
                threadId,
                newMessage.getSubject(),
                newMessage.getMessage())) {

              // post event
              sakaiProxy.postEvent(
                  ProfileConstants.EVENT_MESSAGE_SENT, "/profile/" + newMessage.getTo(), true);

              // success
              formFeedback.setDefaultModel(new ResourceModel("success.message.send.ok"));
              formFeedback.add(new AttributeModifier("class", true, new Model<String>("success")));

              // target.appendJavascript("$('#" + form.getMarkupId() + "').slideUp();");
              target.appendJavaScript("setMainFrameHeight(window.name);");

              // PRFL-797 all fields when successful, to prevent multiple messages.
              // User can just click Compose message again to get a new form
              this.setEnabled(false);
              autocompleteField.setEnabled(false);
              subjectField.setEnabled(false);
              messageField.setEnabled(false);
              target.add(this);
              target.add(autocompleteField);
              target.add(subjectField);
              target.add(messageField);

            } else {
              // error
              formFeedback.setDefaultModel(new ResourceModel("error.message.send.failed"));
              formFeedback.add(
                  new AttributeModifier("class", true, new Model<String>("alertMessage")));
            }

            formFeedback.setVisible(true);
            target.add(formFeedback);
          }

          protected void onError(AjaxRequestTarget target, Form form) {

            // check which item didn't validate and update the feedback model
            if (!toField.isValid()) {
              formFeedback.setDefaultModel(new ResourceModel("error.message.required.to"));
            }
            if (!messageField.isValid()) {
              formFeedback.setDefaultModel(new ResourceModel("error.message.required.body"));
            }
            formFeedback.add(
                new AttributeModifier("class", true, new Model<String>("alertMessage")));

            target.add(formFeedback);
          }
        };
    form.add(sendButton);
    sendButton.setModel(new ResourceModel("button.message.send"));

    add(form);
  }
    public AdminOrderPageForm(String id) {
      super(id);

      errorPanel = new FeedbackPanel("feedback");
      username = new TextField<String>("username", Model.of(""));
      email = new TextField<String>("email", Model.of(""));
      countryCostModel = Model.of("");
      hotelCostModel = Model.of("");
      tourCostModel = Model.of("");

      countryCost = new Label("countryCostLabel", countryCostModel);
      hotelCost = new Label("hotelCostLabel", hotelCostModel);
      tourCost = new Label("tourCostLabel", tourCostModel);

      order = new Order();
      orderDao = new OrderDao();
      hotelOptions = new HashMap<String, List<String>>();
      tourOptions = new HashMap<String, List<String>>();

      countries = orderDao.getCountries();
      hotels = orderDao.getHotels();
      tours = orderDao.getTours();

      for (OrderObject country : countries) {
        hotelOptions.put(country.getName(), getNames(hotels, country.getName()));
        tourOptions.put(country.getName(), getNames(tours, country.getName()));
      }

      IModel<List<? extends String>> makeCountryChoises =
          new AbstractReadOnlyModel<List<? extends String>>() {
            @Override
            public List<String> getObject() {
              return new ArrayList<String>(hotelOptions.keySet());
            }
          };

      IModel<List<? extends String>> modelTownChoices =
          new AbstractReadOnlyModel<List<? extends String>>() {
            @Override
            public List<String> getObject() {
              List<String> models = hotelOptions.get(selectedOption);
              if (models == null) {
                models = Collections.emptyList();
              }
              return models;
            }
          };

      IModel<List<? extends String>> modelTourChoices =
          new AbstractReadOnlyModel<List<? extends String>>() {
            @Override
            public List<String> getObject() {
              List<String> models = tourOptions.get(selectedOption);
              if (models == null) {
                models = Collections.emptyList();
              }
              return models;
            }
          };

      countryDropDown =
          new DropDownChoice<String>(
              "countryDropDown",
              new PropertyModel<String>(this, "selectedOption"),
              makeCountryChoises);

      hotelDropDown =
          new DropDownChoice<String>(
              "hotelDropDown", new PropertyModel<String>(this, "selectedHotel"), modelTownChoices);

      tourDropDown =
          new DropDownChoice<String>(
              "tourDropDown", new PropertyModel<String>(this, "selectedTour"), modelTourChoices);
      totalCostSumModel = new PropertyModel<String>(this, "calculatedTotalCostSum");
      totalCostSum = new TextField("totalCostSumLabel", totalCostSumModel);

      hotelDropDown.setOutputMarkupId(true);
      tourDropDown.setOutputMarkupId(true);
      countryCost.setOutputMarkupId(true);
      hotelCost.setOutputMarkupId(true);
      tourCost.setOutputMarkupId(true);
      totalCostSum.setOutputMarkupId(true);

      countryDropDown.add(
          new AjaxFormComponentUpdatingBehavior("onchange") {
            @Override
            protected void onUpdate(AjaxRequestTarget target) {
              target.add(hotelDropDown);
              target.add(tourDropDown);

              String cost = getCost(countries, selectedOption);
              countryCostModel.setObject(cost);
              hotelCostModel.setObject(getCost(hotels, selectedHotel));
              tourCostModel.setObject(getCost(tours, selectedTour));
              totalCostSumModel.setObject(getTotalCostSum());

              target.add(countryCost);
              target.add(hotelCost);
              target.add(tourCost);
              target.add(totalCostSum);
            }
          });
      hotelDropDown.add(
          new AjaxFormComponentUpdatingBehavior("onchange") {
            @Override
            protected void onUpdate(AjaxRequestTarget target) {
              hotelCostModel.setObject(getCost(hotels, selectedHotel));
              totalCostSumModel.setObject(getTotalCostSum());
              target.add(hotelCost);
              target.add(totalCostSum);
            }
          });
      tourDropDown.add(
          new AjaxFormComponentUpdatingBehavior("onchange") {
            @Override
            protected void onUpdate(AjaxRequestTarget target) {
              tourCostModel.setObject(getCost(tours, selectedTour));
              totalCostSumModel.setObject(getTotalCostSum());
              target.add(tourCost);
              target.add(totalCostSum);
            }
          });
      add(new Label("feedBack", feedBack));
      add(errorPanel);
      add(username);
      add(email);
      add(countryDropDown);
      add(hotelDropDown);
      add(tourDropDown);
      add(countryCost);
      add(hotelCost);
      add(tourCost);
      add(totalCostSum);
    }
  public AdvancedCorrelationPanel(String id) {
    super(id);

    Form<Void> advancedCorrelationForm = new WarnOnExitForm("advancedCorrelationForm");
    add(advancedCorrelationForm);

    timeCorrelationCheckBox =
        new AjaxCheckBox("timeCheckBox", Model.of(Boolean.FALSE)) {

          @Override
          protected void onUpdate(AjaxRequestTarget target) {
            timeCorrelationSelected = timeCorrelationSelected ? false : true;
          }
        };
    timeCorrelationCheckBox.setOutputMarkupId(true);
    advancedCorrelationForm.add(timeCorrelationCheckBox);

    timeCorrelationEventTypeSelect =
        new DropDownChoice<SushiEventType>(
            "timeEventTypeSelect",
            new PropertyModel<SushiEventType>(this, "selectedEventType"),
            new ArrayList<SushiEventType>());
    timeCorrelationEventTypeSelect.setOutputMarkupId(true);
    timeCorrelationEventTypeSelect.add(
        new AjaxFormComponentUpdatingBehavior("onChange") {

          @Override
          protected void onUpdate(AjaxRequestTarget target) {
            if (selectedEventType != null) {
              conditionPanel.setSelectedEventTypes(Arrays.asList((selectedEventType)));
              conditionPanel.updateAttributesValues();
            } else {
              conditionPanel.getConditionAttributeSelect().setChoices(new ArrayList<String>());
              conditionPanel.getConditionValueSelect().setChoices(new ArrayList<Serializable>());
            }
            target.add(conditionPanel.getConditionAttributeSelect());
            target.add(conditionPanel.getConditionValueSelect());
          }
        });
    advancedCorrelationForm.add(timeCorrelationEventTypeSelect);

    timeCorrelationMinutesInput = new TextField<String>("timeMinutesInput", Model.of(""));
    timeCorrelationMinutesInput.setOutputMarkupId(true);
    timeCorrelationMinutesInput.add(
        new AjaxFormComponentUpdatingBehavior("onChange") {

          @Override
          protected void onUpdate(AjaxRequestTarget target) {
            timeCorrelationMinutes = timeCorrelationMinutesInput.getValue();
          }
        });
    advancedCorrelationForm.add(timeCorrelationMinutesInput);

    timeCorrelationAfterOrBeforeType =
        new RadioChoice<String>(
            "afterOrBeforeRadioGroup",
            new PropertyModel<String>(this, "selectedTimeRadioOption"),
            timeCorrelationRadioValues) {
          public String getSuffix() {
            return "&nbsp;&nbsp;&nbsp;";
          }
        };
    advancedCorrelationForm.add(timeCorrelationAfterOrBeforeType);

    conditionPanel = new ConditionInputPanel("conditionInput", true);
    advancedCorrelationForm.add(conditionPanel);

    multipleConditionsTextField =
        new TextField<String>("multipleConditionsTextField", new Model<String>());
    multipleConditionsTextField.setOutputMarkupId(true);
    OnChangeAjaxBehavior onChangeAjaxBehavior =
        new OnChangeAjaxBehavior() {
          private static final long serialVersionUID = -5737941362786901904L;

          @Override
          protected void onUpdate(AjaxRequestTarget target) {
            if (isMultipleConditionsTextFieldFilled()) {
              conditionPanel.disableAllComponents(target);
            } else {
              conditionPanel.enableAllComponents(target);
            }
          }
        };
    multipleConditionsTextField.add(onChangeAjaxBehavior);
    advancedCorrelationForm.add(multipleConditionsTextField);
  }
  private void initLayout(final IModel<TaskDto> taskDtoModel) {

    WebMarkupContainer threadsConfigurationPanel =
        new WebMarkupContainer(ID_THREADS_CONFIGURATION_PANEL);
    add(threadsConfigurationPanel);

    threadsConfigurationPanel.add(
        new VisibleEnableBehaviour() {
          @Override
          public boolean isVisible() {
            return taskDtoModel.getObject().configuresWorkerThreads();
          }
        });

    final TextField<Integer> workerThreads =
        new TextField<>(
            ID_WORKER_THREADS, new PropertyModel<Integer>(taskDtoModel, TaskDto.F_WORKER_THREADS));
    workerThreads.setOutputMarkupId(true);
    workerThreads.add(
        new VisibleEnableBehaviour() {
          @Override
          public boolean isEnabled() {
            return parentPage.isEdit();
          }
        });
    threadsConfigurationPanel.add(workerThreads);

    VisibleEnableBehaviour hiddenWhenEditingOrNoSubtasks =
        new VisibleEnableBehaviour() {
          @Override
          public boolean isVisible() {
            return !parentPage.isEdit() && !taskDtoModel.getObject().getSubtasks().isEmpty();
          }
        };

    Label subtasksLabel =
        new Label(ID_SUBTASKS_LABEL, new ResourceModel("pageTaskEdit.subtasksLabel"));
    subtasksLabel.add(hiddenWhenEditingOrNoSubtasks);
    add(subtasksLabel);
    SubtasksPanel subtasksPanel =
        new SubtasksPanel(
            ID_SUBTASKS_PANEL,
            new PropertyModel<List<TaskDto>>(taskDtoModel, TaskDto.F_SUBTASKS),
            parentPage.getWorkflowManager().isEnabled());
    subtasksPanel.add(hiddenWhenEditingOrNoSubtasks);
    add(subtasksPanel);

    VisibleEnableBehaviour hiddenWhenNoSubtasks =
        new VisibleEnableBehaviour() {
          @Override
          public boolean isVisible() {
            TaskDto taskDto = taskDtoModel.getObject();
            return taskDto != null && !taskDto.getTransientSubtasks().isEmpty();
          }
        };

    Label workerThreadsTableLabel =
        new Label(ID_WORKER_THREADS_TABLE_LABEL, new ResourceModel("TaskStatePanel.workerThreads"));
    workerThreadsTableLabel.add(hiddenWhenNoSubtasks);
    add(workerThreadsTableLabel);
    List<IColumn<WorkerThreadDto, String>> columns = new ArrayList<>();
    columns.add(
        new PropertyColumn(
            createStringResourceStatic(this, "TaskStatePanel.subtaskName"),
            WorkerThreadDto.F_NAME));
    columns.add(
        new EnumPropertyColumn<WorkerThreadDto>(
            createStringResourceStatic(this, "TaskStatePanel.subtaskState"),
            WorkerThreadDto.F_EXECUTION_STATUS));
    columns.add(
        new PropertyColumn(
            createStringResourceStatic(this, "TaskStatePanel.subtaskObjectsProcessed"),
            WorkerThreadDto.F_PROGRESS));
    ISortableDataProvider<WorkerThreadDto, String> threadsProvider =
        new ListDataProvider<>(
            this,
            new AbstractReadOnlyModel<List<WorkerThreadDto>>() {
              @Override
              public List<WorkerThreadDto> getObject() {
                List<WorkerThreadDto> rv = new ArrayList<>();
                TaskDto taskDto = taskDtoModel.getObject();
                if (taskDto != null) {
                  for (TaskDto subtaskDto : taskDto.getTransientSubtasks()) {
                    rv.add(new WorkerThreadDto(subtaskDto));
                  }
                }
                return rv;
              }
            });
    TablePanel<WorkerThreadDto> workerThreadsTablePanel =
        new TablePanel<>(ID_WORKER_THREADS_TABLE, threadsProvider, columns);
    workerThreadsTablePanel.add(hiddenWhenNoSubtasks);
    add(workerThreadsTablePanel);
  }
Beispiel #10
0
  /**
   * Constructor.
   *
   * @param parameters the current page parameters
   */
  public MailTemplate(final PageParameters parameters) {
    super(parameters);

    final FeedbackPanel feedback = new FeedbackPanel("feedback");
    feedback.setOutputMarkupId(true);
    add(feedback);

    final Form<Void> form = new Form<>("form");
    add(form);

    TextField<String> nameTextField =
        new TextField<>("name", new PropertyModel<String>(MailTemplate.this, "name"));
    nameTextField.setOutputMarkupId(true);
    form.add(nameTextField);

    final MultiLineLabel result = new MultiLineLabel("result", new Model<>());
    result.setOutputMarkupId(true);
    add(result);

    AjaxSubmitLink basedOnPageLink =
        new AjaxSubmitLink("pageBasedLink", form) {
          private static final long serialVersionUID = 1L;

          @Override
          protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
            PageParameters parameters = new PageParameters();
            parameters.set("name", name);
            PageProvider pageProvider = new PageProvider(TemplateBasedOnPage.class, parameters);
            CharSequence pageHtml = ComponentRenderer.renderPage(pageProvider);

            updateResult(result, pageHtml, target);
            target.add(feedback);
          }

          @Override
          protected void onError(AjaxRequestTarget target, Form<?> form) {
            target.add(feedback);
          }
        };

    AjaxSubmitLink basedOnPanelLink =
        new AjaxSubmitLink("panelBasedLink", form) {
          private static final long serialVersionUID = 1L;

          @Override
          protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
            CharSequence panelHtml =
                ComponentRenderer.renderComponent(
                    new MailTemplatePanel(
                        "someId", new PropertyModel<String>(MailTemplate.this, "name")));

            updateResult(result, panelHtml, target);
            target.add(feedback);
          }

          @Override
          protected void onError(AjaxRequestTarget target, Form<?> form) {
            target.add(feedback);
          }
        };

    AjaxSubmitLink basedOnTextTemplateLink =
        new AjaxSubmitLink("textTemplateBasedLink", form) {
          private static final long serialVersionUID = 1L;

          @Override
          protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
            Map<String, Object> variables = new HashMap<>();
            variables.put("name", name);

            CharSequence relativeUrl =
                urlFor(new PackageResourceReference(MailTemplate.class, "resource.txt"), null);
            String href =
                getRequestCycle().getUrlRenderer().renderFullUrl(Url.parse(relativeUrl.toString()));
            variables.put("downloadLink", href);

            PackageTextTemplate template =
                new PackageTextTemplate(MailTemplate.class, "mail-template.tmpl");
            CharSequence templateHtml = template.asString(variables);
            updateResult(result, templateHtml, target);
            target.add(feedback);
          }

          @Override
          protected void onError(AjaxRequestTarget target, Form<?> form) {
            target.add(feedback);
          }
        };

    add(basedOnPageLink, basedOnPanelLink, basedOnTextTemplateLink);
  }