Add software variant admin page.

This commit is contained in:
2020-08-09 02:41:00 +01:00
parent 9b4c950557
commit 01b69e7601
15 changed files with 1431 additions and 1 deletions

View File

@@ -60,5 +60,7 @@ namespace Marechai.Database.Models
public virtual ICollection<RequiredSoftwareBySoftwareVariant> RequiredSoftware { get; set; } public virtual ICollection<RequiredSoftwareBySoftwareVariant> RequiredSoftware { get; set; }
public virtual ICollection<SoundBySoftwareVariant> SupportedSound { get; set; } public virtual ICollection<SoundBySoftwareVariant> SupportedSound { get; set; }
public virtual ICollection<StandaloneFile> Files { get; set; } public virtual ICollection<StandaloneFile> Files { get; set; }
public ulong? ParentId { get; set; }
public ulong SoftwareVersionId { get; set; }
} }
} }

View File

@@ -2,7 +2,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<Version>4.0.0.1816</Version> <Version>4.0.0.1817</Version>
<Company>Canary Islands Computer Museum</Company> <Company>Canary Islands Computer Museum</Company>
<Copyright>Copyright © 2003-2020 Natalia Portillo</Copyright> <Copyright>Copyright © 2003-2020 Natalia Portillo</Copyright>
<Product>Canary Islands Computer Museum Website</Product> <Product>Canary Islands Computer Museum Website</Product>

View File

