Skip to content

Commit fb69ab3

Browse files
author
Ubuntu
committed
カスタムフィールドに対応
1 parent cc5ebc6 commit fb69ab3

15 files changed

+295
-45
lines changed

redmine-net-api-dev.sln

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.10.34916.146
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "redmine-net-api", "src\redmine-net-api\redmine-net-api.csproj", "{E955CF52-3F03-46A6-9B72-420726AE1FCD}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sample", "sample\sample.csproj", "{CEA0AE5A-09F5-412E-848F-58CE72C8F114}"
9+
EndProject
10+
Global
11+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
12+
Debug|Any CPU = Debug|Any CPU
13+
DebugJson|Any CPU = DebugJson|Any CPU
14+
Release|Any CPU = Release|Any CPU
15+
EndGlobalSection
16+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
17+
{E955CF52-3F03-46A6-9B72-420726AE1FCD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
18+
{E955CF52-3F03-46A6-9B72-420726AE1FCD}.Debug|Any CPU.Build.0 = Debug|Any CPU
19+
{E955CF52-3F03-46A6-9B72-420726AE1FCD}.DebugJson|Any CPU.ActiveCfg = DebugJson|Any CPU
20+
{E955CF52-3F03-46A6-9B72-420726AE1FCD}.DebugJson|Any CPU.Build.0 = DebugJson|Any CPU
21+
{E955CF52-3F03-46A6-9B72-420726AE1FCD}.Release|Any CPU.ActiveCfg = Release|Any CPU
22+
{E955CF52-3F03-46A6-9B72-420726AE1FCD}.Release|Any CPU.Build.0 = Release|Any CPU
23+
{CEA0AE5A-09F5-412E-848F-58CE72C8F114}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24+
{CEA0AE5A-09F5-412E-848F-58CE72C8F114}.Debug|Any CPU.Build.0 = Debug|Any CPU
25+
{CEA0AE5A-09F5-412E-848F-58CE72C8F114}.DebugJson|Any CPU.ActiveCfg = Debug|Any CPU
26+
{CEA0AE5A-09F5-412E-848F-58CE72C8F114}.DebugJson|Any CPU.Build.0 = Debug|Any CPU
27+
{CEA0AE5A-09F5-412E-848F-58CE72C8F114}.Release|Any CPU.ActiveCfg = Release|Any CPU
28+
{CEA0AE5A-09F5-412E-848F-58CE72C8F114}.Release|Any CPU.Build.0 = Release|Any CPU
29+
EndGlobalSection
30+
GlobalSection(SolutionProperties) = preSolution
31+
HideSolutionNode = FALSE
32+
EndGlobalSection
33+
GlobalSection(ExtensibilityGlobals) = postSolution
34+
SolutionGuid = {D7E10C0C-0862-43D7-A3F8-23D13B8DFD3F}
35+
EndGlobalSection
36+
EndGlobal

src/redmine-net-api/IRedmineManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ void Delete<T>(string id, RequestOptions requestOptions = null)
103103
/// Returns the token for uploaded file.
104104
/// </returns>
105105
/// <exception cref="RedmineException"></exception>
106-
Upload UploadFile(byte[] data);
106+
Upload UploadFile(byte[] data, RequestOptions requestOptions = null);
107107

108108
/// <summary>
109109
/// Downloads a file from the specified address.

src/redmine-net-api/Net/WebClient/InternalRedmineApiWebClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ public ApiResponseMessage Download(string address, RequestOptions requestOptions
131131
public ApiResponseMessage Upload(string address, byte[] data, RequestOptions requestOptions = null)
132132
{
133133
var content = new ByteArrayApiRequestMessageContent(data);
134-
return HandleRequest(address, HttpVerbs.UPLOAD, requestOptions, content);
134+
return HandleRequest(address, HttpVerbs.POST, requestOptions, content);
135135
}
136136

137137
#if !(NET20)

src/redmine-net-api/Net/WebClient/MessageContent/ByteArrayApiRequestMessageContent.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ internal class ByteArrayApiRequestMessageContent : ApiRequestMessageContent
2121
public ByteArrayApiRequestMessageContent(byte[] content)
2222
{
2323
Body = content;
24+
ContentType = RedmineConstants.CONTENT_TYPE_APPLICATION_STREAM;
2425
}
2526
}

src/redmine-net-api/RedmineKeys.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,10 @@ public static class RedmineKeys
268268
/// <summary>
269269
///
270270
/// </summary>
271+
public const string FIELD = "field";
272+
/// <summary>
273+
///
274+
/// </summary>
271275
public const string FIELD_FORMAT = "field_format";
272276
/// <summary>
273277
///
@@ -362,7 +366,7 @@ public static class RedmineKeys
362366
/// <summary>
363367
///
364368
/// </summary>
365-
public const string ISSUE_CUSTOM_FIELD_IDS = "issue_custom_field_ids";
369+
public const string ISSUE_CUSTOM_FIELDS = "issue_custom_fields";
366370
/// <summary>
367371
///
368372
/// </summary>
@@ -849,6 +853,10 @@ public static class RedmineKeys
849853
///
850854
/// </summary>
851855
public const string WIKI_PAGES = "wiki_pages";
856+
/// <summary>
857+
///
858+
/// </summary>
859+
public const string ENABLED_STANDARD_FIELDS = "enabled_standard_fields";
852860

853861

854862
}

