com.google.gerrit.client.changes.PublishTopicCommentScreen.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gerrit.client.changes.PublishTopicCommentScreen.java

Source

// Copyright (C) 2011 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.client.changes;

import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.patches.CommentEditorContainer;
import com.google.gerrit.client.patches.CommentEditorPanel;
import com.google.gerrit.client.patches.PatchUtil;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.ScreenLoadCallback;
import com.google.gerrit.client.ui.AccountScreen;
import com.google.gerrit.client.ui.PatchLink;
import com.google.gerrit.client.ui.SmallHeading;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.common.data.AccountInfo;
import com.google.gerrit.common.data.AccountInfoCache;
import com.google.gerrit.common.data.ApprovalType;
import com.google.gerrit.common.data.ApprovalTypes;
import com.google.gerrit.common.data.ChangeDetail;
import com.google.gerrit.common.data.ChangeSetDetail;
import com.google.gerrit.common.data.ChangeSetPublishDetail;
import com.google.gerrit.common.data.PatchSetPublishDetail;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.common.data.PermissionRange;
import com.google.gerrit.reviewdb.Account;
import com.google.gerrit.reviewdb.ApprovalCategory;
import com.google.gerrit.reviewdb.ApprovalCategoryValue;
import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.ChangeSet;
import com.google.gerrit.reviewdb.ChangeSetInfo;
import com.google.gerrit.reviewdb.Patch;
import com.google.gerrit.reviewdb.PatchLineComment;
import com.google.gerrit.reviewdb.PatchSet;
import com.google.gerrit.reviewdb.PatchSetApproval;
import com.google.gerrit.reviewdb.Topic;
import com.google.gerrit.reviewdb.UserIdentity;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwtexpui.globalkey.client.NpTextArea;
import com.google.gwtjsonrpc.client.VoidResult;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

public class PublishTopicCommentScreen extends AccountScreen implements ClickHandler, CommentEditorContainer {
    private static SavedState lastState;

    private final ChangeSet.Id changeSetId;
    private Collection<ValueRadioButton> approvalButtons;
    private TopicDescriptionBlock descBlock;
    private Panel approvalPanel;
    private NpTextArea message;
    private FlowPanel draftsPanel;
    private Button send;
    private Button submit;
    private Button cancel;
    private boolean saveStateOnUnload = true;
    private List<CommentEditorPanel> commentEditors;

    public PublishTopicCommentScreen(final ChangeSet.Id csi) {
        changeSetId = csi;
    }

    @Override
    protected void onInitUI() {
        super.onInitUI();
        addStyleName(Gerrit.RESOURCES.css().publishCommentsScreen());

        approvalButtons = new ArrayList<ValueRadioButton>();

        descBlock = new TopicDescriptionBlock();
        add(descBlock);

        final FormPanel form = new FormPanel();
        final FlowPanel body = new FlowPanel();
        form.setWidget(body);
        form.addSubmitHandler(new FormPanel.SubmitHandler() {
            @Override
            public void onSubmit(final SubmitEvent event) {
                event.cancel();
            }
        });
        add(form);

        approvalPanel = new FlowPanel();
        body.add(approvalPanel);
        initMessage(body);

        draftsPanel = new FlowPanel();
        body.add(draftsPanel);

        final FlowPanel buttonRow = new FlowPanel();
        buttonRow.setStyleName(Gerrit.RESOURCES.css().patchSetActions());
        body.add(buttonRow);

        send = new Button(Util.C.buttonPublishCommentsSend());
        send.addClickHandler(this);
        buttonRow.add(send);

        submit = new Button(Util.C.buttonPublishSubmitSend());
        submit.addClickHandler(this);
        buttonRow.add(submit);

        cancel = new Button(Util.C.buttonPublishCommentsCancel());
        cancel.addClickHandler(this);
        buttonRow.add(cancel);
    }

