Projekt

Obecné

Profil

« Předchozí | Další » 

Revize a35cb648

Přidáno uživatelem Vojtěch Bartička před asi 2 roky(ů)

Added comments to backend

Zobrazit rozdíly:

Backend/Backend/Authentication/AuthorizationAttribute.cs
6 6

  
7 7
namespace RestAPI.Authentication;
8 8

  
9
/// <summary>
10
/// Authorization attribute for endpoints and controllers
11
/// By default minimum role is ANNOTATOR
12
/// Access is granted to any role with same or higher privilege than the specified one (or default, if none is specified)
13
/// </summary>
9 14
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
10 15
public class AuthorizeAttribute : Attribute, IAuthorizationFilter
11 16
{
Backend/Backend/Controllers/AnnotationController.cs
10 10
using Models.Tags;
11 11
using Core.Services.TagService;
12 12

  
13

  
13
/// <summary>
14
/// /annotation* endpoint controller
15
/// </summary>
14 16
namespace RestAPI.Controllers
15 17
{
16 18
    public class AnnotationController : CommonControllerBase
Backend/Backend/Controllers/AuthController.cs
10 10

  
11 11
namespace RestAPI.Controllers;
12 12

  
13
/// <summary>
14
/// Authentication controller
15
/// </summary>
13 16
public class AuthController : CommonControllerBase
14 17
{
15 18
    private readonly IAuthService authService;
......
48 51
        }
49 52
    }
50 53

  
54
    /// <summary>
55
    /// Test only
56
    /// </summary>
57
    /// <param name="clientInfo"></param>
58
    /// <returns></returns>
51 59
    [HttpGet("/auth/test")]
52 60
    [ProducesResponseType((int) HttpStatusCode.OK, Type = typeof(ClientInfo))]
53 61
    [ProducesResponseType((int) HttpStatusCode.Forbidden)]
......
56 64
        return clientInfo;
57 65
    }
58 66
    
59
    
67
    /// <summary>
68
    /// Test only
69
    /// </summary>
70
    /// <param name="clientInfo"></param>
71
    /// <returns></returns>
60 72
    [AllowAnonymous]
61 73
    [HttpGet("/auth/test/aa")]
62 74
    [ProducesResponseType((int) HttpStatusCode.OK, Type = typeof(ClientInfo))]
