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:SubwayNav component added #133

Merged
merged 2 commits into from
Dec 2, 2022
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
4 changes: 3 additions & 1 deletion .github/workflows/create-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ jobs:
- run: npm ci
working-directory: "./Shimmer"
- run: npm ci
working-directory: "./Spinner"
working-directory: "./Spinner"
- run: npm ci
working-directory: "./SubwayNav"
- run: npm ci
working-directory: "./TagList"
- run: npm ci
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/pr_validate_all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ jobs:
- "./SearchBox"
- "./Spinner"
- "./Shimmer"
- "./SubwayNav"
- "./TagList"


Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ The following table provides an index to the code components in this repository:
| [SearchBox](SearchBox) | User Interface | [Fluent UI SearchBox control](https://developer.microsoft.com/en-us/fluentui#/controls/web/searchbox) for use in canvas & custom pages. | **✅** | **✅** | **✅** | ⬜ | ⬜ |
| [Shimmer](Shimmer) | User Interface | This code component wraps the [Fluent Shimmer control](https://developer.microsoft.com/en-us/fluentui#/controls/web/shimmer) for use in canvas & custom pages. | **✅** | **✅** | **✅** | ⬜ | ⬜ |
| [Spinner](Spinner) | User Interface | This code component wraps the [Fluent Spinner control](https://developer.microsoft.com/en-us/fluentui#/controls/web/spinner) for use in canvas & custom pages. | **✅** | **✅** | **✅** | ⬜ | ⬜ |
| [SubwayNav](SubwayNav) | User Interface | | **✅** | **✅** | **✅** | ⬜ | ⬜ |
| [TagList](TagList) | User Interface | This code component provides a Tag List that provides flexible width rendering bound to a collection. | **✅** | **✅** | **✅** | ⬜ | ⬜ |

## Building & Deploying
Expand Down
1 change: 1 addition & 0 deletions Solution/Solution.cdsproj
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
<ProjectReference Include="..\SearchBox\SearchBox.pcfproj" />
<ProjectReference Include="..\Shimmer\Shimmer.pcfproj" />
<ProjectReference Include="..\Spinner\Spinner.pcfproj" />
<ProjectReference Include="..\SubwayNav\SubwayNav.pcfproj" />
<ProjectReference Include="..\TagList\TagList.pcfproj" />
<ProjectReference Include="..\ThemeGenerator\themeGenerator.pcfproj" />
</ItemGroup>
Expand Down
2 changes: 2 additions & 0 deletions SubwayNav/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Ignore Forked components for linting
/SubwayNav/utilities
52 changes: 52 additions & 0 deletions SubwayNav/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": [
"react",
"react-hooks",
"@typescript-eslint",
"prettier",
"sonarjs"
],
"settings": {
"react": {
"pragma": "React",
"version": "detect"
}
},
"ignorePatterns": ["**/generated/*.ts"],
"rules": {
"eqeqeq": [2, "smart"],
"react-hooks/exhaustive-deps": "warn",
"prettier/prettier": "error",
"arrow-body-style": "off",
"prefer-arrow-callback": "off",
"linebreak-style": [
"error",
"windows"
],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
]
}
}
17 changes: 17 additions & 0 deletions SubwayNav/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules

# generated directory
**/generated

# output directory
/coverage

# output directory
/out

# msbuild output directories
/bin
/obj
8 changes: 8 additions & 0 deletions SubwayNav/.prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"semi": true,
"trailingComma": "all",
"singleQuote": true,
"printWidth": 120,
"tabWidth": 4,
"endOfLine": "auto"
}
144 changes: 144 additions & 0 deletions SubwayNav/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# SubwayNav

This code component provides a SubwayNav that allows you to visualize the steps required for a given wizard & it is bound to a collection.

| Canvas apps | Custom pages | Model-driven apps | Portals |
| ----------- | ------------ | ----------------- | ------- |
| ✅ | ✅ | ⬜ | ⬜ |

## Glimpse of SubwayNav

<img src="./media/SubwayNav-Action.gif" alt="SubwayNav" width="200"/>

## Configuration

The control accepts the following properties:

- **Items** - The action items to render
- **ItemKey** - The key to use to indicate which item/step is selected. The keys must be unique.
- **ItemLabel** - Label for the step
- **ItemState** - Specifying the state of the step. Here is the list of State available. Current|NotStarted|Completed|Unsaved|ViewedNotCompleted|Error|CurrentWithSubSteps|Skipped|WizardComplete

- **SubwayNav state** - To mark the overall state of SubwayNav to Complete or Error.

### Style Properties

- **Theme** - Accepts a JSON string that is generated using [Fluent UI Theme Designer (windows.net)](https://fabricweb.z5.web.core.windows.net/pr-deploy-site/refs/heads/master/theming-designer/). Leaving this blank will use the default theme defined by Power Apps.
- **AccessibilityLabel** - Screen reader aria-label
- **ApplyDarkTheme** - Select in case Darktheme is used.

### Event Properties

- **InputEvent** - An event to send to the control. E.g. `SetFocus`. See below.

### Usage

Example of input collection value for Items property

```PowerFx
Table({ItemKey:"1",ItemLabel:"Step 1",ItemState:"Current"},
{ItemKey:"2",ItemLabel:"Step 2",ItemState:"Completed"},
{ItemKey:"3",ItemLabel:"Step 3",ItemState:"Unsaved"},
{ItemKey:"4",ItemLabel:"Step 4",ItemState:"ViewedNotCompleted"},
{ItemKey:"5",ItemLabel:"Step 5",ItemState:"Error"},
{ItemKey:"6",ItemLabel:"Step 6",ItemState:"WizardComplete"})
```

To get the selected step by the user, use the OnSelect or OnChange Property

Example code below

```PowerFx
Notify(Concatenate(Self.Selected.ItemLabel, " Selected & its status is ", Self.Selected.ItemState))
```

#### Example for Substep scenarios

Below is a sample item collection example that defines how substeps needs to be linked with main/parent step using ParentItemKey.

```PowerFx
Table({ItemKey:"1",ItemLabel:"Step 1",ItemState:"Current"},
{ItemKey:"2",ItemLabel:"Step 2 have sub-steps",ItemState:"WizardComplete"},
{ItemKey:"3",ItemLabel:"Sub Step 2.1",ParentItemKey:"2",ItemState:"Error"},
{ItemKey:"4",ItemLabel:"Sub Step 2.2",ParentItemKey:"2",ItemState:"WizardComplete"},
{ItemKey:"5",ItemLabel:"Sub Step 3.1",ParentItemKey:"8",ItemState:"ViewedNotCompleted"},
{ItemKey:"6",ItemLabel:"Sub Step 3.2",ParentItemKey:"8",ItemState:"Unsaved"},
{ItemKey:"7",ItemLabel:"Sub Step 3.2",ParentItemKey:"8",ItemState:"Unsaved"},
{ItemKey:"8",ItemLabel:"Step 3 too have sub-steps",ItemState:"Unsaved"},
{ItemKey:"9",ItemLabel:"Step 4",ItemState:"Error"},
{ItemKey:"10",ItemLabel:"Step 5",ItemState:"WizardComplete"})
```

### Output Schema

State of each item(Step) changes as we select or move to different step happens internally, especially the *Current* & *CurrentWithSubStep*. The current status can be determined using Output property called *Steps*.

Example code below

```PowerFx
Self.Steps

//Or

SubwayNav1.Steps
```

### Example Theme

The following is an example of setting the theme based on the output from the [Fluent UI Theme Designer (windows.net)](https://fabricweb.z5.web.core.windows.net/pr-deploy-site/refs/heads/master/theming-designer/).

```PowerFx
Set(varThemeBlue, {
palette: {
themePrimary: ColorValue("#0078d4"),
themeLighterAlt: ColorValue("#eff6fc"),
themeLighter: ColorValue("#deecf9"),
themeLight: ColorValue("#c7e0f4"),
themeTertiary: ColorValue("#71afe5"),
themeSecondary: ColorValue("#2b88d8"),
themeDarkAlt: ColorValue("#106ebe"),
themeDark: ColorValue("#005a9e"),
themeDarker: ColorValue("#004578"),
neutralLighterAlt: ColorValue("#faf9f8"),
neutralLighter: ColorValue("#f3f2f1"),
neutralLight: ColorValue("#edebe9"),
neutralQuaternaryAlt: ColorValue("#e1dfdd"),
neutralQuaternary: ColorValue("#d0d0d0"),
neutralTertiaryAlt: ColorValue("#c8c6c4"),
neutralTertiary: ColorValue("#a19f9d"),
neutralSecondary: ColorValue("#605e5c"),
neutralPrimaryAlt: ColorValue("#3b3a39"),
neutralPrimary:ColorValue( "#323130"),
neutralDark: ColorValue("#201f1e"),
black: ColorValue("#000000"),
white: ColorValue("#ffffff")
}});

Set(varThemeBlueJSON,"{""palette"":{
""themePrimary"": ""#0078d4"",
""themeLighterAlt"": ""#eff6fc"",
""themeLighter"": ""#deecf9"",
""themeLight"": ""#c7e0f4"",
""themeTertiary"": ""#71afe5"",
""themeSecondary"": ""#2b88d8"",
""themeDarkAlt"": ""#106ebe"",
""themeDark"": ""#005a9e"",
""themeDarker"": ""#004578"",
""neutralLighterAlt"": ""#faf9f8"",
""neutralLighter"": ""#f3f2f1"",
""neutralLight"": ""#edebe9"",
""neutralQuaternaryAlt"": ""#e1dfdd"",
""neutralQuaternary"": ""#d0d0d0"",
""neutralTertiaryAlt"": ""#c8c6c4"",
""neutralTertiary"": ""#a19f9d"",
""neutralSecondary"": ""#605e5c"",
""neutralPrimaryAlt"": ""#3b3a39"",
""neutralPrimary"": ""#323130"",
""neutralDark"": ""#201f1e"",
""black"": ""#000000"",
""white"": ""#ffffff""
}
}");
```

The Theme JSON string is passed to the component property, whilst the varTheme can be used to style other standard components such as buttons using the individual colors.
47 changes: 47 additions & 0 deletions SubwayNav/SubwayNav.pcfproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PowerAppsTargetsPath>$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\PowerApps</PowerAppsTargetsPath>
</PropertyGroup>

<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
<Import Project="$(PowerAppsTargetsPath)\Microsoft.PowerApps.VisualStudio.Pcf.props" Condition="Exists('$(PowerAppsTargetsPath)\Microsoft.PowerApps.VisualStudio.Pcf.props')" />

<PropertyGroup>
<Name>SubwayNav</Name>
<ProjectGuid>26a5c16a-fada-4f6a-a4fe-ba7b7da729de</ProjectGuid>
<OutputPath>$(MSBuildThisFileDirectory)out\controls</OutputPath>
<PcfBuildMode>production</PcfBuildMode>
</PropertyGroup>

<PropertyGroup>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<!--Remove TargetFramework when this is available in 16.1-->
<TargetFramework>net462</TargetFramework>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.PowerApps.MSBuild.Pcf" Version="1.*" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>

<ItemGroup>
<ExcludeDirectories Include="$(MSBuildThisFileDirectory)\.gitignore" />
<ExcludeDirectories Include="$(MSBuildThisFileDirectory)\bin\**" />
<ExcludeDirectories Include="$(MSBuildThisFileDirectory)\obj\**" />
<ExcludeDirectories Include="$(OutputPath)\**" />
<ExcludeDirectories Include="$(MSBuildThisFileDirectory)\*.pcfproj" />
<ExcludeDirectories Include="$(MSBuildThisFileDirectory)\*.pcfproj.user" />
<ExcludeDirectories Include="$(MSBuildThisFileDirectory)\*.sln" />
<ExcludeDirectories Include="$(MSBuildThisFileDirectory)\node_modules\**" />
</ItemGroup>

<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)\**" Exclude="@(ExcludeDirectories)" />
</ItemGroup>

<Import Project="$(MSBuildToolsPath)\Microsoft.Common.targets" />
<Import Project="$(PowerAppsTargetsPath)\Microsoft.PowerApps.VisualStudio.Pcf.targets" Condition="Exists('$(PowerAppsTargetsPath)\Microsoft.PowerApps.VisualStudio.Pcf.targets')" />

</Project>
8 changes: 8 additions & 0 deletions SubwayNav/SubwayNav/ContextExtended.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// This is undocumented - but needed since canvas apps sets non-zero tabindexes
// so we must use the tabindex provided by the context for accessibility purposes
export interface ContextEx {
accessibility: {
assignedTabIndex: number;
assignedTooltip?: string;
};
}
38 changes: 38 additions & 0 deletions SubwayNav/SubwayNav/ControlManifest.Input.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest>
<control namespace="PowerCAT" constructor="SubwayNav" version="0.0.1" display-name-key="SubwayNav" description-key="SubwayNav_Desc" control-type="virtual">
<!-- Style Properties -->
<property name="Theme" display-name-key="Theme" of-type="Multiple" usage="input" required="false" />
<property name="AccessibilityLabel" display-name-key="AccessibilityLabel" of-type="SingleLine.Text" usage="input" required="false" />
<!-- InputEvent : SetFocus -->
<property name="InputEvent" display-name-key="InputEvent" of-type="SingleLine.Text" usage="input" />
<!-- DarkModeOn : SetDarkTheme -->
<property name="ApplyDarkTheme" display-name-key="ApplyDarkTheme" of-type="TwoOptions" usage="input" />
<!-- Wizard Complete -->
<property name="WizardCompleteorError" display-name-key="WizardCompleteorError" description-key="WizardCompleteorError" usage="input" of-type="Enum" required="false">
<value name="None" display-name-key="None" description-key="None" default="true">None</value>
<value name="WizardComplete" display-name-key="WizardComplete" description-key="WizardComplete">WizardComplete</value>
<value name="Error" display-name-key="Error" description-key="Error">Error</value>
</property>
<!-- dataset node represents a set of entity records on CDS; allow more than one datasets -->
<data-set name="items" display-name-key="Items">
<property-set name="ItemLabel" display-name-key="Item Label" of-type="SingleLine.Text" usage="bound" required="true" />
<property-set name="ItemKey" display-name-key="Key" of-type="SingleLine.Text" usage="bound" required="true" />
<property-set name="ParentItemKey" display-name-key="Parent Key" of-type="SingleLine.Text" usage="bound" required="true" />
<property-set name="ItemState" display-name-key="Item State" of-type="SingleLine.Text" usage="bound" required="true" />
<property-set name="ItemDisabled" display-name-key="Item Disabled" of-type="TwoOptions" usage="bound" required="false" />
<property-set name="ItemVisuallyDisabled" display-name-key="Item Visually Disabled" of-type="TwoOptions" usage="bound" required="false" />
</data-set>
<property name="Steps" display-name-key="Steps" of-type="Object" usage="output"/>
<property name="StepsSchema" display-name-key="StepsSchema" of-type="SingleLine.Text" usage="bound" hidden="true"/>
<property-dependencies>
<property-dependency input="StepsSchema" output="Steps" required-for="schema" />
</property-dependencies>
<resources>
<code path="index.ts" order="1" />
<resx path="strings/Subwaynav.1033.resx" version="1.0.0" />
<platform-library name="React" version="16.8.6" />
<platform-library name="Fluent" version="8.29.0" />
</resources>
</control>
</manifest>
21 changes: 21 additions & 0 deletions SubwayNav/SubwayNav/ManifestConstants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export const enum ManifestPropertyNames {
dataset = 'dataset',
}

export const enum ItemColumns {
Label = 'ItemLabel',
Key = 'ItemKey',
State = 'ItemState',
Disabled = 'ItemDisabled',
VisuallyDisabled = 'ItemVisuallyDisabled',
ParentKey = 'ParentItemKey',
}

export const enum InputEvents {
SetFocus = 'SetFocus',
}

export const enum InputProperties {
InputEvent = 'InputEvent',
SelectedKey = 'SelectedKey',
}
Loading