Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: display the children in a folder for a file list #3339

Merged
merged 7 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"stylelint.packageManager": "yarn",
"stylelint.snippet": ["css", "less", "postcss", "scss"],
"stylelint.validate": ["css", "less", "postcss", "scss"],
"cSpell.words": ["mailenabledsecurity"],
"cSpell.words": ["mailenabledsecurity", "noreferrer"],
"liveServer.settings.root": "storybook-static",
"liveServer.settings.port": 6006
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ $show-more-button-border-bottom-left-radius: var(
);
$progress-ring-size: var(--progress-ring-size, 24px);

@mixin nested-file-list($margin: 0) {
margin-inline-start: calc(#{$margin} * 2);
}

:host {
font-size: $font-size;

Expand Down Expand Up @@ -58,6 +62,25 @@ $progress-ring-size: var(--progress-ring-size, 24px);
flex-direction: column;
list-style: none;

.file-list-children {
&-show {
display: block;
@include nested-file-list(16px);

ul {
list-style: none;

li {
padding: 8px 0;
}
}
}

&-hide {
display: none;
}
}

.file-item {
cursor: pointer;
border-radius: var(--file-border-radius);
Expand All @@ -77,6 +100,10 @@ $progress-ring-size: var(--progress-ring-size, 24px);
--file-border-radius: 2px;
--file-background-color: var(--file-item-background-color, var(--neutral-layer-1));
}

.file-list-children {
background-color: beige;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {
ProviderState,
mgtHtml,
MgtTemplatedTaskComponent,
registerComponent
registerComponent,
customElementHelper
} from '@microsoft/mgt-element';
import { DriveItem, SharedInsight } from '@microsoft/microsoft-graph-types';
import { html, TemplateResult } from 'lit';
Expand Down Expand Up @@ -516,6 +517,7 @@ export class MgtFileList extends MgtTemplatedTaskComponent implements CardSectio
class="file-list"
>
<li
id="file-list-item-${this.files[0].id}"
tabindex="0"
class="file-item"
@keydown="${this.onFileListKeyDown}"
Expand All @@ -528,6 +530,7 @@ export class MgtFileList extends MgtTemplatedTaskComponent implements CardSectio
f => f.id,
f => html`
<li
id="file-list-item-${f.id}"
class="file-item"
@keydown="${this.onFileListKeyDown}"
@click=${(e: UIEvent) => this.handleItemSelect(f, e)}>
Expand Down Expand Up @@ -587,7 +590,7 @@ export class MgtFileList extends MgtTemplatedTaskComponent implements CardSectio
: null;

return html`
<div class="shared_insight_file" @click=${(e: MouseEvent) => this.handleFileClick(file, e)} tabindex="0">
<div class="shared_insight_file" @click=${(e: MouseEvent) => this.handleSharedInsightClick(file, e)} tabindex="0">
<div class="shared_insight_file__icon">
<img alt="${file.resourceVisualization.title}" src=${getFileTypeIconUri(
file.resourceVisualization.type,
Expand Down Expand Up @@ -665,7 +668,13 @@ export class MgtFileList extends MgtTemplatedTaskComponent implements CardSectio
* @param event
*/
private readonly onFileListKeyDown = (event: KeyboardEvent): void => {
const fileList = this.renderRoot.querySelector('.file-list');
const target = event.target as HTMLElement;
let fileList: HTMLElement;
if (!target.classList) {
fileList = this.renderRoot.querySelector('.file-list-children');
} else {
fileList = this.renderRoot.querySelector('.file-list');
}
let focusedItem: HTMLElement;

if (!fileList?.children.length) {
Expand Down Expand Up @@ -822,6 +831,18 @@ export class MgtFileList extends MgtTemplatedTaskComponent implements CardSectio
this.files = files;
}
}
for (const file of this.files) {
if (file?.folder?.childCount > 0) {
// expand the file with children
const driveId = file?.parentReference?.driveId;
const itemId = file?.id;
const iterator = await getDriveFilesByIdIterator(graph, driveId, itemId, 5);
if (iterator) {
const children = [...iterator.value];
file.children = children;
}
}
}
}

/**
Expand Down Expand Up @@ -894,15 +915,52 @@ export class MgtFileList extends MgtTemplatedTaskComponent implements CardSectio
this.requestUpdate();
}

private readonly handleFileClick = (file: DriveItem | SharedInsight, e?: MouseEvent) => {
if (e && isSharedInsight(file) && file.resourceReference?.webUrl && !this.disableOpenOnClick) {
private readonly handleSharedInsightClick = (file: SharedInsight, e?: MouseEvent) => {
if (file.resourceReference?.webUrl && !this.disableOpenOnClick) {
e.preventDefault();
window.open(file.resourceReference.webUrl, '_blank', 'noreferrer');
} else if (!isSharedInsight(file) && file?.webUrl && !this.disableOpenOnClick) {
}
};

private readonly handleFileClick = (file: DriveItem) => {
const hasChildFolders = file?.folder?.childCount > 0 && file?.children;
// the item has child folders, on click should get the child folders and render them
if (hasChildFolders) {
this.showChildren(file.id);
return;
}

if (file?.webUrl && !this.disableOpenOnClick) {
window.open(file.webUrl, '_blank', 'noreferrer');
}
};

private readonly showChildren = (fileId: string) => {
const itemDOM = this.renderRoot.querySelector(`#file-list-item-${fileId}`);
this.renderChildren(fileId, itemDOM);
};

private readonly renderChildren = (itemId: string, itemDOM: Element) => {
const fileListName = customElementHelper.isDisambiguated
? `${customElementHelper.prefix}-file-list`
: 'mgt-file-list';
const childrenContainer = this.renderRoot.querySelector(`#file-list-children-${itemId}`);
if (!childrenContainer) {
const fl = document.createElement(fileListName);
fl.setAttribute('item-id', itemId);
fl.setAttribute('id', `file-list-children-${itemId}`);
fl.setAttribute('class', 'file-list-children-show');
itemDOM.after(fl);
} else {
// toggle to show/hide the children container
if (childrenContainer.classList.contains('file-list-children-hide')) {
childrenContainer.setAttribute('class', 'file-list-children-show');
} else {
childrenContainer.setAttribute('class', 'file-list-children-hide');
}
}
};

/**
* Get file extension string from file name
*
Expand Down
2 changes: 1 addition & 1 deletion packages/mgt-element/src/utils/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
// THIS FILE IS AUTO GENERATED
// ANY CHANGES WILL BE LOST DURING BUILD

export const PACKAGE_VERSION = '4.2.4';
export const PACKAGE_VERSION = '4.3.0';
64 changes: 21 additions & 43 deletions stories/components/fileList/fileList.html.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,60 +102,38 @@ export const openFolderBreadcrumbs = () => html`
<ul class="breadcrumb" id="nav">
<li><a id="home">Files</a></li>
</ul>
<mgt-file-list></mgt-file-list>
<mgt-file-list id="parent-file-list"></mgt-file-list>

<script type="module">
const fileList = document.querySelector('mgt-file-list');
const fileList = document.getElementById('parent-file-list');
const nav = document.getElementById('nav');
const home = document.getElementById('home');

let homeListId;
if (fileList.itemId) {
homeListId = fileList.itemId;
} else {
homeListId = null;
}

// handle default file list menu item
home.addEventListener('click', e => {
fileList.itemId = homeListId;
removeListItems(1);
});

// handle create and remove menu items
fileList.addEventListener('itemClick', e => {
if (e.detail && e.detail.folder) {
const id = e.detail.id;
const name = e.detail.name;

// render new file list
fileList.itemId = id;

// create breadcrumb menu item
const li = document.createElement('li');
const a = document.createElement('a');
li.setAttribute('id', id);
a.appendChild(document.createTextNode(name));
li.appendChild(a);
nav.appendChild(li);

// remove breadcrumb menu items and render file list based on clicked item
a.addEventListener('click', e => {
const nodes = Array.from(nav.children);
const index = nodes.indexOf(li);
if (e.target) {
removeListItems(index + 1);
fileList.itemId = li.id;
const breadcrumbId = "breadcrumb-"+ id;

// check if it is set
const breadcrumbSet = document.getElementById(breadcrumbId);
if (!breadcrumbSet) {
// create breadcrumb menu item
const li = document.createElement('li');
const a = document.createElement('a');
li.setAttribute('id', breadcrumbId);
a.appendChild(document.createTextNode(name));
li.appendChild(a);
if (nav.children.length > 1){
const firstBreadcrumb = nav.children[0];
nav.replaceChildren(firstBreadcrumb);
}
});
nav.appendChild(li);
} else {
breadcrumbSet.remove();

}
}
});

// remove li of ul where index is larger than n
function removeListItems(n) {
while (nav.getElementsByTagName('li').length > n) {
nav.removeChild(nav.lastChild);
}
}
</script>
`;
Loading