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 ;" >  ; </th >
25+ <th style =" width : 1px ;" >  ; </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