
ORIGINALLY: Iafd4b80af53624027c347f0f443b4cdfde292e29 This change makes the change view and the diff view change edit aware. Mutation operations on edit itself, like editing files in editor, are beyond the scope of this change. Change edits must be fetched with a separate change edit endpoint and merged into the change.revisions object. The _number of an editInfo is 'edit'. It has a special property called 'basePatchNum' that marks which patch set the edit is based on. In patch set selectors, the edit is sorted right after its basePatchNum. Alternative implementation considerations: It could be easier to handle edits on the Polygerrit UI, if GET /changes/<id>/detail endpoint would optionally include the change edit in the resulting change.revsions map. TODOs: * Overwrite change.current_revision with change edit commit in some use cases * Mark the change edit as Change Edit in the header of the change view * Allow for modification of the edit in the change/diff view * Disable commenting on files in edit patchsets * Modify file list rows to have appropriate actions when edit is selected (e.g. allow revert, disable marking as reviewed) * Identify and whitelist valid change/revision actions for an edit Bug: Issue 4437 Change-Id: Ia4690d20954de730cd625ac76920e849beb12f7c
346 lines
11 KiB
HTML
346 lines
11 KiB
HTML
<!--
|
|
Copyright (C) 2015 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.
|
|
-->
|
|
|
|
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
|
<link rel="import" href="../../../behaviors/gr-patch-set-behavior/gr-patch-set-behavior.html">
|
|
<link rel="import" href="../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html">
|
|
<link rel="import" href="../../../behaviors/rest-client-behavior/rest-client-behavior.html">
|
|
<link rel="import" href="../../../bower_components/iron-dropdown/iron-dropdown.html">
|
|
<link rel="import" href="../../core/gr-navigation/gr-navigation.html">
|
|
<link rel="import" href="../../shared/gr-button/gr-button.html">
|
|
<link rel="import" href="../../shared/gr-fixed-panel/gr-fixed-panel.html">
|
|
<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
|
|
<link rel="import" href="../../shared/gr-select/gr-select.html">
|
|
<link rel="import" href="../gr-comment-api/gr-comment-api.html">
|
|
<link rel="import" href="../gr-diff-cursor/gr-diff-cursor.html">
|
|
<link rel="import" href="../gr-diff-preferences/gr-diff-preferences.html">
|
|
<link rel="import" href="../gr-diff/gr-diff.html">
|
|
<link rel="import" href="../gr-patch-range-select/gr-patch-range-select.html">
|
|
<link rel="import" href="../../../styles/shared-styles.html">
|
|
|
|
<dom-module id="gr-diff-view">
|
|
<template>
|
|
<style include="shared-styles">
|
|
:host {
|
|
background-color: var(--view-background-color);
|
|
}
|
|
gr-diff {
|
|
border: none;
|
|
}
|
|
gr-fixed-panel {
|
|
background-color: #fff;
|
|
border-bottom: 1px #eee solid;
|
|
z-index: 1;
|
|
}
|
|
header,
|
|
.subHeader {
|
|
align-items: center;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
}
|
|
header {
|
|
padding: .75em var(--default-horizontal-margin);
|
|
}
|
|
.patchRangeLeft {
|
|
display: flex;
|
|
}
|
|
.navLink:not([href]),
|
|
.downloadLink:not([href]) {
|
|
color: #999;
|
|
}
|
|
.navLinks {
|
|
white-space: nowrap;
|
|
}
|
|
.reviewed {
|
|
display: inline-block;
|
|
margin: 0 .25em;
|
|
vertical-align: .15em;
|
|
}
|
|
.jumpToFileContainer {
|
|
display: inline-block;
|
|
}
|
|
.mobile {
|
|
display: none;
|
|
}
|
|
.downArrow {
|
|
display: inline-block;
|
|
font-size: .6em;
|
|
user-select: none;
|
|
vertical-align: middle;
|
|
}
|
|
.dropdown-trigger {
|
|
color: #00e;
|
|
cursor: pointer;
|
|
padding: 0;
|
|
}
|
|
iron-dropdown {
|
|
position: absolute;
|
|
}
|
|
.dropdown-content {
|
|
background-color: #fff;
|
|
box-shadow: 0 1px 5px rgba(0, 0, 0, .3);
|
|
max-height: 70vh;
|
|
}
|
|
.dropdown-content a {
|
|
cursor: pointer;
|
|
display: block;
|
|
font-weight: normal;
|
|
padding: .3em .5em;
|
|
}
|
|
.dropdown-content a:before {
|
|
color: #ccc;
|
|
content: attr(data-key-nav);
|
|
display: inline-block;
|
|
margin-right: .5em;
|
|
width: .3em;
|
|
}
|
|
.dropdown-content a:hover {
|
|
background-color: #00e;
|
|
color: #fff;
|
|
}
|
|
.dropdown-content a[selected] {
|
|
color: #000;
|
|
font-weight: bold;
|
|
pointer-events: none;
|
|
text-decoration: none;
|
|
}
|
|
.dropdown-content a[selected]:hover {
|
|
background-color: #fff;
|
|
color: #000;
|
|
}
|
|
gr-button {
|
|
font: inherit;
|
|
padding: .3em 0;
|
|
text-decoration: none;
|
|
}
|
|
.loading {
|
|
padding: 0 var(--default-horizontal-margin) 1em;
|
|
color: #666;
|
|
}
|
|
.subHeader {
|
|
flex-wrap: wrap;
|
|
margin: 0 var(--default-horizontal-margin) .75em;
|
|
}
|
|
.subHeader > div {
|
|
margin-top: .25em;
|
|
}
|
|
.prefsButton {
|
|
text-align: right;
|
|
}
|
|
.separator {
|
|
margin: 0 .25em;
|
|
}
|
|
.noOverflow {
|
|
display: block;
|
|
overflow: auto;
|
|
}
|
|
#trigger {
|
|
-moz-user-select: text;
|
|
-ms-user-select: text;
|
|
-webkit-user-select: text;
|
|
user-select: text;
|
|
}
|
|
@media screen and (max-width: 50em) {
|
|
header {
|
|
padding: .5em var(--default-horizontal-margin);
|
|
}
|
|
.dash {
|
|
display: none;
|
|
}
|
|
.desktop {
|
|
display: none;
|
|
}
|
|
.fileNav {
|
|
align-items: flex-start;
|
|
display: flex;
|
|
margin: 0 .25em;
|
|
}
|
|
.fullFileName {
|
|
display: block;
|
|
font-size: .9em;
|
|
font-style: italic;
|
|
min-width: 50%;
|
|
padding: 0 .1em;
|
|
text-align: center;
|
|
width: 100%;
|
|
word-wrap: break-word;
|
|
}
|
|
.reviewed {
|
|
vertical-align: -.1em;
|
|
}
|
|
.mobileJumpToFileContainer {
|
|
display: block;
|
|
width: 100%;
|
|
}
|
|
.mobileJumpToFileContainer select {
|
|
width: 100%;
|
|
}
|
|
.mobileNavLink {
|
|
color: #000;
|
|
font-size: 1.5em;
|
|
font-weight: bold;
|
|
text-decoration: none;
|
|
}
|
|
.mobileNavLink:not([href]) {
|
|
color: #bbb;
|
|
}
|
|
}
|
|
</style>
|
|
<gr-fixed-panel
|
|
floating-disabled="[[_panelFloatingDisabled]]"
|
|
keep-on-scroll
|
|
ready-for-measure="[[!_loading]]">
|
|
<header>
|
|
<h3>
|
|
<a href$="[[_computeChangePath(_change, _patchRange.*, _change.revisions)]]">
|
|
[[_changeNum]]</a><span>:</span>
|
|
<span>[[_change.subject]]</span>
|
|
<span class="dash">—</span>
|
|
<input id="reviewed"
|
|
class="reviewed"
|
|
type="checkbox"
|
|
on-change="_handleReviewedChange"
|
|
hidden$="[[!_loggedIn]]" hidden>
|
|
<div class="jumpToFileContainer desktop">
|
|
<gr-button link class="dropdown-trigger" id="trigger" on-tap="_showDropdownTapHandler">
|
|
<span>[[_computeFileDisplayName(_path)]]</span>
|
|
<span class="downArrow">▼</span>
|
|
</gr-button>
|
|
<!-- *-align="" to disable iron-dropdown's element positioning. -->
|
|
<iron-dropdown id="dropdown"
|
|
allow-outside-scroll
|
|
vertical-align=""
|
|
horizontal-align="">
|
|
<div class="dropdown-content" slot="dropdown-content">
|
|
<template
|
|
is="dom-repeat"
|
|
items="[[_fileList]]"
|
|
as="path"
|
|
initial-count="75">
|
|
<a href$="[[_computeDiffURL(_change, _patchRange.*, path)]]"
|
|
selected$="[[_computeFileSelected(path, _path)]]"
|
|
data-key-nav$="[[_computeKeyNav(path, _path, _fileList)]]"
|
|
on-tap="_handleFileTap">[[_computeFileDisplayName(path)]]</a>
|
|
</template>
|
|
</div>
|
|
</iron-dropdown>
|
|
</div>
|
|
<div class="mobileJumpToFileContainer mobile">
|
|
<select on-change="_handleMobileSelectChange">
|
|
<template is="dom-repeat" items="[[_fileList]]" as="path">
|
|
<option
|
|
value$="[[path]]"
|
|
selected$="[[_computeFileSelected(path, _path)]]">
|
|
[[_computeTruncatedFileDisplayName(path)]]
|
|
</option>
|
|
</template>
|
|
</select>
|
|
</div>
|
|
</h3>
|
|
<div class="navLinks desktop">
|
|
<a class="navLink"
|
|
href$="[[_computeNavLinkURL(_change, _path, _fileList, -1, 1)]]">
|
|
Prev</a>
|
|
/
|
|
<a class="navLink"
|
|
href$="[[_computeChangePath(_change, _patchRange.*, _change.revisions)]]">
|
|
Up</a>
|
|
/
|
|
<a class="navLink"
|
|
href$="[[_computeNavLinkURL(_change, _path, _fileList, 1, 1)]]">
|
|
Next</a>
|
|
</div>
|
|
</header>
|
|
<div class="subHeader">
|
|
<div class="patchRangeLeft">
|
|
<gr-patch-range-select
|
|
path="[[_path]]"
|
|
change-num="[[_changeNum]]"
|
|
patch-range="[[_patchRange]]"
|
|
files-weblinks="[[_filesWeblinks]]"
|
|
available-patches="[[_computeAvailablePatches(_change.revisions, _change.revisions.*)]]"
|
|
revisions="[[_change.revisions]]">
|
|
</gr-patch-range-select>
|
|
<span class="download desktop">
|
|
<span class="separator">/</span>
|
|
<a class="downloadLink"
|
|
href$="[[_computeDownloadLink(_changeNum, _patchRange, _path)]]">
|
|
Download
|
|
</a>
|
|
</span>
|
|
</div>
|
|
<div>
|
|
<gr-select
|
|
id="modeSelect"
|
|
bind-value="{{changeViewState.diffMode}}"
|
|
hidden$="[[_computeModeSelectHidden(_isImageDiff)]]">
|
|
<select>
|
|
<option value="SIDE_BY_SIDE">Side By Side</option>
|
|
<option value="UNIFIED_DIFF">Unified</option>
|
|
</select>
|
|
</gr-select>
|
|
<span id="diffPrefsContainer"
|
|
hidden$="[[_computePrefsButtonHidden(_prefs, _loggedIn)]]" hidden>
|
|
<span class="preferences desktop">
|
|
<span
|
|
hidden$="[[_computeModeSelectHidden(_isImageDiff)]]">/</span>
|
|
<gr-button link
|
|
class="prefsButton"
|
|
on-tap="_handlePrefsTap">Preferences</gr-button>
|
|
</span>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="fileNav mobile">
|
|
<a class="mobileNavLink"
|
|
href$="[[_computeNavLinkURL(_change, _path, _fileList, -1, 1)]]">
|
|
<</a>
|
|
<div class="fullFileName mobile">[[_computeFileDisplayName(_path)]]
|
|
</div>
|
|
<a class="mobileNavLink"
|
|
href$="[[_computeNavLinkURL(_change, _path, _fileList, 1, 1)]]">
|
|
></a>
|
|
</div>
|
|
</gr-fixed-panel>
|
|
<div class="loading" hidden$="[[!_loading]]">Loading...</div>
|
|
<gr-diff
|
|
id="diff"
|
|
hidden
|
|
hidden$="[[_loading]]"
|
|
class$="[[_computeDiffClass(_panelFloatingDisabled)]]"
|
|
is-image-diff="{{_isImageDiff}}"
|
|
files-weblinks="{{_filesWeblinks}}"
|
|
change-num="[[_changeNum]]"
|
|
patch-range="[[_patchRange]]"
|
|
path="[[_path]]"
|
|
prefs="[[_prefs]]"
|
|
project-config="[[_projectConfig]]"
|
|
project-name="[[_change.project]]"
|
|
view-mode="[[_diffMode]]"
|
|
on-line-selected="_onLineSelected">
|
|
</gr-diff>
|
|
<gr-diff-preferences
|
|
id="diffPreferences"
|
|
prefs="{{_prefs}}"
|
|
local-prefs="{{_localPrefs}}"></gr-diff-preferences>
|
|
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
|
|
<gr-storage id="storage"></gr-storage>
|
|
<gr-diff-cursor id="cursor"></gr-diff-cursor>
|
|
<gr-comment-api id="commentAPI"></gr-comment-api>
|
|
</template>
|
|
<script src="gr-diff-view.js"></script>
|
|
</dom-module>
|