f1e0f6b5ef
- Add complete server infrastructure with Gitea, API, PostgreSQL - Implement Obsidian-compatible markdown mindmap converter - Add Flutter service for server synchronization - Configure GitHub Actions for automated build and deploy - Add production docker-compose with health checks - Include VPS setup and deployment scripts - Add comprehensive deployment documentation
127 lines
3.5 KiB
Dart
127 lines
3.5 KiB
Dart
import 'package:cloud_firestore/cloud_firestore.dart';
|
|
|
|
class ProjectModel {
|
|
final String id;
|
|
final String name;
|
|
final String description;
|
|
final String teamId;
|
|
final String ownerId;
|
|
final List<String> memberIds;
|
|
final String status;
|
|
final DateTime startDate;
|
|
final DateTime? endDate;
|
|
final String color;
|
|
final String icon;
|
|
final Map<String, dynamic> settings;
|
|
final DateTime createdAt;
|
|
final DateTime updatedAt;
|
|
|
|
ProjectModel({
|
|
required this.id,
|
|
required this.name,
|
|
required this.description,
|
|
required this.teamId,
|
|
required this.ownerId,
|
|
this.memberIds = const [],
|
|
this.status = 'active',
|
|
required this.startDate,
|
|
this.endDate,
|
|
this.color = '#1976D2',
|
|
this.icon = 'project',
|
|
this.settings = const {},
|
|
required this.createdAt,
|
|
required this.updatedAt,
|
|
});
|
|
|
|
factory ProjectModel.fromFirestore(DocumentSnapshot doc) {
|
|
final data = doc.data();
|
|
if (data == null) {
|
|
throw Exception('Document data is null');
|
|
}
|
|
|
|
final mapData = data is Map<String, dynamic>
|
|
? data
|
|
: (data as Map<dynamic, dynamic>)
|
|
.map((k, v) => MapEntry(k.toString(), v));
|
|
|
|
return ProjectModel(
|
|
id: doc.id,
|
|
name: mapData['name'] ?? '',
|
|
description: mapData['description'] ?? '',
|
|
teamId: mapData['teamId'] ?? '',
|
|
ownerId: mapData['ownerId'] ?? '',
|
|
memberIds: List<String>.from(mapData['memberIds'] ?? []),
|
|
status: mapData['status'] ?? 'active',
|
|
startDate: (mapData['startDate'] as Timestamp).toDate(),
|
|
endDate: mapData['endDate'] != null
|
|
? (mapData['endDate'] as Timestamp).toDate()
|
|
: null,
|
|
color: mapData['color'] ?? '#1976D2',
|
|
icon: mapData['icon'] ?? 'project',
|
|
settings: mapData['settings'] ?? {},
|
|
createdAt: (mapData['createdAt'] as Timestamp).toDate(),
|
|
updatedAt: (mapData['updatedAt'] as Timestamp).toDate(),
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> toFirestore() {
|
|
return {
|
|
'name': name,
|
|
'description': description,
|
|
'teamId': teamId,
|
|
'ownerId': ownerId,
|
|
'memberIds': memberIds,
|
|
'status': status,
|
|
'startDate': Timestamp.fromDate(startDate),
|
|
'endDate': endDate != null ? Timestamp.fromDate(endDate!) : null,
|
|
'color': color,
|
|
'icon': icon,
|
|
'settings': settings,
|
|
'createdAt': Timestamp.fromDate(createdAt),
|
|
'updatedAt': Timestamp.fromDate(updatedAt),
|
|
};
|
|
}
|
|
|
|
ProjectModel copyWith({
|
|
String? id,
|
|
String? name,
|
|
String? description,
|
|
String? teamId,
|
|
String? ownerId,
|
|
List<String>? memberIds,
|
|
String? status,
|
|
DateTime? startDate,
|
|
DateTime? endDate,
|
|
String? color,
|
|
String? icon,
|
|
Map<String, dynamic>? settings,
|
|
DateTime? createdAt,
|
|
DateTime? updatedAt,
|
|
}) {
|
|
return ProjectModel(
|
|
id: id ?? this.id,
|
|
name: name ?? this.name,
|
|
description: description ?? this.description,
|
|
teamId: teamId ?? this.teamId,
|
|
ownerId: ownerId ?? this.ownerId,
|
|
memberIds: memberIds ?? this.memberIds,
|
|
status: status ?? this.status,
|
|
startDate: startDate ?? this.startDate,
|
|
endDate: endDate ?? this.endDate,
|
|
color: color ?? this.color,
|
|
icon: icon ?? this.icon,
|
|
settings: settings ?? this.settings,
|
|
createdAt: createdAt ?? this.createdAt,
|
|
updatedAt: updatedAt ?? this.updatedAt,
|
|
);
|
|
}
|
|
|
|
bool isMember(String userId) {
|
|
return ownerId == userId || memberIds.contains(userId);
|
|
}
|
|
|
|
bool isOwner(String userId) {
|
|
return ownerId == userId;
|
|
}
|
|
}
|