    private void enableForm(final boolean enabled) {
        for (final ValueRadioButton approvalButton : approvalButtons) {
            approvalButton.setEnabled(enabled);
        }
        message.setEnabled(enabled);
        for (final CommentEditorPanel commentEditor : commentEditors) {
            commentEditor.enableButtons(enabled);
        }
        send.setEnabled(enabled);
        submit.setEnabled(enabled);
        cancel.setEnabled(enabled);
    }

    @Override
    protected void onLoad() {
        super.onLoad();
        // TODO
        //    Util.DETAIL_SVC.patchSetPublishDetail(patchSetId,
        //        new ScreenLoadCallback<PatchSetPublishDetail>(this) {
        //          @Override
        //          protected void preDisplay(final PatchSetPublishDetail result) {
        //            send.setEnabled(true);
        //            display(result);
        //          }
        //
        //          @Override
        //          protected void postDisplay() {
        //            message.setFocus(true);
        //          }
        //        });

        // TODO delete the following lines, as it is a replacement for the server side
        // BEGIN
        send.setEnabled(true);
        ChangeSetPublishDetail r = new ChangeSetPublishDetail();

        Account me = Gerrit.getUserAccount();
        Account.Id aId = me.getId();
        AccountInfo ai = new AccountInfo(aId);
        ai.setPreferredEmail("my@email.com");
        List<AccountInfo> aiList = new ArrayList<AccountInfo>();
        aiList.add(ai);
        AccountInfoCache aic = new AccountInfoCache(aiList);

        List<ChangeSet> lcs = new ArrayList<ChangeSet>();
        ChangeSetDetail csDetail = new ChangeSetDetail();
        ChangeSet.Id csId = null;
        lcs.clear();
        UserIdentity uid = new UserIdentity();
        uid.setAccount(aId);
        uid.setEmail("my@email.com");
        uid.setName("FakeName");
        uid.setTimeZone(0);
        Change.Id currentTopicId = new Change.Id(1100011);
        ChangeSetInfo csi = null;
        csId = new ChangeSet.Id(currentTopicId, 1);
        ChangeSet cs = new ChangeSet(csId);
        cs.setTopicId(currentTopicId);
        csDetail.setChangeSet(cs);
        csId = new ChangeSet.Id(currentTopicId, 1);
        csi = new ChangeSetInfo(csId);
        csi.setSubject(
                "This is the subject from the last change set - Problem - which one of the commits we should take??");
        csi.setAuthor(uid);
        csi.setMessage("ChangeSetInfo message");
        csDetail.setInfo(csi);
        lcs.add(cs);

        Topic.Key tKey = new Topic.Key("1100010101101 harcoded");
        Topic topic = new Topic(tKey, currentTopicId, aId, null);
        topic.setCurrentChangeSet(csi);
        topic.setStatus(Change.Status.NEW);
        topic.setTopic("This is the topic string");

        List<PermissionRange> labels = new ArrayList<PermissionRange>();
        PermissionRange pr = new PermissionRange("Permission", -2, 2);
        labels.add(pr);

        r.setAccounts(aic);
        r.setCanSubmit(true);
        r.setChangeSetInfo(csi);
        r.setTopic(topic);
        r.setLabels(labels);

        display(r);
        this.display();
        message.setFocus(true);
        // END
    }

    @Override
    protected void onUnload() {
        super.onUnload();
        lastState = saveStateOnUnload ? new SavedState(this) : null;
    }

    @Override
    public void onClick(final ClickEvent event) {
        final Widget sender = (Widget) event.getSource();
        if (send == sender) {
            onSend(false);
        } else if (submit == sender) {
            onSend(true);
        } else if (cancel == sender) {
            saveStateOnUnload = false;
            goChangeSet();
        }
    }

    @Override
    public void notifyDraftDelta(int delta) {
    }