@@ -0,0 +1,319 @@
@{
/******************************************************************************
// MARECHAI: Master repository of computing history artifacts information
// ----------------------------------------------------------------------------
//
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2003-2020 Natalia Portillo
*******************************************************************************/
}
@page "/admin/software_variants/details/{Id:ulong}"
@page "/admin/software_variants/edit/{Id:ulong}"
@page "/admin/software_variants/create"
@using Marechai.Database
@using Marechai.Database.Models
@inherits OwningComponentBase<SoftwareVariantsService>
@inject IStringLocalizer<SoftwareVariantsService> L
@inject SoftwareVersionsService SoftwareVersionsService
@inject LicensesService LicensesService
@inject NavigationManager NavigationManager
@inject IWebHostEnvironment Host
@inject IJSRuntime JSRuntime
@inject Microsoft.AspNetCore.Identity.UserManager<ApplicationUser> UserManager
@inject AuthenticationStateProvider AuthenticationStateProvider
@attribute [Authorize(Roles = "UberAdmin, Admin")]
<h3>@L["Software variant details"]</h3>
<hr />
@if (!_loaded)
{
<p align="center">@L["Loading..."]</p>
return;
}
<div>
<Field>
<FieldLabel>@L["Software version"]</FieldLabel>
<Select Disabled="!_editing" TValue="ulong" @bind-SelectedValue="@_model.SoftwareVersionId">
@foreach (var version in _softwareVersions)
{
<SelectItem TValue="ulong" Value="@version.Id">@version.Name ?? @version.Version</SelectItem>
}
</Select>
</Field>
@if (_editing || _model.Name != null)
{
<Field>
<FieldLabel>@L["Name, if different from software version name"]</FieldLabel>
@if (_editing)
{
<Check TValue="bool" @bind-Checked="@_unknownName">@L["Unknown (name)"]</Check>
}
@if (!_editing ||
!_unknownName)
{
<Validation Validator="@ValidateName">
<TextEdit Disabled="!_editing" @bind-Text="@_model.Name">
<Feedback>
<ValidationError>@L["Please enter a valid name."]</ValidationError>
</Feedback>
</TextEdit>
</Validation>
}
</Field>
}
@if (_editing || _model.Version != null)
{
<Field>
<FieldLabel>@L["Version, if different from software version's"]</FieldLabel>
@if (_editing)
{
<Check TValue="bool" @bind-Checked="@_unknownVersion">@L["Unknown (version)"]</Check>
}
@if (!_editing ||
!_unknownVersion)
{
<Validation Validator="@ValidateVersion">
<TextEdit Disabled="!_editing" @bind-Text="@_model.Version">
<Feedback>
<ValidationError>@L["Please enter a valid version."]</ValidationError>
</Feedback>
</TextEdit>
</Validation>
}
</Field>
}
@if (_editing || _model.Introduced != null)
{
<Field>
<FieldLabel>@L["Introduced"]</FieldLabel>
@if (_editing)
{
<Check TValue="bool" @bind-Checked="@_unknownIntroduced">@L["Unknown (introduction date)"]</Check>
}
@if (!_editing || !_unknownIntroduced)
{
<Validation Validator="@ValidateIntroduced">
<DateEdit TValue="DateTime?" ReadOnly="!_editing" @bind-Date="@_model.Introduced" >
<Feedback>
<ValidationError>@L["Please enter a valid introduction date."]</ValidationError>
</Feedback>
</DateEdit>
</Validation>
}
</Field>
}
@if (_editing || _model.ParentId != null)
{
<Field>
<FieldLabel>@L["Parent"]</FieldLabel>
@if (_editing)
{
<Check TValue="bool" @bind-Checked="@_unknownParent">@L["Unknown or none (parent variant)"]</Check>
}
@if (!_editing ||
!_unknownParent)
{
<Select Disabled="!_editing" TValue="ulong?" @bind-SelectedValue="@_model.ParentId">
@foreach (var variant in _softwareVariants)
{
<SelectItem TValue="ulong?" Value="@variant.Id">@variant.Name ?? @variant.Version</SelectItem>
}
</Select>
}
</Field>
}
@if (_editing || _model.MinimumMemory.HasValue)
{
<Field>
<FieldLabel>@L["Minimum memory (bytes)"]</FieldLabel>
@if (_editing)
{
<Check TValue="bool" @bind-Checked="@_unknownMinimumMemory">@L["Unknown (minimum memory)"]</Check>
}
@if (!_editing ||
!_unknownMinimumMemory)
{
<Validation Validator="@ValidateUnsignedLongBiggerThanZero">
<NumericEdit Disabled="!_editing" TValue="ulong?" Decimals="0" @bind-Value="@_model.MinimumMemory">
<Feedback>
<ValidationError>@L["Please enter the minimum memory size in bytes."]</ValidationError>
</Feedback>
</NumericEdit>
</Validation>
}
</Field>
}
@if (_editing || _model.RecommendedMemory.HasValue)
{
<Field>
<FieldLabel>@L["Recommended memory (bytes)"]</FieldLabel>
@if (_editing)
{
<Check TValue="bool" @bind-Checked="@_unknownRecommendedMemory">@L["Unknown (recommended memory)"]</Check>
}
@if (!_editing ||
!_unknownRecommendedMemory)
{
<Validation Validator="@ValidateUnsignedLongBiggerThanZero">
<NumericEdit Disabled="!_editing" TValue="ulong?" Decimals="0" @bind-Value="@_model.RecommendedMemory">
<Feedback>
<ValidationError>@L["Please enter the recommended memory size in bytes."]</ValidationError>
</Feedback>
</NumericEdit>
</Validation>
}
</Field>
}
@if (_editing || _model.RequiredStorage.HasValue)
{
<Field>
<FieldLabel>@L["Required storage (bytes)"]</FieldLabel>
@if (_editing)
{
<Check TValue="bool" @bind-Checked="@_unknownRequiredStorage">@L["Unknown (required storage)"]</Check>
}
@if (!_editing ||
!_unknownRequiredStorage)
{
<Validation Validator="@ValidateUnsignedLongBiggerThanZero">
<NumericEdit Disabled="!_editing" TValue="ulong?" Decimals="0" @bind-Value="@_model.RequiredStorage">
<Feedback>
<ValidationError>@L["Please enter the required storage size in bytes."]</ValidationError>
</Feedback>
</NumericEdit>
</Validation>
}
</Field>
}
@if (_editing || _model.PartNumber != null)
{
<Field>
<FieldLabel>@L["Part number"]</FieldLabel>
@if (_editing)
{
<Check TValue="bool" @bind-Checked="@_unknownPartNumber">@L["Unknown (part number)"]</Check>
}
@if (!_editing ||
!_unknownPartNumber)
{
<Validation Validator="@ValidatePartNumber">
<TextEdit Disabled="!_editing" @bind-Text="@_model.PartNumber">
<Feedback>
<ValidationError>@L["Please enter a valid part number."]</ValidationError>
</Feedback>
</TextEdit>
</Validation>
}
</Field>
}
@if (_editing || _model.SerialNumber != null)
{
<Field>
<FieldLabel>@L["Serial number"]</FieldLabel>
@if (_editing)
{
<Check TValue="bool" @bind-Checked="@_unknownSerialNumber">@L["Unknown (serial number)"]</Check>
}
@if(_editing)
{
@L["Serial number is NOT the serial number used to install the software, but a serial number some software manufacturers use as SKU."]
}
@if (!_editing ||
!_unknownSerialNumber)
{
<Validation Validator="@ValidateSerialNumber">
<TextEdit Disabled="!_editing" @bind-Text="@_model.SerialNumber">
<Feedback>
<ValidationError>@L["Please enter a valid serial number."]</ValidationError>
</Feedback>
</TextEdit>
</Validation>
}
</Field>
}
@if (_editing || _model.ProductCode != null)
{
<Field>
<FieldLabel>@L["Product code"]</FieldLabel>
@if (_editing)
{
<Check TValue="bool" @bind-Checked="@_unknownProductCode">@L["Unknown (product code)"]</Check>
}
@if (!_editing ||
!_unknownProductCode)
{
<Validation Validator="@ValidateProductCode">
<TextEdit Disabled="!_editing" @bind-Text="@_model.ProductCode">
<Feedback>
<ValidationError>@L["Please enter a valid product code."]</ValidationError>
</Feedback>
</TextEdit>
</Validation>
}
</Field>
}
@if (_editing || _model.CatalogueNumber != null)
{
<Field>
<FieldLabel>@L["Catalogue number"]</FieldLabel>
@if (_editing)
{
<Check TValue="bool" @bind-Checked="@_unknownCatalogueNumber">@L["Unknown (catalogue number)"]</Check>
}
@if (!_editing ||
!_unknownCatalogueNumber)
{
<Validation Validator="@ValidateCatalogueNumber">
<TextEdit Disabled="!_editing" @bind-Text="@_model.CatalogueNumber">
<Feedback>
<ValidationError>@L["Please enter a valid catalogue number."]</ValidationError>
</Feedback>
</TextEdit>
</Validation>
}
</Field>
}
<Field>
<FieldLabel>@L["Distribution mode"]</FieldLabel>
<Select Disabled="!_editing" TValue="uint" @bind-SelectedValue="@Distribution">
@foreach (uint mode in Enum.GetValues(typeof(DistributionMode)))
{
<SelectItem TValue="uint" Value="@mode">@(((DistributionMode)mode).ToString())</SelectItem>
}
</Select>
</Field>
</div>
<div>
@if (!_editing)
{
<Button Color="Color.Primary" Clicked="@OnEditClicked">@L["Edit"]</Button>
}
else
{
<Button Color="Color.Success" Clicked="@OnSaveClicked">@L["Save"]</Button>
<Button Color="Color.Danger" Clicked="@OnCancelClicked">@L["Cancel"]</Button>
}
<a href="/admin/software_variants" class="btn btn-secondary">@L["Back to list"]</a>
</div>