src/redmine-net-api/RedmineManager.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,15 @@ public List<T> Get<T>(RequestOptions requestOptions = null)
128128
return GetObjects<T>(uri, requestOptions);
129129
}
130130

131+
/// <inheritdoc />
132+
public List<T> GetChildren<T>(string ownerId, RequestOptions requestOptions = null)
133+
where T : class, new()
134+
{
135+
var uri = RedmineApiUrls.GetListFragment<T>(ownerId);
136+
137+
return GetObjects<T>(uri, requestOptions);
138+
}
139+
131140
/// <inheritdoc />
132141
public PagedResults<T> GetPaginated<T>(RequestOptions requestOptions = null)
133142
where T : class, new()
@@ -171,11 +180,11 @@ public void Delete<T>(string id, RequestOptions requestOptions = null)
171180
}
172181

173182
/// <inheritdoc />
174-
public Upload UploadFile(byte[] data)
183+
public Upload UploadFile(byte[] data, RequestOptions requestOptions = null)
175184
{
176185
var url = RedmineApiUrls.UploadFragment();
177186

178-
var response = ApiClient.Upload(url, data);
187+
var response = ApiClient.Upload(url, data, requestOptions);
179188

180189
return response.DeserializeTo<Upload>(Serializer);
181190
}

src/redmine-net-api/RedmineManagerOptionsBuilder.cs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,22 @@ public RedmineManagerOptionsBuilder WithVersion(Version version)
177177
return this;
178178
}
179179

180+
/// <summary>
181+
/// Redmineのルートパス
182+
/// </summary>
183+
public string RootPath { get; private set; }
184+
185+
/// <summary>
186+
/// ルートパスを設定する
187+
/// </summary>
188+
/// <param name="rootPath"></param>
189+
/// <returns></returns>
190+
public RedmineManagerOptionsBuilder WithRootPath(string rootPath)
191+
{
192+
RootPath = rootPath;
193+
return this;
194+
}
195+
180196
/// <summary>
181197
///
182198
/// </summary>
@@ -201,7 +217,7 @@ internal RedmineManagerOptions Build()
201217
{
202218
ClientOptions ??= new RedmineWebClientOptions();
203219

204-
var baseAddress = CreateRedmineUri(Host, ClientOptions.Scheme);
220+
var baseAddress = CreateRedmineUri(Host, ClientOptions.Scheme, RootPath);
205221

206222
var options = new RedmineManagerOptions()
207223
{
@@ -268,7 +284,7 @@ internal static void EnsureDomainNameIsValid(string domainName)
268284
}
269285
}
270286

