Sidebar and tagingfor Technology and solution areas tagging/filtering (#147)

* Filtering sidebar and taging changes for Technology and solution areas tagging/filtering

- Modified item.json, api controller to have Tachnologies instead of types. Renamed Category to solution areas.
- Removed runtime version as now we have Functions 1.x and functions 2.x as first class technologies.
- Modified item.json to have language and technologies string as to be displayed in UI.
- Modifed sidebar and tags component to include all technologies, solution areas and languages.
This commit is contained in:
Pravakar Garnayak 2019-04-24 17:55:38 -07:00 коммит произвёл GitHub
Родитель d447822e1e
Коммит 43ba412443
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 410 добавлений и 472 удалений

Просмотреть файл

@ -48,9 +48,10 @@ class ItemList extends Component {
/>
<p className="description">{item.description}</p>
<ItemTags
type={item.type}
technologies={item.technologies}
language={item.language}
tags={item.tags}
solutionareas={item.solutionareas}
/>
</div>
</div>

Просмотреть файл

@ -1,86 +1,33 @@
import React, { Component } from "react";
import { registerIcons, Icon } from "office-ui-fabric-react";
import { ReactComponent as FunctionappSvg } from "../../assets/functionapp.svg";
import { ReactComponent as LogicappSvg } from "../../assets/logicapp.svg";
import "./ItemTags.css";
registerIcons({
icons: {
"functionapp-svg": <FunctionappSvg className="svg" />,
"logicapp-svg": <LogicappSvg className="svg" />
}
});
class ItemTags extends Component {
ToDisplayType(value) {
if (!value) {
return "";
}
var type = value.toLowerCase();
if (type === "functionapp") {
return "Function App";
} else if (type === "logicapp") {
return "Logic App";
} else {
return value;
}
}
ToDisplayLanguage(value) {
if (!value) {
return "";
}
var language = value.toLowerCase();
if (language === "csharp") {
return "C#";
} else if (language === "javascript") {
return "JavaScript";
} else if (language === "python") {
return "Python";
} else if (language === "java") {
return "Java";
} else if (language === "na") {
return "";
} else {
return value;
}
}
render() {
let svgIconName;
if (this.props.type === "functionapp") {
svgIconName = "functionapp-svg";
} else if (this.props.type === "logicapp") {
svgIconName = "logicapp-svg";
// Tags contain technologies, language, solutionareas and custom tags
let allTags = [];
if (this.props.technologies) {
allTags.push(...this.props.technologies);
}
let itemTypeToDisplay = this.ToDisplayType(this.props.type);
let languageTag;
if (this.props.language !== "" && this.props.language !== "na") {
let itemLanguageToDisplay = this.ToDisplayLanguage(this.props.language);
languageTag = <span className="tag">{itemLanguageToDisplay}</span>;
allTags.push(this.props.language);
}
if (this.props.solutionareas) {
allTags.push(...this.props.solutionareas);
}
let tags;
if (this.props.tags) {
tags = this.props.tags.map((value, index) => {
return (
<span className="tag" key={index}>
{value}
</span>
);
});
allTags.push(...this.props.tags);
}
return (
<div className="tagcontainer">
Tags :
<span className="tag">
<Icon iconName={svgIconName} />
<span>{itemTypeToDisplay}</span>
</span>
{languageTag}
{tags}
{allTags.map((value, index) => (
<span className="tag" key={index}>
{value}
</span>
))}
</div>
);
}

Просмотреть файл

@ -27,25 +27,31 @@ class Main extends Component {
el.title.match(filter) ||
el.description.match(filter) ||
el.language.match(filter) ||
el.type.match(filter) ||
el.repository.replace("https://github.com/", "").match(filter) ||
(el.runtimeversion && el.runtimeversion.match(filter)) ||
(el.tags && el.tags.some(x => x.match(filter))) ||
(el.technologies && el.technologies.some(x => x.match(filter))) ||
(el.solutionareas && el.solutionareas.some(x => x.match(filter))) ||
(el.author && el.author.match(filter))
);
if (currentfilters.categories.types.length > 0) {
if (currentfilters.categories.technologies.length > 0) {
samples = samples.filter(s =>
currentfilters.categories.types.includes(s.type)
s.technologies.some(t=> currentfilters.categories.technologies.includes(t))
);
}
if (currentfilters.categories.languages.length > 0) {
samples = samples.filter(s =>
samples = samples.filter(s =>
currentfilters.categories.languages.includes(s.language)
);
}
if (currentfilters.categories.solutionareas.length > 0) {
samples = samples.filter(s =>
s.solutionareas.some(a=> currentfilters.categories.solutionareas.includes(a))
);
}
return this.Sort(samples, currentfilters.sortby);
}
@ -73,22 +79,26 @@ class Main extends Component {
getFiltersFromQueryParams() {
var filter = {
categories: {
types: [],
languages: []
technologies: [],
languages: [],
solutionareas: [],
},
filtertext: "",
sortby: "totaldownloads"
};
var params = queryStringToParams(this.props.location.search);
if (params.type && params.type.length > 0) {
filter.categories.types = params.type.split(",");
if (params.technology && params.technology.length > 0) {
filter.categories.technologies = params.technology.split(",");
}
if (params.language && params.language.length > 0) {
filter.categories.languages = params.language.split(",");
}
if (params.solutionarea && params.solutionarea.length > 0) {
filter.categories.solutionareas = params.solutionarea.split(",");
}
if (params.filtertext && params.filtertext.length > 0) {
filter.filtertext = params.filtertext;
}

Просмотреть файл

@ -5,6 +5,37 @@ import { Checkbox } from "office-ui-fabric-react/lib/index";
import { paramsToQueryString, queryStringToParams } from "../../helpers";
import "./SideBar.css";
const technologies = [
"Functions 1.x",
"Functions 2.x",
"Logic Apps",
"Cosmos DB"
];
const solutionAreas = [
"Web API",
"Data Processing",
"Integration",
"Authentication",
"Automation",
"Event Processing",
"Machine Learning",
"Scheduled Jobs",
"Static Website",
"Gaming",
"IoT"
];
const languages = [
"JavaScript",
"TypeScript",
"Java",
"C#",
"C# Script",
"F#",
"Python",
"PowerShell"
];
class SideBar extends Component {
constructor(props) {
super(props);
@ -32,50 +63,55 @@ class SideBar extends Component {
ChangeUrl() {
var params = queryStringToParams(this.props.location.search);
delete params["type"];
delete params["technology"];
delete params["language"];
if (this.state.filters.types.length > 0) {
params["type"] = this.state.filters.types.join();
delete params["solutionarea"];
if (this.state.filters.technologies.length > 0) {
params["technology"] = this.state.filters.technologies.join();
}
if (this.state.filters.languages.length > 0) {
params["language"] = this.state.filters.languages.join();
}
if (this.state.filters.solutionareas.length > 0) {
params["solutionarea"] = this.state.filters.solutionareas.join();
}
this.props.history.push(paramsToQueryString(params));
}
render() {
const checkboxStyles = () => {
const checkboxStyles = index => {
return {
root: {
marginTop: "10px",
marginBottom: "5px",
color: "red"
marginTop: index === 0 ? "10px" : "0px",
marginBottom: "5px"
}
};
};
return (
<div>
<h3 className="filterHeader">Filter by </h3>
<div>
<fieldset className="filterset">
<span>Type</span>
<span>Technology</span>
<div className="filterList">
<Checkbox
styles={checkboxStyles}
label="Function app"
defaultChecked={this.isChecked("types", "functionapp")}
onChange={(ev, checked) =>
this.checkboxclicked(ev, checked, "types", "functionapp")
}
/>
<Checkbox
label="Logic app"
defaultChecked={this.isChecked("types", "logicapp")}
onChange={(ev, checked) =>
this.checkboxclicked(ev, checked, "types", "logicapp")
}
/>
{technologies.map((technology, index) => (
<Checkbox
styles={checkboxStyles(index)}
label={technology}
key={technology}
defaultChecked={this.isChecked("technologies", technology)}
onChange={(ev, checked) =>
this.checkboxclicked(
ev,
checked,
"technologies",
technology
)
}
/>
))}
</div>
</fieldset>
</div>
@ -83,21 +119,40 @@ class SideBar extends Component {
<fieldset className="filterset">
<span>Language</span>
<div className="filterList">
<Checkbox
styles={checkboxStyles}
label="C#"
defaultChecked={this.isChecked("languages", "csharp")}
onChange={(ev, checked) =>
this.checkboxclicked(ev, checked, "languages", "csharp")
}
/>
<Checkbox
label="Javascript"
defaultChecked={this.isChecked("languages", "javascript")}
onChange={(ev, checked) =>
this.checkboxclicked(ev, checked, "languages", "javascript")
}
/>
{languages.map((language, index) => (
<Checkbox
styles={checkboxStyles(index)}
label={language}
key={language}
defaultChecked={this.isChecked("languages", language)}
onChange={(ev, checked) =>
this.checkboxclicked(ev, checked, "languages", language)
}
/>
))}
</div>
</fieldset>
</div>
<div>
<fieldset className="filterset">
<span>Solution Area</span>
<div className="filterList">
{solutionAreas.map((solutionarea, index) => (
<Checkbox
styles={checkboxStyles(index)}
label={solutionarea}
key={solutionarea}
defaultChecked={this.isChecked("solutionareas", solutionarea)}
onChange={(ev, checked) =>
this.checkboxclicked(
ev,
checked,
"solutionareas",
solutionarea
)
}
/>
))}
</div>
</fieldset>
</div>

Просмотреть файл

@ -26,25 +26,24 @@ namespace ServerlessLibrary.Controllers
// GET: api/<controller>
[HttpGet]
[ProducesResponseType(typeof(IEnumerable<LibraryItemWithStats>), 200)]
public JsonResult Get(string filterText, string type, string language)
{
public JsonResult Get(string filterText, string language)
{
//TODO: Add filtering for solution areas and technologies.
var results = _cacheService.GetCachedItems();
var filteredResults = results.Where(
x =>
(
(string.IsNullOrWhiteSpace(language) || x.Language == language) &&
(string.IsNullOrWhiteSpace(type) || x.Type == type) &&
(
string.IsNullOrWhiteSpace(filterText)
|| Regex.IsMatch(x.Title, filterText, RegexOptions.IgnoreCase)
|| Regex.IsMatch(x.Description, filterText, RegexOptions.IgnoreCase)
|| Regex.IsMatch(x.Repository.Replace("https://github.com/", "", StringComparison.InvariantCulture), filterText, RegexOptions.IgnoreCase)
|| (!string.IsNullOrWhiteSpace(x.Author) && Regex.IsMatch(x.Author, filterText, RegexOptions.IgnoreCase))
|| (x.RuntimeVersion != null && Regex.IsMatch(x.RuntimeVersion, filterText, RegexOptions.IgnoreCase))
|| (x.Tags != null && x.Tags.Any(t => Regex.IsMatch(t, filterText, RegexOptions.IgnoreCase)))
|| (x.Category != null && x.Category.Any(t => Regex.IsMatch(t, filterText, RegexOptions.IgnoreCase)))
)
|| (x.Technologies != null && x.Technologies.Any(t => Regex.IsMatch(t, filterText, RegexOptions.IgnoreCase)))
|| (x.SolutionAreas != null && x.SolutionAreas.Any(c => Regex.IsMatch(c, filterText, RegexOptions.IgnoreCase)))
)
)
);

Просмотреть файл

@ -41,17 +41,14 @@ namespace ServerlessLibrary.Models
[JsonProperty(PropertyName = "language", DefaultValueHandling = DefaultValueHandling.Include)]
public string Language { get; set; }
[JsonProperty(PropertyName = "type", DefaultValueHandling = DefaultValueHandling.Include)]
public string Type { get; set; }
[JsonProperty(PropertyName = "technologies", DefaultValueHandling = DefaultValueHandling.Include)]
public string[] Technologies { get; set; }
[JsonProperty(PropertyName = "category", DefaultValueHandling = DefaultValueHandling.Include)]
public string[] Category { get; set; }
[JsonProperty(PropertyName = "solutionareas", DefaultValueHandling = DefaultValueHandling.Include)]
public string[] SolutionAreas { get; set; }
[JsonProperty(PropertyName = "author", DefaultValueHandling = DefaultValueHandling.Include)]
public string Author { get; internal set; }
[JsonProperty(PropertyName = "runtimeversion", DefaultValueHandling = DefaultValueHandling.Include)]
public string RuntimeVersion { get; set; }
public string Author { get; internal set; }
internal T ConvertTo<T>()
{

Разница между файлами не показана из-за своего большого размера Загрузить разницу