View File

@@ -0,0 +1,213 @@
/******************************************************************************
// MARECHAI: Master repository of computing history artifacts information
// ----------------------------------------------------------------------------
//
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2003-2020 Natalia Portillo
*******************************************************************************/
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Blazorise;
using Marechai.Database;
using Marechai.Shared;
using Marechai.ViewModels;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization;
namespace Marechai.Pages.Admin.Details
{
public partial class SoftwareVariant
{
AuthenticationState _authState;
bool _creating;
bool _editing;
bool _loaded;
SoftwareVariantViewModel _model;
List<SoftwareVariantViewModel> _softwareVariants;
List<SoftwareVersionViewModel> _softwareVersions;
bool _unknownCatalogueNumber;
bool _unknownIntroduced;
bool _unknownMinimumMemory;
bool _unknownName;
bool _unknownParent;
bool _unknownPartNumber;
bool _unknownProductCode;
bool _unknownRecommendedMemory;
bool _unknownRequiredStorage;
bool _unknownSerialNumber;
bool _unknownVersion;
[Parameter]
public ulong Id { get; set; }
uint Distribution
{
get => (uint)_model.DistributionMode;
set => _model.DistributionMode = (DistributionMode)value;
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if(_loaded)
return;
_loaded = true;
_creating = NavigationManager.ToBaseRelativePath(NavigationManager.Uri).ToLowerInvariant().
StartsWith("admin/software_variants/create",
StringComparison.InvariantCulture);
if(Id <= 0 &&
!_creating)
return;
_softwareVariants = await Service.GetAsync();
_softwareVersions = await SoftwareVersionsService.GetAsync();
_model = _creating ? new SoftwareVariantViewModel() : await Service.GetAsync(Id);
_authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
_editing = _creating || NavigationManager.ToBaseRelativePath(NavigationManager.Uri).ToLowerInvariant().
StartsWith("admin/software_variants/edit/",
StringComparison.InvariantCulture);
if(_editing)
SetCheckboxes();
StateHasChanged();
}
void SetCheckboxes()
{
_unknownName = string.IsNullOrWhiteSpace(_model.Name);
_unknownVersion = string.IsNullOrWhiteSpace(_model.Version);
_unknownParent = !_model.ParentId.HasValue;
_unknownMinimumMemory = !_model.MinimumMemory.HasValue;
_unknownRecommendedMemory = !_model.RecommendedMemory.HasValue;
_unknownRequiredStorage = !_model.RequiredStorage.HasValue;
_unknownPartNumber = string.IsNullOrWhiteSpace(_model.PartNumber);
_unknownSerialNumber = string.IsNullOrWhiteSpace(_model.SerialNumber);
_unknownProductCode = string.IsNullOrWhiteSpace(_model.ProductCode);
_unknownCatalogueNumber = string.IsNullOrWhiteSpace(_model.CatalogueNumber);
_unknownIntroduced = !_model.Introduced.HasValue;
}
void OnEditClicked()
{
_editing = true;
SetCheckboxes();
StateHasChanged();
}
async void OnCancelClicked()
{
_editing = false;
if(_creating)
{
NavigationManager.ToBaseRelativePath("admin/software_variants");
return;
}
_model = await Service.GetAsync(Id);
SetCheckboxes();
StateHasChanged();
}
async void OnSaveClicked()
{
if(_unknownName)
_model.Name = null;
else if(string.IsNullOrWhiteSpace(_model.Name))
return;
if(_unknownVersion)
_model.Version = null;
else if(string.IsNullOrWhiteSpace(_model.Version))
return;
if(_unknownPartNumber)
_model.PartNumber = null;
else if(string.IsNullOrWhiteSpace(_model.PartNumber))
return;
if(_unknownSerialNumber)
_model.SerialNumber = null;
else if(string.IsNullOrWhiteSpace(_model.SerialNumber))
return;
if(_unknownProductCode)
_model.ProductCode = null;
else if(string.IsNullOrWhiteSpace(_model.ProductCode))
return;
if(_unknownCatalogueNumber)
_model.CatalogueNumber = null;
else if(string.IsNullOrWhiteSpace(_model.CatalogueNumber))
return;
if(_unknownParent)
_model.ParentId = null;
else if(_model.ParentId < 1)
return;
if(_unknownIntroduced)
_model.Introduced = null;
else if(_model.Introduced?.Date >= DateTime.UtcNow.Date)
return;
if(_creating)
Id = await Service.CreateAsync(_model, (await UserManager.GetUserAsync(_authState.User)).Id);
else
await Service.UpdateAsync(_model, (await UserManager.GetUserAsync(_authState.User)).Id);
_editing = false;
_creating = false;
_model = await Service.GetAsync(Id);
SetCheckboxes();
StateHasChanged();
}
void ValidateName(ValidatorEventArgs e) =>
Validators.ValidateString(e, L["Name must be smaller than 256 characters."], 256);
void ValidateVersion(ValidatorEventArgs e) =>
Validators.ValidateString(e, L["Version must be smaller than 256 characters."], 256);
void ValidatePartNumber(ValidatorEventArgs e) =>
Validators.ValidateString(e, L["Part number must be smaller than 256 characters."], 256);
void ValidateSerialNumber(ValidatorEventArgs e) =>
Validators.ValidateString(e, L["Serial number must be smaller than 256 characters."], 256);
void ValidateProductCode(ValidatorEventArgs e) =>
Validators.ValidateString(e, L["Product number must be smaller than 256 characters."], 256);
void ValidateCatalogueNumber(ValidatorEventArgs e) =>
Validators.ValidateString(e, L["Catalogue number must be smaller than 256 characters."], 256);
void ValidateIntroduced(ValidatorEventArgs e) => Validators.ValidateDate(e);
void ValidateUnsignedLongBiggerThanZero(ValidatorEventArgs e) => Validators.ValidateUnsignedLong(e);
}
}

