Compare commits

..
4 changed files with 116 additions and 158 deletions

View file

@ -12,132 +12,118 @@
x:DataType="vm:BlogsViewModel" x:DataType="vm:BlogsViewModel"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"> VerticalAlignment="Stretch">
<Design.DataContext> <Design.DataContext>
<vm:BlogsViewModel /> <vm:BlogsViewModel />
</Design.DataContext> </Design.DataContext>
<Grid Margin="12" RowSpacing="12" <Grid Margin="12" RowSpacing="12"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"> VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<WrapPanel Grid.Row="0" HorizontalAlignment="Stretch">
<TextBlock Text="Blog Posts" FontSize="22" FontWeight="SemiBold" />
<TextBox Text="{Binding SearchText, Mode=TwoWay}" PlaceholderText="Filter by title or author..." />
<CommandBar IsDynamicOverflowEnabled="True">
<CommandBar.PrimaryCommands>
<CommandBarButton Label="Filter" Command="{Binding SearchAsync}">
<CommandBarButton.Icon>
<PathIcon Data="{StaticResource FilterIcon}" />
</CommandBarButton.Icon>
</CommandBarButton>
<CommandBarButton Label="Refresh" Command="{Binding RefreshAsync}">
<CommandBarButton.Icon>
<PathIcon Data="{StaticResource RefreshIcon}" />
</CommandBarButton.Icon>
</CommandBarButton>
<CommandBarButton Label="Save" Command="{Binding SaveAsync}">
<CommandBarButton.Icon>
<PathIcon Data="{StaticResource SaveIcon}" />
</CommandBarButton.Icon>
</CommandBarButton>
<CommandBarButton Label="Delete" Command="{Binding DeleteAsync}">
<CommandBarButton.Icon>
<PathIcon Data="{StaticResource DeleteIcon}" />
</CommandBarButton.Icon>
</CommandBarButton>
<CommandBarButton Label="Ajouter fichiers" Click="AddAttachment_Click"
x:Name="AddAttachmentButton">
<CommandBarButton.Icon>
<PathIcon Data="{StaticResource AddIcon}" />
</CommandBarButton.Icon>
</CommandBarButton>
<CommandBarButton x:Name="ManageAclButton"
Label="ACL" Command="{Binding ManageAclAsync}">
<CommandBarButton.Icon>
<PathIcon Data="{StaticResource AclIcon}" />
</CommandBarButton.Icon>
</CommandBarButton>
<CommandBarButton x:Name="OpenCirclesButton"
Label="Mes cercles" Command="{Binding OpenCirclesAsync}">
<CommandBarButton.Icon>
<PathIcon Data="{StaticResource CircleIcon}" />
</CommandBarButton.Icon>
</CommandBarButton>
<CommandBarToggleButton Label="Publié"
IsChecked="{Binding DraftIsPublished, Mode=TwoWay}">
<CommandBarToggleButton.Icon>
<PathIcon Data="{StaticResource PublishedIcon}" />
</CommandBarToggleButton.Icon>
</CommandBarToggleButton>
<CommandBarButton x:Name="OpenSignatureDevButton"
Label="[DEV] Signature" Command="{Binding OpenSignatureDevAsync}">
<CommandBarButton.Icon>
<PathIcon Data="{StaticResource SignIcon}" />
</CommandBarButton.Icon>
</CommandBarButton>
</CommandBar.PrimaryCommands>
</CommandBar>
</WrapPanel>
<Border Grid.Row="1" BorderBrush="Gray" BorderThickness="1" Padding="8">
<ListBox ItemsSource="{Binding FilteredPosts}" SelectedItem="{Binding SelectedPost, Mode=TwoWay}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MinHeight="40">
<ListBox.ItemTemplate>
<DataTemplate x:DataType="models:BlogPostDto">
<StackPanel Spacing="4">
<TextBlock Text="{Binding Title}" FontWeight="SemiBold" />
<TextBlock Text="{Binding DateModified, StringFormat='Updated: {0:yyyy-MM-dd HH:mm}'}" FontSize="10" Foreground="Gray" />
<TextBlock Text="{Binding AuthorId}" FontSize="10" Foreground="DarkSlateGray" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>
<Border Grid.Row="2" BorderBrush="Gray" BorderThickness="1" Padding="8">
<Grid RowSpacing="10"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="*" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Text="Post detail" FontWeight="SemiBold" /> <Border Grid.Row="0"
<TextBox Grid.Row="1" Text="{Binding DraftTitle, Mode=TwoWay}" PlaceholderText="Title" /> HorizontalAlignment="Stretch"
<TextBox Grid.Row="2" PlaceholderText="Write something here !" VerticalAlignment="Top"
Text="{Binding DraftArticle, Mode=TwoWay}" Padding="0">
MinHeight="320" <WrapPanel Orientation="Horizontal">
HorizontalAlignment="Stretch" <Button Command="{Binding RefreshAsync}" Content="🗘 Refresh" />
VerticalAlignment="Stretch" /> <Button Command="{Binding SearchAsync}" Content="🔍 Filter" />
<Button Command="{Binding SaveAsync}" Content="Save" />
<Border Grid.Row="3" BorderBrush="LightGray" BorderThickness="1" Padding="8"> <Button Command="{Binding DeleteAsync}" Content="Delete" />
<StackPanel Spacing="4"> <Button x:Name="AddAttachmentButton"
<TextBlock Text="Pièces jointes" FontWeight="SemiBold" /> Content="Ajouter fichiers"
<ItemsControl ItemsSource="{Binding DraftAttachments}"> Click="AddAttachment_Click" />
<ItemsControl.ItemTemplate> <Button x:Name="ManageAclButton"
<DataTemplate> Command="{Binding ManageAclAsync}"
<TextBlock Text="{Binding FileName}" /> Content="ACL" />
</DataTemplate> <Button x:Name="OpenCirclesButton"
</ItemsControl.ItemTemplate> Command="{Binding OpenCirclesAsync}"
</ItemsControl> Content="Mes cercles" />
</StackPanel> <!-- Publication toggle: a CheckBox wired to
DraftIsPublished. Clicking it fires
TogglePublishCommand, which pushes the
new state to /api/blog/{id}/publish.
The CheckBox is the canonical
AvaloniaXaml 'toggle' surface; binding
IsChecked TwoWay keeps the visual state
and the buffer in sync. -->
<CheckBox Content="Publié"
IsChecked="{Binding DraftIsPublished, Mode=TwoWay}"
Command="{Binding TogglePublishAsync}"
VerticalAlignment="Center"/>
<!--
DEV ONLY: temporary shortcut to open the signature
capture page. Production entry point is a SignalR
push from Yavsc.Org ("devis received, sign here").
Remove this button and its Click handler in
MainPage.axaml.cs once the SignalR handler lands.
-->
<Button x:Name="OpenSignatureDevButton"
Command="{Binding OpenSignatureDevAsync}"
Content="[DEV] Signature"
ToolTip.Tip="DEV ONLY — to remove when SignalR handler lands" />
</WrapPanel>
</Border> </Border>
<postitControls:StatusBar Grid.Row="4" <Border Grid.Row="1" BorderBrush="Gray" BorderThickness="1" Padding="8">
DataContext="{Binding ActionStatus}" /> <ListBox ItemsSource="{Binding FilteredPosts}" SelectedItem="{Binding SelectedPost, Mode=TwoWay}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MinHeight="40">
<ListBox.ItemTemplate>
<DataTemplate x:DataType="models:BlogPostDto">
<StackPanel Spacing="4">
<TextBlock Text="{Binding Title}" FontWeight="SemiBold" />
<TextBlock Text="{Binding DateModified, StringFormat='Updated: {0:yyyy-MM-dd HH:mm}'}" FontSize="10" Foreground="Gray" />
<TextBlock Text="{Binding AuthorId}" FontSize="10" Foreground="DarkSlateGray" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>
</Grid> <Border Grid.Row="2" BorderBrush="Gray" BorderThickness="1" Padding="8">
</Border> <Grid RowSpacing="10"
</Grid> HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Text="Post detail" FontWeight="SemiBold" />
<TextBox Grid.Row="1" Text="{Binding DraftTitle, Mode=TwoWay}" PlaceholderText="Title" />
<TextBox Grid.Row="2" PlaceholderText="Write something here !"
Text="{Binding DraftArticle, Mode=TwoWay}"
MinHeight="320"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
<Border Grid.Row="3" BorderBrush="LightGray" BorderThickness="1" Padding="8">
<StackPanel Spacing="4">
<TextBlock Text="Pièces jointes" FontWeight="SemiBold" />
<ItemsControl ItemsSource="{Binding DraftAttachments}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding FileName}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
<postitControls:StatusBar Grid.Row="4"
DataContext="{Binding ActionStatus}" />
</Grid>
</Border>
</Grid>
</ContentPage> </ContentPage>