    @Override
    public void remove(CommentEditorPanel editor) {
        commentEditors.remove(editor);

        // The editor should be embedded into a panel holding all
        // editors for the same file.
        //
        FlowPanel parent = (FlowPanel) editor.getParent();
        parent.remove(editor);

        // If the panel now holds no editors, remove it.
        //
        int editorCount = 0;
        for (Widget w : parent) {
            if (w instanceof CommentEditorPanel) {
                editorCount++;
            }
        }
        if (editorCount == 0) {
            parent.removeFromParent();
        }

        // If that was the last file with a draft, remove the heading.
        //
        if (draftsPanel.getWidgetCount() == 1) {
            draftsPanel.clear();
        }
    }

    private void initMessage(final Panel body) {
        body.add(new SmallHeading(Util.C.headingCoverMessage()));

        final VerticalPanel mwrap = new VerticalPanel();
        mwrap.setStyleName(Gerrit.RESOURCES.css().coverMessage());
        body.add(mwrap);

        message = new NpTextArea();
        message.setCharacterWidth(60);
        message.setVisibleLines(10);
        message.setSpellCheck(true);
        mwrap.add(message);
    }

    private void initApprovals(final ChangeSetPublishDetail r, final Panel body) {
        ApprovalTypes types = Gerrit.getConfig().getApprovalTypes();

        for (ApprovalType type : types.getApprovalTypes()) {
            String permission = Permission.forLabel(type.getCategory().getLabelName());
            PermissionRange range = r.getRange(permission);
            if (range != null && !range.isEmpty()) {
                initApprovalType(r, body, type, range);
            }
        }

        for (PermissionRange range : r.getLabels()) {
            // TODO
            //      if (!range.isEmpty() && types.byLabel(range.getLabel()) == null) {
            //        // TODO: this is a non-standard label. Offer it without the type.
            //      }
        }
    }

    private void initApprovalType(final ChangeSetPublishDetail r, final Panel body, final ApprovalType ct,
            final PermissionRange range) {
        body.add(new SmallHeading(ct.getCategory().getName() + ":"));

        final VerticalPanel vp = new VerticalPanel();
        vp.setStyleName(Gerrit.RESOURCES.css().approvalCategoryList());
        final List<ApprovalCategoryValue> lst = new ArrayList<ApprovalCategoryValue>(ct.getValues());
        Collections.reverse(lst);
        final ApprovalCategory.Id catId = ct.getCategory().getId();
        final PatchSetApproval prior = r.getChangeApproval(catId);

        for (final ApprovalCategoryValue buttonValue : lst) {
            if (!range.contains(buttonValue.getValue())) {
                continue;
            }

            final ValueRadioButton b = new ValueRadioButton(buttonValue, ct.getCategory().getName());
            b.setText(buttonValue.format());

            if (lastState != null && changeSetId.equals(lastState.changeSetId)
                    && lastState.approvals.containsKey(buttonValue.getCategoryId())) {
                b.setValue(lastState.approvals.get(buttonValue.getCategoryId()).equals(buttonValue));
            } else {
                b.setValue(
                        prior != null ? buttonValue.getValue() == prior.getValue() : buttonValue.getValue() == 0);
            }

            approvalButtons.add(b);
            vp.add(b);
        }
        body.add(vp);
    }

    private void display(final ChangeSetPublishDetail r) {
        // TODO change this
        setPageTitle(Util.M.publishCommentsOnSet(r.getTopic().getKey().abbreviate(), r.getTopic().getTopic()));
        descBlock.display(r.getTopic(), r.getAccounts());

        if (r.getTopic().getStatus().isOpen()) {
            initApprovals(r, approvalPanel);
        }

        if (lastState != null && changeSetId.equals(lastState.changeSetId)) {
            message.setText(lastState.message);
        }

        draftsPanel.clear();
        commentEditors = new ArrayList<CommentEditorPanel>();

        //    if (!r.getDrafts().isEmpty()) {
        //      draftsPanel.add(new SmallHeading(Util.C.headingPatchComments()));
        //
        //      Panel panel = null;
        //      String priorFile = "";
        //      for (final PatchLineComment c : r.getDrafts()) {
        //        final Patch.Key patchKey = c.getKey().getParentKey();
        //        final String fn = patchKey.get();
        //        if (!fn.equals(priorFile)) {
        //          panel = new FlowPanel();
        //          panel.addStyleName(Gerrit.RESOURCES.css().patchComments());
        //          draftsPanel.add(panel);
        //          // Parent table can be null here since we are not showing any
        //          // next/previous links
        //          panel.add(new PatchLink.SideBySide(PatchTable
        //              .getDisplayFileName(patchKey), patchKey, 0, null, null));
        //          priorFile = fn;
        //        }
        //
        //        final CommentEditorPanel editor = new CommentEditorPanel(c);
        //        editor.setAuthorNameText(Util.M.lineHeader(c.getLine()));
        //        editor.setOpen(true);
        //        commentEditors.add(editor);
        //        panel.add(editor);
        //      }
        //    }

        submit.setVisible(r.canSubmit());
    }

