blob: 96521562611165942efd8a45e7a3988cd32a3c54 [file] [log] [blame]
/**
* @license
* Copyright (C) 2020 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.
*/
import {html} from '@polymer/polymer/lib/utils/html-tag.js';
export const htmlTemplate = html`
<style include="shared-styles">
:host {
display: block;
}
.row {
align-items: center;
border-top: 1px solid var(--border-color);
display: flex;
min-height: calc(var(--line-height-normal) + 2*var(--spacing-s));
padding: var(--spacing-xs) var(--spacing-l) var(--spacing-xs) calc(var(--spacing-l) - .35rem);
}
:host(.loading) .row {
opacity: .5;
};
:host(.editMode) .hideOnEdit {
display: none;
}
.showOnEdit {
display: none;
}
:host(.editMode) .showOnEdit {
display: initial;
}
.invisible {
visibility: hidden;
}
.header-row {
background-color: var(--background-color-secondary);
}
.controlRow {
align-items: center;
display: flex;
height: 2.25em;
justify-content: center;
}
.controlRow.invisible,
.show-hide.invisible {
display: none;
}
.reviewed,
.status {
align-items: center;
display: inline-flex;
}
.reviewed,
.status {
display: inline-block;
text-align: left;
width: 1.5em;
}
.file-row {
cursor: pointer;
}
.file-row.expanded {
border-bottom: 1px solid var(--border-color);
position: -webkit-sticky;
position: sticky;
top: 0;
/* Has to visible above the diff view, and by default has a lower
z-index. setting to 1 places it directly above. */
z-index: 1;
}
.file-row:hover {
background-color: var(--hover-background-color);
}
.file-row.selected {
background-color: var(--selection-background-color);
}
.file-row.expanded,
.file-row.expanded:hover {
background-color: var(--expanded-background-color);
}
.path {
cursor: pointer;
flex: 1;
/* Wrap it into multiple lines if too long. */
white-space: normal;
word-break: break-word;
}
.oldPath {
color: var(--deemphasized-text-color);
}
.header-stats {
text-align: center;
min-width: 7.5em;
}
.stats {
text-align: right;
min-width: 7.5em;
}
.comments {
padding-left: var(--spacing-l);
min-width: 7.5em;
}
.row:not(.header-row) .stats,
.total-stats {
font-family: var(--monospace-font-family);
font-size: var(--font-size-mono);
line-height: var(--line-height-mono);
display: flex;
}
.sizeBars {
margin-left: var(--spacing-m);
min-width: 7em;
text-align: center;
}
.sizeBars.hide {
display: none;
}
.added,
.removed {
display: inline-block;
min-width: 3.5em;
}
.added {
color: var(--vote-text-color-recommended);
}
.removed {
color: var(--vote-text-color-disliked);
text-align: left;
min-width: 4em;
padding-left: var(--spacing-s);
}
.drafts {
color: #C62828;
font-weight: var(--font-weight-bold);
}
.show-hide {
margin-left: var(--spacing-s);
width: 1.9em;
}
.fileListButton {
margin: var(--spacing-m);
}
.totalChanges {
justify-content: flex-end;
text-align: right;
}
.warning {
color: var(--deemphasized-text-color);
}
input.show-hide {
display: none;
}
label.show-hide {
cursor: pointer;
display: block;
min-width: 2em;
}
gr-diff {
display: block;
overflow-x: auto;
}
.truncatedFileName {
display: none;
}
.mobile {
display: none;
}
.reviewed {
margin-left: var(--spacing-xxl);
width: 15em;
}
.reviewed label {
color: var(--link-color);
opacity: 0;
justify-content: flex-end;
width: 100%;
}
.reviewed label:hover {
cursor: pointer;
opacity: 100;
}
.row:focus {
outline: none;
}
.row:hover .reviewed label,
.row:focus .reviewed label,
.row.expanded .reviewed label {
opacity: 100;
}
.reviewed input {
display: none;
}
.reviewedLabel {
color: var(--deemphasized-text-color);
margin-right: var(--spacing-l);
opacity: 0;
}
.reviewedLabel.isReviewed {
display: initial;
opacity: 100;
}
.editFileControls {
width: 7em;
}
.markReviewed,
.pathLink {
display: inline-block;
margin: -2px 0;
padding: var(--spacing-s) 0;
text-decoration: none;
}
.pathLink:hover {
text-decoration: underline;
}
/** copy on file path **/
.pathLink gr-copy-clipboard,
.oldPath gr-copy-clipboard {
display: inline-block;
visibility: hidden;
vertical-align: bottom;
text-decoration: none;
--gr-button: {
padding: 0px;
}
}
.pathLink:hover gr-copy-clipboard,
.oldPath:hover gr-copy-clipboard {
visibility: visible;
}
/** small screen breakpoint: 768px */
@media screen and (max-width: 55em) {
.desktop {
display: none;
}
.mobile {
display: block;
}
.row.selected {
background-color: var(--view-background-color);
}
.stats {
display: none;
}
.reviewed,
.status {
justify-content: flex-start;
}
.reviewed {
display: none;
}
.comments {
min-width: initial;
}
.expanded .fullFileName,
.truncatedFileName {
display: inline;
}
.expanded .truncatedFileName,
.fullFileName {
display: none;
}
}
</style>
<div id="container" on-click="_handleFileListClick">
<div class="header-row row">
<div class="status"></div>
<div class="path">File</div>
<div class="comments">Comments</div>
<div class="sizeBars">Size</div>
<div class="header-stats">Delta</div>
<template is="dom-if" if="[[_showDynamicColumns]]">
<template is="dom-repeat" items="[[_dynamicHeaderEndpoints]]" as="headerEndpoint">
<gr-endpoint-decorator name\$="[[headerEndpoint]]">
</gr-endpoint-decorator>
</template>
</template>
<!-- Empty div here exists to keep spacing in sync with file rows. -->
<div class="reviewed hideOnEdit" hidden\$="[[!_loggedIn]]"></div>
<div class="editFileControls showOnEdit"></div>
<div class="show-hide"></div>
</div>
<template is="dom-repeat" items="[[_shownFiles]]" id="files" as="file" initial-count="[[fileListIncrement]]" target-framerate="1">
[[_reportRenderedRow(index)]]
<div class="stickyArea">
<div class\$="file-row row [[_computePathClass(file.__path, _expandedFilePaths.*)]]" data-path\$="[[file.__path]]" tabindex="-1">
<div class\$="[[_computeClass('status', file.__path)]]" tabindex="0" title\$="[[_computeFileStatusLabel(file.status)]]" aria-label\$="[[_computeFileStatusLabel(file.status)]]">
[[_computeFileStatus(file.status)]]
</div>
<!-- TODO: Remove data-url as it appears its not used -->
<span data-url="[[_computeDiffURL(change, patchRange, file.__path, editMode)]]" class="path">
<a class="pathLink" href\$="[[_computeDiffURL(change, patchRange, file.__path, editMode)]]">
<span title\$="[[computeDisplayPath(file.__path)]]" class="fullFileName">
[[computeDisplayPath(file.__path)]]
</span>
<span title\$="[[computeDisplayPath(file.__path)]]" class="truncatedFileName">
[[computeTruncatedPath(file.__path)]]
</span>
<gr-copy-clipboard hide-input="" text="[[file.__path]]"></gr-copy-clipboard>
</a>
<template is="dom-if" if="[[file.old_path]]">
<div class="oldPath" title\$="[[file.old_path]]">
[[file.old_path]]
<gr-copy-clipboard hide-input="" text="[[file.old_path]]"></gr-copy-clipboard>
</div>
</template>
</span>
<div class="comments desktop">
<span class="drafts">
[[_computeDraftsString(changeComments, patchRange, file.__path)]]
</span>
[[_computeCommentsString(changeComments, patchRange, file.__path)]]
</div>
<div class="comments mobile">
<span class="drafts">
[[_computeDraftsStringMobile(changeComments, patchRange,
file.__path)]]
</span>
[[_computeCommentsStringMobile(changeComments, patchRange,
file.__path)]]
</div>
<div class\$="[[_computeSizeBarsClass(_showSizeBars, file.__path)]]">
<svg width="61" height="8">
<rect x\$="[[_computeBarAdditionX(file, _sizeBarLayout)]]" y="0" height="8" fill="#388E3C" width\$="[[_computeBarAdditionWidth(file, _sizeBarLayout)]]"></rect>
<rect x\$="[[_computeBarDeletionX(_sizeBarLayout)]]" y="0" height="8" fill="#D32F2F" width\$="[[_computeBarDeletionWidth(file, _sizeBarLayout)]]"></rect>
</svg>
</div>
<div class\$="[[_computeClass('stats', file.__path)]]">
<span class="added" tabindex="0" aria-label\$="[[file.lines_inserted]] lines added" hidden\$="[[file.binary]]">
+[[file.lines_inserted]]
</span>
<span class="removed" tabindex="0" aria-label\$="[[file.lines_deleted]] lines removed" hidden\$="[[file.binary]]">
-[[file.lines_deleted]]
</span>
<span class\$="[[_computeBinaryClass(file.size_delta)]]" hidden\$="[[!file.binary]]">
[[_formatBytes(file.size_delta)]]
[[_formatPercentage(file.size, file.size_delta)]]
</span>
</div>
<template is="dom-if" if="[[_showDynamicColumns]]">
<template is="dom-repeat" items="[[_dynamicContentEndpoints]]" as="contentEndpoint">
<div class\$="[[_computeClass('', file.__path)]]">
<gr-endpoint-decorator name="[[contentEndpoint]]">
<gr-endpoint-param name="changeNum" value="[[changeNum]]">
</gr-endpoint-param>
<gr-endpoint-param name="patchRange" value="[[patchRange]]">
</gr-endpoint-param>
<gr-endpoint-param name="path" value="[[file.__path]]">
</gr-endpoint-param>
</gr-endpoint-decorator>
</div>
</template>
</template>
<div class="reviewed hideOnEdit" hidden\$="[[!_loggedIn]]" hidden="">
<span class\$="reviewedLabel [[_computeReviewedClass(file.isReviewed)]]">Reviewed</span>
<label>
<input class="reviewed" type="checkbox" checked="[[file.isReviewed]]">
<span class="markReviewed" title\$="[[_reviewedTitle(file.isReviewed)]]">[[_computeReviewedText(file.isReviewed)]]</span>
</label>
</div>
<div class="editFileControls showOnEdit">
<template is="dom-if" if="[[editMode]]">
<gr-edit-file-controls class\$="[[_computeClass('', file.__path)]]" file-path="[[file.__path]]"></gr-edit-file-controls>
</template>
</div>
<div class="show-hide">
<label class="show-hide" data-path\$="[[file.__path]]" data-expand="true">
<input type="checkbox" class="show-hide" checked\$="[[_isFileExpanded(file.__path, _expandedFilePaths.*)]]" data-path\$="[[file.__path]]" data-expand="true">
<iron-icon id="icon" icon="[[_computeShowHideIcon(file.__path, _expandedFilePaths.*)]]">
</iron-icon>
</label>
</div>
</div>
<template is="dom-if" if="[[_isFileExpanded(file.__path, _expandedFilePaths.*)]]">
<gr-diff-host no-auto-render="" show-load-failure="" display-line="[[_displayLine]]" hidden="[[!_isFileExpanded(file.__path, _expandedFilePaths.*)]]" change-num="[[changeNum]]" patch-range="[[patchRange]]" path="[[file.__path]]" prefs="[[diffPrefs]]" project-name="[[change.project]]" on-line-selected="_onLineSelected" no-render-on-prefs-change="" view-mode="[[diffViewMode]]"></gr-diff-host>
</template>
</div>
</template>
</div>
<div class="row totalChanges" hidden\$="[[_hideChangeTotals]]">
<div class="total-stats">
<span class="added" tabindex="0" aria-label\$="[[_patchChange.inserted]] lines added">
+[[_patchChange.inserted]]
</span>
<span class="removed" tabindex="0" aria-label\$="[[_patchChange.deleted]] lines removed">
-[[_patchChange.deleted]]
</span>
</div>
<template is="dom-if" if="[[_showDynamicColumns]]">
<template is="dom-repeat" items="[[_dynamicSummaryEndpoints]]" as="summaryEndpoint">
<gr-endpoint-decorator name="[[summaryEndpoint]]">
</gr-endpoint-decorator>
</template>
</template>
<!-- Empty div here exists to keep spacing in sync with file rows. -->
<div class="reviewed hideOnEdit" hidden\$="[[!_loggedIn]]"></div>
<div class="editFileControls showOnEdit"></div>
<div class="show-hide"></div>
</div>
<div class="row totalChanges" hidden\$="[[_hideBinaryChangeTotals]]">
<div class="total-stats">
<span class="added" aria-label="Total lines added">
[[_formatBytes(_patchChange.size_delta_inserted)]]
[[_formatPercentage(_patchChange.total_size,
_patchChange.size_delta_inserted)]]
</span>
<span class="removed" aria-label="Total lines removed">
[[_formatBytes(_patchChange.size_delta_deleted)]]
[[_formatPercentage(_patchChange.total_size,
_patchChange.size_delta_deleted)]]
</span>
</div>
</div>
<div class\$="row controlRow [[_computeFileListControlClass(numFilesShown, _files)]]">
<gr-button class="fileListButton" id="incrementButton" link="" on-click="_incrementNumFilesShown">
[[_computeIncrementText(numFilesShown, _files)]]
</gr-button>
<gr-tooltip-content has-tooltip="[[_computeWarnShowAll(_files)]]" show-icon="[[_computeWarnShowAll(_files)]]" title\$="[[_computeShowAllWarning(_files)]]">
<gr-button class="fileListButton" id="showAllButton" link="" on-click="_showAllFiles">
[[_computeShowAllText(_files)]]
</gr-button><!--
--></gr-tooltip-content>
</div>
<gr-diff-preferences-dialog id="diffPreferencesDialog" diff-prefs="{{diffPrefs}}" on-reload-diff-preference="_handleReloadingDiffPreference">
</gr-diff-preferences-dialog>
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
<gr-storage id="storage"></gr-storage>
<gr-diff-cursor id="diffCursor"></gr-diff-cursor>
<gr-cursor-manager id="fileCursor" scroll-behavior="keep-visible" focus-on-move="" cursor-target-class="selected"></gr-cursor-manager>
<gr-reporting id="reporting"></gr-reporting>
`;