271-
internal static Uri CreateRedmineUri(string host, string scheme = null)
287+
internal static Uri CreateRedmineUri(string host, string scheme = null, string root = null)
272288
{
273289
if (host.IsNullOrWhiteSpace() || host.Equals("string.Empty", StringComparison.OrdinalIgnoreCase))
274290
{
@@ -362,6 +378,10 @@ internal static Uri CreateRedmineUri(string host, string scheme = null)
362378
uriBuilder.Port = int.TryParse(uri.LocalPath, out var port) ? port : uri.Port;
363379
uriBuilder.Host = uri.Host;
364380
}
381+
if (!string.IsNullOrWhiteSpace(root))
382+
{
383+
uriBuilder.Path = root;
384+
}
365385
}
366386

367387
try

src/redmine-net-api/Types/CustomField.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ public sealed class CustomField : IdentifiableName, IEquatable<CustomField>
7373
///
7474
/// </summary>
7575
public bool Searchable { get; internal set; }
76+
/// <summary>
77+
///
78+
/// </summary>
79+
public string Description { get; internal set; }
7680

7781
/// <summary>
7882
///
@@ -139,6 +143,7 @@ public override void ReadXml(XmlReader reader)
139143
case RedmineKeys.SEARCHABLE: Searchable = reader.ReadElementContentAsBoolean(); break;
140144
case RedmineKeys.TRACKERS: Trackers = reader.ReadElementContentAsCollection<TrackerCustomField>(); break;
141145
case RedmineKeys.VISIBLE: Visible = reader.ReadElementContentAsBoolean(); break;
146+
case RedmineKeys.DESCRIPTION: Description = reader.ReadElementContentAsString().Trim(); break;
142147
default: reader.Read(); break;
143148
}
144149
}
@@ -206,13 +211,13 @@ public bool Equals(CustomField other)
206211
&& Multiple == other.Multiple
207212
&& Searchable == other.Searchable
208213
&& Visible == other.Visible
209-
&& string.Equals(CustomizedType,other.CustomizedType, StringComparison.OrdinalIgnoreCase)
210-
&& string.Equals(DefaultValue,other.DefaultValue, StringComparison.OrdinalIgnoreCase)
211-
&& string.Equals(FieldFormat,other.FieldFormat, StringComparison.OrdinalIgnoreCase)
214+
&& string.Equals(CustomizedType, other.CustomizedType, StringComparison.OrdinalIgnoreCase)
215+
&& string.Equals(DefaultValue, other.DefaultValue, StringComparison.OrdinalIgnoreCase)
216+
&& string.Equals(FieldFormat, other.FieldFormat, StringComparison.OrdinalIgnoreCase)
212217
&& MaxLength == other.MaxLength
213218
&& MinLength == other.MinLength
214-
&& string.Equals(Name,other.Name, StringComparison.OrdinalIgnoreCase)
215-
&& string.Equals(Regexp,other.Regexp, StringComparison.OrdinalIgnoreCase)
219+
&& string.Equals(Name, other.Name, StringComparison.OrdinalIgnoreCase)
220+
&& string.Equals(Regexp, other.Regexp, StringComparison.OrdinalIgnoreCase)
216221
&& PossibleValues.Equals(other.PossibleValues)
217222
&& Roles.Equals(other.Roles)
218223
&& Trackers.Equals(other.Trackers);

src/redmine-net-api/Types/CustomFieldValue.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,19 @@ public CustomFieldValue()
4242
/// <summary>
4343
///
4444
/// </summary>
45+
/// <param name="token"></param>
4546
/// <param name="value"></param>
46-
public CustomFieldValue(string value)
47+
public CustomFieldValue(string value, bool token = false)
4748
{
4849
Info = value;
50+
IsToken = token;
4951
}
50-
52+
53+
/// <summary>
54+
///
55+
/// </summary>
56+
public bool IsToken { get; private set; }
57+
5158
#region Properties
5259