    private void onSend(final boolean submit) {
        if (commentEditors.isEmpty()) {
            onSend2(submit);
        } else {
            final GerritCallback<VoidResult> afterSaveDraft = new GerritCallback<VoidResult>() {
                private int done;

                @Override
                public void onSuccess(final VoidResult result) {
                    if (++done == commentEditors.size()) {
                        onSend2(submit);
                    }
                }
            };
            for (final CommentEditorPanel p : commentEditors) {
                p.saveDraft(afterSaveDraft);
            }
        }
    }

    private void onSend2(final boolean submit) {
        final Map<ApprovalCategory.Id, ApprovalCategoryValue.Id> values = new HashMap<ApprovalCategory.Id, ApprovalCategoryValue.Id>();
        for (final ValueRadioButton b : approvalButtons) {
            if (b.getValue()) {
                values.put(b.value.getCategoryId(), b.value.getId());
            }
        }

        enableForm(false);
        // TODO
        //    PatchUtil.DETAIL_SVC.publishComments(patchSetId, message.getText().trim(),
        //        new HashSet<ApprovalCategoryValue.Id>(values.values()),
        //        new GerritCallback<VoidResult>() {
        //          public void onSuccess(final VoidResult result) {
        //            if(submit) {
        //              submit();
        //            } else {
        //              saveStateOnUnload = false;
        //              goChangeSet();
        //            }
        //          }
        //
        //          @Override
        //          public void onFailure(Throwable caught) {
        //            super.onFailure(caught);
        //            enableForm(true);
        //          }
        //        });
    }

    private void submit() {
        // TODO
        //    Util.MANAGE_SVC.submit(patchSetId,
        //        new GerritCallback<ChangeDetail>() {
        //          public void onSuccess(ChangeDetail result) {
        //            saveStateOnUnload = false;
        //            goChangeSet();
        //          }
        //
        //          @Override
        //          public void onFailure(Throwable caught) {
        //            goChangeSet();
        //            super.onFailure(caught);
        //          }
        //        });
    }

    private void goChangeSet() {
        final Change.Id ck = changeSetId.getParentKey();
        // TODO
        // We need a new entity to return to, instead of a query
        Gerrit.display(PageLinks.toTopic(ck), new TopicScreen(ck));
    }

    private static class ValueRadioButton extends RadioButton {
        final ApprovalCategoryValue value;

        ValueRadioButton(final ApprovalCategoryValue v, final String label) {
            super(label);
            value = v;
        }
    }

    private static class SavedState {
        final ChangeSet.Id changeSetId;
        final String message;
        final Map<ApprovalCategory.Id, ApprovalCategoryValue> approvals;

        SavedState(final PublishTopicCommentScreen p) {
            changeSetId = p.changeSetId;
            message = p.message.getText();
            approvals = new HashMap<ApprovalCategory.Id, ApprovalCategoryValue>();
            for (final ValueRadioButton b : p.approvalButtons) {
                if (b.getValue()) {
                    approvals.put(b.value.getCategoryId(), b.value);
                }
            }
        }
    }
}