View File

@@ -137,5 +137,8 @@
<li> <li>
<a href="/admin/software_versions">@L["Software versions"]</a> <a href="/admin/software_versions">@L["Software versions"]</a>
</li> </li>
<li>
<a href="/admin/software_variants">@L["Software variants"]</a>
</li>
</ul> </ul>
</div> </div>

View File

@@ -0,0 +1,110 @@
@{
/******************************************************************************
// MARECHAI: Master repository of computing history artifacts information
// ----------------------------------------------------------------------------
//
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2003-2020 Natalia Portillo
*******************************************************************************/
}
@page "/admin/software_variants"
@using Marechai.Database.Models
@inherits OwningComponentBase<SoftwareVariantsService>
@inject IStringLocalizer<SoftwareVariantsService> L
@inject Microsoft.AspNetCore.Identity.UserManager<ApplicationUser> UserManager
@inject AuthenticationStateProvider AuthenticationStateProvider
@attribute [Authorize(Roles = "UberAdmin, Admin")]
<h3>@L["Software variants"]</h3>
@if (_softwareVariants is null)
{
<p>@L["Loading..."]</p>
return;
}
<p>
<a class="btn btn-primary" href="/admin/software_variants/create">@L["Create new"]</a>
</p>
<table class="table table-striped">
<thead>
<tr>
<th>
@L["Family"]
</th>
<th>
@L["Software version"]
</th>
<th>
@L["Name"]
</th>
<th>
@L["Version"]
</th>
<th>
@L["Introduced"]
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in _softwareVariants)
{
<tr>
<td>
@item.Family
</td>
<td>
@item.SoftwareVersion
</td>
<td>
@item.Name
</td>
<td>
@item.Version
</td>
<td>
@($"{item.Introduced:d}")
</td>
<td>
<a class="btn btn-primary" href="/admin/software_variants/details/@item.Id">@L["Details"]</a>
<a class="btn btn-secondary" href="/admin/software_variants/edit/@item.Id">@L["Edit"]</a>
<Button Color="Color.Danger" Clicked="() => {ShowModal(item.Id);}">@L["Delete"]</Button>
</td>
</tr>
}
</tbody>
</table>
<Modal @ref="_frmDelete" IsCentered="true" Closing="@ModalClosing">
<ModalBackdrop/>
<ModalContent Centered="true">
<ModalHeader>
<ModalTitle>@L["Delete software variant"]</ModalTitle>
<CloseButton Clicked="@HideModal"/>
</ModalHeader>
<ModalBody>
<Text>@string.Format(@L["Are you sure you want to delete the software variant {0}?"], _currentSoftwareVariant?.Name ?? _currentSoftwareVariant?.Version)</Text>
</ModalBody>
<ModalFooter>
<Button Color="Color.Primary" Clicked="@HideModal" Disabled="@_deleteInProgress">@L["Cancel"]</Button>
<Button Color="Color.Danger" Clicked="@ConfirmDelete" Disabled="@_deleteInProgress">@L["Delete"]</Button>
</ModalFooter>
</ModalContent>
</Modal>

View File

