Skip to content

Commit 4930ffd

Browse files
committed
Add project files.
1 parent d14da04 commit 4930ffd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+2560
-0
lines changed

Client/AssemblyInfo.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
using System.Resources;
2+
using Microsoft.Extensions.Localization;
3+
4+
[assembly: RootNamespace("GIBS.Module.QuickPoll.Client")]
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Razor">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net9.0</TargetFramework>
5+
<Version>1.0.1</Version>
6+
<Authors>GIBS</Authors>
7+
<Company>GIBS</Company>
8+
<Description>Quick Poll module supports both registered and anonymous users</Description>
9+
<Product>GIBS.Module.QuickPoll</Product>
10+
<Copyright>GIBS</Copyright>
11+
<AssemblyName>GIBS.Module.QuickPoll.Client.Oqtane</AssemblyName>
12+
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
13+
</PropertyGroup>
14+
15+
<ItemGroup>
16+
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.9" />
17+
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.9" />
18+
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.9" />
19+
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.9" />
20+
<PackageReference Include="System.Net.Http.Json" Version="9.0.9" />
21+
</ItemGroup>
22+
23+
<ItemGroup>
24+
<ProjectReference Include="..\Shared\GIBS.Module.QuickPoll.Shared.csproj" />
25+
</ItemGroup>
26+
27+
<ItemGroup>
28+
<Reference Include="Oqtane.Client"><HintPath>..\..\oqtane.framework-6.2.1-Source\Oqtane.Server\bin\Debug\net9.0\Oqtane.Client.dll</HintPath></Reference>
29+
<Reference Include="Oqtane.Shared"><HintPath>..\..\oqtane.framework-6.2.1-Source\Oqtane.Server\bin\Debug\net9.0\Oqtane.Shared.dll</HintPath></Reference>
30+
</ItemGroup>
31+
32+
<PropertyGroup>
33+
<!-- there may be other elements here -->
34+
<BlazorWebAssemblyEnableLinking>false</BlazorWebAssemblyEnableLinking>
35+
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
36+
</PropertyGroup>
37+
38+
</Project>