View file

@ -1,22 +1,20 @@
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Yavsc.Models;
namespace Yavsc.Org.Tests.Mandatory namespace Yavsc.Org.Tests.Mandatory
{[Collection("Database")] {
[Collection("Database")]
[Trait("regression", "II")] [Trait("regression", "II")]
[Trait("dev", "wip")] [Trait("dev", "wip")]
public class Database: IClassFixture<WebServerFixture>, IDisposable public class Database: IClassFixture<WebServerFixture>, IDisposable
{ {
readonly ITestOutputHelper output;
readonly WebServerFixture _serverFixture; readonly WebServerFixture _serverFixture;
readonly ITestOutputHelper output;
public Database(ITestOutputHelper output, WebServerFixture _serverFixture) public Database(WebServerFixture serverFixture, ITestOutputHelper output)
{ {
this.output = output; this.output = output;
this._serverFixture = _serverFixture; _serverFixture = serverFixture;
} }
/// <summary> /// <summary>
@ -32,13 +30,5 @@ namespace Yavsc.Org.Tests.Mandatory
} }
} }
[Fact]
public void TestDatabaseMigration()
{
// Test logic goes here
_serverFixture.ResetAndMigrateDatabase();
}
} }
} }

View file

@ -189,20 +189,6 @@ public sealed class WebServerFixture : WebHostFixture
return app; return app;
} }
public void ResetAndMigrateDatabase()
{
using var scope = Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
db.Database.EnsureDeleted();
if (db.Database.IsRelational())
{
db.Database.Migrate();
return;
}
db.Database.EnsureCreated();
}
protected override async Task<WebApplication> ConfigurePipelineAsync(WebApplication app) protected override async Task<WebApplication> ConfigurePipelineAsync(WebApplication app)
{ {
// The MSBuild target CopyYavscOrgStaticAssets in // The MSBuild target CopyYavscOrgStaticAssets in

View file

@ -11,10 +11,6 @@ namespace Yavsc.Migrations
/// <inheritdoc /> /// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)
{ {
var declarationDateDefaultSql = ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite"
? "CURRENT_TIMESTAMP"
: "LOCALTIMESTAMP";
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "Activities", name: "Activities",
columns: table => new columns: table => new
@ -1488,7 +1484,7 @@ namespace Yavsc.Migrations
Platform = table.Column<string>(type: "text", nullable: true), Platform = table.Column<string>(type: "text", nullable: true),
Version = table.Column<string>(type: "text", nullable: true), Version = table.Column<string>(type: "text", nullable: true),
DeviceOwnerId = table.Column<string>(type: "text", nullable: true), DeviceOwnerId = table.Column<string>(type: "text", nullable: true),
DeclarationDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false, defaultValueSql: declarationDateDefaultSql), DeclarationDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false, defaultValueSql: "LOCALTIMESTAMP"),
LatestActivityUpdate = table.Column<DateTime>(type: "timestamp with time zone", nullable: true) LatestActivityUpdate = table.Column<DateTime>(type: "timestamp with time zone", nullable: true)
}, },
constraints: table => constraints: table =>