@@ -0,0 +1,88 @@
/******************************************************************************
// MARECHAI: Master repository of computing history artifacts information
// ----------------------------------------------------------------------------
//
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2003-2020 Natalia Portillo
*******************************************************************************/
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Blazorise;
using Marechai.ViewModels;
using Microsoft.AspNetCore.Components.Authorization;
namespace Marechai.Pages.Admin
{
public partial class SoftwareVariants
{
SoftwareVariantViewModel _currentSoftwareVariant;
bool _deleteInProgress;
Modal _frmDelete;
bool _loaded;
List<SoftwareVariantViewModel> _softwareVariants;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if(_loaded)
return;
_softwareVariants = await Service.GetAsync();
_loaded = true;
StateHasChanged();
}
void ShowModal(ulong itemId)
{
_currentSoftwareVariant = _softwareVariants.FirstOrDefault(n => n.Id == itemId);
_frmDelete.Show();
}
void HideModal() => _frmDelete.Hide();
async void ConfirmDelete()
{
if(_currentSoftwareVariant is null)
return;
_deleteInProgress = true;
_softwareVariants = null;
AuthenticationState authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
// Yield thread to let UI to update
await Task.Yield();
await Service.DeleteAsync(_currentSoftwareVariant.Id, (await UserManager.GetUserAsync(authState.User)).Id);
_softwareVariants = await Service.GetAsync();
_deleteInProgress = false;
_frmDelete.Hide();
// Yield thread to let UI to update
await Task.Yield();
// Tell we finished loading
StateHasChanged();
}
void ModalClosing(ModalClosingEventArgs obj) => _currentSoftwareVariant = null;
}
}

View File

@@ -47,4 +47,7 @@
<data name="Software versions" xml:space="preserve"> <data name="Software versions" xml:space="preserve">
<value>Software versions</value> <value>Software versions</value>
</data> </data>
<data name="Software variants" xml:space="preserve">
<value>Software variants</value>
</data>
</root> </root>

View File

@@ -246,4 +246,7 @@
<data name="Software versions" xml:space="preserve"> <data name="Software versions" xml:space="preserve">
<value>Versiones de software</value> <value>Versiones de software</value>
</data> </data>
<data name="Software variants" xml:space="preserve">
<value>Variantes de software</value>
</data>
</root> </root>

View File

@@ -0,0 +1,182 @@
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Catalogue number must be smaller than 256 characters." xml:space="preserve">
<value>Catalogue number must be smaller than 256 characters.</value>
</data>
<data name="Product code must be smaller than 256 characters." xml:space="preserve">
<value>Product code must be smaller than 256 characters.</value>
</data>
<data name="Serial number must be smaller than 256 characters." xml:space="preserve">
<value>Serial number must be smaller than 256 characters.</value>
</data>
<data name="Part number must be smaller than 256 characters." xml:space="preserve">
<value>Part number must be smaller than 256 characters.</value>
</data>
<data name="Version must be smaller than 256 characters." xml:space="preserve">
<value>Version must be smaller than 256 characters.</value>
</data>
<data name="Name must be smaller than 256 characters." xml:space="preserve">
<value>Name must be smaller than 256 characters.</value>
</data>
<data name="Back to list" xml:space="preserve">
<value>Back to list</value>
</data>
<data name="Cancel" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="Save" xml:space="preserve">
<value>Save</value>
</data>
<data name="Edit" xml:space="preserve">
<value>Edit</value>
</data>
<data name="Distribution mode" xml:space="preserve">
<value>Distribution mode</value>
</data>
<data name="Please enter a valid catalogue number." xml:space="preserve">
<value>Please enter a valid catalogue number.</value>
</data>
<data name="Unknown (catalogue number)" xml:space="preserve">
<value>Unknown</value>
</data>
<data name="Catalogue number" xml:space="preserve">
<value>Catalogue number</value>
</data>
<data name="Please enter a valid product code." xml:space="preserve">
<value>Please enter a valid product code.</value>
</data>
<data name="Unknown (product code)" xml:space="preserve">
<value>Unknown</value>
</data>
<data name="Product code" xml:space="preserve">
<value>Product code</value>
</data>
<data name="Please enter a valid serial number." xml:space="preserve">
<value>Please enter a valid serial number.</value>
</data>
<data name="Serial number is NOT the serial number used to install the software, but a serial number some software manufacturers use as SKU." xml:space="preserve">
<value>Serial number is NOT the serial number used to install the software, but a serial number some software manufacturers use as SKU.</value>
</data>
<data name="Unknown (serial number)" xml:space="preserve">
<value>Unknown</value>
</data>
<data name="Serial number" xml:space="preserve">
<value>Serial number</value>
</data>
<data name="Please enter a valid part number." xml:space="preserve">
<value>Please enter a valid part number.</value>
</data>
<data name="Unknown (part number)" xml:space="preserve">
<value>Unknown</value>
</data>
<data name="Part number" xml:space="preserve">
<value>Part number</value>
</data>
<data name="Please enter the required storage size in bytes." xml:space="preserve">
<value>Please enter the required storage size in bytes.</value>
</data>
<data name="Unknown (required storage)" xml:space="preserve">
<value>Unknown</value>
</data>
<data name="Required storage (bytes)" xml:space="preserve">
<value>Required storage (bytes)</value>
</data>
<data name="Please enter the recommended memory size in bytes." xml:space="preserve">
<value>Please enter the recommended memory size in bytes.</value>
</data>
<data name="Unknown (recommended memory)" xml:space="preserve">
<value>Unknown</value>
</data>
<data name="Recommended memory (bytes)" xml:space="preserve">
<value>Recommended memory (bytes)</value>
</data>
<data name="Please enter the minimum memory size in bytes." xml:space="preserve">
<value>Please enter the minimum memory size in bytes.</value>
</data>
<data name="Unknown (minimum memory)" xml:space="preserve">
<value>Unknown</value>
</data>
<data name="Minimum memory (bytes)" xml:space="preserve">
<value>Minimum memory (bytes)</value>
</data>
<data name="Unknown or none (parent variant)" xml:space="preserve">
<value>Unknown or none</value>
</data>
<data name="Parent" xml:space="preserve">
<value>Parent</value>
</data>
<data name="Please enter a valid introduction date." xml:space="preserve">
<value>Please enter a valid introduction date.</value>
</data>
<data name="Unknown (introduction date)" xml:space="preserve">
<value>Unknown</value>
</data>
<data name="Introduced" xml:space="preserve">
<value>Introduced</value>
</data>
<data name="Please enter a valid version." xml:space="preserve">
<value>Please enter a valid version.</value>
</data>
<data name="Unknown (version)" xml:space="preserve">
<value>Unknown</value>
</data>
<data name="Version, if different from software version's" xml:space="preserve">
<value>Version, if different from software version's</value>
</data>
<data name="Please enter a valid name." xml:space="preserve">
<value>Please enter a valid name.</value>
</data>
<data name="Unknown (name)" xml:space="preserve">
<value>Unknown</value>
</data>
<data name="Name, if different from software version name" xml:space="preserve">
<value>Name, if different from software version name</value>
</data>
<data name="Software version" xml:space="preserve">
<value>Software version</value>
</data>
<data name="Software variant details" xml:space="preserve">
<value>Software variant details</value>
</data>
<data name="Are you sure you want to delete the software variant {0}?" xml:space="preserve">
<value>Are you sure you want to delete the software variant {0}?</value>
</data>
<data name="Delete software variant" xml:space="preserve">
<value>Delete software variant</value>
</data>
<data name="Delete" xml:space="preserve">
<value>Delete</value>
</data>
<data name="Details" xml:space="preserve">
<value>Details</value>
</data>
<data name="Version" xml:space="preserve">
<value>Version</value>
</data>
<data name="Name" xml:space="preserve">
<value>Name</value>
</data>
<data name="Family" xml:space="preserve">
<value>Family</value>
</data>
<data name="Create new" xml:space="preserve">
<value>Create new</value>
</data>
<data name="Loading..." xml:space="preserve">
<value>Loading...</value>
</data>
<data name="Software variants" xml:space="preserve">
<value>Software variants</value>
</data>
</root>