Client/Interop.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using Microsoft.JSInterop;
2+
using System.Threading.Tasks;
3+
4+
namespace GIBS.Module.QuickPoll
5+
{
6+
public class Interop
7+
{
8+
private readonly IJSRuntime _jsRuntime;
9+
10+
public Interop(IJSRuntime jsRuntime)
11+
{
12+
_jsRuntime = jsRuntime;
13+
}
14+
}
15+
}
Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
@using Oqtane.Modules.Controls
2+
@using GIBS.Module.QuickPoll.Services
3+
@using GIBS.Module.QuickPoll.Models
4+
5+
@namespace GIBS.Module.QuickPoll
6+
@inherits ModuleBase
7+
@inject IQuickPollService QuickPollService
8+
@inject NavigationManager NavigationManager
9+
@inject IStringLocalizer<Edit> Localizer
10+
11+
@if (_view == "list")
12+
{
13+
<ActionLink Action="Add" Security="SecurityAccessLevel.Edit" Text="Create QuickPoll" Class="btn btn-primary" OnClick="@(() => Add())" />
14+
<br />
15+
<br />
16+
@if (_quickPolls == null)
17+
{
18+
<p><em>Loading...</em></p>
19+
}
20+
else if (_quickPolls.Count != 0)
21+
{
22+
<Pager Items="@_quickPolls">
23+
<Header>
24+
<th style="width: 1px;">&nbsp;</th>
25+
<th style="width: 1px;">&nbsp;</th>
26+
<th>@Localizer["Name"]</th>
27+
<th>Question</th>
28+
<th>Active</th>
29+
</Header>
30+
<Row>
31+
<td><ActionLink Action="Edit" Security="SecurityAccessLevel.Edit" Parameters="@($"id={context.PollId}")" ResourceKey="Edit" /></td>
32+
<td><ActionDialog Header="Delete QuickPoll" Message="Are You Sure You Wish To Delete This QuickPoll?" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" OnClick="@(async () => await Delete(context))" ResourceKey="Delete" Id="@context.PollId.ToString()" /></td>
33+
<td>@context.Name</td>
34+
<td>@context.Question</td>
35+
<td>@context.IsActive</td>
36+
</Row>
37+
</Pager>
38+
}
39+
else
40+
{
41+
<p>@Localizer["Message.DisplayNone"]</p>
42+
}
43+
}
44+
else
45+
{
46+
<form @ref="form" class="@(validated ? " was-validated" : "needs-validation")" novalidate>
47+
<div class="container">
48+
<div class="row mb-1 align-items-center">
49+
<Label Class="col-sm-3" For="name" HelpText="Enter a name" ResourceKey="Name">Name: </Label>
50+
<div class="col-sm-9">
51+
<input id="name" class="form-control" @bind="@_quickPoll.Name" required />
52+
</div>
53+
</div>
54+
<div class="row mb-1 align-items-center">
55+
<Label Class="col-sm-3" For="question" HelpText="Enter a question" ResourceKey="Question">Question: </Label>
56+
<div class="col-sm-9">
57+
<input id="question" class="form-control" @bind="@_quickPoll.Question" required />
58+
</div>
59+
</div>
60+
<div class="row mb-1 align-items-center">
61+
<Label Class="col-sm-3" For="active" HelpText="Is Active" ResourceKey="IsActive">Active: </Label>
62+
<div class="col-sm-9">
63+
<input id="active" type="checkbox" @bind="@_quickPoll.IsActive" />
64+
</div>
65+
</div>
66+
<div class="row mb-1 align-items-center">
67+
<Label Class="col-sm-3" For="anonymous" HelpText="Allow Anonymous" ResourceKey="AllowAnonymous">Allow Anonymous: </Label>
68+
<div class="col-sm-9">
69+
<input id="anonymous" type="checkbox" @bind="@_quickPoll.AllowAnonymous" />
70+
</div>
71+
</div>
72+
<div class="row mb-1 align-items-center">
73+
<Label Class="col-sm-3" For="startdate" HelpText="Leave blank for the poll to start immediately" ResourceKey="StartDateTime">Start Date/Time: </Label>
74+
<div class="col-sm-9">
75+
<input id="startdate" type="datetime-local" class="form-control" @bind="@_quickPoll.StartDateTime" />
76+
</div>
77+
</div>
78+
<div class="row mb-1 align-items-center">
79+
<Label Class="col-sm-3" For="enddate" HelpText="Leave blank for the poll to never expire" ResourceKey="EndDateTime">End Date/Time: </Label>
80+
<div class="col-sm-9">
81+
<input id="enddate" type="datetime-local" class="form-control" @bind="@_quickPoll.EndDateTime" />
82+
</div>
83+
</div>
84+
85+
<hr />
86+
<h5>Options</h5>
87+
<table class="table table-borderless">
88+
<thead>
89+
<tr>
90+
<th>Option Text</th>
91+
<th style="width: 100px;">Order</th>
92+
<th style="width: 10px;"></th>
93+
</tr>
94+
</thead>
95+
<tbody>
96+
@foreach (var option in _quickPoll.Options.OrderBy(item => item.ViewOrder).ToList())
97+
{
98+
<tr>
99+
<td><input class="form-control" @bind="@option.OptionText" required /></td>
100+
<td><input type="number" class="form-control" @bind="@option.ViewOrder" required /></td>
101+
<td><button type="button" class="btn btn-danger" @onclick="@(() => RemoveOption(option))">X</button></td>
102+
</tr>
103+
}
104+
</tbody>
105+
</table>
106+
<button type="button" class="btn btn-secondary" @onclick="AddOption">Add Option</button>
107+
</div>
108+
<br />
109+
<button type="button" class="btn btn-success" @onclick="Save">@Localizer["Save"]</button>
110+
<button type="button" class="btn btn-secondary" @onclick="Cancel">@Localizer["Cancel"]</button>
111+
<br /><br />
112+
@if (_id != 0)
113+
{
114+
<AuditInfo CreatedBy="@_quickPoll.CreatedBy" CreatedOn="@_quickPoll.CreatedOn" ModifiedBy="@_quickPoll.ModifiedBy" ModifiedOn="@_quickPoll.ModifiedOn"></AuditInfo>
115+
}
116+
</form>
117+
}
118+
119+
@code {
120+
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
121+
public override bool UseAdminContainer => false;
122+
public override string RenderMode => RenderModes.Interactive;
123+
124+
public override string Actions => "Add,Edit";
125+
126+
public override string Title => "Manage QuickPoll";
127+
128+
public override List<Resource> Resources => new List<Resource>()
129+
{
130+
new Stylesheet("_content/GIBS.Module.QuickPoll/Module.css")
131+
};
132+
133+
private ElementReference form;
134+
private bool validated = false;
135+
private string _view = "list";
136+
private int _id = 0;
137+
138+
private List<QuickPoll> _quickPolls;
139+
private QuickPoll _quickPoll = new();
140+
141+
protected override async Task OnInitializedAsync()
142+
{
143+
try
144+
{
145+
if (PageState.Action == "Edit" && PageState.QueryString.ContainsKey("id"))
146+
{
147+
if (int.TryParse(PageState.QueryString["id"], out _id))
148+
{
149+
_quickPoll = await QuickPollService.GetQuickPollAsync(_id, ModuleState.ModuleId);
150+
if (_quickPoll != null)
151+
{
152+
if (_quickPoll.Options == null) _quickPoll.Options = new List<PollOption>();
153+
_view = "edit";
154+
}
155+
else
156+
{
157+
AddModuleMessage(Localizer["Message.LoadError"], MessageType.Error);
158+
_view = "list"; // return to list if item not found
159+
await LoadList();
160+
}
161+
}
162+
}
163+
else if (PageState.Action == "Add")
164+
{
165+
Add();
166+
}
167+
else
168+
{
169+
await LoadList();
170+
}
171+
}
172+
catch (Exception ex)
173+
{
174+
await logger.LogError(ex, "Error Initializing QuickPoll Edit Page {Error}", ex.Message);
175+
AddModuleMessage(Localizer["Message.LoadError"], MessageType.Error);
176+
}
177+
}
178+
179+
private async Task LoadList()
180+
{
181+
try
182+
{
183+
_quickPolls = await QuickPollService.GetQuickPollsAsync(ModuleState.ModuleId);
184+
_view = "list";
185+
_id = 0; // Reset id
186+
}
187+
catch (Exception ex)
188+
{
189+
await logger.LogError(ex, "Error Loading QuickPolls {Error}", ex.Message);
190+
AddModuleMessage(Localizer["Message.LoadError"], MessageType.Error);
191+
}
192+
}
193+
194+
private void Add()
195+
{
196+
_id = 0;
197+
_quickPoll = new QuickPoll { ModuleId = ModuleState.ModuleId, IsActive = true, Options = new List<PollOption>() };
198+
_view = "edit";
199+
validated = false;
200+
}
201+
202+
private async Task EditPoll(QuickPoll item)
203+
{
204+
try
205+
{
206+
if (item == null) return; // Guard against null item
207+
208+
_id = item.PollId;
209+
_quickPoll = await QuickPollService.GetQuickPollAsync(_id, ModuleState.ModuleId);
210+
211+
if (_quickPoll != null) // Ensure the poll was loaded successfully
212+
{
213+
if (_quickPoll.Options == null)
214+
{
215+
_quickPoll.Options = new List<PollOption>();
216+
}
217+
_view = "edit";
218+
validated = false;
219+
}
220+
else
221+
{
222+
AddModuleMessage(Localizer["Message.LoadError"], MessageType.Error);
223+
}
224+
}
225+
catch (Exception ex)
226+
{
227+
await logger.LogError(ex, "Error Loading QuickPoll {QuickPollId} {Error}", item?.PollId, ex.Message);
228+
AddModuleMessage(Localizer["Message.LoadError"], MessageType.Error);
229+
}
230+
}
231+
232+
private async Task Delete(QuickPoll QuickPoll)
233+
{
234+
try
235+
{
236+
await QuickPollService.DeleteQuickPollAsync(QuickPoll.PollId, ModuleState.ModuleId);
237+
await logger.LogInformation("QuickPoll Deleted {QuickPoll}", QuickPoll);
238+
await LoadList();
239+
StateHasChanged();
240+
}
241+
catch (Exception ex)
242+
{
243+
await logger.LogError(ex, "Error Deleting QuickPoll {QuickPoll} {Error}", QuickPoll, ex.Message);
244+
AddModuleMessage(Localizer["Message.DeleteError"], MessageType.Error);
245+
}
246+
}
247+
248+
private void AddOption()
249+
{
250+
_quickPoll.Options.Add(new PollOption { ViewOrder = _quickPoll.Options.Count + 1 });
251+
}
252+
253+
private void RemoveOption(PollOption option)
254+
{
255+
_quickPoll.Options.Remove(option);
256+
}
257+
258+
private void Cancel()
259+
{
260+
NavigationManager.NavigateTo(NavigateUrl());
261+
}
262+
263+
private async Task Save()
264+
{
265+
try
266+
{
267+
validated = true;
268+
var interop = new Oqtane.UI.Interop(JSRuntime);
269+
if (await interop.FormValid(form))
270+
{
271+
if (_id == 0)
272+
{
273+
_quickPoll = await QuickPollService.AddQuickPollAsync(_quickPoll);
274+
await logger.LogInformation("QuickPoll Added {QuickPoll}", _quickPoll);
275+
}
276+
else
277+
{
278+
_quickPoll = await QuickPollService.UpdateQuickPollAsync(_quickPoll);
279+
await logger.LogInformation("QuickPoll Updated {QuickPoll}", _quickPoll);
280+
}
281+
NavigationManager.NavigateTo(NavigateUrl());
282+
}
283+
else
284+
{
285+
AddModuleMessage(Localizer["Message.SaveValidation"], MessageType.Warning);
286+
}
287+
}
288+
catch (Exception ex)
289+
{
290+
await logger.LogError(ex, "Error Saving QuickPoll {Error}", ex.Message);
291+
AddModuleMessage(Localizer["Message.SaveError"], MessageType.Error);
292+
}
293+
}
294+
}

0 commit comments

Comments
 (0)