Skip to content
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
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
# [1.9.0-feat-button-for-cicd-testing.1](https://github.com/TechnologyEnhancedLearning/TELBlazor/compare/v1.8.0...v1.9.0-feat-button-for-cicd-testing.1) (2025-06-25)


### Bug Fixes

* **search:** Improved debounce ([fbc7b0b](https://github.com/TechnologyEnhancedLearning/TELBlazor/commit/fbc7b0be762982b8701c24e696133e0dd2facd97))


### Features

* **searchexperiment:** in theory ([fee2b91](https://github.com/TechnologyEnhancedLearning/TELBlazor/commit/fee2b9124b859f9a548e3fa257d53294ce83dc08))
* **showcase:** added component readme displayer ([a058fe6](https://github.com/TechnologyEnhancedLearning/TELBlazor/commit/a058fe6f034b5097fb72c9f72a8b98c57ed2b607))

# [1.9.0-feat-button-for-cicd-testing.1](https://github.com/TechnologyEnhancedLearning/TELBlazor/compare/v1.8.0...v1.9.0-feat-button-for-cicd-testing.1) (2025-06-25)


### Features

* **searchexperiment:** in theory ([fee2b91](https://github.com/TechnologyEnhancedLearning/TELBlazor/commit/fee2b9124b859f9a548e3fa257d53294ce83dc08))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
builder.Services.AddBlazoredLocalStorage();

//Scoped because being consumed with storage where singleton doesnt survive mvc page teardown
// qqqq do we need it builder.Services.AddScoped<LoggingLevelSwitch>(sp => levelSwitch);
builder.Services.AddScoped<LoggingLevelSwitch>(sp => levelSwitch);
builder.Services.AddScoped<ILogLevelSwitcherService, SerilogLogLevelSwitcherService>();
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddTELBlazorComponentServicesForTestComponents();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
@if (ComponentReadMeMarkdownUrl != string.Empty)
{
<section class="component-readme">
<h2>ReadMe.Md from Components Folder in the Solution</h2>
<h2>README.md from Components Folder in the Solution</h2>
<a href="@ComponentReadMeMarkdownUrl" target="_blank" rel="noopener noreferrer">See the file directly</a>
<div class="component-readme-html-container">@((MarkupString)ComponentReadMeHtmlContent)</div>
</section>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@
private string NoJSActionUrl = "/nojsformsubmitstubpage";
private List<string> NoJSSearchResults = new List<string>() {"In a nojs browser", " the user would first get a blanks components ", " they then send their data", " the Controller would provide","this static info back", "including original provideds search", "having used the same service", "serverside in its controller"};
private List<string> NoJSSuggestions = new List<string>() {"Unsure if this would work ","it might do but we wouldnt", " want to spam a page reload per button press ", " so maybe there would be different suggestions in nojs" };
private string ComponentReadMeMarkdownUrl = "https://raw.githubusercontent.com/TechnologyEnhancedLearning/TELBlazor/refs/heads/master/TELBlazor.Components/OptionalImplementations/TestComponents/SearchExperiment/README.md";
private string ComponentReadMeMarkdownUrl = "https://raw.githubusercontent.com/TechnologyEnhancedLearning/TELBlazor/refs/heads/master/TELBlazor.Components/OptionalImplementations/Test/TestComponents/SearchExperiment/README.md";
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public interface IAccessibleComponent
/// <summary>
/// The title attribute for the button, shown as a tooltip.
/// <h1>😱😱😱😱😱 1st rule of aria don't use aria, second rule of aria ... 😱😱😱😱</h1>
/// qqqq
/// qqqq get feedback :(
/// </summary>
/// <remarks>
/// Use a brief message that reinforces the button's action.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,55 +10,55 @@ public static class DummyData
{
public static readonly List<string> AllTerms = new()
{
"Dental care", "Dental hygiene", "Dental implants", "Dental braces", "Dental bleeding",
"Dental crowns", "Dental fillings", "Dental anxiety", "Dental pain", "Dental treatment",
"Dental checkup", "Dental cleaning", "Dental x-ray", "Dental surgery", "Dental emergency",
"Tooth extraction", "Toothache", "Tooth infection", "Tooth decay", "Tooth whitening",
"Gum disease", "Gum bleeding", "Gum recession", "Gum pain", "Gum treatment",
"False teeth", "Dentures", "Dental prosthetics", "Teeth grinding", "Teeth straightening",
"Teeth sensitivity", "Teeth whitening kits", "Wisdom teeth", "Root canal", "Jaw pain",
//"Dental care", "Dental hygiene", "Dental implants", "Dental braces", "Dental bleeding",
//"Dental crowns", "Dental fillings", "Dental anxiety", "Dental pain", "Dental treatment",
//"Dental checkup", "Dental cleaning", "Dental x-ray", "Dental surgery", "Dental emergency",
//"Tooth extraction", "Toothache", "Tooth infection", "Tooth decay", "Tooth whitening",
//"Gum disease", "Gum bleeding", "Gum recession", "Gum pain", "Gum treatment",
//"False teeth", "Dentures", "Dental prosthetics", "Teeth grinding", "Teeth straightening",
//"Teeth sensitivity", "Teeth whitening kits", "Wisdom teeth", "Root canal", "Jaw pain",

"Mouth ulcers", "Mouth guards", "Mouthwash", "Oral hygiene", "Oral pain", "Oral cancer",
"Oral surgery", "Oral examination", "Oral infection", "Bad breath", "Plaque control",
//"Mouth ulcers", "Mouth guards", "Mouthwash", "Oral hygiene", "Oral pain", "Oral cancer",
//"Oral surgery", "Oral examination", "Oral infection", "Bad breath", "Plaque control",

"Medical checkup", "Health checkup", "General examination", "Annual physical",
"Blood test", "Urine test", "X-ray chest", "CT scan", "MRI brain", "Eye examination",
"Vision test", "Hearing test", "Hearing aid fitting", "Skin check", "Skin biopsy",
//"Medical checkup", "Health checkup", "General examination", "Annual physical",
//"Blood test", "Urine test", "X-ray chest", "CT scan", "MRI brain", "Eye examination",
//"Vision test", "Hearing test", "Hearing aid fitting", "Skin check", "Skin biopsy",

"Back pain", "Neck pain", "Joint pain", "Chest pain", "Abdominal pain",
"Leg swelling", "Arm numbness", "Foot infection", "Hand injury", "Hip replacement",
//"Back pain", "Neck pain", "Joint pain", "Chest pain", "Abdominal pain",
//"Leg swelling", "Arm numbness", "Foot infection", "Hand injury", "Hip replacement",

"Heart checkup", "Heart surgery", "Heart failure", "Heart palpitations", "Chest tightness",
"Lung infection", "Pneumonia treatment", "Breathing problems", "Shortness of breath", "Asthma attack",
//"Heart checkup", "Heart surgery", "Heart failure", "Heart palpitations", "Chest tightness",
//"Lung infection", "Pneumonia treatment", "Breathing problems", "Shortness of breath", "Asthma attack",

"Skin rash", "Skin irritation", "Eczema treatment", "Psoriasis care", "Acne treatment",
"Wound dressing", "Burn treatment", "Scar removal", "Skin peeling", "Allergy treatment",
//"Skin rash", "Skin irritation", "Eczema treatment", "Psoriasis care", "Acne treatment",
//"Wound dressing", "Burn treatment", "Scar removal", "Skin peeling", "Allergy treatment",

"Ear infection", "Throat infection", "Sinus infection", "Eye infection", "Nasal bleeding",
"Frequent nosebleeds", "Throat pain", "Swollen lymph nodes", "Ear pain", "Voice loss",
//"Ear infection", "Throat infection", "Sinus infection", "Eye infection", "Nasal bleeding",
//"Frequent nosebleeds", "Throat pain", "Swollen lymph nodes", "Ear pain", "Voice loss",

"Fever symptoms", "High temperature", "Cough treatment", "Cold remedies", "Flu vaccination",
"COVID-19 testing", "COVID-19 symptoms", "Headache relief", "Migraine treatment", "Dizziness causes",
//"Fever symptoms", "High temperature", "Cough treatment", "Cold remedies", "Flu vaccination",
//"COVID-19 testing", "COVID-19 symptoms", "Headache relief", "Migraine treatment", "Dizziness causes",

"Depression treatment", "Anxiety management", "Mental health support", "Counseling services",
"Sleep disorder", "Insomnia treatment", "Panic attacks", "Therapy sessions", "Psychiatric assessment",
//"Depression treatment", "Anxiety management", "Mental health support", "Counseling services",
//"Sleep disorder", "Insomnia treatment", "Panic attacks", "Therapy sessions", "Psychiatric assessment",

"Diabetes checkup", "Blood sugar test", "Insulin treatment", "Weight management", "Obesity care",
"Dietician referral", "Nutrition advice", "Cholesterol test", "Hypertension treatment", "Blood pressure check",
//"Diabetes checkup", "Blood sugar test", "Insulin treatment", "Weight management", "Obesity care",
//"Dietician referral", "Nutrition advice", "Cholesterol test", "Hypertension treatment", "Blood pressure check",

"Cancer screening", "Mammogram exam", "Colon cancer test", "Prostate exam", "Biopsy procedure",
"Tumor removal", "Oncology referral", "Radiation therapy", "Chemotherapy care", "Cancer pain management",
//"Cancer screening", "Mammogram exam", "Colon cancer test", "Prostate exam", "Biopsy procedure",
//"Tumor removal", "Oncology referral", "Radiation therapy", "Chemotherapy care", "Cancer pain management",

"Pregnancy test", "Prenatal checkup", "Fertility consultation", "Birth plan", "Ultrasound scan",
"Labour support", "Midwife appointment", "Postnatal care", "Infant checkup", "Child immunisation",
//"Pregnancy test", "Prenatal checkup", "Fertility consultation", "Birth plan", "Ultrasound scan",
//"Labour support", "Midwife appointment", "Postnatal care", "Infant checkup", "Child immunisation",

"Vaccination record", "Tetanus shot", "Flu jab", "Hepatitis B shot", "Travel vaccines",
//"Vaccination record", "Tetanus shot", "Flu jab", "Hepatitis B shot", "Travel vaccines",

"Infection treatment", "Antibiotic prescription", "Inflammation control", "Immune system check",
"Wound infection", "Blood poisoning", "Sepsis symptoms", "Fungal infection", "Viral infection", "Bacterial infection",
//"Infection treatment", "Antibiotic prescription", "Inflammation control", "Immune system check",
//"Wound infection", "Blood poisoning", "Sepsis symptoms", "Fungal infection", "Viral infection", "Bacterial infection",

"Pain management", "Bleeding control", "Emergency care", "Treatment plan", "Recovery plan",
"Follow-up visit", "Health advice", "Patient education", "Medication review", "Drug interaction"
//"Pain management", "Bleeding control", "Emergency care", "Treatment plan", "Recovery plan",
//"Follow-up visit", "Health advice", "Patient education", "Medication review", "Drug interaction"
};

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,10 @@ For searching
# NoJs

The component has parameter for the search button action. On search it will hit the specified controller.
IT receives search information via the same interface so it can be populated in a view.
IT receives search information via the same interface so it can be populated in a view.

# Future
It currently doesnt use a cancellation token, and doesnt keep a list of suggestion responses.
If it kept the response from the first suggestion list and whittled them down from that list as long
as there are no deletions it would only need to call suggestions once. Assuming suggestions give everything.
if it will make a call per press it needs a cancel token potentially.
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
@using System.Diagnostics
<!--qqqq see microsoft default and ecommerce-->
<!--@bind-value="SearchText"
@bind-value:event="oninput"-->
<!--will want debounce-->
<!--will want cancel if still going-->
@inherits TELComponentBase
<!--think it will be a specific service instead but we would probably have this in an option on this component potentially?-->
<!-- NavigationManager.NavigateTo($"search/{searchText}/1");-->
<!--also we on query a bit so navigation manager would be good for that https://example.com/search?Term=blazor&Filters=video&Filters=article&Sortby=1&CataloguePageIndex=2-->
@inject NavigationManager NavigationManager
@inject ISearchExperimentService searchExperimentService
@* @implements IDisposable *@
Expand All @@ -17,7 +9,6 @@
<div class="nhsuk-width-container nhsuk-header__container app-width-container ">
<div class="nhsuk-header__search">
<div class="nhsuk-header__search-wrap" id="wrap-search">
<!--qqqq ending up with nojsfallback in both places may need button redesign-->
<EditForm Model="FormData" OnSubmit="SendSearchRequest" action="@(NoJSActionUrl)"
FormName="SearchMainForm"
name="SearchMainForm"
Expand Down Expand Up @@ -110,7 +101,7 @@
private CancellationTokenSource _cts;
/*avoid potential memory leak from mvc taredown by counting down not up by not search on first 3 letters can initiate*/
private Timer? _debounceTimer;
private readonly TimeSpan _debouncePeriod = TimeSpan.FromMilliseconds(500);
private readonly TimeSpan _debouncePeriod = TimeSpan.FromMilliseconds(300);

// SendSearchRequest SendSuggestionRequest presumeably same end point but maybe a bool for no suggestions

Expand All @@ -125,73 +116,81 @@

private void StartDebounceCountdown()
{
// Dispose any existing timer first
_debounceTimer?.Dispose();

// Start a new one-shot countdown timer
_debounceTimer = new Timer(_ =>
// Reset timer on every keystroke
_debounceTimer?.Dispose();
_debounceTimer = null;
_debounceTimer = new Timer(async _ =>
{
// Invoke on UI thread
Logger.LogInformation($"debounce searchText {searchText}");
await InvokeAsync(() => GetSuggestionsAsync());
_debounceTimer?.Dispose();
_debounceTimer = null;
},
null,
_debouncePeriod,
Timeout.InfiniteTimeSpan);


}, null, _debouncePeriod, Timeout.InfiniteTimeSpan);
}

private async Task SendSearchRequest()
{
<!--qqqq will look very similar because isnt meta data or additional information per term to display-->
suggestions.Clear();
//suggestions.Clear();

_cts?.Cancel(); // cancel prior search
_cts = new CancellationTokenSource();
// _cts?.Cancel(); // cancel prior search
// _cts = new CancellationTokenSource();

try
{
// try
// {
searchResults = (await searchExperimentService.SearchAsync(searchText)).ToList<string>();
}
catch (OperationCanceledException)
{
// Ignore cancelled searches
}
await InvokeAsync(StateHasChanged);
// }
// catch (OperationCanceledException)
// {
// // Ignore cancelled searches
// }
}
private async Task GetSuggestionsAsync()
{
_cts?.Cancel(); // cancel prior search
_cts = new CancellationTokenSource();

try
{
suggestions = (await searchExperimentService.GetSuggestionsAsync(searchText)).ToList<string>();

}
catch (OperationCanceledException)
{
// Ignore cancelled searches
}
// _cts?.Cancel(); // cancel prior search
// _cts = new CancellationTokenSource();

// try
// {
Logger.LogInformation($"GetSuggestionsAsync searchText {searchText}");
suggestions = (await searchExperimentService.GetSuggestionsAsync(searchText)).ToList<string>();
await InvokeAsync(StateHasChanged);
// }
// catch (OperationCanceledException)
// {
// // Ignore cancelled searches
// }
}


public async Task HandleInput(KeyboardEventArgs args)
{
Logger.LogInformation($"handleinput searchText {searchText}");
if (args.Key == null || args.Key.Equals("Enter"))
{

/*fire forget?*/
//suggestions.Clear();
await SendSearchRequest();
//_ = SendSearchRequest();
}
else if (_debounceTimer != null || searchText.Length < 4 )
else if ( searchText.Length < 3 )
{
StartDebounceCountdown();

_debounceTimer?.Dispose();
_debounceTimer = null;

}
else
{
StartDebounceCountdown();
/*fire forget?*/
await GetSuggestionsAsync();
//await GetSuggestionsAsync();
// _ = GetSuggestionsAsync();
}
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -147,50 +147,24 @@ private class ConceptDocument

private class ConceptItem
{
public string id { get; set; }
//public string id { get; set; }
public string title { get; set; }
public string concept { get; set; }
//public string concept { get; set; }
public Click click { get; set; }
}

private class Click
{
public Payload payload { get; set; }
public string url { get; set; }
//public string url { get; set; }
}

private class Payload
{
public string clickTargetUrl { get; set; }
}

// // Minimal classes to match the API response shape
// private class SearchResponse
// {
// public ConceptDocument conceptDocument { get; set; }
// }

// private class ConceptDocument
// {
// public List<ConceptItem> conceptDocumentList { get; set; }
// }

// private class ConceptItem
// {
// public string title { get; set; }
// public Click click { get; set; }
// }

// private class Click
// {
// public Payload payload { get; set; }
// }

// private class Payload
// {
// public string clickTargetUrl { get; set; }
// }
}

}

}