View File

@@ -0,0 +1,289 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- ReSharper disable MarkupTextTypo -->
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Catalogue number must be smaller than 256 characters." xml:space="preserve">
<value>El número de catálogo debe contener menos de 256 caracteres.</value>
</data>
<data name="Product code must be smaller than 256 characters." xml:space="preserve">
<value>El código de producto debe contener menos de 256 caracteres.</value>
</data>
<data name="Serial number must be smaller than 256 characters." xml:space="preserve">
<value>El número de serie debe contener menos de 256 caracteres.</value>
</data>
<data name="Part number must be smaller than 256 characters." xml:space="preserve">
<value>El número de pieza debe contener menos de 256 caracteres.</value>
</data>
<data name="Version must be smaller than 256 characters." xml:space="preserve">
<value>La versión debe contener menos de 256 caracteres.</value>
</data>
<data name="Name must be smaller than 256 characters." xml:space="preserve">
<value>El nombre debe contener menos de 256 caracteres.</value>
</data>
<data name="Back to list" xml:space="preserve">
<value>Volver a la lista</value>
</data>
<data name="Cancel" xml:space="preserve">
<value>Cancelar</value>
</data>
<data name="Save" xml:space="preserve">
<value>Guardar</value>
</data>
<data name="Edit" xml:space="preserve">
<value>Editar</value>
</data>
<data name="Distribution mode" xml:space="preserve">
<value>Modo de distribución</value>
</data>
<data name="Please enter a valid catalogue number." xml:space="preserve">
<value>Por favor introduce un número de catálogo válido.</value>
</data>
<data name="Unknown (catalogue number)" xml:space="preserve">
<value>Desconocido</value>
</data>
<data name="Catalogue number" xml:space="preserve">
<value>Número de catálogo</value>
</data>
<data name="Please enter a valid product code." xml:space="preserve">
<value>Por favor introduce un código de producto válido.</value>
</data>
<data name="Unknown (product code)" xml:space="preserve">
<value>Desconocido</value>
</data>
<data name="Product code" xml:space="preserve">
<value>Código de producto</value>
</data>
<data name="Please enter a valid serial number." xml:space="preserve">
<value>Por favor introduce un número de serie válido.</value>
</data>
<data name="Serial number is NOT the serial number used to install the software, but a serial number some software manufacturers use as SKU." xml:space="preserve">
<value>El número de serie NO ES el número de serie utilizado para instalar el software, sino un número de serie algunos fabricantes usan como inventario.</value>
</data>
<data name="Unknown (serial number)" xml:space="preserve">
<value>Desconocido</value>
</data>
<data name="Serial number" xml:space="preserve">
<value>Número de serie</value>
</data>
<data name="Please enter a valid part number." xml:space="preserve">
<value>Por favor introduce un número de pieza válido.</value>
</data>
<data name="Unknown (part number)" xml:space="preserve">
<value>Desconocido</value>
</data>
<data name="Part number" xml:space="preserve">
<value>Número de pieza</value>
</data>
<data name="Please enter the required storage size in bytes." xml:space="preserve">
<value>Por favor introduce el tamaño de almacenamiento requerido en bytes.</value>
</data>
<data name="Unknown (required storage)" xml:space="preserve">
<value>Desconocido</value>
</data>
<data name="Required storage (bytes)" xml:space="preserve">
<value>Tamaño de almacenamiento requerido (bytes)</value>
</data>
<data name="Please enter the recommended memory size in bytes." xml:space="preserve">
<value>Por favor introduce la memoria recomendada en bytes.</value>
</data>
<data name="Unknown (recommended memory)" xml:space="preserve">
<value>Desconocida</value>
</data>
<data name="Recommended memory (bytes)" xml:space="preserve">
<value>Memoria recomendada (bytes)</value>
</data>
<data name="Please enter the minimum memory size in bytes." xml:space="preserve">
<value>Por favor introduce la memoria mínima en bytes.</value>
</data>
<data name="Unknown (minimum memory)" xml:space="preserve">
<value>Desconocida</value>
</data>
<data name="Minimum memory (bytes)" xml:space="preserve">
<value>Memoria mínima (bytes)</value>
</data>
<data name="Unknown or none (parent variant)" xml:space="preserve">
<value>Desconocida o ninguna</value>
</data>
<data name="Parent" xml:space="preserve">
<value>Predecesora</value>
</data>
<data name="Please enter a valid introduction date." xml:space="preserve">
<value>Por favor introduce una fecha de introducción válida.</value>
</data>
<data name="Unknown (introduction date)" xml:space="preserve">
<value>Desconocida</value>
</data>
<data name="Introduced" xml:space="preserve">
<value>Introducida</value>
</data>
<data name="Please enter a valid version." xml:space="preserve">
<value>Por favor introduce una versión válida.</value>
</data>
<data name="Unknown (version)" xml:space="preserve">
<value>Desconocida</value>
</data>
<data name="Version, if different from software version's" xml:space="preserve">
<value>Versión, si es diferente de la versión de software</value>
</data>
<data name="Please enter a valid name." xml:space="preserve">
<value>Por favor introduce un nombre válido.</value>
</data>
<data name="Unknown (name)" xml:space="preserve">
<value>Desconocido</value>
</data>
<data name="Name, if different from software version name" xml:space="preserve">
<value>Nombre, si es diferente del nombre de la versión de software</value>
</data>
<data name="Software version" xml:space="preserve">
<value>Versión de software</value>
</data>
<data name="Software variant details" xml:space="preserve">
<value>Detalles de variante de software</value>
</data>
<data name="Are you sure you want to delete the software variant {0}?" xml:space="preserve">
<value>¿Estás seguro de eliminar la variante de software {0}?</value>
</data>
<data name="Delete software variant" xml:space="preserve">
<value>Eliminar variante de software</value>
</data>
<data name="Delete" xml:space="preserve">
<value>Eliminar</value>
</data>
<data name="Details" xml:space="preserve">
<value>Detalles</value>
</data>
<data name="Version" xml:space="preserve">
<value>Versión</value>
</data>
<data name="Name" xml:space="preserve">
<value>Nombre</value>
</data>
<data name="Family" xml:space="preserve">
<value>Familia</value>
</data>
<data name="Create new" xml:space="preserve">
<value>Crear nueva</value>
</data>
<data name="Loading..." xml:space="preserve">
<value>Cargando...</value>
</data>
<data name="Software variants" xml:space="preserve">
<value>Variantes de software</value>
</data>
</root>

