///////////////////////////////////////////////////////////////////////////// // // Project ProjectForge Community Edition // www.projectforge.org // // Copyright (C) 2001-2014 Kai Reinhard (k.reinhard@micromata.de) // // ProjectForge is dual-licensed. // // This community edition is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as published // by the Free Software Foundation; version 3 of the License. // // This community edition is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General // Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, see http://www.gnu.org/licenses/. // ///////////////////////////////////////////////////////////////////////////// package org.projectforge.plugins.skillmatrix; import java.util.List; import java.util.ListIterator; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxEventBehavior; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.FormComponent; import org.apache.wicket.markup.html.form.SubmitLink; import org.apache.wicket.markup.repeater.RepeatingView; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.request.mapper.parameter.PageParameters; import org.apache.wicket.spring.injection.annot.SpringBean; import org.hibernate.Hibernate; import org.projectforge.web.CSSColor; import org.projectforge.web.fibu.ISelectCallerPage; import org.projectforge.web.wicket.AbstractEditPage; import org.projectforge.web.wicket.AbstractSecuredPage; import org.projectforge.web.wicket.AbstractSelectPanel; import org.projectforge.web.wicket.WicketUtils; import org.projectforge.web.wicket.flowlayout.ComponentWrapperPanel; import org.projectforge.web.wicket.flowlayout.FieldsetPanel; import org.projectforge.web.wicket.flowlayout.IconPanel; import org.projectforge.web.wicket.flowlayout.IconType; /** * @author Billy Duong (b.duong@micromata.de) * */ public class SkillSelectPanel extends AbstractSelectPanel<SkillDO> implements ComponentWrapperPanel { private static final long serialVersionUID = -7231190025292695850L; public static final String I18N_KEY_SELECT_ANCESTOR_SKILL_TOOLTIP = "plugins.skillmatrix.skill.selectPanel.selectAncestorSkill.tooltip"; public static final String I18N_KEY_DISPLAY_SKILL_TOOLTIP = "plugins.skillmatrix.skill.selectPanel.displaySkill.tooltip"; public static final String I18N_KEY_SELECT_SKILL_TOOLTIP = "plugins.skillmatrix.skill.selectPanel.selectSkill"; public static final String I18N_KEY_UNSELECT_SKILL_TOOLTIP = "plugins.skillmatrix.skill.selectPanel.unselectSkill"; @SpringBean(name = "skillDao") private SkillDao skillDao; private boolean showPath = true; private final WebMarkupContainer divContainer; private RepeatingView ancestorRepeater; private Integer currentSkillId; private boolean ajaxSkillSelectMode; private WebMarkupContainer userselectContainer; private FieldsetPanel fieldsetPanel; public SkillSelectPanel(final FieldsetPanel fieldsetPanel, final IModel<SkillDO> model, final ISelectCallerPage caller, final String selectProperty) { super(fieldsetPanel.newChildId(), model, caller, selectProperty); this.fieldsetPanel = fieldsetPanel; fieldsetPanel.getFieldset().setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true); SkillDO skill = model.getObject(); if (Hibernate.isInitialized(skill) == false) { skill = getSkillTree().getSkillById(skill.getId()); model.setObject(skill); } divContainer = new WebMarkupContainer("div") { private static final long serialVersionUID = -8150112323444983335L; /** * @see org.apache.wicket.Component#isVisible() */ @Override public boolean isVisible() { // display only, if we are not in ajax skill select mode return ajaxSkillSelectMode == false; } }; divContainer.setOutputMarkupId(true); divContainer.setOutputMarkupPlaceholderTag(true); add(divContainer); ajaxSkillSelectMode = false; } /** * @see org.projectforge.web.wicket.AbstractSelectPanel#onBeforeRender() */ @SuppressWarnings("serial") @Override protected void onBeforeRender() { super.onBeforeRender(); final SkillDO skill = getModelObject(); final Integer skillId = skill != null ? skill.getId() : null; if (currentSkillId == skillId) { return; } currentSkillId = skillId; if (showPath == true && skill != null) { ancestorRepeater.removeAll(); final SkillNode skillNode = getSkillTree().getSkillNodeById(skill.getId()); final List<Integer> ancestorIds = skillNode.getAncestorIds(); final ListIterator<Integer> it = ancestorIds.listIterator(ancestorIds.size()); while (it.hasPrevious() == true) { final Integer ancestorId = it.previous(); final SkillDO ancestorSkill = getSkillTree().getSkillById(ancestorId); if (ancestorSkill.getParent() == null) { // Don't show root node: continue; } final WebMarkupContainer cont = new WebMarkupContainer(ancestorRepeater.newChildId()); ancestorRepeater.add(cont); final SubmitLink selectSkillLink = new SubmitLink("ancestorSkillLink") { @Override public void onSubmit() { caller.select(selectProperty, ancestorSkill.getId()); } }; selectSkillLink.setDefaultFormProcessing(false); cont.add(selectSkillLink); WicketUtils.addTooltip(selectSkillLink, getString(I18N_KEY_SELECT_ANCESTOR_SKILL_TOOLTIP)); selectSkillLink.add(new Label("name", ancestorSkill.getTitle())); } ancestorRepeater.setVisible(true); } else { ancestorRepeater.setVisible(false); } } @Override @SuppressWarnings("serial") public SkillSelectPanel init() { super.init(); ancestorRepeater = new RepeatingView("ancestorSkills"); divContainer.add(ancestorRepeater); final SubmitLink skillLink = new SubmitLink("skillLink") { @Override public void onSubmit() { final SkillDO skill = getModelObject(); if (skill == null) { return; } final PageParameters pageParams = new PageParameters(); pageParams.add(AbstractEditPage.PARAMETER_KEY_ID, String.valueOf(skill.getId())); final SkillEditPage editPage = new SkillEditPage(pageParams); editPage.setReturnToPage((AbstractSecuredPage) getPage()); setResponsePage(editPage); } }; skillLink.setDefaultFormProcessing(false); divContainer.add(skillLink); // auto complete panels initAutoCompletePanels(); WicketUtils.addTooltip(skillLink, getString(I18N_KEY_DISPLAY_SKILL_TOOLTIP)); skillLink.add(new Label("name", new Model<String>() { /** * @see org.apache.wicket.model.Model#getObject() */ @Override public String getObject() { final SkillDO skill = getModelObject(); return skill != null ? skill.getTitle() : ""; } })); final SubmitLink selectButton = new SubmitLink("select") { @Override public void onSubmit() { final SkillTreePage skillTreePage = new SkillTreePage(caller, selectProperty); if (getModelObject() != null) { skillTreePage.setHighlightedRowId(getModelObject().getId()); // Preselect node for highlighting. } setResponsePage(skillTreePage); }; }; selectButton.setDefaultFormProcessing(false); divContainer.add(selectButton); selectButton.add(new IconPanel("selectHelp", IconType.TASK, getString(I18N_KEY_SELECT_SKILL_TOOLTIP))); final SubmitLink unselectButton = new SubmitLink("unselect") { @Override public void onSubmit() { caller.unselect(selectProperty); } @Override public boolean isVisible() { return isRequired() == false && getModelObject() != null; } }; unselectButton.setDefaultFormProcessing(false); divContainer.add(unselectButton); unselectButton.add(new IconPanel("unselectHelp", IconType.REMOVE_SIGN, getString(I18N_KEY_UNSELECT_SKILL_TOOLTIP)).setColor(CSSColor.RED)); return this; } /** * */ private void initAutoCompletePanels() { userselectContainer = new WebMarkupContainer("userselectContainer") { private static final long serialVersionUID = -4871020567729661148L; /** * @see org.apache.wicket.Component#isVisible() */ @Override public boolean isVisible() { // only show if we are in ajax select skill mode return ajaxSkillSelectMode == true; } }; add(userselectContainer); userselectContainer.setOutputMarkupId(true); userselectContainer.setOutputMarkupPlaceholderTag(true); final SkillSelectAutoCompleteFormComponent searchSkillInput = new SkillSelectAutoCompleteFormComponent("searchSkillInput") { private static final long serialVersionUID = -7741009167252308262L; /** * @see org.projectforge.web.skill.SkillSelectAutoCompleteFormComponent#onModelChanged(org.apache.wicket.ajax.AjaxRequestTarget) */ @Override protected void onModelSelected(final AjaxRequestTarget target, final SkillDO skillDo) { ajaxSkillSelectMode = false; target.appendJavaScript("hideAllTooltips();"); SkillSelectPanel.this.setModelObject(skillDo); SkillSelectPanel.this.onModelSelected(target, skillDo); } }; userselectContainer.add(searchSkillInput); // opener link final WebMarkupContainer searchSkillInputOpen = new WebMarkupContainer("searchSkillInputOpen"); WicketUtils.addTooltip(searchSkillInputOpen, getString("quickselect")); searchSkillInputOpen.add(new AjaxEventBehavior("click") { private static final long serialVersionUID = -938527474172868488L; @Override protected void onEvent(final AjaxRequestTarget target) { ajaxSkillSelectMode = true; target.appendJavaScript("hideAllTooltips();"); target.add(divContainer); target.add(userselectContainer); target.focusComponent(searchSkillInput); } }); // close link final WebMarkupContainer searchSkillInputClose = new WebMarkupContainer("searchSkillInputClose"); divContainer.add(searchSkillInputClose); searchSkillInputClose.add(new AjaxEventBehavior("click") { private static final long serialVersionUID = -4334830387094758960L; @Override protected void onEvent(final AjaxRequestTarget target) { ajaxSkillSelectMode = false; target.appendJavaScript("hideAllTooltips();"); target.add(divContainer); target.add(userselectContainer); } }); userselectContainer.add(searchSkillInputClose); divContainer.add(searchSkillInputOpen); } /** * Hook method which is called, when the skill is set by auto complete field * * @param target * @param skillDo */ protected void onModelSelected(final AjaxRequestTarget target, final SkillDO skillDo) { target.add(fieldsetPanel.getFieldset()); target.add(divContainer); target.add(userselectContainer); } /** * Will be called if the user has chosen an entry of the skill favorites drop down choice. * @param skill */ protected void selectSkill(final SkillDO skill) { setModelObject(skill); caller.select(selectProperty, skill.getId()); } @Override public Component getClassModifierComponent() { return divContainer; } @Override protected void convertInput() { setConvertedInput(getModelObject()); } /** * If true (default) then the path from the root skill to the currently selected will be shown, otherwise only the name of the skill is * displayed. * @param showPath */ public void setShowPath(final boolean showPath) { this.showPath = showPath; } /** * @see org.projectforge.web.wicket.flowlayout.ComponentWrapperPanel#getComponentOutputId() */ @Override public String getComponentOutputId() { divContainer.setOutputMarkupId(true); return divContainer.getMarkupId(); } /** * @see org.projectforge.web.wicket.flowlayout.ComponentWrapperPanel#getFormComponent() */ @Override public FormComponent< ? > getFormComponent() { return null; } public SkillTree getSkillTree() { return skillDao.getSkillTree(); } /** * @return the currentSkillId */ public Integer getCurrentSkillId() { return currentSkillId; } }