11using Definitions ;
2+ using Definitions . DTO ;
23using Definitions . ObjectModels ;
34using ReactiveUI ;
45using System ;
56using System . Collections . Generic ;
7+ using System . Collections . ObjectModel ;
68using System . Linq ;
9+ using System . Reactive ;
10+ using System . Threading . Tasks ;
711
812namespace Gui . ViewModels ;
913
1014public class ObjectMetadataViewModel : ReactiveObject
1115{
12- public ObjectMetadataViewModel ( ObjectMetadata metadata )
16+ readonly Gui . ObjectServiceClient ? objectServiceClient ;
17+
18+ public ObjectMetadataViewModel ( ObjectMetadata metadata , Gui . ObjectServiceClient ? objectServiceClient = null )
1319 {
1420 Metadata = metadata ;
1521 description = metadata . Description ;
16- availability = metadata . Availability ;
1722 createdDate = metadata . CreatedDate ;
1823 modifiedDate = metadata . ModifiedDate ;
24+ selectedLicence = metadata . Licence ;
25+
26+ // Initialize observable collections from metadata
27+ Authors = new ObservableCollection < DtoAuthorEntry > ( metadata . Authors ) ;
28+ Tags = new ObservableCollection < DtoTagEntry > ( metadata . Tags ) ;
29+ ObjectPacks = new ObservableCollection < DtoItemPackEntry > ( metadata . ObjectPacks ) ;
30+
31+ this . objectServiceClient = objectServiceClient ;
32+
33+ // Initialize commands
34+ AddAuthorCommand = ReactiveCommand . Create < DtoAuthorEntry ? > ( author =>
35+ {
36+ if ( author != null && ! Authors . Contains ( author ) )
37+ {
38+ Authors . Add ( author ) ;
39+ SyncAuthorsToMetadata ( ) ;
40+ }
41+ } ) ;
42+
43+ RemoveAuthorCommand = ReactiveCommand . Create < DtoAuthorEntry > ( author =>
44+ {
45+ Authors . Remove ( author ) ;
46+ SyncAuthorsToMetadata ( ) ;
47+ } ) ;
48+
49+ AddTagCommand = ReactiveCommand . Create < DtoTagEntry ? > ( tag =>
50+ {
51+ if ( tag != null && ! Tags . Contains ( tag ) )
52+ {
53+ Tags . Add ( tag ) ;
54+ SyncTagsToMetadata ( ) ;
55+ }
56+ } ) ;
57+
58+ RemoveTagCommand = ReactiveCommand . Create < DtoTagEntry > ( tag =>
59+ {
60+ Tags . Remove ( tag ) ;
61+ SyncTagsToMetadata ( ) ;
62+ } ) ;
63+
64+ AddObjectPackCommand = ReactiveCommand . Create < DtoItemPackEntry ? > ( pack =>
65+ {
66+ if ( pack != null && ! ObjectPacks . Contains ( pack ) )
67+ {
68+ ObjectPacks . Add ( pack ) ;
69+ SyncObjectPacksToMetadata ( ) ;
70+ }
71+ } ) ;
72+
73+ RemoveObjectPackCommand = ReactiveCommand . Create < DtoItemPackEntry > ( pack =>
74+ {
75+ ObjectPacks . Remove ( pack ) ;
76+ SyncObjectPacksToMetadata ( ) ;
77+ } ) ;
78+
79+ // Load data from server if we have a client
80+ if ( objectServiceClient != null )
81+ {
82+ _ = LoadServerDataAsync ( ) ;
83+ }
1984 }
2085
2186 public ObjectMetadataViewModel ( ) : this ( new ObjectMetadata ( "<empty>" ) )
@@ -27,8 +92,114 @@ public ObjectMetadataViewModel() : this(new ObjectMetadata("<empty>"))
2792 // InternalName is readonly (init-only in the model)
2893 public string InternalName => Metadata . InternalName ;
2994
30- // Available values for Availability enum
31- public IEnumerable < ObjectAvailability > AvailabilityValues => Enum . GetValues < ObjectAvailability > ( ) ;
95+ // Availability is readonly (user cannot change this)
96+ public ObjectAvailability Availability => Metadata . Availability ;
97+
98+ // Collections for editing
99+ public ObservableCollection < DtoAuthorEntry > Authors { get ; }
100+ public ObservableCollection < DtoTagEntry > Tags { get ; }
101+ public ObservableCollection < DtoItemPackEntry > ObjectPacks { get ; }
102+
103+ // Commands
104+ public ReactiveCommand < DtoAuthorEntry ? , Unit > AddAuthorCommand { get ; }
105+ public ReactiveCommand < DtoAuthorEntry , Unit > RemoveAuthorCommand { get ; }
106+ public ReactiveCommand < DtoTagEntry ? , Unit > AddTagCommand { get ; }
107+ public ReactiveCommand < DtoTagEntry , Unit > RemoveTagCommand { get ; }
108+ public ReactiveCommand < DtoItemPackEntry ? , Unit > AddObjectPackCommand { get ; }
109+ public ReactiveCommand < DtoItemPackEntry , Unit > RemoveObjectPackCommand { get ; }
110+
111+ // Available items for selection
112+ ObservableCollection < DtoAuthorEntry > availableAuthors = [ ] ;
113+ public ObservableCollection < DtoAuthorEntry > AvailableAuthors
114+ {
115+ get => availableAuthors ;
116+ set => this . RaiseAndSetIfChanged ( ref availableAuthors , value ) ;
117+ }
118+
119+ ObservableCollection < DtoTagEntry > availableTags = [ ] ;
120+ public ObservableCollection < DtoTagEntry > AvailableTags
121+ {
122+ get => availableTags ;
123+ set => this . RaiseAndSetIfChanged ( ref availableTags , value ) ;
124+ }
125+
126+ ObservableCollection < DtoItemPackEntry > availableObjectPacks = [ ] ;
127+ public ObservableCollection < DtoItemPackEntry > AvailableObjectPacks
128+ {
129+ get => availableObjectPacks ;
130+ set => this . RaiseAndSetIfChanged ( ref availableObjectPacks , value ) ;
131+ }
132+
133+ // Available licences
134+ ObservableCollection < DtoLicenceEntry ? > availableLicences = [ ] ;
135+ public ObservableCollection < DtoLicenceEntry ? > AvailableLicences
136+ {
137+ get => availableLicences ;
138+ set => this . RaiseAndSetIfChanged ( ref availableLicences , value ) ;
139+ }
140+
141+ async Task LoadServerDataAsync ( )
142+ {
143+ if ( objectServiceClient == null )
144+ {
145+ return ;
146+ }
147+
148+ try
149+ {
150+ // Load licences
151+ var licences = await objectServiceClient . GetLicencesAsync ( ) ;
152+ var licenceList = new List < DtoLicenceEntry ? > { null } ; // Add None option
153+ licenceList . AddRange ( licences ) ;
154+ AvailableLicences = new ObservableCollection < DtoLicenceEntry ? > ( licenceList ) ;
155+
156+ // Load authors, tags, and object packs
157+ var authors = await objectServiceClient . GetAuthorsAsync ( ) ;
158+ AvailableAuthors = new ObservableCollection < DtoAuthorEntry > ( authors ) ;
159+
160+ var tags = await objectServiceClient . GetTagsAsync ( ) ;
161+ AvailableTags = new ObservableCollection < DtoTagEntry > ( tags ) ;
162+
163+ var objectPacks = await objectServiceClient . GetObjectPacksAsync ( ) ;
164+ AvailableObjectPacks = new ObservableCollection < DtoItemPackEntry > ( objectPacks ) ;
165+ }
166+ catch ( Exception )
167+ {
168+ // If we can't load data (e.g., offline mode), just set empty lists
169+ AvailableLicences = new ObservableCollection < DtoLicenceEntry ? > { null } ;
170+ AvailableAuthors = new ObservableCollection < DtoAuthorEntry > ( ) ;
171+ AvailableTags = new ObservableCollection < DtoTagEntry > ( ) ;
172+ AvailableObjectPacks = new ObservableCollection < DtoItemPackEntry > ( ) ;
173+ }
174+ }
175+
176+ // Commands for adding/removing items
177+ void SyncAuthorsToMetadata ( )
178+ {
179+ Metadata . Authors . Clear ( ) ;
180+ foreach ( var author in Authors )
181+ {
182+ Metadata . Authors . Add ( author ) ;
183+ }
184+ }
185+
186+ void SyncTagsToMetadata ( )
187+ {
188+ Metadata . Tags . Clear ( ) ;
189+ foreach ( var tag in Tags )
190+ {
191+ Metadata . Tags . Add ( tag ) ;
192+ }
193+ }
194+
195+ void SyncObjectPacksToMetadata ( )
196+ {
197+ Metadata . ObjectPacks . Clear ( ) ;
198+ foreach ( var pack in ObjectPacks )
199+ {
200+ Metadata . ObjectPacks . Add ( pack ) ;
201+ }
202+ }
32203
33204 string ? description ;
34205 public string ? Description
@@ -41,14 +212,14 @@ public string? Description
41212 }
42213 }
43214
44- ObjectAvailability availability ;
45- public ObjectAvailability Availability
215+ DtoLicenceEntry ? selectedLicence ;
216+ public DtoLicenceEntry ? SelectedLicence
46217 {
47- get => availability ;
218+ get => selectedLicence ;
48219 set
49220 {
50- _ = this . RaiseAndSetIfChanged ( ref availability , value ) ;
51- Metadata . Availability = value ;
221+ _ = this . RaiseAndSetIfChanged ( ref selectedLicence , value ) ;
222+ Metadata . Licence = value ;
52223 }
53224 }
54225
0 commit comments