View File

@@ -78,6 +78,7 @@ namespace Marechai.Services
services.AddScoped<MagazineIssuesService>(); services.AddScoped<MagazineIssuesService>();
services.AddScoped<SoftwareFamiliesService>(); services.AddScoped<SoftwareFamiliesService>();
services.AddScoped<SoftwareVersionsService>(); services.AddScoped<SoftwareVersionsService>();
services.AddScoped<SoftwareVariantsService>();
} }
} }
} }

View File

@@ -0,0 +1,156 @@
/******************************************************************************
// MARECHAI: Master repository of computing history artifacts information
// ----------------------------------------------------------------------------
//
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2003-2020 Natalia Portillo
*******************************************************************************/
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Marechai.Database.Models;
using Marechai.ViewModels;
using Microsoft.EntityFrameworkCore;
namespace Marechai.Services
{
public class SoftwareVariantsService
{
readonly MarechaiContext _context;
public SoftwareVariantsService(MarechaiContext context) => _context = context;
public async Task<List<SoftwareVariantViewModel>> GetAsync() => await _context.
SoftwareVariants.
OrderBy(b => b.SoftwareVersion.Family.
Name).
ThenBy(b => b.SoftwareVersion.Version).
ThenBy(b => b.Name).
ThenBy(b => b.Version).
ThenBy(b => b.Introduced).
Select(b => new SoftwareVariantViewModel
{
Id = b.Id,
Name = b.Name,
Version = b.Version,
Introduced = b.Introduced,
ParentId = b.ParentId,
Parent =
b.Parent.Name ?? b.Parent.Version,
SoftwareVersionId =
b.SoftwareVersionId,
SoftwareVersion =
b.SoftwareVersion.Name ??
b.SoftwareVersion.Version,
MinimumMemory = b.MinimumMemory,
RecommendedMemory =
b.RecommendedMemory,
RequiredStorage = b.RequiredStorage,
PartNumber = b.PartNumber,
SerialNumber = b.SerialNumber,
ProductCode = b.ProductCode,
CatalogueNumber = b.CatalogueNumber,
DistributionMode = b.DistributionMode
}).ToListAsync();
public async Task<SoftwareVariantViewModel> GetAsync(ulong id) =>
await _context.SoftwareVariants.Where(b => b.Id == id).Select(b => new SoftwareVariantViewModel
{
Id = b.Id,
Name = b.Name,
Version = b.Version,
Introduced = b.Introduced,
ParentId = b.ParentId,
Parent = b.Parent.Name ?? b.Parent.Version,
SoftwareVersionId = b.SoftwareVersionId,
SoftwareVersion = b.SoftwareVersion.Name ?? b.SoftwareVersion.Version,
MinimumMemory = b.MinimumMemory,
RecommendedMemory = b.RecommendedMemory,
RequiredStorage = b.RequiredStorage,
PartNumber = b.PartNumber,
SerialNumber = b.SerialNumber,
ProductCode = b.ProductCode,
CatalogueNumber = b.CatalogueNumber,
DistributionMode = b.DistributionMode
}).FirstOrDefaultAsync();
public async Task UpdateAsync(SoftwareVariantViewModel viewModel, string userId)
{
SoftwareVariant model = await _context.SoftwareVariants.FindAsync(viewModel.Id);
if(model is null)
return;
model.Name = viewModel.Name;
model.Version = viewModel.Version;
model.Introduced = viewModel.Introduced;
model.ParentId = viewModel.ParentId;
model.SoftwareVersionId = viewModel.SoftwareVersionId;
model.MinimumMemory = viewModel.MinimumMemory;
model.RecommendedMemory = viewModel.RecommendedMemory;
model.RequiredStorage = viewModel.RequiredStorage;
model.PartNumber = viewModel.PartNumber;
model.SerialNumber = viewModel.SerialNumber;
model.ProductCode = viewModel.ProductCode;
model.CatalogueNumber = viewModel.CatalogueNumber;
model.DistributionMode = viewModel.DistributionMode;
await _context.SaveChangesWithUserAsync(userId);
}
public async Task<ulong> CreateAsync(SoftwareVariantViewModel viewModel, string userId)
{
var model = new SoftwareVariant
{
Name = viewModel.Name,
Version = viewModel.Version,
Introduced = viewModel.Introduced,
ParentId = viewModel.ParentId,
SoftwareVersionId = viewModel.SoftwareVersionId,
MinimumMemory = viewModel.MinimumMemory,
RecommendedMemory = viewModel.RecommendedMemory,
RequiredStorage = viewModel.RequiredStorage,
PartNumber = viewModel.PartNumber,
SerialNumber = viewModel.SerialNumber,
ProductCode = viewModel.ProductCode,
CatalogueNumber = viewModel.CatalogueNumber,
DistributionMode = viewModel.DistributionMode
};
await _context.SoftwareVariants.AddAsync(model);
await _context.SaveChangesWithUserAsync(userId);
return model.Id;
}
public async Task DeleteAsync(ulong id, string userId)
{
SoftwareVariant item = await _context.SoftwareVariants.FindAsync(id);
if(item is null)
return;
_context.SoftwareVariants.Remove(item);
await _context.SaveChangesWithUserAsync(userId);
}
}
}

