fixes show all extensions button #10445 #10625 (#11104)

* fixes button alignment and missing icons issues with ads welcome page

* removes dead code, registers new Button

* creates one button component and adds proper attributes depending on platform

* Add CodeQL Analysis workflow (#10195)

* Add CodeQL Analysis workflow

* Fix path

* adds return types to functions

* fixes show all extensions command

* formats css

* fixes layering issue

* updates querySelectors to be more specific

Co-authored-by: Justin Hutchings <jhutchings1@users.noreply.github.com>
This commit is contained in:
v-bbrady
2020-07-06 14:01:08 -07:00
committed by GitHub
parent 84a7d1916a
commit eabacae0c0
5 changed files with 184 additions and 128 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

@@ -11,7 +11,7 @@ export default () => `
<div class="welcomePage">
<div class="ads-homepage splash">
<div class="gradient">
<div class="preview-text tool-tip">
<div class="ads-homepage-section tool-tip">
<div class="tool-tip-container" id="tool-tip-container-wide">
<a class="ads-welcome-page-link" aria-describedby="tooltip-text-wide" id="preview-link-wide" class="preview-link" tabindex="0" name="preview"><p>Preview</p><i class="icon-info themed-icon"></i></a>
<span role="tooltip" id="tooltip-text-wide" class="tool-tip-text" aria-hidden="true">
@@ -40,27 +40,10 @@ export default () => `
<span class="icon xs"></span><h1 class="caption"></h1>
</div>
<div class="flex btn-container">
<div>
<button id="dropdown-btn" class="btn btn-primary dropdown" role="navigation" aria-haspopup="true" aria-controls="dropdown">
<div class="dropdown-text" style="pointer-events: none;">
<span>${escape(localize('welcomePage.new', "New"))}</span><i class="icon-arrow-down"></i>
</div>
</button>
<nav role="navigation" class="dropdown-nav">
<ul id="dropdown" class="dropdown-content" aria-hidden="true" aria-label="submenu" role="menu" aria-labelledby="dropdown-btn">
<li role="none"><a class="ads-welcome-page-link" role="menuitem" tabIndex="-1" class="move" href="command:registeredServers.addConnection">${escape(localize('welcomePage.newConnection', "New connection"))}</a></li>
<li role="none"><a class="ads-welcome-page-link" role="menuitem" tabIndex="-1" class="move" href="command:workbench.action.files.newUntitledFile">${escape(localize('welcomePage.newQuery', "New query"))}</a></li>
<li role="none"><a class="ads-welcome-page-link" role="menuitem" tabIndex="-1" class="move" href="command:notebook.command.new">${escape(localize('welcomePage.newNotebook', "New notebook"))}</a></li>
<li role="none" id="dropdown-mac-only"><a class="ads-welcome-page-link" role="menuitem" tabIndex="-1" class="move mac-only" href="command:workbench.action.files.openLocalFileFolder">${escape(localize('welcomePage.openFileMac', "Open file"))}</a></li>
<li role="none" id="dropdown-windows-linux-only"><a class="ads-welcome-page-link" role="menuitem" tabIndex="-1" class="move windows-only linux-only" href="command:workbench.action.files.openFile">${escape(localize('welcomePage.openFileLinuxPC', "Open file"))}</a></li>
</ul>
</nav>
<div id="dropdown-btn-container" class="btn btn-primary dropdown">
</div>
<div id="open-file-btn-container" class="btn btn-secondary">
</div>
<a class="windows-only linux-only btn btn-secondary"
href="command:workbench.action.files.openFile">
${escape(localize('welcomePage.openFileLinuxPC', "Open file"))}
</a>
<a class="mac-only btn btn-secondary" href="command:workbench.action.files.openLocalFileFolder">${escape(localize('welcomePage.openFileMac', "Open file"))}</a>
</div>
</div>
</div>
@@ -158,8 +141,6 @@ export default () => `
<p>${escape(localize('welcomePage.documentationBody',
"Visit the documentation center for quickstarts, how-to guides, and references for PowerShell, APIs, etc."))}
</p>
<div class="videos-container row">
<h2>Videos</h2>
<div class="flex flex-container-video">
@@ -169,7 +150,6 @@ export default () => `
<h4>${escape(localize('welcomePage.videoDescriptionOverview',
"Overview of Azure Data Studio"))}</h4>
</a>
</div>
<div class="videos-container-video">
<a href="https://www.youtube.com/watch?v=Nt4kIHQ0IOc" class="video overview ads-welcome-page-link">
@@ -186,7 +166,7 @@ export default () => `
<div class="ads-homepage-section content extensions">
<div class="flex flex-j-between">
<h2>Extend your data studio</h2>
<a class="link-show-all flex ads-welcome-page-link" href="command:extensions.listView.focus">${escape(localize('welcomePage.showAll', "Show All"))} <span class="icon-arrow-right"></span></a>
<a class="link-show-all flex" href="command:workbench.view.extensions">${escape(localize('welcomePage.showAll', "Show All"))} <span class="icon-arrow-right"></span></a>
</div>
<div class="row ads-grid grip-gap-50">
<div

View File

@@ -144,43 +144,6 @@
justify-content: flex-start
}
.ads-homepage.XS:not(.SM) .btn-container div {
width: 100%;
width: 100%;
}
.ads-homepage.XS:not(.SM) .btn {
box-sizing: border-box;
width: 100%;
height: 34px;
padding-top: 1px;
font-size: 1.08em;
line-height: 29px;
border-radius: 2px;
display: flex;
align-content: center;
justify-content: center;
text-align: center;
text-decoration: none;
margin: 10px 0
}
.ads-homepage.SM .btn {
box-sizing: border-box;
width: 100%;
height: 34px;
padding-top: 1px;
font-size: 1.08em;
line-height: 29px;
border-radius: 2px;
display: flex;
align-content: center;
justify-content: center;
text-align: center;
text-decoration: none;
margin: 10px 0
}
.ads-homepage .btn span {
display: block
}
@@ -192,7 +155,6 @@
.ads-homepage.XS .btn {
margin: 0 8px 0 0;
width: 77px;
height: 25px;
line-height: 18px
}
@@ -304,7 +266,17 @@
}
.ads-homepage #tool-tip-container-wide {
display: none
display: none;
}
.ads-homepage #tool-tip-container-wide .ads-welcome-page-link{
display: flex;
align-items: center;
}
.ads-homepage #tool-tip-container-narrow .ads-welcome-page-link{
display: flex;
align-items: center;
}
.ads-homepage #tool-tip-container-narrow {
@@ -319,7 +291,9 @@
}
.ads-homepage.XL #tool-tip-container-wide {
display: block
display: flex;
justify-content: flex-end;
padding-top: 10px;
}
.ads-homepage.XL #tool-tip-container-narrow {
@@ -331,6 +305,7 @@
visibility: hidden;
padding: 10px 15px;
z-index: 1;
top: 32px;
right: -72px;
text-align: center;
border-radius: 6px;
@@ -420,6 +395,7 @@
width: 12px;
height: 12px;
margin-left: 6px;
margin-top: 3px;
-webkit-mask: url(../../media/info.svg) no-repeat;
-webkit-mask-size: 12px 12px;
mask: url(../../media/info.svg) no-repeat;
@@ -450,6 +426,11 @@
margin: auto
}
.ads-homepage .codicon-chevron-right {
transform: rotate(90deg);
pointer-events: none;
}
.ads-homepage .icon-arrow-right {
position: relative;
height: 16px;
@@ -484,7 +465,6 @@
mask: url(../../media/link_icon.svg) no-repeat;
mask-size: 11px 11px;
height: 11px;
width: 11px
}
.ads-homepage .icon-arrow-down-dark {
@@ -504,7 +484,6 @@
display: inline-block;
width: 11px;
height: 6px;
content: "";
transform: rotate(90deg);
top: 14px;
bottom: 5px;
@@ -555,6 +534,14 @@
grid-template-columns: repeat(2, 1fr)
}
.ads_homepage .dropdown_btn_container {
margin: 10px 10px 10px 0;
}
.ads_homepage.XS:not(.SM) .dropdown_btn_container {
width: 100%;
}
.ads-homepage.XS.SM.MD.LG.XL .extension-pack-container {
grid-template-columns: repeat(8, 1fr)
}
@@ -574,12 +561,12 @@
.ads-homepage .tile:not(.extension):not(.extension-pack) {
border: 1px solid;
border-radius: 4px
border-radius: 4px;
}
.ads-homepage .tile.extension-pack {
border: 1px solid;
border-radius: 4px
border-radius: 4px;
}
.ads-homepage .extension-list {
@@ -588,17 +575,17 @@
.ads-homepage.XS.SM.MD.LG.XL .extension-list {
grid-column: 5/span 4;
grid-row: 1/span 4
grid-row: 1/span 4;
}
.ads-homepage .extension-header, .ads-homepage .extension-pack-extension-list-header {
font-weight: 600;
font-size: 1.33em
font-size: 1.33em;
}
.ads-homepage .tile {
transition: all .5s ease;
border-radius: 4px
border-radius: 4px;
}
.ads-homepage .tile:hover:not(.no-hover) {
@@ -1342,7 +1329,7 @@
font-size: 1.16em;
font-family: Segoe UI, Frutiger, Frutiger Linotype, Dejavu Sans, Helvetica Neue, Arial, sans-serif;
font-weight: normal;
padding: 10px 0 10px;
padding: 10px 15px 10px 0;
}
.ads-homepage .guided-tour-banner b {

View File

@@ -45,13 +45,12 @@ import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IProductService } from 'vs/platform/product/common/productService';
import { KeyCode } from 'vs/base/common/keyCodes';
import { joinPath } from 'vs/base/common/resources';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { addStandardDisposableListener, EventHelper } from 'vs/base/browser/dom';
import { GuidedTour } from 'sql/workbench/contrib/welcome/page/browser/gettingStartedTour';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
import { Button } from 'sql/base/browser/ui/button/button';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
const configurationKey = 'workbench.startupEditor';
const oldConfigurationKey = 'workbench.welcome.enabled';
const telemetryFrom = 'welcomePage';
@@ -137,6 +136,7 @@ function isGuidedTourEnabled(configurationService: IConfigurationService): boole
export class WelcomePageAction extends Action {
public static readonly ID = 'workbench.action.showWelcomePage';
public static readonly LABEL = localize('welcomePage', "Welcome");
@@ -191,9 +191,9 @@ const extensionPackExtensions: ExtensionPackExtensions[] = [
];
const extensions: ExtensionSuggestion[] = [
{ name: localize('welcomePage.powershell', "Powershell"), id: 'microsoft.powershell', description: localize('welcomePage.powershellDescription', "Write and execute PowerShell scripts using Azure Data Studio's rich query editor"), icon: 'https://raw.githubusercontent.com/PowerShell/vscode-powershell/master/images/PowerShell_icon.png', link: `command:azdata.extension.open?{"id":"microsoft.powershell"}` },
{ name: localize('welcomePage.powershell', "Powershell"), id: 'microsoft.powershell', description: localize('welcomePage.powershellDescription', "Write and execute PowerShell scripts using Azure Data Studio's rich query editor"), icon: require.toUrl('./../../media/icon_powershell.png'), link: `command:azdata.extension.open?{"id":"microsoft.powershell"}` },
{ name: localize('welcomePage.dataVirtualization', "Data Virtualization"), id: 'microsoft.datavirtualization', description: localize('welcomePage.dataVirtualizationDescription', "Virtualize data with SQL Server 2019 and create external tables using interactive wizards"), icon: require.toUrl('./../../media/defaultExtensionIcon.svg'), link: `command:azdata.extension.open?{"id":"microsoft.datavirtualization"}` },
{ name: localize('welcomePage.PostgreSQL', "PostgreSQL"), id: 'microsoft.azuredatastudio-postgresql', description: localize('welcomePage.PostgreSQLDescription', "Connect, query, and manage Postgres databases with Azure Data Studio"), icon: 'https://raw.githubusercontent.com/Microsoft/azuredatastudio-postgresql/master/images/extension-icon.png', link: `command:azdata.extension.open?{"id":"microsoft.azuredatastudio-postgresql"}` },
{ name: localize('welcomePage.PostgreSQL', "PostgreSQL"), id: 'microsoft.azuredatastudio-postgresql', description: localize('welcomePage.PostgreSQLDescription', "Connect, query, and manage Postgres databases with Azure Data Studio"), icon: require.toUrl('./../../media/icon_postgre_sql.png'), link: `command:azdata.extension.open?{"id":"microsoft.azuredatastudio-postgresql"}` },
];
const extensionPackStrings = {
@@ -228,7 +228,9 @@ class WelcomePage extends Disposable {
@IHostService private readonly hostService: IHostService,
@IFileService fileService: IFileService,
@IProductService private readonly productService: IProductService,
@IWorkbenchLayoutService protected layoutService: IWorkbenchLayoutService) {
@IWorkbenchLayoutService protected layoutService: IWorkbenchLayoutService,
@ICommandService private readonly commandService: ICommandService,
) {
super();
this._register(lifecycleService.onShutdown(() => this.dispose()));
const recentlyOpened = this.workspacesService.getRecentlyOpened();
@@ -317,7 +319,7 @@ class WelcomePage extends Disposable {
while (ul.firstChild) {
ul.removeChild(ul.firstChild);
}
await this.mapListEntries(workspacesToShow, fileService);
await this.mapListEntries(workspacesToShow, fileService, container);
};
await updateEntries();
this._register(this.labelService.onDidChangeFormatters(updateEntries));
@@ -334,11 +336,76 @@ class WelcomePage extends Disposable {
}
}
}));
this.createButtons();
this.createDropDown();
this.createWidePreviewToolTip();
this.createPreviewModal();
}
private createButtons(): void {
const container = document.querySelector('.ads-homepage .hero');
const dropdownButtonContainer = document.querySelector('#dropdown-btn-container') as HTMLElement;
const dropdownUl = document.createElement('ul');
const i = document.createElement('div');
const nav = document.createElement('nav');
const newText = localize('welcomePage.new', "New");
let dropdownBtn = this._register(new Button(dropdownButtonContainer));
dropdownBtn.label = newText;
const iconClassList = ['twisties', 'codicon', 'codicon-chevron-right'];
i.classList.add(...iconClassList);
const openFileCopy = localize('welcomePage.openFile', "Open file");
dropdownUl.classList.add('dropdown-content');
dropdownUl.setAttribute('aria-hidden', 'true');
dropdownUl.setAttribute('aria-label', 'submenu');
dropdownUl.setAttribute('role', 'menu');
dropdownUl.setAttribute('aria-labelledby', 'dropdown-btn');
dropdownUl.id = 'dropdown';
dropdownUl.innerHTML =
`<li role="none"><a role="menuitem" tabIndex="-1" class="move" href="command:registeredServers.addConnection">${(localize('welcomePage.newConnection', "New connection"))} </a></li>
<li role="none"><a role="menuitem" tabIndex="-1" class="move" href="command:workbench.action.files.newUntitledFile">${(localize('welcomePage.newQuery', "New query"))}</a></li>
<li role="none"><a role="menuitem" tabIndex="-1" class="move" href="command:notebook.command.new">${(localize('welcomePage.newNotebook', "New notebook"))}</a></li>
<li role="none"><a role="menuitem" tabIndex="-1" class="move" href="command:azdata.resource.deploy">${(localize('welcomePage.deployServer', "Deploy a Server"))}</a></li>
<li role="none" id="dropdown-mac-only"><a role="menuitem" tabIndex="-1" class="move mac-only" href="command:workbench.action.files.openLocalFileFolder">${openFileCopy}</a></li>
<li role="none" id="dropdown-windows-linux-only"><a role="menuitem" tabIndex="-1" class="move windows-only linux-only" href="command:workbench.action.files.openFile">${openFileCopy}</a></li`;
const getDropdownBtn = container.querySelector('#dropdown-btn-container .monaco-button') as HTMLElement;
getDropdownBtn.id = 'dropdown-btn';
getDropdownBtn.setAttribute('role', 'navigation');
getDropdownBtn.setAttribute('aria-haspopup', 'true');
getDropdownBtn.setAttribute('aria-controls', 'dropdown');
nav.setAttribute('role', 'navigation');
nav.classList.add('dropdown-nav');
dropdownUl.classList.add('dropdown');
getDropdownBtn.id = 'dropdown-btn';
getDropdownBtn.appendChild(i);
nav.appendChild(dropdownUl);
dropdownButtonContainer.appendChild(nav);
const fileBtnWindowsClasses = ['windows-only', 'linux-only', 'btn-secondary'];
const fileBtnMacClasses = ['mac-only', 'btn-secondary'];
const fileBtnContainer = container.querySelector('#open-file-btn-container') as HTMLElement;
const openFileText = openFileCopy;
let openFileButton = this._register(new Button(fileBtnContainer));
openFileButton.label = openFileText;
const getNewFileBtn = container.querySelector('#open-file-btn-container .monaco-button') as HTMLAnchorElement;
const body = document.querySelector('body');
if (body.classList.contains('windows') || body.classList.contains('linux')) {
getNewFileBtn.classList.add(...fileBtnWindowsClasses);
openFileButton.onDidClick(async () => {
await this.commandService.executeCommand('workbench.action.files.openFile');
}
);
} else if (body.classList.contains('mac')) {
getNewFileBtn.classList.add(...fileBtnMacClasses);
openFileButton.onDidClick(async () => {
await this.commandService.executeCommand('workbench.action.files.openLocalFileFolder');
}
);
}
}
private enableGuidedTour(): void {
const guidedTour = this.instantiationService.createInstance(GuidedTour);
const adsHomepage = document.querySelector('.ads-homepage');
@@ -375,6 +442,7 @@ class WelcomePage extends Disposable {
guidedTour.create();
});
removeTourBtn.addEventListener('click', (e: MouseEvent) => {
this.configurationService.updateValue(configurationKey, 'welcomePage', ConfigurationTarget.USER);
guidedTourNotificationContainer.classList.add('hide');
@@ -390,10 +458,11 @@ class WelcomePage extends Disposable {
}
private createWidePreviewToolTip(): void {
const previewLink = document.querySelector('#tool-tip-container-wide') as HTMLElement;
const tooltip = document.querySelector('#tooltip-text-wide') as HTMLElement;
const previewModalBody = document.querySelector('.preview-tooltip-body') as HTMLElement;
const previewModalHeader = document.querySelector('.preview-tooltip-header') as HTMLElement;
const container = document.querySelector('.ads-homepage .tool-tip');
const previewLink = container.querySelector('#tool-tip-container-wide') as HTMLElement;
const tooltip = container.querySelector('#tooltip-text-wide') as HTMLElement;
const previewModalBody = container.querySelector('.preview-tooltip-body') as HTMLElement;
const previewModalHeader = container.querySelector('.preview-tooltip-header') as HTMLElement;
addStandardDisposableListener(previewLink, 'mouseover', () => {
tooltip.setAttribute('aria-hidden', 'true');
tooltip.classList.toggle('show');
@@ -431,6 +500,7 @@ class WelcomePage extends Disposable {
}
}
});
window.addEventListener('click', (event) => {
const target = event.target as HTMLTextAreaElement;
if (!target.matches('.tooltip')) {
@@ -442,8 +512,9 @@ class WelcomePage extends Disposable {
}
private createDropDown(): void {
const dropdownBtn = document.querySelector('#dropdown-btn') as HTMLElement;
const dropdown = document.querySelector('#dropdown') as HTMLInputElement;
const container = document.querySelector('.ads-homepage .hero');
const dropdownBtn = container.querySelector('#dropdown-btn') as HTMLElement;
const dropdown = container.querySelector('#dropdown') as HTMLInputElement;
addStandardDisposableListener(dropdownBtn, 'click', () => {
dropdown.classList.toggle('show');
});
@@ -466,24 +537,25 @@ class WelcomePage extends Disposable {
const body = document.querySelector('body');
if (body.classList.contains('windows') || body.classList.contains('linux')) {
const macOnly = document.querySelector('#dropdown-mac-only');
const macOnly = container.querySelector('#dropdown-mac-only');
macOnly.remove();
} else if (body.classList.contains('mac')) {
const windowsLinuxOnly = document.querySelector('#dropdown-windows-linux-only');
const windowsLinuxOnly = container.querySelector('#dropdown-windows-linux-only');
windowsLinuxOnly.remove();
}
window.addEventListener('click', (event) => {
const target = event.target as HTMLTextAreaElement;
if (!target.matches('.dropdown')) {
if (!target.matches('#dropdown-btn')) {
if (dropdown.classList.contains('show')) {
dropdown.classList.remove('show');
dropdown.classList.toggle('show');
}
}
});
addStandardDisposableListener(dropdown, 'keydown', event => {
const dropdownLastElement = document.querySelector('#dropdown').lastElementChild.children[0] as HTMLInputElement;
const dropdownFirstElement = document.querySelector('#dropdown').firstElementChild.children[0] as HTMLInputElement;
const container = document.querySelector('.ads-homepage .hero');
const dropdownLastElement = container.querySelector('#dropdown').lastElementChild.children[0] as HTMLInputElement;
const dropdownFirstElement = container.querySelector('#dropdown').firstElementChild.children[0] as HTMLInputElement;
if (event.equals(KeyCode.Tab)) {
EventHelper.stop(event);
return;
@@ -492,7 +564,7 @@ class WelcomePage extends Disposable {
if (event.target === dropdownFirstElement) {
dropdownLastElement.focus();
} else {
const movePrev = <HTMLElement>document.querySelector('.move:focus').parentElement.previousElementSibling.children[0] as HTMLElement;
const movePrev = <HTMLElement>container.querySelector('.move:focus').parentElement.previousElementSibling.children[0] as HTMLElement;
movePrev.focus();
}
}
@@ -500,7 +572,7 @@ class WelcomePage extends Disposable {
if (event.target === dropdownLastElement) {
dropdownFirstElement.focus();
} else {
const moveNext = <HTMLElement>document.querySelector('.move:focus').parentElement.nextElementSibling.children[0] as HTMLElement;
const moveNext = <HTMLElement>container.querySelector('.move:focus').parentElement.nextElementSibling.children[0] as HTMLElement;
moveNext.focus();
}
}
@@ -508,13 +580,15 @@ class WelcomePage extends Disposable {
}
private createPreviewModal(): void {
const modal = document.querySelector('#preview-modal') as HTMLElement;
const btn = document.querySelector('#tool-tip-container-narrow') as HTMLElement;
const span = document.querySelector('.close-icon') as HTMLElement;
const previewModalHeader = document.querySelector('.preview-modal-header') as HTMLElement;
const container = document.querySelector('.ads-homepage');
const modal = container.querySelector('#preview-modal') as HTMLElement;
const btn = container.querySelector('#tool-tip-container-narrow') as HTMLElement;
const span = container.querySelector('.close-icon') as HTMLElement;
const previewModalHeader = container.querySelector('.preview-modal-header') as HTMLElement;
btn.addEventListener('click', function () {
modal.classList.toggle('show');
});
span.addEventListener('click', function () {
modal.classList.remove('show');
});
@@ -548,10 +622,9 @@ class WelcomePage extends Disposable {
}
}
});
modal.addEventListener('keydown', function (e: KeyboardEvent) {
const previewModalBody = document.querySelector('.preview-modal-body') as HTMLElement;
const previewModalHeader = document.querySelector('.preview-modal-header') as HTMLElement;
const previewModalBody = container.querySelector('.preview-modal-body') as HTMLElement;
const previewModalHeader = container.querySelector('.preview-modal-header') as HTMLElement;
let event = new StandardKeyboardEvent(e);
if (event.equals(KeyCode.Tab)) {
@@ -566,7 +639,7 @@ class WelcomePage extends Disposable {
});
}
private async createListEntries(fileService: IFileService, fullPath: URI, windowOpenable: IWindowOpenable, relativePath: string): Promise<HTMLElement[]> {
private async createListEntries(container: HTMLElement, fileService: IFileService, fullPath: URI, windowOpenable: IWindowOpenable, relativePath: string): Promise<HTMLElement[]> {
let result: HTMLElement[] = [];
const value = await fileService.resolve(fullPath);
let date = new Date(value.mtime);
@@ -578,12 +651,13 @@ class WelcomePage extends Disposable {
const icon = document.createElement('i');
const a = document.createElement('a');
const span = document.createElement('span');
const ul = document.querySelector('.recent ul');
const ul = container.querySelector('.list');
icon.title = relativePath;
a.innerText = name;
a.title = relativePath;
a.setAttribute('aria-label', localize('welcomePage.openFolderWithPath', "Open folder {0} with path {1}", name, parentPath));
a.href = 'javascript:void(0)';
a.addEventListener('click', e => {
this.telemetryService.publicLog2<WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification>('workbenchActionExecuted', {
id: 'openRecentFolder',
@@ -606,7 +680,7 @@ class WelcomePage extends Disposable {
return result;
}
private async mapListEntries(recents: (IRecentWorkspace | IRecentFolder)[], fileService: IFileService): Promise<HTMLElement[]> {
private async mapListEntries(recents: (IRecentWorkspace | IRecentFolder)[], fileService: IFileService, container: HTMLElement): Promise<HTMLElement[]> {
const result: HTMLElement[] = [];
for (let i = 0; i < recents.length; i++) {
const recent = recents[i];
@@ -621,7 +695,7 @@ class WelcomePage extends Disposable {
relativePath = recent.label || this.labelService.getWorkspaceLabel(recent.workspace, { verbose: true });
windowOpenable = { workspaceUri: recent.workspace.configPath };
}
const elements = await this.createListEntries(fileService, fullPath, windowOpenable, relativePath);
const elements = await this.createListEntries(container, fileService, fullPath, windowOpenable, relativePath);
result.push(...elements);
}
return result;
@@ -662,33 +736,46 @@ class WelcomePage extends Disposable {
}
private addExtensionPack(container: HTMLElement, anchorSelector: string): void {
const btnContainer = container.querySelector(anchorSelector);
const btnContainer = container.querySelector(anchorSelector) as HTMLElement;
if (btnContainer) {
extensionPacks.forEach((extension, i) => {
const a = document.createElement('a');
const classes = ['btn', 'btn-secondary', 'a-self-end', 'flex', 'flex-a-center', 'flex-j-center'];
const btn = document.createElement('button');
const description = document.querySelector('.extension-pack-body');
const header = document.querySelector('.extension-pack-header');
a.classList.add(...classes);
a.innerText = localize('welcomePage.install', "Install");
a.title = extension.title || (extension.isKeymap ? localize('welcomePage.installKeymap', "Install {0} keymap", extension.name) : localize('welcomePage.installExtensionPack', "Install additional support for {0}", extension.name));
a.classList.add('installExtension');
a.setAttribute('data-extension', extension.id);
a.href = 'javascript:void(0)';
a.addEventListener('click', e => {
extensionPacks.forEach((extension) => {
const installText = localize('welcomePage.install', "Install");
let dropdownBtn = this._register(new Button(btnContainer));
dropdownBtn.label = installText;
const classes = ['btn', 'btn-secondary'];
const getDropdownBtn = container.querySelector('.extensionPack .monaco-button:first-of-type') as HTMLAnchorElement;
getDropdownBtn.id = 'dropdown-btn';
getDropdownBtn.classList.add(...classes);
getDropdownBtn.title = extension.title || (extension.isKeymap ? localize('welcomePage.installKeymap', "Install {0} keymap", extension.name) : localize('welcomePage.installExtensionPack', "Install additional support for {0}", extension.name));
getDropdownBtn.setAttribute('aria-haspopup', 'true');
getDropdownBtn.setAttribute('aria-controls', 'dropdown');
getDropdownBtn.id = 'dropdown-btn';
getDropdownBtn.classList.add('installExtension');
getDropdownBtn.setAttribute('data-extension', extension.id);
getDropdownBtn.href = 'javascript:void(0)';
getDropdownBtn.addEventListener('click', e => {
this.installExtension(extension);
e.preventDefault();
e.stopPropagation();
});
btnContainer.appendChild(a);
btn.innerText = localize('welcomePage.installed', "Installed");
btn.title = extension.isKeymap ? localize('welcomePage.installedKeymap', "{0} keymap is already installed", extension.name) : localize('welcomePage.installedExtensionPack', "{0} support is already installed", extension.name);
btn.classList.add('enabledExtension');
btn.classList.add(...classes);
btn.setAttribute('disabled', 'true');
btn.setAttribute('data-extension', extension.id);
btnContainer.appendChild(btn);
const description = container.querySelector('.extension-pack-body');
const header = container.querySelector('.extension-pack-header');
const installedText = localize('welcomePage.installed', "Installed");
let installedButton = new Button(btnContainer);
installedButton.label = installedText;
installedButton.enabled = false;
const getInstalledButton = container.querySelector('.extensionPack .monaco-button:nth-of-type(2)') as HTMLAnchorElement;
getInstalledButton.innerText = localize('welcomePage.installed', "Installed");
getInstalledButton.title = extension.isKeymap ? localize('welcomePage.installedKeymap', "{0} keymap is already installed", extension.name) : localize('welcomePage.installedExtensionPack', "{0} support is already installed", extension.name);
getInstalledButton.classList.add('enabledExtension');
getInstalledButton.classList.add(...classes);
getInstalledButton.setAttribute('data-extension', extension.id);
description.innerHTML = extension.description;
header.innerHTML = extension.name;
this.addExtensionPackList(container, '.extension-pack-extension-list');
@@ -923,6 +1010,7 @@ registerThemingParticipant((theme, collector) => {
const tileBackgroundColor = theme.getColor(inputBackground);
if (tileBackgroundColor) {
collector.addRule(`.monaco-workbench .part.editor > .content .welcomePageContainer .tile:not(.extension):not(.extension-pack) { background-color: ${tileBackgroundColor}; }`);
collector.addRule(`.monaco-workbench .part.editor > .content .welcomePageContainer .btn-secondary .monaco-button { background-color: ${tileBackgroundColor} !important; }`);
collector.addRule(`.monaco-workbench .part.editor > .content .welcomePageContainer .tool-tip .tool-tip-text { background-color: ${tileBackgroundColor}; }`);
collector.addRule(`.monaco-workbench .part.editor > .content .welcomePageContainer .modal-content { background-color: ${tileBackgroundColor}; }`);
}
@@ -955,7 +1043,7 @@ registerThemingParticipant((theme, collector) => {
}
const buttonSecondaryBackgroundColor = theme.getColor(buttonSecondaryBackground);
if (buttonSecondaryBackgroundColor) {
collector.addRule(`.monaco-workbench .part.editor > .content .welcomePageContainer .btn-secondary { background-color: ${buttonSecondaryBackgroundColor};}`);
collector.addRule(`.monaco-workbench .part.editor > .content .welcomePageContainer .btn-secondary { background-color: ${buttonSecondaryBackgroundColor} !important;}`);
}
const buttonSecondaryBorderColor = theme.getColor(buttonSecondaryBorder);
if (buttonSecondaryBorderColor) {
@@ -963,7 +1051,7 @@ registerThemingParticipant((theme, collector) => {
}
const buttonSecondaryColor = theme.getColor(buttonSecondary);
if (buttonSecondaryColor) {
collector.addRule(`.monaco-workbench .part.editor > .content .welcomePageContainer .btn-secondary { color: ${buttonSecondaryColor};}`);
collector.addRule(`.monaco-workbench .part.editor > .content .welcomePageContainer .btn-secondary { color: ${buttonSecondaryColor} !important;}`);
}
const buttonSecondaryHover = theme.getColor(buttonSecondaryHoverColor);
if (buttonSecondaryColor) {
@@ -1037,6 +1125,7 @@ registerThemingParticipant((theme, collector) => {
const link = theme.getColor(textLinkForeground);
if (link) {
collector.addRule(`.monaco-workbench .part.editor > .content .welcomePage a { color: ${link}; }`);
collector.addRule(`.monaco-workbench .part.editor > .content .welcomePage .btn-primary .monaco-button { border: 1px solid ${link}; }`);
}
const activeLink = theme.getColor(textLinkActiveForeground);
if (activeLink) {