Customizable FS network url

This commit is contained in:
Andre Beging
2022-05-31 12:25:11 +02:00
parent bba0a377b5
commit cd22c2f215
10 changed files with 388 additions and 24 deletions

View File

@@ -1,3 +1,5 @@
using FoodsharingSiegen.Contracts.Model;
namespace FoodsharingSiegen.Contracts.Entity namespace FoodsharingSiegen.Contracts.Entity
{ {
/// <summary> /// <summary>
@@ -118,6 +120,42 @@ namespace FoodsharingSiegen.Contracts.Entity
Ambassador = 400 Ambassador = 400
} }
/// <summary>
/// The fs network type enum
/// </summary>
public enum FsNetworkType
{
/// <summary>
/// The germany fs network type
/// </summary>
[CustomValue("https://foodsharing.de")]
Germany = 0,
/// <summary>
/// The germany beta fs network type
/// </summary>
[CustomValue("https://beta.foodsharing.de")]
GermanyBeta = 10,
/// <summary>
/// The austria fs network type
/// </summary>
[CustomValue("https://foodsharing.at")]
Austria = 20,
/// <summary>
/// The austria beta fs network type
/// </summary>
[CustomValue("https://beta.foodsharing.at")]
AustriaBeta = 30,
/// <summary>
/// The switzerland fs network type
/// </summary>
[CustomValue("https://foodsharing.network")]
Switzerland = 40
}
/// <summary> /// <summary>
/// The interaction type enum /// The interaction type enum
/// </summary> /// </summary>

View File

@@ -4,7 +4,6 @@ using FoodsharingSiegen.Contracts.Helper;
namespace FoodsharingSiegen.Contracts.Entity namespace FoodsharingSiegen.Contracts.Entity
{ {
/// <summary> /// <summary>
/// The user class (a. beging, 06.04.2022) /// The user class (a. beging, 06.04.2022)
/// </summary> /// </summary>
@@ -51,7 +50,8 @@ namespace FoodsharingSiegen.Contracts.Entity
/// <summary> /// <summary>
/// Gets or sets the value of the id (ab) /// Gets or sets the value of the id (ab)
/// </summary> /// </summary>
[Key] public Guid Id { get; set; } [Key]
public Guid Id { get; set; }
/// <summary> /// <summary>
/// Gets or sets the value of the interactions (ab) /// Gets or sets the value of the interactions (ab)
@@ -73,6 +73,17 @@ namespace FoodsharingSiegen.Contracts.Entity
/// </summary> /// </summary>
public string Name { get; set; } public string Name { get; set; }
/// <summary>
/// Gets or sets the value of the network (ab)
/// </summary>
public FsNetworkType Network { get; set; }
/// <summary>
/// Gets the value of the network link (ab)
/// </summary>
[NotMapped]
public string NetworkLink => Network.GetCustomValue();
/// <summary> /// <summary>
/// Gets or sets the value of the password (ab) /// Gets or sets the value of the password (ab)
/// </summary> /// </summary>
@@ -101,7 +112,7 @@ namespace FoodsharingSiegen.Contracts.Entity
/// Clones this instance (a. beging, 11.04.2022) /// Clones this instance (a. beging, 11.04.2022)
/// </summary> /// </summary>
/// <returns>The user</returns> /// <returns>The user</returns>
public User Clone() => (User) MemberwiseClone(); public User Clone() => (User)MemberwiseClone();
#endregion #endregion
} }

View File

@@ -0,0 +1,43 @@
using FoodsharingSiegen.Contracts.Model;
namespace FoodsharingSiegen.Contracts.Helper
{
/// <summary>
/// The attribute extensions class (a. beging, 31.05.2022)
/// </summary>
public static class AttributeExtensions
{
#region Public Method GetCustomValue
/// <summary>
/// Gets the custom value using the specified enum val (a. beging, 31.05.2022)
/// </summary>
/// <param name="enumVal">The enum val</param>
/// <returns>The string</returns>
public static string GetCustomValue(this Enum enumVal)
{
var attribute = enumVal.GetAttributeOfType<CustomValueAttribute>();
return attribute?.Value ?? string.Empty;
}
#endregion
#region Private Method GetAttributeOfType
/// <summary>
/// Gets the attribute of type using the specified enum val (a. beging, 31.05.2022)
/// </summary>
/// <typeparam name="T">The </typeparam>
/// <param name="enumVal">The enum val</param>
/// <returns>The</returns>
private static T? GetAttributeOfType<T>(this Enum enumVal) where T : Attribute
{
var type = enumVal.GetType();
var memInfo = type.GetMember(enumVal.ToString());
var attributes = memInfo[0].GetCustomAttributes(typeof(T), false);
return attributes.Length > 0 ? (T)attributes[0] : null;
}
#endregion
}
}

View File

@@ -0,0 +1,28 @@
namespace FoodsharingSiegen.Contracts.Model
{
/// <summary>
/// The custom value attribute class (a. beging, 31.05.2022)
/// </summary>
/// <seealso cref="Attribute" />
public sealed class CustomValueAttribute : Attribute
{
#region Public Properties
/// <summary>
/// Gets the value of the value (ab)
/// </summary>
public string Value { get; }
#endregion
#region Setup/Teardown
/// <summary>
/// Initializes a new instance of the <see cref="CustomValueAttribute" /> class
/// </summary>
/// <param name="value">The value (ab)</param>
public CustomValueAttribute(string value) => Value = value;
#endregion
}
}

View File

@@ -17,7 +17,7 @@
@Prospect.Name @Prospect.Name
<small style="font-size: .9rem; opacity: .7;"> <small style="font-size: .9rem; opacity: .7;">
<a class="invert" href="https://foodsharing.de/profile/@Prospect.FsId" target="_blank">Profil öffnen</a> <a class="invert" href="@(CurrentUser.NetworkLink)/profile/@Prospect.FsId" target="_blank">Profil öffnen</a>
</small> </small>
</h5> </h5>
<div>@Prospect.Memo</div> <div>@Prospect.Memo</div>