Backend/Backend/Controllers/Common/CommonControllerBase.cs
4 4

  
5 5
namespace RestAPI.Controllers.Common;
6 6

  
7
/// <summary>
8
/// Base controller with universal headers
9
/// Note that by default endpoints are [Authorize], so if an endpoint should not be logged-user-only, add [AllowAnonymous]
10
/// </summary>
7 11
[ApiController]
8 12
[Authorize]
9 13
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
Backend/Backend/Controllers/DocumentController.cs
15 15
namespace RestAPI.Controllers;
16 16

  
17 17

  
18

  
18
/// <summary>
19
/// /document* endpoint controller
20
/// </summary>
19 21
public class DocumentController : Common.CommonControllerBase
20 22
{
21 23
    private readonly IDocumentService documentService;
Backend/Backend/Controllers/TagController.cs
13 13
namespace RestAPI.Controllers;
14 14

  
15 15

  
16

  
16
/// <summary>
17
/// /tag* endpoint controller
18
/// </summary>
17 19
public class TagController : Common.CommonControllerBase
18 20
{
19 21
    private readonly ITagService tagService;
20 22
    private readonly ILogger logger;
21 23

  
22

  
23 24
    public TagController(ITagService tagService, ILogger logger)
24 25
    {
25 26
        this.tagService = tagService;
Backend/Backend/Controllers/UserController.cs
11 11

  
12 12
namespace RestAPI.Controllers
13 13
{
14
    /// <summary>
15
    /// /user* endpoint controller
16
    /// </summary>
14 17
    public class UserController : CommonControllerBase
15 18
    {
16 19
        private readonly Serilog.ILogger logger;
Backend/Backend/Exceptions/BadRequestException.cs
6 6

  
7 7
namespace RestAPI.Exceptions
8 8
{
9
    /// <summary>
10
    /// Exception raised when there is a problem with client's request
11
    /// Catched by error handling middleware
12
    /// </summary>
9 13
    public class BadRequestException : Exception
10 14
    {
11 15
        public BadRequestException() { }
Backend/Backend/Exceptions/InternalErrorException.cs
6 6

  
7 7
namespace RestAPI.Exceptions
8 8
{
9
    /// <summary>
10
    /// Exception raised when there is an internal server error
11
    /// Catched by error handling middleware
12
    /// </summary>
9 13
    public class InternalErrorException : Exception
10 14
    {
11 15
        public InternalErrorException() { }
Backend/Backend/Middleware/ErrorMiddleware.cs
4 4

  
5 5
namespace RestAPI.Middleware
6 6
{
7
    /// <summary>
8
    /// Middleware for global error handling
9
    /// </summary>
7 10
    public class ErrorMiddleware
8 11
    {
9 12
        private readonly RequestDelegate _next;
Backend/Backend/Program.cs
76 76
    app.UseSwaggerUI();
77 77
}
78 78

  
79
//app.UseHttpsRedirection();
80

  
81 79
// CORS
82 80
app.UseCors(builder => builder
83 81
                .AllowAnyHeader()
Backend/Backend/Utils/ClientInfo.cs
2 2

  
3 3
namespace RestAPI.Utils;
4 4

  
5
/// <summary>
6
/// Request client information
7
/// </summary>
5 8
public class ClientInfo
6 9
{
7 10
    public bool IsLogged => LoggedUser != null;
8

  
9 11
    public User? LoggedUser { get; set; } = null;
10

  
11 12
    public string IP { get; set; } = "unknown";
12 13
}
Backend/Backend/Utils/ContextUtils.cs
18 18
        }
19 19
    }
20 20

  
21
    /// <summary>
22
    /// Exctracts client information given HttpContext
23
    /// </summary>
24
    /// <param name="context"></param>
25
    /// <returns></returns>
21 26
    public static ClientInfo GetClientInfo(HttpContext? context)
22 27
    {
23 28
        var ci = new ClientInfo();
Backend/Core/Authentication/JwtUtils.cs
16 16

  
17 17
public class JwtUtils : IJwtUtils
18 18
{
19
    private const int EXPIRATION_SECONDS = 8 * 60 * 60; // 8 hod
19
    private const int EXPIRATION_SECONDS = 8 * 60 * 60; // 8 hrs
20 20

  
21 21
    private readonly JwtConfig _jwtConfig;
22 22
    private readonly TokenValidationParameters _tokenValidationParameters;
Backend/Core/Constants/Constants.cs
8 8
{
9 9
    public class Constants
10 10
    {
11
        /// <summary>
12
        /// Key for RequiredAnnotation value in database
13
        /// </summary>
11 14
        public static string RequiredAnnotationsKey { get; } = "RequiredAnnotations"; 
12 15
    }
13 16
}
Backend/Core/Contexts/DatabaseContext.cs
35 35
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
36 36
        {
37 37
            optionsBuilder.UseNpgsql(_configuration["ConnectionString"], b => b.MigrationsAssembly("RestAPI"));
38
            //optionsBuilder.UseNpgsql("Host=localhost:5432;Database=dbo;Username=myuser;Password=password");
39
        }
40

  
41
        protected override void OnModelCreating(ModelBuilder modelBuilder)
42
        {
43 38
        }
44 39
    }
45 40
}
Backend/Core/Entities/Annotation.cs
11 11
{
12 12
    public class Annotation : BaseEntity
13 13
    {
14
        /*[ForeignKey("Document")]
15
        public int DocumentId { get; set; }*/
14
        /// <summary>
15
        /// Document that the annotation refers to
16
        /// </summary>
16 17
        public Document Document { get; set; }
17 18
        
18
        /*[ForeignKey("User")]
19
        public int UserId { get; set; }*/
19
        /// <summary>
20
        /// User the annotation is assigned to
21
        /// </summary>
20 22
        public User User { get; set; }
21 23

  
22
        /*[ForeignKey("User")]
23
        public int UserAssignedId { get; set; }*/
24
        /// <summary>
25
        /// The user that assigned the annotation
26
        /// </summary>
24 27
        public User UserAssigned { get; set; }
25 28

  
29
        /// <summary>
30
        /// The date the annotation was assigned
31
        /// </summary>
26 32
        public DateTime DateAssigned { get; set; }
33
        
34
        /// <summary>
35
        /// The state of the annotation
36
        /// </summary>
27 37
        public EState State { get; set; }
38

  
39
        /// <summary>
40
        /// The date the annotation was last modified
41
        /// </summary>
28 42
        public DateTime DateLastChanged { get; set; }
43

  
44
        /// <summary>
45
        /// Annotation note
46
        /// </summary>
29 47
        public string Note { get; set; } = "";
30 48

  
49
        //Cached information START
31 50
        public string CachedDocumentHTML { get; set; } = "";
32 51
        public string CachedStartPositions { get; set; } = "";
33 52
        public string CachedLengths { get; set; } = "";
34 53
        public string CachedClosingPositions { get; set; } = "";
35 54
        public string CachedClosingLengths { get; set; } = "";
36 55
        public string CachedCSS { get; set; } = "";
56
        //Cached information END 
37 57

  
58
        /// <summary>
59
        /// ID of the last modified tag
60
        /// </summary>
38 61
        public Guid? LastModifiedTagId { get; set; }
62

  
63
        /// <summary>
64
        /// The modification that is done
65
        /// </summary>
39 66
        public EModified ModifiedType { get; set; } = EModified.NONE;
40 67

  
68
        /// <summary>
69
        /// Unused
70
        /// </summary>
41 71
        public ICollection<Class> Classes { get; set; } = new List<Class>();
42 72

  
73
        /// <summary>
74
        /// So that EF creates a join table as 1 final annotation to N annotations
75
        /// </summary>
76

  
43 77
        public ICollection<FinalAnnotation> FinalAnnotations { get; set; } = new List<FinalAnnotation>();
44 78
    }
45 79
}
Backend/Core/Entities/AnnotationTag.cs
11 11
{
12 12
    public class AnnotationTag : AnnotationTagGeneric
13 13
    {
14
        /// <summary>
15
        /// The annotation the annotation tag is linked to
16
        /// </summary>
14 17
        public Annotation Annotation { get; set; }
15 18
    }
16 19
}
Backend/Core/Entities/AnnotationTagGeneric.cs
7 7

  
8 8
namespace Core.Entities
9 9
{
10
    /// <summary>
11
    /// Base class for tag occurences in annotations
12
    /// </summary>
10 13
    public class AnnotationTagGeneric : BaseEntity
11 14
    {
15
        /// <summary>
16
        /// Tag
17
        /// </summary>
12 18
        public Tag Tag { get; set; }
13 19

  
14
        /** Nullable for optional */
20
        /// <summary>
21
        /// Subtag, nulllable for optional
22
        /// </summary>
15 23
        public SubTag? SubTag { get; set; }
16 24

  
25
        /// <summary>
26
        /// Id of the instance (shared by multipart tags)
27
        /// </summary>
17 28
        public Guid Instance { get; set; }
29

  
30
        /// <summary>
31
        /// The tag note
32
        /// </summary>
18 33
        public string Note { get; set; }
19 34
        public int Position { get; set; }
20 35
        public int Length { get; set; }
36

  
37
        /// <summary>
38
        /// Sentiment of the tag, nullable for optional
39
        /// </summary>
21 40
        public ETagSentiment? Sentiment { get; set; }
41
        
42
        /// <summary>
43
        /// The text that the tag is covering
44
        /// </summary>
22 45
        public string SelectedText { get; set; }
23 46
    }
24 47
}
Backend/Core/Entities/BaseEntity.cs
7 7

  
8 8
namespace Core.Entities
9 9
{
10
    /// <summary>
11
    /// Base entity, defines the ID
12
    /// </summary>
10 13
    public class BaseEntity
11 14
    {
12 15
       [Key]
Backend/Core/Entities/Class.cs
7 7

  
8 8
namespace Core.Entities
9 9
{
10
    /// <summary>
11
    /// Unused
12
    /// </summary>
10 13
    public class Class : BaseEntity
11 14
    {
12 15
        public string Name { get; set; }
Backend/Core/Entities/ConfigurationItem.cs
6 6

  
7 7
namespace Core.Entities
8 8
{
9
    /// <summary>
10
    /// Configuration for the key-value database storage
11
    /// </summary>
9 12
    public class ConfigurationItem : BaseEntity
10 13
    {
11 14
        public string Value { get; set; }
Backend/Core/Entities/Document.cs
11 11
#nullable disable
12 12
    public class Document : BaseEntity
13 13
    {
14
        /// <summary>
15
        /// Document name
16
        /// </summary>
14 17
        public string Name { get; set; }
18

  
19
        /// <summary>
20
        /// Length in characters
21
        /// </summary>
15 22
        public int Length { get; set; }
16 23

  
24
        /// <summary>
25
        /// Actual content
26
        /// </summary>
17 27
        public DocumentContent Content { get; set; }
18 28

  
29
        /// <summary>
30
        /// Date added
31
        /// </summary>
19 32
        public DateTime DateAdded { get; set; }
20 33

  
34
        /// <summary>
35
        /// User who added it
36
        /// </summary>
21 37
        public User UserAdded { get; set; }
22 38

  
39
        /// <summary>
40
        /// Number of required annotations
41
        /// </summary>
23 42
        public int RequiredAnnotations { get; set; }
24 43
    }
25 44
}
Backend/Core/Entities/DocumentContent.cs
10 10
{
11 11
    public class DocumentContent : BaseEntity
12 12
    {
13
        /// <summary>
14
        /// String with the document content
15
        /// </summary>
13 16
        public string Content { get; set; }
14 17
    }
15 18
}
Backend/Core/Entities/FinalAnnotation.cs
9 9
{
10 10
    public class FinalAnnotation : Annotation
11 11
    {
12
        /// <summary>
13
        /// List of annotations that were used to create the final annotation
14
        /// </summary>
12 15
        public List<Annotation> Annotations { get; set; } = new();
13 16
    }
14 17
}
Backend/Core/Entities/FinalAnnotationTag.cs
8 8
{
9 9
    public class FinalAnnotationTag : AnnotationTagGeneric
10 10
    {
11
        /// <summary>
12
        /// FinalAnnotation the tag is linked to
13
        /// </summary>
11 14
        public FinalAnnotation Annotation { get; set; }
15

  
16
        /// <summary>
17
        /// Whether the tag is marked as final or not
18
        /// </summary>
12 19
        public bool IsFinal { get; set; } = false;
20
        
21
        /// <summary>
22
        /// List of users who have agreed on this tag
23
        /// </summary>
13 24
        public ICollection<User> Users { get; set; } = new List<User>();
14 25
    }
15 26
}
Backend/Core/Entities/SubTag.cs
12 12
        public string Name { get; set; }
13 13
        public string Description { get; set; }
14 14
        public Tag Tag { get; set; }
15

  
16
        /// <summary>
17
        /// Whether or not this tag supports sentiment
18
        /// </summary>
15 19
        public bool SentimentEnabled { get; set; } = false;
16 20
    }
17 21
}
Backend/Core/Entities/Tag.cs
14 14
        public string Name { get; set; }
15 15
        public string Description { get; set; }
16 16
        public string Color { get; set; }
17

  
18
        /// <summary>
19
        /// Whether or not this tag supports sentiment
20
        /// </summary>
17 21
        public bool SentimentEnabled { get; set; } = false;
18 22
    }
19 23
}
Backend/Core/Entities/TagCategory.cs
13 13
        public string Name { get; set; }
14 14
        public string Color { get; set; }
15 15
        public string Description { get; set; }
16

  
17
        /// <summary>
18
        /// Whether or not this category is only visible to admins
19
        /// </summary>
16 20
        public bool DisabledForAnnotators { get; set; } = false;
17 21
    }
18 22
}
Backend/Core/Entities/User.cs
21 21

  
22 22
        public ERole Role { get; set; }
23 23

  
24
        /// <summary>
25
        /// Force EF to create a join table
26
        /// </summary>
24 27
        public ICollection<FinalAnnotationTag> FinalAnnotationTags { get; set; } = new List<FinalAnnotationTag>();
25 28
    }
26 29
}
Backend/Core/GraphUtils/Intersections.cs
4 4
{
5 5
    public class Intersections
6 6
    {
7
        /// <summary>
8
        /// Finds intersections between 1D segments
9
        /// </summary>
10
        /// <param name="tags"></param>
11
        /// <returns></returns>
7 12
        public static Dictionary<AnnotationTagGeneric, List<AnnotationTagGeneric>> FindIntersections(List<AnnotationTagGeneric> tags)
8 13
        {
9 14
            var intersections = new Dictionary<AnnotationTagGeneric, List<AnnotationTagGeneric>>();
......
27 32
            return intersections;
28 33
        }
29 34

  
35
        /// <summary>
36
        /// Graph coloring
37
        /// </summary>
38
        /// <param name="source"></param>
39
        /// <returns></returns>
30 40
        public static Dictionary<AnnotationTagGeneric, int> ColorGraph(Dictionary<AnnotationTagGeneric, List<AnnotationTagGeneric>> source)
31 41
        {
32 42
            var res = ConvertToMatrix(source);
Backend/Core/MapperProfiles/DocumentProfileEF.cs
14 14
        public DocumentProfileEF()
15 15
        {
16 16
            CreateMap<Document, DocumentListInfo>();
17
                /*.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id))
18
                .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name))
19
                .ForMember(dest => dest.Length, opt => opt.MapFrom(src => src.Length))
20
                .ForMember(dest => dest.RequiredAnnotations, opt => opt.MapFrom(src => src.RequiredAnnotations));*/
21

  
22 17
        }
23 18
    }
24 19
}
Backend/Core/MapperProfiles/RegisterMappings.cs
11 11
{
12 12
    public class RegisterMappings
13 13
    {
14
        /// <summary>
15
        /// Registers mappings for AutoMapper in DI
16
        /// </summary>
17
        /// <param name="builder"></param>
14 18
        public static void Register(WebApplicationBuilder builder)
15 19
        {
16
            builder.Services.AddAutoMapper(typeof(UserProfileEF), typeof(DocumentProfileEF));
20
            builder.Services.AddAutoMapper(typeof(UserProfileEF), typeof(DocumentProfileEF), typeof(TagProfileEF));
17 21
        }
18 22
    }
19 23
}
Backend/Core/Services/AnnotationService/IAnnotationService.cs
11 11
{
12 12
    public interface IAnnotationService
13 13
    {
14
        /// <summary>
15
        /// Assign users to documents
16
        /// </summary>
17
        /// <param name="request"></param>
18
        /// <param name="userId"></param>
14 19
        public void CreateDocumentAnnotations(AnnotationsAddRequest request, Guid userId);
20
        /// <summary>
21
        /// Given user, return their annotations
22
        /// </summary>
23
        /// <param name="userId"></param>
24
        /// <returns></returns>
15 25
        public AnnotationListResponse GetUserAnnotations(Guid userId);
26
        /// <summary>
27
        /// Return given annotation
28
        /// </summary>
29
        /// <param name="annotationId"></param>
30
        /// <param name="userId"></param>
31
        /// <param name="userRole"></param>
32
        /// <param name="isFinal">is it final annotation or standard annotation</param>
33
        /// <returns></returns>
16 34
        public AnnotationInfo GetAnnotation(Guid annotationId, Guid userId, ERole userRole, bool isFinal);
35
        /// <summary>
36
        /// Adds a tag to an annotation
37
        /// </summary>
38
        /// <param name="annotationId"></param>
39
        /// <param name="userId"></param>
40
        /// <param name="userRole"></param>
41
        /// <param name="request"></param>
42
        /// <param name="isFinal">is it final annotation or standard annotation</param>
17 43
        public void AddAnnotationInstance(Guid annotationId, Guid userId, ERole userRole, AnnotationInstanceAddRequest request, bool isFinal);
44
        /// <summary>
45
        /// Remove a tag from annotation
46
        /// </summary>
47
        /// <param name="annotationId"></param>
48
        /// <param name="tagInstanceId"></param>
49
        /// <param name="loggedUserId"></param>
50
        /// <param name="userRole"></param>
51
        /// <param name="isFinal">is it final annotation or standard annotation</param>
18 52
        public void DeleteAnnotationInstance(Guid annotationId, Guid tagInstanceId, Guid loggedUserId, ERole userRole, bool isFinal);
53
        /// <summary>
54
        /// Add note to annotation
55
        /// </summary>
56
        /// <param name="annotationId"></param>
57
        /// <param name="userId"></param>
58
        /// <param name="userRole"></param>
59
        /// <param name="request"></param>
60
        /// <param name="isFinal">is it final annotation or standard annotation</param>
19 61
        public void AddNoteToAnnotation(Guid annotationId, Guid userId, ERole userRole, AddNoteToAnnotationRequest request, bool isFinal);
62
        /// <summary>
63
        /// Set sentiment of a tag
64
        /// </summary>
65
        /// <param name="annotationId"></param>
66
        /// <param name="instanceId"></param>
67
        /// <param name="userId"></param>
68
        /// <param name="userRole"></param>
69
        /// <param name="sentiment"></param>
70
        /// <param name="isFinal">is it final annotation or standard annotation</param>
20 71
        public void SetTagInstanceSentiment(Guid annotationId, Guid instanceId, Guid userId, ERole userRole, ETagSentiment sentiment, bool isFinal);
72
        /// <summary>
73
        /// Set the annotation state to DONE or IN_PROGRESS
74
        /// </summary>
75
        /// <param name="annotationId"></param>
76
        /// <param name="userId"></param>
77
        /// <param name="userRole"></param>
78
        /// <param name="done">is it DONE or not</param>
79
        /// <param name="isFinal"is it final annotation or standard annotation></param>
21 80
        public void MarkAnnotationAsDone(Guid annotationId, Guid userId, ERole userRole, bool done, bool isFinal);
81
        /// <summary>
82
        /// Creates a final annotation
83
        /// </summary>
84
        /// <param name="documentId"></param>
85
        /// <param name="userId"></param>
86
        /// <returns>ID of the final annotation</returns>
22 87
        public Guid CreateFinalAnnotation(Guid documentId, Guid userId);
88
        /// <summary>
89
        /// Performs an export
90
        /// </summary>
91
        /// <param name="request"></param>
92
        /// <returns>ZIP memory stream</returns>
23 93
        public MemoryStream Export(ExportRequest request);
94
        /// <summary>
95
        /// Marks tag as final 
96
        /// </summary>
97
        /// <param name="annotationId"></param>
98
        /// <param name="occurenceId"></param>
99
        /// <param name="isFinal">is the tag final or not</param>
24 100
        public void SetTagIsFinal(Guid annotationId, Guid occurenceId, bool isFinal);
25 101
    }
26 102
}
Backend/Core/Services/AuthService/IAuthService.cs
5 5

  
6 6
public interface IAuthService
7 7
{
8
    /// <summary>
9
    /// Check username and password
10
    /// </summary>
11
    /// <param name="username"></param>
12
    /// <param name="password"></param>
13
    /// <returns></returns>
8 14
    public LoginResponse? Login(string username, string password);
9 15
}
Backend/Core/Services/DocumentService/DocumentServiceEF.cs
63 63
        }
64 64

  
65 65
        /// <summary>
66
        /// 
66
        /// Process a zip file and returns a list of names and documents
67 67
        /// </summary>
68 68
        /// <param name="base64encoded"></param>
69 69
        /// <returns></returns>
......
91 91
            return (names, contents);
92 92
        }
93 93

  
94
        /// <summary>
95
        /// Save a document in the database
96
        /// </summary>
97
        /// <param name="content"></param>
98
        /// <param name="userAdded"></param>
99
        /// <param name="documentName"></param>
100
        /// <param name="requiredAnnotations"></param>
94 101
        private void SaveDocument(string content, User userAdded, string documentName, int requiredAnnotations)
95 102
        {
96 103
            DocumentContent documentContent = new DocumentContent()
......
140 147
                }
141 148

  
142 149
                DocumentListInfo dli = mapper.Map<DocumentListInfo>(document);
150
                // Add list of users taht annotate the document
143 151
                dli.AnnotatingUsers = annotatingUsersDto;
144 152

  
153
                // Add info about the finalized version
145 154
                dli.FinalizedExists = databaseContext.FinalAnnotations.Any(fa => fa.Document == document);
146 155
                if (dli.FinalizedExists)
147 156
                {
......
154 163
                    dli.FinalizedState = finalizedAnnotation.State;
155 164
                    dli.FinalAnnotations = new();
156 165

  
166
                    // Add information about which annotations were used to create the finalized version
157 167
                    foreach (var annotation in finalizedAnnotation.Annotations)
158 168
                    {
159 169
                        dli.FinalAnnotations.Add(new()
Backend/Core/Services/DocumentService/IDocumentService.cs
11 11
{
12 12
    public interface IDocumentService
13 13
    {
14
        /// <summary>
15
        /// Add list of documents to a list of users
16
        /// </summary>
17
        /// <param name="request"></param>
18
        /// <param name="userId"></param>
14 19
        public void AddDocuments(DocumentAddRequest request, Guid userId);
20
        /// <summary>
21
        /// Returns all documents
22
        /// </summary>
23
        /// <returns></returns>
15 24
        public DocumentListResponse GetDocuments();
25
        /// <summary>
26
        /// Returns a preview of a document (HTML)
27
        /// </summary>
28
        /// <param name="documentId"></param>
29
        /// <returns></returns>
16 30
        public DocumentPreviewResponse GetDocumentPreview(Guid documentId);
31
        /// <summary>
32
        /// Delete a list of documents
33
        /// </summary>
34
        /// <param name="request"></param>
17 35
        public void DeleteDocuments(DeleteDocumentsRequest request);
36
        /// <summary>
37
        /// Set required number of annotations for a list of documents
38
        /// </summary>
39
        /// <param name="request"></param>
18 40
        public void SetRequiredAnnotationsForDocuments(SetRequiredAnnotationsRequest request);
41
        /// <summary>
42
        /// Set default required number of annotations
43
        /// </summary>
44
        /// <param name="requiredAnnotations"></param>
19 45
        public void SetRequiredAnnotationsGlobal(int requiredAnnotations);
46
        /// <summary>
47
        /// Get default required number of annotations
48
        /// </summary>
49
        /// <returns></returns>
20 50
        public int GetRequiredAnnotationsGlobal();
51
        /// <summary>
52
        /// Remove an annotator from a document
53
        /// </summary>
54
        /// <param name="documentId"></param>
55
        /// <param name="annotatorId"></param>
21 56
        public void RemoveAnnotatorFromDocument(Guid documentId, Guid annotatorId);
22 57
    }
23 58
}
Backend/Core/Services/HTMLService/HTMLService.cs
13 13
{
14 14
    public class HTMLService : IHTMLService
15 15
    {
16

  
16
        /// <summary>
17
        /// Attribute name for uniquely identifying each tag in the HTML document on the frontend
18
        /// </summary>
17 19
        private const string TAG_ID_ATTRIBUTE_NAME = "aswi-tag-id";
20

  
21
        /// <summary>
22
        /// Attribute name for tag instance so that each marked out tag can be given a style
23
        /// </summary>
18 24
        private const string TAG_INSTANCE_ATTRIBUTE_NAME = "aswi-tag-instance";
25

  
26
        /// <summary>
27
        /// Attribute name for EF Tag IDs so that the frontend can reference them to the backend for deletion
28
        /// </summary>
19 29
        private const string TAG_EF_ID_ATTRIBUTE_NAME = "aswi-tag-ef-id";
20 30

  
31
        /// <summary>
32
        /// Info that is cached in tha database
33
        /// </summary>
21 34
        public class CachedInfo
22 35
        {
36
            /// <summary>
37
            /// Positions of opening tags in the original HTML document
38
            /// </summary>
23 39
            public List<int> TagStartPositions = new();
40
            /// <summary>
41
            /// Lengths of opening tags in the original HTML document
42
            /// </summary>
24 43
            public List<int> TagStartLengths = new();
44
            /// <summary>
45
            /// Positions of closing tags in the original HTML document
46
            /// </summary>
25 47
            public List<int> TagClosingPositions = new();
48
            /// <summary>
49
            /// Lengths for closing tags in the original HTML document
50
            /// </summary>
26 51
            public List<int> TagClosingLengths = new();
52
            /// <summary>
53
            /// Unused
54
            /// </summary>
27 55
            public Dictionary<HtmlNode, HtmlNode> NodeDict = new();
56
            /// <summary>
57
            /// Cached CSS for each tag
58
            /// </summary>
28 59
            public List<TagInstanceCSSInfo> TagInstanceCSS = new();
29 60
        }
30 61

  
......
35 66
        private Dictionary<HtmlNode, HtmlNode> NodeDict = new();
36 67
        private List<TagInstanceCSSInfo> TagInstanceCSS = new();
37 68

  
69
        /// <summary>
70
        /// Unpack cached info into local (request-scoped) variables
71
        /// </summary>
72
        /// <param name="cachedInfo"></param>
38 73
        private void UnpackCachedInfo(CachedInfo cachedInfo)
39 74
        {
40 75
            TagStartPositions = cachedInfo.TagStartPositions;
......
62 97

  
63 98
            int currentId = 0;
64 99

  
100
            // Create mapping original-document-node -> to-edit-document-node
65 101
            FillNodeDict(descendantsOriginal, descendantsToEdit);
102

  
103
            // Assign IDs to all original rtags
66 104
            AssignIdsToOriginalDocument(descendantsOriginal, ref currentId);
67 105

  
106
            // Wrap all text that is not in a tag or where the parent node contains tags as children also in spans
68 107
            WrapTextInSpan(descendantsOriginal, docToEdit);
69 108

  
70 109
            descendantsToEdit = docToEdit.DocumentNode.DescendantsAndSelf().ToList();
......
156 195
            });
157 196
        }
158 197

  
198
        /// <summary>
199
        /// Wrap text in span when the target text is the whole text of the target tag
200
        /// </summary>
201
        /// <param name="node">text node to wrap</param>
202
        /// <param name="selectionStart">start of the selection in the edited document</param>
203
        /// <param name="selectionEnd">end of the selection in the edited document</param>
204
        /// <param name="start">start of the node</param>
205
        /// <param name="end">end of the node</param>
206
        /// <param name="docToEdit">document to edit</param>
207
        /// <param name="tag">tag we are adding</param>
208
        /// <returns></returns>
159 209
        private HtmlNode SolveFullFill(HtmlNode node, int selectionStart, int selectionEnd, int start, int end, HtmlDocument docToEdit, AnnotationTagGeneric tag)
160 210
        {
161 211
            // full fill
......
185 235
            return spanSelected;
186 236
        }
187 237

  
238
        /// <summary>
239
        /// Wrap text in span when the target text starts at the start of the tag and leaves space on the right side
240
        /// </summary>
241
        /// <param name="node">text node to wrap</param>
242
        /// <param name="selectionStart">start of the selection in the edited document</param>
243
        /// <param name="selectionEnd">end of the selection in the edited document</param>
244
        /// <param name="start">start of the node</param>
245
        /// <param name="end">end of the node</param>
246
        /// <param name="docToEdit">document to edit</param>
247
        /// <param name="tag">tag we are adding</param>
248
        /// <returns></returns>
188 249
        private List<HtmlNode> SolveRightGap(HtmlNode node, int selectionStart, int selectionEnd, int start, int end, HtmlDocument docToEdit,
189 250
                                             AnnotationTagGeneric tag)
190 251
        {
......
215 276
            return new() { spanSelected, spanAfter };
216 277
        }
217 278

  
279
        /// <summary>
280
        /// Wrap text in span when the target text ends at the end of the tag but leaves space on the left
281
        /// </summary>
282
        /// <param name="node">text node to wrap</param>
283
        /// <param name="selectionStart">start of the selection in the edited document</param>
284
        /// <param name="selectionEnd">end of the selection in the edited document</param>
285
        /// <param name="start">start of the node</param>
286
        /// <param name="end">end of the node</param>
287
        /// <param name="docToEdit">document to edit</param>
288
        /// <param name="tag">tag we are adding</param>
289
        /// <returns></returns>
218 290
        private List<HtmlNode> SolveLeftGap(HtmlNode node, int selectionStart, int selectionEnd, int start, int end, HtmlDocument docToEdit,
219 291
                                             AnnotationTagGeneric tag)
220 292
        {
......
245 317
            return new() { spanSelected, spanBefore };
246 318
        }
247 319

  
320
        /// <summary>
321
        /// Wrap text in span when the target text is contained in the node but neither starts or ends match
322
        /// </summary>
323
        /// <param name="node">text node to wrap</param>
324
        /// <param name="selectionStart">start of the selection in the edited document</param>
325
        /// <param name="selectionEnd">end of the selection in the edited document</param>
326
        /// <param name="start">start of the node</param>
327
        /// <param name="end">end of the node</param>
328
        /// <param name="docToEdit">document to edit</param>
329
        /// <param name="tag">tag we are adding</param>
330
        /// <returns></returns>
248 331
        private List<HtmlNode> SolveLeftRightGap(HtmlNode node, int selectionStart, int selectionEnd, int start, int end, HtmlDocument docToEdit,
249 332
                                                 AnnotationTagGeneric tag)
250 333
        {
......
274 357
            return new() { spanSelected, spanBefore, spanAfter };
275 358
        }
276 359

  
360
        /// <summary>
361
        /// Create span utility method
362
        /// </summary>
363
        /// <param name="doc">document</param>
364
        /// <param name="text">inner text of the span</param>
365
        /// <param name="tagId">ID of the tag (TAG_ID_ATTRIBUTE_NAME)</param>
366
        /// <param name="instanceId">ID of the instance (TAG_INSTANCE_ATTRIBUTE_NAME)</param>
367
        /// <param name="entityId">Id of the EF entity (TAG_EF_ID_NAME)</param>
368
        /// <param name="startPosition"></param>
369
        /// <param name="position"></param>
370
        /// <returns></returns>
277 371
        private HtmlNode CreateSpan(HtmlDocument doc, string text, int tagId, Guid? instanceId, Guid? entityId, int startPosition, EPosition position = EPosition.MARK_NONE)
278 372
        {
279 373
            HtmlNode span = doc.CreateElement("span");
......
312 406
            MARK_NONE = 0
313 407
        }
314 408

  
409
        /// <summary>
410
        /// Redirect all links
411
        /// </summary>
412
        /// <param name="descendantsOriginal"></param>
315 413
        private void ModifyLinks(IEnumerable<HtmlNode> descendantsOriginal)
316 414
        {
317 415
            foreach (var descendant in descendantsOriginal)
......
327 425
            }
328 426
        }
329 427

  
428
        /// <summary>
429
        /// Wrap all #text nodes in spans
430
        /// </summary>
431
        /// <param name="descendantsOriginal"></param>
432
        /// <param name="docToEdit"></param>
330 433
        private void WrapTextInSpan(IEnumerable<HtmlNode> descendantsOriginal, HtmlDocument docToEdit)
331 434
        {
332 435
            // Special case for non-html documents
......
389 492
                        foreach (var child in node.ChildNodes)
390 493
                        {
391 494
                            if (child.Name.Contains("#text"))
392
                            {
495
                            { 
393 496
                                HtmlNode coveringSpan = docToEdit.CreateElement("span");
394 497
                                coveringSpan.InnerHtml = child.InnerHtml;
498
                                
499
                                // Add length of 0 - in they were not in the original document
395 500
                                TagStartPositions.Add(child.InnerStartIndex);
396 501
                                TagStartLengths.Add(0);
397 502
                                TagClosingPositions.Add(child.InnerStartIndex + child.InnerLength);
......
410 515
            }
411 516
        }
412 517

  
518
        /// <summary>
519
        /// Generate CSS for all tag instances
520
        /// </summary>
521
        /// <param name="tags"></param>
413 522
        private void GenerateCSS(List<AnnotationTagGeneric> tags)
414 523
        {
415 524
            /*string inner = "span.annotation {border-bottom: 2px solid;}";
......
428 537
            }
429 538
        }
430 539

  
540
        /// <summary>
541
        /// Add IDs to all tags in the original document
542
        /// </summary>
543
        /// <param name="descendantsOriginal"></param>
544
        /// <param name="currentId"></param>
431 545
        private void AssignIdsToOriginalDocument(IEnumerable<HtmlNode> descendantsOriginal, ref int currentId)
432 546
        {
433 547
            foreach (var node in descendantsOriginal)
......
446 560
                    currentId = TagStartPositions.Count - 1;
447 561
                    toEditNode.Attributes.Add(TAG_ID_ATTRIBUTE_NAME, currentId.ToString());
448 562

  
563
                    // Cross-referencing of the original document to the edited document
449 564
                    TagClosingPositions.Add(originalNode.InnerStartIndex + originalNode.InnerLength);
450 565
                    TagClosingLengths.Add((originalNode.OuterStartIndex + originalNode.OuterLength) - (originalNode.InnerStartIndex + originalNode.InnerLength));
451 566
                }
......
476 591
         *      Partial HTML Preprocessing ----------------------------------------------------------------------------
477 592
         */
478 593

  
594
        /// <summary>
595
        /// Incrementally modifies the html to render and cached info by adding a new tag
596
        /// </summary>
597
        /// <param name="htmlToEdit"></param>
598
        /// <param name="htmlOriginal"></param>
599
        /// <param name="tagToAdd"></param>
600
        /// <param name="tags"></param>
601
        /// <param name="cachedInfo"></param>
602
        /// <returns></returns>
479 603
        public (string, CachedInfo) PartialPreprocessHTMLAddTag(string htmlToEdit, string htmlOriginal, AnnotationTagGeneric tagToAdd, List<AnnotationTagGeneric> tags, CachedInfo cachedInfo)
480 604
        {
481 605
            UnpackCachedInfo(cachedInfo);
......
547 671
            });
548 672
        }
549 673

  
550

  
674
        /// <summary>
675
        /// Removing tag effectively just cleans up the attributes and CSS thus has no effect
676
        /// </summary>
677
        /// <param name="htmlToEdit"></param>
678
        /// <param name="htmlOriginal"></param>
679
        /// <param name="tagToRemove"></param>
680
        /// <param name="tags"></param>
681
        /// <param name="cachedInfo"></param>
682
        /// <returns></returns>
551 683
        public (string, CachedInfo) PartialPreprocessHTMLRemoveTag(string htmlToEdit, string htmlOriginal, AnnotationTagGeneric tagToRemove, List<AnnotationTagGeneric> tags, CachedInfo cachedInfo)
552 684
        {
553 685
            UnpackCachedInfo(cachedInfo);
Backend/Core/Services/HTMLService/IHTMLService.cs
10 10
{
11 11
    public interface IHTMLService
12 12
    {
13
        /// <summary>
14
        /// Make a full preprocessing of an HTML document and incorporate any existing tags into it
15
        /// </summary>
16
        /// <param name="htmlSource"></param>
17
        /// <param name="tags"></param>
18
        /// <returns>tuple of (HTML document to render, info to cache in the database)</returns>
13 19
        public (string, CachedInfo) FullPreprocessHTML(string htmlSource, List<AnnotationTagGeneric> tags);
20
        /// <summary>
21
        /// Make a partial preprocessing of an HTML document by adding a new tag into it
22
        /// </summary>
23
        /// <param name="htmlToEdit">already preprocessed HTML document</param>
24
        /// <param name="htmlOriginal">original HTML document</param>
25
        /// <param name="tagToAdd">the tag to add</param>
26
        /// <param name="tags">list of all tags related to the annotation</param>
27
        /// <param name="cachedInfo">database-cached info</param>
28
        /// <returns></returns>
14 29
        public (string, CachedInfo) PartialPreprocessHTMLAddTag(string htmlToEdit, string htmlOriginal, AnnotationTagGeneric tagToAdd, List<AnnotationTagGeneric> tags, CachedInfo cachedInfo);
30
        /// <summary>
31
        /// Make a partial preprocessing of an HTML document by remove an existing tag from it
32
        /// </summary>
33
        /// <param name="htmlToEdit">already preprocessed HTML document</param>
34
        /// <param name="htmlOriginal">original HTML document</param>
35
        /// <param name="tagToRemove">the tag to remove</param>
36
        /// <param name="tags">list of all tags related to the annotation</param>
37
        /// <param name="cachedInfo">database-cached info</param>
38
        /// <returns></returns>
15 39
        public (string, CachedInfo) PartialPreprocessHTMLRemoveTag(string htmlToEdit, string htmlOriginal, AnnotationTagGeneric tagToRemove, List<AnnotationTagGeneric> tags, CachedInfo cachedInfo);
16 40
    }
17 41
}
Backend/Core/Services/Registration.cs
7 7

  
8 8
namespace Core.Services
9 9
{
10
    /// <summary>
11
    /// Add new services here
12
    /// </summary>
10 13
    public class Registration
11 14
    {
15
        /// <summary>
16
        /// Registers services
17
        /// </summary>
18
        /// <param name="builder"></param>
12 19
        public static void RegisterServices(WebApplicationBuilder builder)
13 20
        {
14 21
            builder.Services.AddScoped<IUserService, UserServiceEF>();
Backend/Core/Services/TagService/ITagService.cs
12 12
{
13 13
    public interface ITagService
14 14
    {
15
        /// <summary>
16
        /// Returns a tree-like structure with tag categories, tags, and subtags
17
        /// </summary>
18
        /// <param name="userRole">Role is used to discriminate categories available to admins only</param>
19
        /// <returns></returns>
15 20
        public TagTreeResponse GetTagTree(ERole userRole);
21
        /// <summary>
22
        /// Creates a new category
23
        /// </summary>
24
        /// <param name="request"></param>
16 25
        public void CreateCategory(CreateCategoryRequest request);
26
        /// <summary>
27
        /// Deleted a category by Id
28
        /// </summary>
29
        /// <param name="categoryId"></param>
17 30
        public void DeleteCategory(Guid categoryId);
31
        /// <summary>
32
        /// Updates a category by Id
33
        /// </summary>
34
        /// <param name="request"></param>
35
        /// <param name="categoryId"></param>
18 36
        public void UpdateCategory(ModifyCategoryRequest request, Guid categoryId);
37
        /// <summary>
38
        /// Creates a new tag
39
        /// </summary>
40
        /// <param name="request"></param>
19 41
        public void CreateTag(CreateTagRequest request);
42
        /// <summary>
43
        /// Delete tag by Id
44
        /// </summary>
45
        /// <param name="tagId"></param>
20 46
        public void DeleteTag(Guid tagId);
47
        /// <summary>
48
        /// Update tag by Id
49
        /// </summary>
50
        /// <param name="request"></param>
51
        /// <param name="tagId"></param>
21 52
        public void UpdateTag(ModifyTagRequest request, Guid tagId);
53
        /// <summary>
54
        /// Create a subtag
55
        /// </summary>
56
        /// <param name="request"></param>
22 57
        public void CreateSubTag(CreateSubTagRequest request);
58
        /// <summary>
59
        /// Delete subtag by Id
60
        /// </summary>
61
        /// <param name="subtagId"></param>
23 62
        public void DeleteSubTag(Guid subtagId);
63
        /// <summary>
64
        /// Update subtag by Id
65
        /// </summary>
66
        /// <param name="request"></param>
67
        /// <param name="subtagId"></param>
24 68
        public void UpdateSubTag(ModifySubTagRequest request, Guid subtagId);
69
        /// <summary>
70
        /// Adds a note to tag's instance
71
        /// </summary>
72
        /// <param name="annotationId">Annotation</param>
73
        /// <param name="occurrenceId">Id of the Tag</param>
74
        /// <param name="user">User that's doing the adding</param>
75
        /// <param name="request"></param>
76
        /// <param name="isFinal">Whether the annotationId is for a FinalAnnotation or Annotation</param>
25 77
        public void AddNoteToTagInstance(Guid annotationId, Guid occurrenceId, User user, AddNoteToTagOccurenceRequest request, bool isFinal);
26 78
    }
27 79
}
Backend/Core/Services/TagService/TagServiceEF.cs
274 274

  
275 275
        public void AddNoteToTagInstance(Guid annotationId, Guid occurrenceId, User user, AddNoteToTagOccurenceRequest request, bool isFinal)
276 276
        {
277
            // We need to differentiate whether or not the annotation is final
277 278
            Annotation annotation = null;
278 279
            try
279 280
            {
Backend/Core/Services/UserService/IUserService.cs
11 11
{
12 12
    public interface IUserService
13 13
    {
14
        /// <summary>
15
        /// Creates a new user
16
        /// </summary>
17
        /// <param name="username"></param>
18
        /// <param name="name"></param>
19
        /// <param name="surname"></param>
20
        /// <param name="password"></param>
21
        /// <param name="role"></param>
22
        /// <returns></returns>
14 23
        public User? CreateUser(string username, string name, string surname, string password, ERole role);
24
        /// <summary>
25
        /// Returns a user with the specified username or null if no such user exists
26
        /// </summary>
27
        /// <param name="username"></param>
28
        /// <returns></returns>
15 29
        public User? GetUserByUsername(string username);
30
        /// <summary>
31
        /// Returns a user with the specified Id or null if no such user exists
32
        /// </summary>
33
        /// <param name="id"></param>
34
        /// <returns></returns>
16 35
        public User? GetUserById(Guid id);
36
        /// <summary>
37
        /// Updates information about the user
38
        /// Pass null as a parameter if you dont want to update it
39
        /// </summary>
40
        /// <param name="user"></param>
41
        /// <param name="username"></param>
42
        /// <param name="name"></param>
43
        /// <param name="surname"></param>
44
        /// <param name="role"></param>
45
        /// <returns></returns>
17 46
        public User UpdateUser(User user, string? username = null, string? name = null, string? surname = null, ERole? role = null);
47
        /// <summary>
48
        /// Updates information about the user
49
        /// Pass null as a parameter if you dont want to update it
50
        /// </summary>
51
        /// <param name="user"></param>
52
        /// <param name="username"></param>
53
        /// <param name="name"></param>
54
        /// <param name="surname"></param>
55
        /// <param name="role"></param>
56
        /// <returns></returns>
18 57
        public User? UpdateUser(Guid userId, string? username = null, string? name = null, string? surname = null, ERole? role = null);
58
        /// <summary>
59
        /// Sets a new password
60
        /// </summary>
61
        /// <param name="user"></param>
62
        /// <param name="newPassword"></param>
63
        /// <returns></returns>
19 64
        public User ChangePassword(User user, string newPassword);
65
        /// <summary>
66
        /// Sets a new password
67
        /// </summary>
68
        /// <param name="user"></param>
69
        /// <param name="newPassword"></param>
70
        /// <returns></returns>
20 71
        public User? ChangePassword(Guid userId, string newPassword);
72
        /// <summary>
73
        /// Check if the user with this username has this password
74
        /// </summary>
75
        /// <param name="username"></param>
76
        /// <param name="password"></param>
77
        /// <returns></returns>
21 78
        public User? CheckUsernamePassword(string username, string password);
79
        /// <summary>
80
        /// Returns list of all users
81
        /// </summary>
82
        /// <returns></returns>
22 83
        public UserList GetUsers();
84
        /// <summary>
85
        /// Deletes a user
86
        /// </summary>
87
        /// <param name="userId"></param>
23 88
        public void DeleteUser(Guid userId);
24 89
    }
25 90
}
Backend/Core/Services/UserService/UserServiceEF.cs
16 16
{
17 17
    public class UserServiceEF : IUserService
18 18
    {
19
        // DI
20

  
19 21
        private readonly DatabaseContext _databaseContext;
20 22
        private readonly ILogger _logger;
21 23
        private readonly IMapper _mapper;
Backend/Core/ZipUtils/Export.cs
10 10

  
11 11
namespace Core.ZipUtils
12 12
{
13
    /// <summary>
14
    /// Static methods for database exporting
15
    /// </summary>
13 16
    public class Export
14 17
    {
18
        /// <summary>
19
        /// Exports the specified annotations
20
        /// </summary>
21
        /// <param name="documents">list of documents to export</param>
22
        /// <param name="documentAnnotations">document-annotations to export mapping</param>
23
        /// <param name="documentFinalAnnotations">document-final annotations to export mapping</param>
24
        /// <param name="annotationTags">annotation-annotation tags mapping</param>
25
        /// <param name="finalAnnotationTags">final annotation-final annotation tags mapping</param>
26
        /// <returns></returns>
15 27
        public static MemoryStream FullExport(List<Document> documents, Dictionary<Document, List<Annotation>> documentAnnotations, Dictionary<Document, FinalAnnotation> documentFinalAnnotations,
16 28
            Dictionary<Annotation, List<AnnotationTag>> annotationTags, Dictionary<FinalAnnotation, List<FinalAnnotationTag>> finalAnnotationTags)
17 29
        {
18 30
            MemoryStream ms = new MemoryStream();
31
            // Set keepOpen to true so that Dispose() does not close the MemoryStream
19 32
            var archive = new ZipArchive(ms, ZipArchiveMode.Create, true);
20 33

  
21 34
            for (int docIndex = 0; docIndex < documents.Count; docIndex++)
......
37 50
                    CreateFile(documentDir + $"/annotation_{annotationIndex:00000}.json", annotationInfoJson, archive);
38 51
                }
39 52

  
53
                // Deal with final annotation if it exists
40 54
                var finalAnnotation = documentFinalAnnotations[document];
41 55
                if (finalAnnotation == null)
42 56
                {
......
48 62
                CreateFile(documentDir + "/final.json", finalAnnotationInfoJson, archive);
49 63
            }
50 64

  
65
            // Dispose of archive to close the header
51 66
            archive.Dispose();
52 67
            ms.Position = 0;
53 68
            return ms;
54 69
        }
55 70

  
71
        /// <summary>
72
        /// Creates a file and writes to it
73
        /// </summary>
74
        /// <param name="path">path to file</param>
75
        /// <param name="fileContent">string to write</param>
76
        /// <param name="archive">archive to write it to</param>
56 77
        private static void CreateFile(string path, string fileContent, ZipArchive archive)
57 78
        {
58 79
            var entry = archive.CreateEntry(path);
......
61 82
            entryStream.Close();
62 83
        }
63 84

  
85
        /// <summary>
86
        /// Dumps a Document into JSON-serialized ExportDocumentInfo
87
        /// </summary>
88
        /// <param name="document">Document to serialize</param>
89
        /// <returns>JSON-serialized ExportDocumentInfo</returns>
64 90
        private static string DumpDocument(Document document)
65 91
        {
66 92
            ExportDocumentInfo documentInfo = new();
......
71 97
            return JsonConvert.SerializeObject(documentInfo);
72 98
        }
73 99

  
100
        /// <summary>
101
        /// Dumps annotation into JSON-serialized ExportAnnotationInfo
102
        /// </summary>
103
        /// <param name="annotation">Annotation to dump</param>
104
        /// <param name="tags">Tags related to the annotation</param>
105
        /// <param name="documentId">Id of the document the annotation is related to</param>
106
        /// <returns>JSON-serialized ExportAnnotationInfo</returns>
74 107
        private static string DumpAnnotation(Annotation annotation, List<AnnotationTagGeneric> tags, Guid documentId)
75 108
        {
76 109
            ExportAnnotationInfo annotationInfo = new();
......
108 141

  
109 142
    public class ExportDocumentInfo
110 143
    {
144
        /// <summary>
145
        /// Document name
146
        /// </summary>
111 147
        public string Name { get; set; }
148
        /// <summary>
149
        /// Original document content
150
        /// </summary>
112 151
        public string Content { get; set; }
152
        /// <summary>
153
        /// Id of the document
154
        /// </summary>
113 155
        public Guid DocumentId { get; set; }
114 156
    }
115 157

  
116 158
    public class ExportAnnotationInfo
117 159
    {
160
        /// <summary>
... Rozdílový soubor je zkrácen, protože jeho délka přesahuje max. limit.

Také k dispozici: Unified diff