Skip to content

Commit fb7e9b2

Browse files
Adam-itSaurabh7019DevPio
authored
Release v3.4.0 (#275)
## 🎯 Aim The aim is to prepare a new minor release with the latest changes that introduced improvements in the welcome experience, filter sample gallery and create a project walkthrough step, ## 📷 Result ![image](https://github.com/user-attachments/assets/0eecddcd-077f-4a5c-9c5c-36067e451102) ## ✅ What was done - [X] Improves welcome experience - [X] Fixes lags in sample gallery search - [X] Improves sample gallery filter functionalities - [X] Improves create project step in walkthrough --------- Co-authored-by: Saurabh Tripathi <[email protected]> Co-authored-by: Luccas Castro <[email protected]>
1 parent 13484e7 commit fb7e9b2

File tree

11 files changed

+234
-44
lines changed

11 files changed

+234
-44
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Change Log
22

3+
## [3.4.0] - 2024-07-18
4+
5+
- Improved welcome experience
6+
- Fixed lags in sample gallery search
7+
- Improved sample gallery filter functionalities
8+
- Improved create project step in walkthrough
9+
310
## [3.3.0] - 2024-06-16
411

512
- Refactored scaffolding form to smaller components

README.md

+2-14
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222

2323
<p align="center">
2424
<a href="#-capabilities">Capabilities</a> |
25-
<a href="#-preview-features">Preview features</a> |
2625
<a href="#%EF%B8%8F-architecture">Architecture</a> |
2726
<a href="#-wiki">Wiki</a> |
2827
<a href="#-contributing">Contributing</a> |
@@ -264,12 +263,7 @@ By default, the SharePoint Framework Toolkit will use the Node.js version that i
264263

265264
You can use the settings to change which Node.js version manager you want to use. You may choose between `nvm` and `nvs`. If you wish to avoid using a Node.js version manager, you can set the value to `none`
266265

267-
## 🧪 Preview features
268-
269-
> [!WARNING]
270-
> Features described in this section are considered as an early beta feature. They may change or be removed in a future major or minor release.
271-
272-
### 1️⃣ SPFx Toolkit GitHub Chat Participant
266+
### 1️⃣3️⃣ SPFx Toolkit GitHub Chat Participant
273267

274268
![SPFx Toolkit chat](./assets/images/chat-intro.png)
275269

@@ -286,13 +280,7 @@ Currently, we support the following commands:
286280
- `/new` - that may be used to get guidance on how to create a new solution or find and reuse an existing sample from the PnP SPFx sample gallery
287281
- `/code` - that is fine-tuned to provide help in coding your SharePoint Framework project and provides additional boosters like validating the correctness of your SPFx project, scaffolding a CI/CD workflow, or renaming your project, and many more.
288282

289-
> [!IMPORTANT]
290-
> In order for this feature to work you need to meet the following requirements:
291-
> - Use the [Visual Studio Code Insiders](https://code.visualstudio.com/insiders/) release
292-
> - Use the pre-release version of the [GitHub Copilot Chat](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot-chat) extension
293-
> - Use latest version of [SPFx Toolkit](https://marketplace.visualstudio.com/items?itemName=m365pnp.viva-connections-toolkit)
294-
295-
[Check out our docs for more details](https://github.com/pnp/vscode-viva/wiki/8.-Preview-features)
283+
[Check out our docs for more details](https://github.com/pnp/vscode-viva/wiki/8.-SPFx-Toolkit-GitHub-Chat-Participant)
296284

297285
## ⚙️ Architecture
298286

assets/walkthrough/create-new-project.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,15 @@ Check it out in action 👇.
88

99
![Create new project](../images/scaffolding-form.gif)
1010

11-
It's possible to scaffold any kind of SPFx project.
11+
It's possible to scaffold any kind of SPFx project including web parts, extensions, library components, and adaptive card extensions.
1212

1313
![All SPFx project support](../images/scaffolding-support.png)
1414

15+
- **Web parts** are reusable elements that serve as the building blocks for SharePoint pages. They allow you to create customizable controls that can be used across multiple pages.
16+
- **Extensions** enable you to extend the SharePoint user experience by adding scripts to pages, modifying views, adding new actions, and altering list form experiences.
17+
- **Library components** are reusable code elements that can be shared across all the components in the tenant.
18+
- **Adaptive Card Extensions (ACEs)** allow you to build rich, native extensions for Viva Connections Dashboards and SharePoint Pages.
19+
1520
Install additional dependencies with a single click straight from the scaffolding form. Currently we support installing [PnP reusable property pane controls](https://pnp.github.io/sp-dev-fx-property-controls/), [PnP reusable React controls](https://pnp.github.io/sp-dev-fx-controls-react/), and [PnPjs](https://pnp.github.io/pnpjs/).
1621

1722
![Additional dependency step](../images/scaffolding-additional-step.png)

npm-shrinkwrap.json

+15-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+4-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "viva-connections-toolkit",
33
"displayName": "SharePoint Framework Toolkit",
44
"description": "SharePoint Framework Toolkit aims to boost your productivity in developing and managing SharePoint Framework solutions helping at every stage of your development flow, from setting up your development workspace to deploying a solution straight to your tenant without the need to leave VS Code and now even create a CI/CD pipeline to introduce automate deployment of your app. This toolkit is provided by the community.",
5-
"version": "3.3.0",
5+
"version": "3.4.0",
66
"publisher": "m365pnp",
77
"preview": false,
88
"homepage": "https://github.com/pnp/vscode-viva",
@@ -260,7 +260,7 @@
260260
"viewsWelcome": [
261261
{
262262
"view": "pnp-view-empty",
263-
"contents": "Welcome to SharePoint Framework Toolkit\n\n\nTo start create a new SharePoint Framework project. \n[Create a new project](command:spfx-toolkit.createProject)\n\n\n\n\n\nUse a sample to kick off a new project and boost your development.\n[View samples](command:spfx-toolkit.samplesGallery)\n\n\n\n\n\nYou can also open an existing app.\n[Open folder](command:vscode.openFolder)\n\n\n\n\n\nValidate your local workspace and check if you have the required dependencies.\n[Check dependencies](command:spfx-toolkit.checkDependencies)\n\n\n\n\n\nInstall the required dependencies.\n[Install dependencies](command:spfx-toolkit.installDependencies)\n\n\n\nIf you need additional help or resources visit the [extension wiki](https://github.com/pnp/vscode-viva/wiki) for more information or go over the [walkthrough](command:spfx-toolkit.welcome)."
263+
"contents": "Welcome to SharePoint Framework Toolkit\n\n\nTo start create a new SharePoint Framework project. \n[Create a new project](command:spfx-toolkit.createProject)\n\n\n\n\n\nUse a sample to kick off a new project and boost your development.\n[View samples](command:spfx-toolkit.samplesGallery)\n\n\n\n\n\nYou can also open an existing app.\n[Open folder](command:vscode.openFolder)\n\n\n\n\n\nValidate your local workspace and check if you have the required dependencies.\n[Check dependencies](command:spfx-toolkit.checkDependencies)\n\n\n\n\n\nInstall the required dependencies.\n[Install dependencies](command:spfx-toolkit.installDependencies)\n\n\n\nLearn more about SharePoint Framework and this toolkit.\n[Walkthrough](command:spfx-toolkit.welcome)\n\n\n\nFor additional help or resources visit the [extension wiki](https://github.com/pnp/vscode-viva/wiki)."
264264
}
265265
],
266266
"commands": [
@@ -473,6 +473,7 @@
473473
"@pnp/cli-microsoft365": "6.11.0",
474474
"node-forge": "^1.3.1",
475475
"react-markdown": "^9.0.1",
476-
"remark-gfm": "^4.0.0"
476+
"remark-gfm": "^4.0.0",
477+
"use-debounce": "^10.0.1"
477478
}
478479
}

src/webview/view/components/controls/MultiSelect.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ export const MultiSelect: React.FunctionComponent<IMultiSelectProps> = ({ onChan
147147
<Dropdown
148148
placeholder={label ?? 'Select'}
149149
multiSelect
150+
selectedKeys={[...options.filter((option) => option.selected).map((option) => option.key as any)]}
150151
options={options}
151152
styles={getDropdownStyles()}
152153
onChange={onChange}

src/webview/view/components/gallery/DetailsView.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export const DetailsView: React.FunctionComponent<IDetailsViewProps> = ({ }: Rea
2121
useEffect(() => {
2222
const { item } = state;
2323
setSample(item);
24-
24+
window.scrollTo(0, 0);
2525
const url = item.url.replace('github.com', 'raw.githubusercontent.com').replace('/blob', '').replace('/tree', '');
2626

2727
const fetchData = async () => {

src/webview/view/components/gallery/GalleryView.tsx

+59-9
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,36 @@
11
import * as React from 'react';
2-
import { useState } from 'react';
2+
import { useEffect } from 'react';
33
import useSamples from '../../hooks/useSamples';
44
import { List } from './List';
5-
import { SearchBar } from './SearchBar';
5+
import { ISelectedFilter, SearchBar } from './SearchBar';
66
import { NoResults } from './NoResults';
77
import { GalleryHeader } from './GalleryHeader';
88
import { GalleryLoader } from './GalleryLoader';
99
import { IDropdownOption } from '@fluentui/react';
10+
import useLocalStorage from '../../hooks/useLocalStorage ';
1011

1112

1213
export interface IGalleryViewProps { }
1314

1415
export const GalleryView: React.FunctionComponent<IGalleryViewProps> = ({ }: React.PropsWithChildren<IGalleryViewProps>) => {
1516
const [samples, versions, search] = useSamples();
16-
const [query, setQuery] = useState<string>('');
17-
const [spfxVersions, setSPFxVersions] = useState<string[]>();
18-
const [showOnlyScenarios, setShowOnlyScenarios] = useState<boolean>(false);
19-
const [componentTypes, setComponentTypes] = useState<string[]>();
17+
const [selectedFilters, setSelectedFilters] = useLocalStorage<ISelectedFilter[]>('selectedFilters', []);
18+
const [query, setQuery] = useLocalStorage<string>('query', '');
19+
const [spfxVersions, setSPFxVersions] = useLocalStorage<string[]>('spfxVersions', []);
20+
const [showOnlyScenarios, setShowOnlyScenarios] = useLocalStorage('showOnlyScenarios', false);
21+
const [componentTypes, setComponentTypes] = useLocalStorage<string[]>('componentTypes', []);
2022

2123
const onSearchTextboxChange = (event: any) => {
2224
const input: string = event.target.value;
2325
setQuery(input);
2426
search(input, componentTypes ?? [], spfxVersions ?? [], showOnlyScenarios);
2527
};
2628

29+
const onClearTextboxChange = () => {
30+
setQuery('');
31+
search('', componentTypes ?? [], spfxVersions ?? [], showOnlyScenarios);
32+
};
33+
2734
const onFilterOnlyScenariosChange = () => {
2835
setShowOnlyScenarios(!showOnlyScenarios);
2936
search(query, componentTypes ?? [], spfxVersions ?? [], !showOnlyScenarios);
@@ -33,22 +40,42 @@ export const GalleryView: React.FunctionComponent<IGalleryViewProps> = ({ }: Rea
3340
let spfxVersionsInput: string[] = [];
3441
if (option?.selected) {
3542
spfxVersionsInput = [...spfxVersions ?? [], option.key as string];
43+
setSelectedFilters([...selectedFilters, {
44+
key: option.key as string,
45+
text: option.key as string,
46+
kind: 'spfxVersion'
47+
}]);
3648
} else {
3749
spfxVersionsInput = spfxVersions?.filter(componentType => componentType !== option?.key) ?? [];
50+
const removedFilter = selectedFilters.filter(filter => filter.key !== option?.key);
51+
setSelectedFilters(removedFilter);
3852
}
39-
4053
setSPFxVersions(spfxVersionsInput);
4154
search(query, componentTypes ?? [], spfxVersionsInput, showOnlyScenarios);
4255
};
4356

57+
const onRemoveFilterBySPFxVersion = (key: string) => {
58+
onFilterBySPFxVersionChange(null, { key: key, text: key, selected: false });
59+
};
60+
61+
const onRemoveFilterByComponentType = (key: string) => {
62+
onFilterByComponentTypeChange(null, { key: key, text: key, selected: false });
63+
};
64+
4465
const onFilterByComponentTypeChange = (event: any, option?: IDropdownOption) => {
4566
let componentTypesInput: string[] = [];
4667
if (option?.selected) {
4768
componentTypesInput = [...componentTypes ?? [], option.key as string];
69+
setSelectedFilters([...selectedFilters, {
70+
key: option.key as string,
71+
text: option.text as string,
72+
kind: 'componentType'
73+
}]);
4874
} else {
4975
componentTypesInput = componentTypes?.filter(componentType => componentType !== option?.key) ?? [];
76+
const removedFilter = selectedFilters.filter(filter => filter.key !== option?.key);
77+
setSelectedFilters(removedFilter);
5078
}
51-
5279
setComponentTypes(componentTypesInput);
5380
search(query, componentTypesInput, spfxVersions ?? [], showOnlyScenarios);
5481
};
@@ -57,21 +84,38 @@ export const GalleryView: React.FunctionComponent<IGalleryViewProps> = ({ }: Rea
5784
const dropdownOptions: IDropdownOption[] = versions.map(version => ({
5885
key: version,
5986
text: version,
87+
selected: selectedFilters.filter(filter => filter.key === version).length > 0
6088
})).filter((value, index, self) =>
6189
value.key !== null &&
6290
index === self.findIndex((v) => v.key === value.key)
6391
);
6492
return dropdownOptions;
6593
};
6694

95+
useEffect(() => {
96+
if (samples !== undefined) {
97+
setShowOnlyScenarios(showOnlyScenarios);
98+
search(query, componentTypes ?? [], spfxVersions ?? [], showOnlyScenarios);
99+
}
100+
}, [samples]);
101+
102+
const clearFilters = () => {
103+
localStorage.clear();
104+
setSelectedFilters([]);
105+
setSPFxVersions([]);
106+
setComponentTypes([]);
107+
setShowOnlyScenarios(false);
108+
setQuery('');
109+
search('', [], [], false);
110+
};
111+
67112
return (
68113
<div className={'w-full h-full max-w-7xl mx-auto sm:px-6 lg:px-8 py-16'}>
69114
{
70115
samples === undefined && (
71116
<GalleryLoader />
72117
)
73118
}
74-
75119
{
76120
samples !== undefined && (
77121
<div className={'pb-16'}>
@@ -82,6 +126,12 @@ export const GalleryView: React.FunctionComponent<IGalleryViewProps> = ({ }: Rea
82126
onFilterByComponentTypeChange={(event, option) => onFilterByComponentTypeChange(event, option)}
83127
onFilterOnlyScenariosChange={() => onFilterOnlyScenariosChange()}
84128
initialQuery={query}
129+
selectedFilters={selectedFilters}
130+
onRemoveFilterBySPFxVersion={onRemoveFilterBySPFxVersion}
131+
onRemoveFilterByComponentType={onRemoveFilterByComponentType}
132+
clearAllFilters={clearFilters}
133+
onClearTextboxChange={onClearTextboxChange}
134+
showOnlyScenarios={showOnlyScenarios}
85135
spfxVersions={getSPFxVersions()} />
86136

87137
{

0 commit comments

Comments
 (0)