View File

@@ -138,6 +138,7 @@ namespace FoodsharingSiegen.Server.Data.Service
entityUser.Type = user.Type; entityUser.Type = user.Type;
entityUser.Verified = user.Verified; entityUser.Verified = user.Verified;
entityUser.Groups = user.Groups; entityUser.Groups = user.Groups;
entityUser.Network = user.Network;
if (!Context.HasChanges()) if (!Context.HasChanges())
return new OperationResult(new Exception("Nichts zum Speichern gefunden")); return new OperationResult(new Exception("Nichts zum Speichern gefunden"));

View File

@@ -0,0 +1,198 @@
// <auto-generated />
using System;
using FoodsharingSiegen.Server.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace FoodsharingSiegen.Server.Migrations
{
[DbContext(typeof(FsContext))]
[Migration("20220531100143_User-Network")]
partial class UserNetwork
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "6.0.1");
modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.Audit", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<DateTime>("Created")
.HasColumnType("TEXT");
b.Property<string>("Data1")
.HasColumnType("TEXT");
b.Property<string>("Data2")
.HasColumnType("TEXT");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.Property<Guid?>("UserID")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("UserID");
b.ToTable("Audits");
});
modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.Interaction", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<bool>("Alert")
.HasColumnType("INTEGER");
b.Property<DateTime>("Created")
.HasColumnType("TEXT");
b.Property<DateTime>("Date")
.HasColumnType("TEXT");
b.Property<string>("Info")
.HasColumnType("TEXT");
b.Property<bool>("NotNeeded")
.HasColumnType("INTEGER");
b.Property<Guid>("ProspectID")
.HasColumnType("TEXT");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.Property<Guid>("UserID")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("ProspectID");
b.HasIndex("UserID");
b.ToTable("Interactions");
});
modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.Prospect", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<DateTime>("Created")
.HasColumnType("TEXT");
b.Property<int>("FsId")
.HasColumnType("INTEGER");
b.Property<string>("Memo")
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Prospects");
});
modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.User", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<DateTime>("Created")
.HasColumnType("TEXT");
b.Property<string>("EncryptedPassword")
.IsRequired()
.HasColumnType("TEXT");
b.Property<bool>("ForceLogout")
.HasColumnType("INTEGER");
b.Property<string>("Groups")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Mail")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Memo")
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Network")
.HasColumnType("INTEGER");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.Property<bool>("Verified")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.ToTable("Users");
});
modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.Audit", b =>
{
b.HasOne("FoodsharingSiegen.Contracts.Entity.User", "User")
.WithMany()
.HasForeignKey("UserID");
b.Navigation("User");
});
modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.Interaction", b =>
{
b.HasOne("FoodsharingSiegen.Contracts.Entity.Prospect", "Prospect")
.WithMany("Interactions")
.HasForeignKey("ProspectID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("FoodsharingSiegen.Contracts.Entity.User", "User")
.WithMany("Interactions")
.HasForeignKey("UserID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Prospect");
b.Navigation("User");
});
modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.Prospect", b =>
{
b.Navigation("Interactions");
});
modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.User", b =>
{
b.Navigation("Interactions");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace FoodsharingSiegen.Server.Migrations
{
public partial class UserNetwork : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "Network",
table: "Users",
type: "INTEGER",
nullable: false,
defaultValue: 0);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Network",
table: "Users");
}
}
}

View File

@@ -139,6 +139,9 @@ namespace FoodsharingSiegen.Server.Migrations
.IsRequired() .IsRequired()
.HasColumnType("TEXT"); .HasColumnType("TEXT");
b.Property<int>("Network")
.HasColumnType("INTEGER");
b.Property<int>("Type") b.Property<int>("Type")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");

View File

@@ -2,6 +2,8 @@
@using FoodsharingSiegen.Server.Dialogs @using FoodsharingSiegen.Server.Dialogs
@using FoodsharingSiegen.Server.BaseClasses @using FoodsharingSiegen.Server.BaseClasses
@using FoodsharingSiegen.Contracts.Entity
@using FoodsharingSiegen.Contracts.Helper
@inherits FsBase @inherits FsBase
@@ -33,9 +35,23 @@
</Validations> </Validations>
</Fields> </Fields>
<hr /> <hr/>
<h3>Allgemeines</h3>
<p class="mt-4 mb-1">
Die ausgewählte URL wird zum Beispiel verwendet, um die Profile der Neulinge zu verlinken
<Select TValue="FsNetworkType" @bind-SelectedValue="User.Network">
@foreach (var networkType in Enum.GetValues<FsNetworkType>())
{
<SelectItem Value="networkType">@networkType (@networkType.GetCustomValue())</SelectItem>
}
</Select>
</p>
<hr/>
<h3>Sicherheit</h3> <h3>Sicherheit</h3>
<p class="mt-4 mb-1"> <p class="mt-4 mb-1">
Die Änderung deines Passworts ist sofort aktiv. Im Anschluss wirst du ausgeloggt und kannst dich neu einloggen. Die Änderung deines Passworts ist sofort aktiv. Im Anschluss wirst du ausgeloggt und kannst dich neu einloggen.
<Button Color="Color.Primary" Class="d-block" Clicked="() => PasswordModal?.Show(User)!"><i class="fa-solid fa-key"></i>&nbsp;Passwort ändern</Button> <Button Color="Color.Primary" Class="d-block" Clicked="() => PasswordModal?.Show(User)!"><i class="fa-solid fa-key"></i>&nbsp;Passwort ändern</Button>