5360
/// <summary>

src/redmine-net-api/Types/Field.cs

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
Copyright 2011 - 2023 Adrian Popescu
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
using System;
18+
using System.Diagnostics;
19+
using System.Xml;
20+
using System.Xml.Schema;
21+
using System.Xml.Serialization;
22+
using Newtonsoft.Json;
23+
using Redmine.Net.Api.Internals;
24+
using Redmine.Net.Api.Serialization;
25+
26+
namespace Redmine.Net.Api.Types
27+
{
28+
/// <summary>
29+
///
30+
/// </summary>
31+
[DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")]
32+
[XmlRoot(RedmineKeys.FIELD)]
33+
#pragma warning disable CA1711
34+
public sealed class Field : IXmlSerializable, IJsonSerializable, IEquatable<Field>
35+
#pragma warning restore CA1711
36+
{
37+
#region Properties
38+
/// <summary>
39+
///
40+
/// </summary>
41+
public string Info { get; internal set; }
42+
#endregion
43+
44+
#region Implementation of IXmlSerializable
45+
46+
/// <summary>
47+
///
48+
/// </summary>
49+
/// <returns></returns>
50+
public XmlSchema GetSchema() { return null; }
51+
52+
/// <summary>
53+
///
54+
/// </summary>
55+
/// <param name="reader"></param>
56+
public void ReadXml(XmlReader reader)
57+
{
58+
reader.Read();
59+
if (reader.NodeType == XmlNodeType.Text)
60+
{
61+
Info = reader.Value;
62+
}
63+
}
64+
65+
/// <summary>
66+
///
67+
/// </summary>
68+
/// <param name="writer"></param>
69+
public void WriteXml(XmlWriter writer) { }
70+
71+
#endregion
72+
73+
#region Implementation of IJsonSerialization
74+
/// <summary>
75+
///
76+
/// </summary>
77+
/// <param name="reader"></param>
78+
public void ReadJson(JsonReader reader)
79+
{
80+
if (reader.TokenType == JsonToken.String)
81+
{
82+
Info = reader.Value.ToString();
83+
}
84+
}
85+
86+
/// <summary>
87+
///
88+
/// </summary>
89+
/// <param name="writer"></param>
90+
public void WriteJson(JsonWriter writer) { }
91+
#endregion
92+
93+
#region Implementation of IEquatable<Field>
94+
/// <summary>
95+
///
96+
/// </summary>
97+
/// <param name="other"></param>
98+
/// <returns></returns>
99+
public bool Equals(Field other)
100+
{
101+
return other != null && Info == other.Info;
102+
}
103+
104+
/// <summary>
105+
///
106+
/// </summary>
107+
/// <param name="obj"></param>
108+
/// <returns></returns>
109+
public override bool Equals(object obj)
110+
{
111+
if (ReferenceEquals(null, obj)) return false;
112+
if (ReferenceEquals(this, obj)) return true;
113+
if (obj.GetType() != GetType()) return false;
114+
return Equals(obj as Field);
115+
}
116+
117+
/// <summary>
118+
///
119+
/// </summary>
120+
/// <returns></returns>
121+
public override int GetHashCode()
122+
{
123+
unchecked
124+
{
125+
var hashCode = 13;
126+
hashCode = HashCodeHelper.GetHashCode(Info, hashCode);
127+
return hashCode;
128+
}
129+
}
130+
#endregion
131+
132+
/// <summary>
133+
///
134+
/// </summary>
135+
/// <returns></returns>
136+
private string DebuggerDisplay => $"[{nameof(Field)}: {Info}]";
137+
138+
}
139+
}

0 commit comments

Comments
 (0)