diff --git a/ExamNETIntermediate/Form1.Designer.cs b/ExamNETIntermediate/Form1.Designer.cs index ece918a..c404c3c 100644 --- a/ExamNETIntermediate/Form1.Designer.cs +++ b/ExamNETIntermediate/Form1.Designer.cs @@ -28,12 +28,379 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(800, 450); - this.Text = "Form1"; + listBoxSongs = new ListBox(); + labelListBox = new Label(); + buttonRefresh = new Button(); + tableLayoutPanelForm = new TableLayoutPanel(); + labelMinutes = new Label(); + buttonClearForm = new Button(); + dateTimePickerReleaseDate = new DateTimePicker(); + buttonAdd = new Button(); + buttonEdit = new Button(); + buttonDelete = new Button(); + textBoxArtist = new TextBox(); + textBoxTitle = new TextBox(); + labelTitle = new Label(); + labelArtist = new Label(); + labelGenre = new Label(); + labelLength = new Label(); + labelAvailable = new Label(); + checkBoxAvailable = new CheckBox(); + comboBoxGenre = new ComboBox(); + numericUpDownLengthMinutes = new NumericUpDown(); + numericUpDownLengthSeconds = new NumericUpDown(); + labelDatePicker = new Label(); + labelSeconds = new Label(); + labelStatus = new Label(); + labelMessage = new Label(); + textBoxSearch = new TextBox(); + labelSearch = new Label(); + tableLayoutPanelForm.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)numericUpDownLengthMinutes).BeginInit(); + ((System.ComponentModel.ISupportInitialize)numericUpDownLengthSeconds).BeginInit(); + SuspendLayout(); + // + // listBoxSongs + // + listBoxSongs.FormattingEnabled = true; + listBoxSongs.Location = new Point(12, 53); + listBoxSongs.Name = "listBoxSongs"; + listBoxSongs.Size = new Size(186, 284); + listBoxSongs.TabIndex = 0; + listBoxSongs.SelectedIndexChanged += listBoxSongs_SelectedIndexChanged; + // + // labelListBox + // + labelListBox.AutoSize = true; + labelListBox.Location = new Point(12, 19); + labelListBox.Name = "labelListBox"; + labelListBox.Size = new Size(69, 20); + labelListBox.TabIndex = 1; + labelListBox.Text = "Song List"; + // + // buttonRefresh + // + buttonRefresh.Location = new Point(54, 343); + buttonRefresh.Name = "buttonRefresh"; + buttonRefresh.Size = new Size(94, 29); + buttonRefresh.TabIndex = 2; + buttonRefresh.Text = "Refresh"; + buttonRefresh.UseVisualStyleBackColor = true; + buttonRefresh.Click += buttonRefresh_Click; + // + // tableLayoutPanelForm + // + tableLayoutPanelForm.ColumnCount = 6; + tableLayoutPanelForm.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 28F)); + tableLayoutPanelForm.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 12.5F)); + tableLayoutPanelForm.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 12.5F)); + tableLayoutPanelForm.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 12.5F)); + tableLayoutPanelForm.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 12.5F)); + tableLayoutPanelForm.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 22F)); + tableLayoutPanelForm.Controls.Add(labelMinutes, 2, 3); + tableLayoutPanelForm.Controls.Add(buttonClearForm, 5, 0); + tableLayoutPanelForm.Controls.Add(dateTimePickerReleaseDate, 1, 4); + tableLayoutPanelForm.Controls.Add(buttonAdd, 1, 6); + tableLayoutPanelForm.Controls.Add(buttonEdit, 3, 6); + tableLayoutPanelForm.Controls.Add(buttonDelete, 5, 6); + tableLayoutPanelForm.Controls.Add(textBoxArtist, 1, 1); + tableLayoutPanelForm.Controls.Add(textBoxTitle, 1, 0); + tableLayoutPanelForm.Controls.Add(labelTitle, 0, 0); + tableLayoutPanelForm.Controls.Add(labelArtist, 0, 1); + tableLayoutPanelForm.Controls.Add(labelGenre, 0, 2); + tableLayoutPanelForm.Controls.Add(labelLength, 0, 3); + tableLayoutPanelForm.Controls.Add(labelAvailable, 0, 5); + tableLayoutPanelForm.Controls.Add(checkBoxAvailable, 1, 5); + tableLayoutPanelForm.Controls.Add(comboBoxGenre, 1, 2); + tableLayoutPanelForm.Controls.Add(numericUpDownLengthMinutes, 1, 3); + tableLayoutPanelForm.Controls.Add(numericUpDownLengthSeconds, 3, 3); + tableLayoutPanelForm.Controls.Add(labelDatePicker, 0, 4); + tableLayoutPanelForm.Controls.Add(labelSeconds, 4, 3); + tableLayoutPanelForm.Location = new Point(274, 53); + tableLayoutPanelForm.Name = "tableLayoutPanelForm"; + tableLayoutPanelForm.RowCount = 7; + tableLayoutPanelForm.RowStyles.Add(new RowStyle(SizeType.Absolute, 40F)); + tableLayoutPanelForm.RowStyles.Add(new RowStyle(SizeType.Absolute, 40F)); + tableLayoutPanelForm.RowStyles.Add(new RowStyle(SizeType.Absolute, 40F)); + tableLayoutPanelForm.RowStyles.Add(new RowStyle(SizeType.Absolute, 40F)); + tableLayoutPanelForm.RowStyles.Add(new RowStyle(SizeType.Absolute, 40F)); + tableLayoutPanelForm.RowStyles.Add(new RowStyle(SizeType.Absolute, 40F)); + tableLayoutPanelForm.RowStyles.Add(new RowStyle(SizeType.Absolute, 40F)); + tableLayoutPanelForm.Size = new Size(413, 284); + tableLayoutPanelForm.TabIndex = 3; + // + // labelMinutes + // + labelMinutes.Anchor = AnchorStyles.Left; + labelMinutes.AutoSize = true; + labelMinutes.Font = new Font("Segoe UI", 8F); + labelMinutes.Location = new Point(169, 130); + labelMinutes.Name = "labelMinutes"; + labelMinutes.Size = new Size(32, 19); + labelMinutes.TabIndex = 8; + labelMinutes.Text = "min"; + // + // buttonClearForm + // + buttonClearForm.Location = new Point(322, 3); + buttonClearForm.Name = "buttonClearForm"; + buttonClearForm.Size = new Size(88, 29); + buttonClearForm.TabIndex = 8; + buttonClearForm.Text = "Reset"; + buttonClearForm.UseVisualStyleBackColor = true; + buttonClearForm.Click += buttonClearForm_Click; + // + // dateTimePickerReleaseDate + // + tableLayoutPanelForm.SetColumnSpan(dateTimePickerReleaseDate, 5); + dateTimePickerReleaseDate.Location = new Point(118, 163); + dateTimePickerReleaseDate.Name = "dateTimePickerReleaseDate"; + dateTimePickerReleaseDate.Size = new Size(250, 27); + dateTimePickerReleaseDate.TabIndex = 8; + dateTimePickerReleaseDate.Value = new DateTime(2024, 3, 15, 0, 0, 0, 0); + // + // buttonAdd + // + tableLayoutPanelForm.SetColumnSpan(buttonAdd, 2); + buttonAdd.Location = new Point(118, 243); + buttonAdd.Name = "buttonAdd"; + buttonAdd.Size = new Size(94, 29); + buttonAdd.TabIndex = 4; + buttonAdd.Text = "Add"; + buttonAdd.UseVisualStyleBackColor = true; + buttonAdd.Click += buttonAdd_Click; + // + // buttonEdit + // + tableLayoutPanelForm.SetColumnSpan(buttonEdit, 2); + buttonEdit.Location = new Point(220, 243); + buttonEdit.Name = "buttonEdit"; + buttonEdit.Size = new Size(96, 29); + buttonEdit.TabIndex = 5; + buttonEdit.Text = "Edit"; + buttonEdit.UseVisualStyleBackColor = true; + buttonEdit.Click += buttonEdit_Click; + // + // buttonDelete + // + buttonDelete.Location = new Point(322, 243); + buttonDelete.Name = "buttonDelete"; + buttonDelete.Size = new Size(88, 29); + buttonDelete.TabIndex = 6; + buttonDelete.Text = "Delete"; + buttonDelete.UseVisualStyleBackColor = true; + buttonDelete.Click += buttonDelete_Click; + // + // textBoxArtist + // + tableLayoutPanelForm.SetColumnSpan(textBoxArtist, 4); + textBoxArtist.Location = new Point(118, 43); + textBoxArtist.Name = "textBoxArtist"; + textBoxArtist.Size = new Size(179, 27); + textBoxArtist.TabIndex = 10; + // + // textBoxTitle + // + tableLayoutPanelForm.SetColumnSpan(textBoxTitle, 4); + textBoxTitle.Location = new Point(118, 3); + textBoxTitle.Name = "textBoxTitle"; + textBoxTitle.Size = new Size(179, 27); + textBoxTitle.TabIndex = 4; + // + // labelTitle + // + labelTitle.Anchor = AnchorStyles.Right; + labelTitle.Location = new Point(71, 10); + labelTitle.Name = "labelTitle"; + labelTitle.Size = new Size(41, 20); + labelTitle.TabIndex = 5; + labelTitle.Text = "Title:"; + // + // labelArtist + // + labelArtist.Anchor = AnchorStyles.Right; + labelArtist.AutoSize = true; + labelArtist.Location = new Point(65, 50); + labelArtist.Name = "labelArtist"; + labelArtist.Size = new Size(47, 20); + labelArtist.TabIndex = 6; + labelArtist.Text = "Artist:"; + // + // labelGenre + // + labelGenre.Anchor = AnchorStyles.Right; + labelGenre.AutoSize = true; + labelGenre.Location = new Point(61, 90); + labelGenre.Name = "labelGenre"; + labelGenre.Size = new Size(51, 20); + labelGenre.TabIndex = 7; + labelGenre.Text = "Genre:"; + // + // labelLength + // + labelLength.Anchor = AnchorStyles.Right; + labelLength.AutoSize = true; + labelLength.Location = new Point(58, 130); + labelLength.Name = "labelLength"; + labelLength.Size = new Size(54, 20); + labelLength.TabIndex = 8; + labelLength.Text = "Length"; + // + // labelAvailable + // + labelAvailable.Anchor = AnchorStyles.Right; + labelAvailable.AutoSize = true; + labelAvailable.Location = new Point(28, 210); + labelAvailable.Name = "labelAvailable"; + labelAvailable.Size = new Size(84, 20); + labelAvailable.TabIndex = 9; + labelAvailable.Text = "IsAvailable:"; + // + // checkBoxAvailable + // + checkBoxAvailable.AutoSize = true; + tableLayoutPanelForm.SetColumnSpan(checkBoxAvailable, 3); + checkBoxAvailable.Location = new Point(118, 203); + checkBoxAvailable.Name = "checkBoxAvailable"; + checkBoxAvailable.Size = new Size(93, 24); + checkBoxAvailable.TabIndex = 11; + checkBoxAvailable.Text = "Available"; + checkBoxAvailable.UseVisualStyleBackColor = true; + // + // comboBoxGenre + // + tableLayoutPanelForm.SetColumnSpan(comboBoxGenre, 4); + comboBoxGenre.DropDownStyle = ComboBoxStyle.DropDownList; + comboBoxGenre.FormattingEnabled = true; + comboBoxGenre.Location = new Point(118, 83); + comboBoxGenre.Name = "comboBoxGenre"; + comboBoxGenre.Size = new Size(179, 28); + comboBoxGenre.TabIndex = 12; + // + // numericUpDownLengthMinutes + // + numericUpDownLengthMinutes.Location = new Point(118, 123); + numericUpDownLengthMinutes.Name = "numericUpDownLengthMinutes"; + numericUpDownLengthMinutes.Size = new Size(45, 27); + numericUpDownLengthMinutes.TabIndex = 13; + // + // numericUpDownLengthSeconds + // + numericUpDownLengthSeconds.Location = new Point(220, 123); + numericUpDownLengthSeconds.Maximum = new decimal(new int[] { 60, 0, 0, 0 }); + numericUpDownLengthSeconds.Name = "numericUpDownLengthSeconds"; + numericUpDownLengthSeconds.Size = new Size(45, 27); + numericUpDownLengthSeconds.TabIndex = 14; + numericUpDownLengthSeconds.ValueChanged += numericUpDownLengthSeconds_ValueChanged; + // + // labelDatePicker + // + labelDatePicker.Anchor = AnchorStyles.Right; + labelDatePicker.AutoSize = true; + labelDatePicker.Location = new Point(13, 170); + labelDatePicker.Name = "labelDatePicker"; + labelDatePicker.Size = new Size(99, 20); + labelDatePicker.TabIndex = 15; + labelDatePicker.Text = "Release Date:"; + // + // labelSeconds + // + labelSeconds.Anchor = AnchorStyles.Left; + labelSeconds.AutoSize = true; + labelSeconds.Font = new Font("Segoe UI", 8F); + labelSeconds.Location = new Point(271, 130); + labelSeconds.Name = "labelSeconds"; + labelSeconds.Size = new Size(28, 19); + labelSeconds.TabIndex = 16; + labelSeconds.Text = "sec"; + // + // labelStatus + // + labelStatus.AutoSize = true; + labelStatus.Location = new Point(274, 370); + labelStatus.Name = "labelStatus"; + labelStatus.Size = new Size(62, 20); + labelStatus.TabIndex = 4; + labelStatus.Text = "STATUS:"; + // + // labelMessage + // + labelMessage.AutoSize = true; + labelMessage.Location = new Point(274, 400); + labelMessage.Name = "labelMessage"; + labelMessage.Size = new Size(69, 20); + labelMessage.TabIndex = 5; + labelMessage.Text = "Waiting..."; + // + // textBoxSearch + // + textBoxSearch.Location = new Point(73, 393); + textBoxSearch.Name = "textBoxSearch"; + textBoxSearch.PlaceholderText = "enter song title..."; + textBoxSearch.Size = new Size(125, 27); + textBoxSearch.TabIndex = 6; + textBoxSearch.TextChanged += textBoxSearch_TextChanged; + // + // labelSearch + // + labelSearch.AutoSize = true; + labelSearch.Location = new Point(11, 396); + labelSearch.Name = "labelSearch"; + labelSearch.Size = new Size(56, 20); + labelSearch.TabIndex = 7; + labelSearch.Text = "Search:"; + // + // Form1 + // + AutoScaleDimensions = new SizeF(8F, 20F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(800, 450); + Controls.Add(labelSearch); + Controls.Add(textBoxSearch); + Controls.Add(labelMessage); + Controls.Add(labelStatus); + Controls.Add(tableLayoutPanelForm); + Controls.Add(buttonRefresh); + Controls.Add(labelListBox); + Controls.Add(listBoxSongs); + Name = "Form1"; + Text = "Form1"; + tableLayoutPanelForm.ResumeLayout(false); + tableLayoutPanelForm.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)numericUpDownLengthMinutes).EndInit(); + ((System.ComponentModel.ISupportInitialize)numericUpDownLengthSeconds).EndInit(); + ResumeLayout(false); + PerformLayout(); } #endregion + + private ListBox listBoxSongs; + private Label labelListBox; + private Button buttonRefresh; + private TableLayoutPanel tableLayoutPanelForm; + private TextBox textBoxTitle; + private Label labelTitle; + private Label labelArtist; + private Label labelGenre; + private Label labelLength; + private Label labelAvailable; + private TextBox textBoxArtist; + private CheckBox checkBoxAvailable; + private ComboBox comboBoxGenre; + private NumericUpDown numericUpDownLengthMinutes; + private NumericUpDown numericUpDownLengthSeconds; + private Button buttonAdd; + private Button buttonEdit; + private Button buttonDelete; + private Label labelStatus; + private Label labelMessage; + private TextBox textBoxSearch; + private Label labelSearch; + private DateTimePicker dateTimePickerReleaseDate; + private Label labelDatePicker; + private Button buttonClearForm; + private Label labelMinutes; + private Label labelSeconds; } } diff --git a/ExamNETIntermediate/Form1.cs b/ExamNETIntermediate/Form1.cs index 3302c50..a4e6025 100644 --- a/ExamNETIntermediate/Form1.cs +++ b/ExamNETIntermediate/Form1.cs @@ -1,10 +1,292 @@ +using ExamNETIntermediate.Models; +using Newtonsoft.Json; + namespace ExamNETIntermediate { public partial class Form1 : Form { + List songs = new List(); + List genres = new List(); + HttpClient httpClient = new HttpClient(); + string baseUrl = "https://new-dev.accelist.com:10000/api"; public Form1() { InitializeComponent(); + GetDataListBox(); + GetDataGenre(); + Deselect(); } + /// + /// Uses http GET request to the API to get song list. Listbox displays each song's title. Clears and repopulates listbox and internal List every call. + /// + /// + /// Does not use .DataSource to populate because it autoselects listbox and ruins other functions. + /// + public async void GetDataListBox() + { + var response = await httpClient.GetAsync(baseUrl + "/song"); + response.EnsureSuccessStatusCode(); + var jsonContent = await response.Content.ReadAsStringAsync(); + var content = JsonConvert.DeserializeObject>(jsonContent); + if (content != null) songs = content; + + listBoxSongs.Items.Clear(); + var contentObject = songs.Cast().ToArray(); + listBoxSongs.Items.AddRange(contentObject); + listBoxSongs.DisplayMember = "title"; + } + /// + /// Gets genre list from API. Since genre can only be changed by host, this is a one time call in initialization. Genre populates combobox, displays genre name. + /// + public async void GetDataGenre() + { + var response = await httpClient.GetAsync(baseUrl + "/genre"); + response.EnsureSuccessStatusCode(); + var jsonContent = await response.Content.ReadAsStringAsync(); + var content = JsonConvert.DeserializeObject>(jsonContent); + if (content != null) genres = content; + + var contentObject = genres.Cast().ToArray(); + comboBoxGenre.Items.AddRange(contentObject); + comboBoxGenre.DisplayMember = "genreName"; + } + /// + /// Method to reset the form. Sets fields values to null/zero/empty. Also deselects lisbox and combobox. + /// + public void ClearForm() + { + textBoxTitle.Text = ""; + textBoxArtist.Text = ""; + comboBoxGenre.SelectedItem = null; + numericUpDownLengthMinutes.Value = 0; + numericUpDownLengthSeconds.Value = 0; + checkBoxAvailable.Checked = false; + + labelMessage.Text = "Waiting..."; + Deselect(); + } + /// + /// Deselects listbox and combobox. When listbox is not selecting an item, user can only use add button for new songs. + /// + public void Deselect() + { + comboBoxGenre.SelectedIndex = -1; + listBoxSongs.SelectedIndex = -1; + buttonAdd.Enabled = true; + buttonEdit.Enabled = false; + buttonDelete.Enabled = false; + } + /// + /// Method called when user selects a listbox item. This populates all the form's fields with the selected item's data. User can then edit or delete the item from list, but can not add new items until deselect happens. + /// + /// + /// + private void listBoxSongs_SelectedIndexChanged(object sender, EventArgs e) + { + SongModel? selectedItem = listBoxSongs.SelectedItem as SongModel; + if (selectedItem == null) { return; } //handle null case + + textBoxTitle.Text = selectedItem.Title; + textBoxArtist.Text = selectedItem.Artist; + comboBoxGenre.SelectedItem = genres.Where(Q => Q.GenreName == selectedItem.GenreName).FirstOrDefault(); + DateTime utcTime = selectedItem.ReleaseDate; + dateTimePickerReleaseDate.Value = utcTime.ToLocalTime(); + int minutes = selectedItem.Length / 60; + int seconds = selectedItem.Length % 60; + numericUpDownLengthMinutes.Value = minutes; + numericUpDownLengthSeconds.Value = seconds; + checkBoxAvailable.Checked = selectedItem.IsAvailable; + + buttonEdit.Enabled = true; + buttonDelete.Enabled = true; + buttonAdd.Enabled = false; + } + + private void buttonRefresh_Click(object sender, EventArgs e) + { + GetDataListBox(); + } + + /// + /// Method that processes form inputs and sends the new song to the API(POST). Validation includes no fields are empty or zero, and the song's release date must be at most 7 days from now. Success/fail is displayed in the message label. Form is cleared and lists deselected as well. + /// + /// + /// + private async void buttonAdd_Click(object sender, EventArgs e) + { + GenreModel? inputGenre = comboBoxGenre.SelectedItem as GenreModel; + + //input form validation + if (string.IsNullOrEmpty(textBoxTitle.Text) + || string.IsNullOrEmpty(textBoxArtist.Text) + || inputGenre == null + || (numericUpDownLengthMinutes.Value == 0 && numericUpDownLengthSeconds.Value == 0)) + { + labelMessage.Text = "Fields must not be empty!"; + return; + } + DateTime currentTime = DateTime.UtcNow; + TimeSpan timeDiff = dateTimePickerReleaseDate.Value - currentTime; + if (timeDiff.Days > 7) + { + labelMessage.Text = "Release date can not be more than 7 days from now!"; + return; + } + + SongInputModel input = new SongInputModel(); + input.Title = textBoxTitle.Text; + input.Artist = textBoxArtist.Text; + input.GenreId = inputGenre.GenreId; + DateTime localTime = dateTimePickerReleaseDate.Value; + input.ReleaseDate = localTime.ToUniversalTime(); + input.Length = (int)numericUpDownLengthMinutes.Value * 60 + (int)numericUpDownLengthSeconds.Value; + input.IsAvailable = checkBoxAvailable.Checked; + + var jsonContent = JsonConvert.SerializeObject(input); + var content = new StringContent(jsonContent); + content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); + if (content == null) { return; } + + var response = await httpClient.PostAsync(baseUrl + "/song", content); + response.EnsureSuccessStatusCode(); + if (response.IsSuccessStatusCode) + { + GetDataListBox(); + ClearForm(); + labelMessage.Text = "Song upload successful!"; + } + else + { + labelMessage.Text = "Song upload failed!"; + } + } + /// + /// Similar to the edit button event. The only major difference is that the POST and PUT API has different requirements, so uses different class. + /// + /// + /// + private async void buttonEdit_Click(object sender, EventArgs e) + { + SongModel? selectedItem = listBoxSongs.SelectedItem as SongModel; + if (selectedItem == null) + { + labelMessage.Text = "selected item does not exist"; + return; + } + GenreModel? inputGenre = comboBoxGenre.SelectedItem as GenreModel; + SongEditModel editItem = new SongEditModel(); + + if (string.IsNullOrEmpty(textBoxTitle.Text) + || string.IsNullOrEmpty(textBoxArtist.Text) + || inputGenre == null + || (numericUpDownLengthMinutes.Value == 0 && numericUpDownLengthSeconds.Value == 0)) + { + labelMessage.Text = "Fields must not be empty!"; + return; + } + DateTime currentTime = DateTime.UtcNow; + TimeSpan timeDiff = dateTimePickerReleaseDate.Value - currentTime; + if (timeDiff.Days > 7) + { + labelMessage.Text = "Release date can not be more than 7 days from now!"; + return; + } + + editItem.SongId = selectedItem.SongId; + editItem.Title = textBoxTitle.Text; + editItem.Artist = textBoxArtist.Text; + editItem.GenreId = inputGenre.GenreId; + editItem.Length = (int)numericUpDownLengthMinutes.Value * 60 + (int)numericUpDownLengthSeconds.Value; + DateTime localTime = dateTimePickerReleaseDate.Value; + editItem.ReleaseDate = localTime.ToUniversalTime(); + editItem.IsAvailable = checkBoxAvailable.Checked; + + var jsonContent = JsonConvert.SerializeObject(editItem); + var content = new StringContent(jsonContent); + content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); + + var response = await httpClient.PutAsync(baseUrl + "/song", content); + if (response.IsSuccessStatusCode) + { + GetDataListBox(); + ClearForm(); + labelMessage.Text = "Edit success!"; + } + else + { + labelMessage.Text = "Edit failed!"; + } + + } + + /// + /// Delete button event. Grabs songId from the selected listbox item and sends a DELETE request to API. + /// + /// + /// + private async void buttonDelete_Click(object sender, EventArgs e) + { + SongModel? selectedItem = listBoxSongs.SelectedItem as SongModel; + if (selectedItem == null) + { + labelMessage.Text = "Item does not exist!"; + return; + } + int songId = selectedItem.SongId; + + var response = await httpClient.DeleteAsync(baseUrl + $"/song/{songId}"); + response.EnsureSuccessStatusCode(); + if (response.IsSuccessStatusCode) + { + GetDataListBox(); + ClearForm(); + labelMessage.Text = $"Delete success! (ID: {songId})"; + } + else + { + labelMessage.Text = "Delete failed!"; + } + } + + private void buttonClearForm_Click(object sender, EventArgs e) + { + ClearForm(); + } + + /// + /// Method to search local list of songs. Detects change in textbox value and searches the local list according to input. Emptying out the textbox returns the whole list. + /// + /// + /// + private void textBoxSearch_TextChanged(object sender, EventArgs e) + { + listBoxSongs.Items.Clear(); + var search = textBoxSearch.Text; + if (string.IsNullOrEmpty(search)) + { + listBoxSongs.Items.AddRange(songs.Cast().ToArray()); + listBoxSongs.DisplayMember = "title"; + + return; + } + var list = songs.Where(Q => Q.Title.Contains(search)).ToList(); + listBoxSongs.Items.AddRange(list.Cast().ToArray()); + listBoxSongs.DisplayMember = "title"; + } + /// + /// Handles the 'seconds' numericUpDown control. Converts 60 seconds to one minute. + /// + /// + /// + private void numericUpDownLengthSeconds_ValueChanged(object sender, EventArgs e) + { + if (numericUpDownLengthSeconds.Value >= 60) + { + numericUpDownLengthSeconds.Value = 0; + numericUpDownLengthMinutes.Value += 1; + } + } + + } } diff --git a/ExamNETIntermediate/Form1.resx b/ExamNETIntermediate/Form1.resx new file mode 100644 index 0000000..af32865 --- /dev/null +++ b/ExamNETIntermediate/Form1.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ExamNETIntermediate/Models/GenreModel.cs b/ExamNETIntermediate/Models/GenreModel.cs new file mode 100644 index 0000000..434dfc3 --- /dev/null +++ b/ExamNETIntermediate/Models/GenreModel.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ExamNETIntermediate.Models +{ + internal class GenreModel + { + public int GenreId { get; set; } + public string GenreName { get; set; } = string.Empty; + } +} diff --git a/ExamNETIntermediate/Models/SongModel.cs b/ExamNETIntermediate/Models/SongModel.cs new file mode 100644 index 0000000..04bd371 --- /dev/null +++ b/ExamNETIntermediate/Models/SongModel.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ExamNETIntermediate.Models +{ + /// + /// Classses for storing Song information. Different variables are required for GET, POST, and PUT, so there are 3 different classes. + /// + internal class SongModel + { + public int SongId { get; set; } + public string Title { get; set; } = string.Empty; + public string Artist { get; set; } = string.Empty; + public string GenreName { get; set; } = string.Empty; + public int Length { get; set; } + public DateTime ReleaseDate { get; set; } + public bool IsAvailable { get; set; } + + } + + internal class SongInputModel + { + public string Title { get; set; } = string.Empty; + public string Artist { get; set; } = string.Empty; + public int GenreId { get; set; } + public int Length { get; set; } + public DateTime ReleaseDate { get; set; } + public bool IsAvailable { get; set; } + } + + internal class SongEditModel + { + public int SongId { get; set; } + public string Title { get; set; } = string.Empty; + + public string Artist { get; set; } = string.Empty; + public int GenreId { get; set; } + public int Length { get; set; } + public DateTime ReleaseDate { get; set; } + public bool IsAvailable { get; set; } + } +}