View File

@@ -249,5 +249,16 @@ namespace Marechai.Shared
else if(modulo == issn[7] - 0x30) else if(modulo == issn[7] - 0x30)
e.Status = ValidationStatus.Success; e.Status = ValidationStatus.Success;
} }
public static void ValidateUnsignedLong(ValidatorEventArgs e, ulong minValue = 0,
ulong maxValue = long.MaxValue)
{
if(!(e.Value is ulong item) ||
item < minValue ||
item > maxValue)
e.Status = ValidationStatus.Error;
else
e.Status = ValidationStatus.Success;
}
} }
} }

View File

@@ -0,0 +1,50 @@
/******************************************************************************
// MARECHAI: Master repository of computing history artifacts information
// ----------------------------------------------------------------------------
//
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2003-2020 Natalia Portillo
*******************************************************************************/
using System;
using Marechai.Database;
namespace Marechai.ViewModels
{
public class SoftwareVariantViewModel : BaseViewModel<ulong>
{
public string Name { get; set; }
public string Version { get; set; }
public DateTime? Introduced { get; set; }
public ulong? ParentId { get; set; }
public string Parent { get; set; }
public ulong SoftwareVersionId { get; set; }
public string SoftwareVersion { get; set; }
public ulong? MinimumMemory { get; set; }
public ulong? RecommendedMemory { get; set; }
public ulong? RequiredStorage { get; set; }
public string PartNumber { get; set; }
public string SerialNumber { get; set; }
public string ProductCode { get; set; }
public string CatalogueNumber { get; set; }
public DistributionMode DistributionMode { get; set; }
public string Family { get; set; }
}
}