Merge pull request #762 from ChenGong-lessen/features/dashboard
Features/dashboard
This commit is contained in:
commit
c7a94b1d11
|
|
@ -32,9 +32,13 @@ public interface IBotSharpRepository : IHaveServiceProvider
|
|||
List<User> GetUserByIds(List<string> ids) => throw new NotImplementedException();
|
||||
List<User> GetUsersByAffiliateId(string affiliateId) => throw new NotImplementedException();
|
||||
User? GetUserByUserName(string userName) => throw new NotImplementedException();
|
||||
Dashboard? GetDashboard(string id = null) => throw new NotImplementedException();
|
||||
void CreateUser(User user) => throw new NotImplementedException();
|
||||
void UpdateExistUser(string userId, User user) => throw new NotImplementedException();
|
||||
void UpdateUserVerified(string userId) => throw new NotImplementedException();
|
||||
void AddDashboardConversation(string userId, string conversationId) => throw new NotImplementedException();
|
||||
void RemoveDashboardConversation(string userId, string conversationId) => throw new NotImplementedException();
|
||||
void UpdateDashboardConversation(string userId, DashboardConversation dashConv) => throw new NotImplementedException();
|
||||
void UpdateUserVerificationCode(string userId, string verficationCode) => throw new NotImplementedException();
|
||||
void UpdateUserPassword(string userId, string password) => throw new NotImplementedException();
|
||||
void UpdateUserEmail(string userId, string email) => throw new NotImplementedException();
|
||||
|
|
|
|||
|
|
@ -29,4 +29,8 @@ public interface IUserService
|
|||
Task<bool> UpdatePassword(string newPassword, string verificationCode);
|
||||
Task<DateTime> GetUserTokenExpires();
|
||||
Task<bool> UpdateUsersIsDisable(List<string> userIds, bool isDisable);
|
||||
Task<bool> AddDashboardConversation(string userId, string conversationId);
|
||||
Task<bool> RemoveDashboardConversation(string userId, string conversationId);
|
||||
Task UpdateDashboardConversation(string userId, DashboardConversation dashConv);
|
||||
Task<Dashboard?> GetDashboard(string userId);
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
namespace BotSharp.Abstraction.Users.Models;
|
||||
|
||||
public class Dashboard
|
||||
{
|
||||
public IList<DashboardConversation> ConversationList { get; set; } = [];
|
||||
}
|
||||
|
||||
public class DashboardComponent
|
||||
{
|
||||
public required string Id { get; set; }
|
||||
public string? Name { get; set; }
|
||||
}
|
||||
|
||||
public class DashboardConversation : DashboardComponent
|
||||
{
|
||||
public string? ConversationId { get; set; }
|
||||
public string? Instruction { get; set; } = "";
|
||||
}
|
||||
|
||||
|
|
@ -41,6 +41,11 @@ public partial class FileRepository
|
|||
return Users.FirstOrDefault(x => x.UserName == userName.ToLower());
|
||||
}
|
||||
|
||||
public Dashboard? GetDashboard(string id = null)
|
||||
{
|
||||
return Dashboards.FirstOrDefault();
|
||||
}
|
||||
|
||||
public void CreateUser(User user)
|
||||
{
|
||||
var userId = Guid.NewGuid().ToString();
|
||||
|
|
@ -191,4 +196,68 @@ public partial class FileRepository
|
|||
_users = [];
|
||||
return true;
|
||||
}
|
||||
|
||||
public void AddDashboardConversation(string userId, string conversationId)
|
||||
{
|
||||
var user = GetUserById(userId);
|
||||
if (user == null) return;
|
||||
|
||||
// one user only has one dashboard currently
|
||||
var dash = Dashboards.FirstOrDefault();
|
||||
dash ??= new();
|
||||
var existingConv = dash.ConversationList.FirstOrDefault(x => string.Equals(x.ConversationId, conversationId, StringComparison.OrdinalIgnoreCase));
|
||||
if (existingConv != null) return;
|
||||
|
||||
var dashconv = new DashboardConversation
|
||||
{
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
ConversationId = conversationId
|
||||
};
|
||||
|
||||
dash.ConversationList.Add(dashconv);
|
||||
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, USERS_FOLDER, userId);
|
||||
var path = Path.Combine(dir, DASHBOARD_FILE);
|
||||
File.WriteAllText(path, JsonSerializer.Serialize(dash, _options));
|
||||
}
|
||||
|
||||
public void RemoveDashboardConversation(string userId, string conversationId)
|
||||
{
|
||||
var user = GetUserById(userId);
|
||||
if (user == null) return;
|
||||
|
||||
// one user only has one dashboard currently
|
||||
var dash = Dashboards.FirstOrDefault();
|
||||
if (dash == null) return;
|
||||
|
||||
var dashconv = dash.ConversationList.FirstOrDefault(
|
||||
c => string.Equals(c.ConversationId, conversationId, StringComparison.OrdinalIgnoreCase));
|
||||
if (dashconv == null) return;
|
||||
|
||||
dash.ConversationList.Remove(dashconv);
|
||||
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, USERS_FOLDER, userId);
|
||||
var path = Path.Combine(dir, DASHBOARD_FILE);
|
||||
File.WriteAllText(path, JsonSerializer.Serialize(dash, _options));
|
||||
}
|
||||
|
||||
public void UpdateDashboardConversation(string userId, DashboardConversation dashConv)
|
||||
{
|
||||
var user = GetUserById(userId);
|
||||
if (user == null) return;
|
||||
|
||||
// one user only has one dashboard currently
|
||||
var dash = Dashboards.FirstOrDefault();
|
||||
if (dash == null) return;
|
||||
|
||||
var curIdx = dash.ConversationList.ToList().FindIndex(
|
||||
x => string.Equals(x.ConversationId, dashConv.ConversationId, StringComparison.OrdinalIgnoreCase));
|
||||
if (curIdx < 0) return;
|
||||
|
||||
dash.ConversationList[curIdx] = dashConv;
|
||||
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, USERS_FOLDER, userId);
|
||||
var path = Path.Combine(dir, DASHBOARD_FILE);
|
||||
File.WriteAllText(path, JsonSerializer.Serialize(dash, _options));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ public partial class FileRepository : IBotSharpRepository
|
|||
private const string AGENT_FILE = "agent.json";
|
||||
private const string AGENT_INSTRUCTION_FILE = "instruction";
|
||||
private const string AGENT_SAMPLES_FILE = "samples.txt";
|
||||
private const string DASHBOARD_FILE = "dashboard.json";
|
||||
private const string AGENT_INSTRUCTIONS_FOLDER = "instructions";
|
||||
private const string AGENT_FUNCTIONS_FOLDER = "functions";
|
||||
private const string AGENT_TEMPLATES_FOLDER = "templates";
|
||||
|
|
@ -83,6 +84,7 @@ public partial class FileRepository : IBotSharpRepository
|
|||
|
||||
private List<Role> _roles = new List<Role>();
|
||||
private List<User> _users = new List<User>();
|
||||
private List<Dashboard> _dashboards = [];
|
||||
private List<Agent> _agents = new List<Agent>();
|
||||
private List<RoleAgent> _roleAgents = new List<RoleAgent>();
|
||||
private List<UserAgent> _userAgents = new List<UserAgent>();
|
||||
|
|
@ -170,6 +172,36 @@ public partial class FileRepository : IBotSharpRepository
|
|||
}
|
||||
}
|
||||
|
||||
private IQueryable<Dashboard> Dashboards
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_dashboards.IsNullOrEmpty())
|
||||
{
|
||||
return _dashboards.AsQueryable();
|
||||
}
|
||||
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, USERS_FOLDER);
|
||||
_dashboards = [];
|
||||
if (Directory.Exists(dir))
|
||||
{
|
||||
foreach (var d in Directory.GetDirectories(dir))
|
||||
{
|
||||
var dashboardFile = Path.Combine(d, DASHBOARD_FILE);
|
||||
if (!Directory.Exists(d) || !File.Exists(dashboardFile))
|
||||
continue;
|
||||
|
||||
var json = File.ReadAllText(dashboardFile);
|
||||
var dash = JsonSerializer.Deserialize<Dashboard>(json, _options);
|
||||
|
||||
if (dash == null) continue;
|
||||
_dashboards.Add(dash);
|
||||
}
|
||||
}
|
||||
return _dashboards.AsQueryable();
|
||||
}
|
||||
}
|
||||
|
||||
private IQueryable<Agent> Agents
|
||||
{
|
||||
get
|
||||
|
|
|
|||
|
|
@ -736,4 +736,42 @@ public class UserService : IUserService
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> AddDashboardConversation(string userId, string conversationId)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
db.AddDashboardConversation(userId, conversationId);
|
||||
|
||||
await Task.CompletedTask;
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> RemoveDashboardConversation(string userId, string conversationId)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
db.RemoveDashboardConversation(userId, conversationId);
|
||||
|
||||
await Task.CompletedTask;
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task UpdateDashboardConversation(string userId, DashboardConversation newDashConv)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var dashConv = db.GetDashboard(userId)?.ConversationList.FirstOrDefault(x => string.Equals(x.ConversationId, newDashConv.ConversationId));
|
||||
if (dashConv == null) return;
|
||||
dashConv.Name = newDashConv.Name ?? dashConv.Name;
|
||||
dashConv.Instruction = newDashConv.Instruction ?? dashConv.Instruction;
|
||||
db.UpdateDashboardConversation(userId, dashConv);
|
||||
await Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
public async Task<Dashboard?> GetDashboard(string userId)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var dash = db.GetDashboard();
|
||||
await Task.CompletedTask;
|
||||
return dash;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -511,6 +511,28 @@ public class ConversationController : ControllerBase
|
|||
}
|
||||
#endregion
|
||||
|
||||
#region miscellaneous
|
||||
[HttpPut("/agent/{agentId}/conversation/{conversationId}/dashboard")]
|
||||
public async Task<bool> PinConversationToDashboard([FromRoute] string agentId, [FromRoute] string conversationId)
|
||||
{
|
||||
var userService = _services.GetRequiredService<IUserService>();
|
||||
|
||||
var user = await userService.GetUser(_user.Id);
|
||||
var pinned = await userService.AddDashboardConversation(user.Id, conversationId);
|
||||
return pinned;
|
||||
}
|
||||
|
||||
[HttpDelete("/agent/{agentId}/conversation/{conversationId}/dashboard")]
|
||||
public async Task<bool> UnpinConversationFromDashboard([FromRoute] string agentId, [FromRoute] string conversationId)
|
||||
{
|
||||
var userService = _services.GetRequiredService<IUserService>();
|
||||
|
||||
var user = await userService.GetUser(_user.Id);
|
||||
var unpinned = await userService.RemoveDashboardConversation(user.Id, conversationId);
|
||||
return unpinned;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private methods
|
||||
private void SetStates(IConversationService conv, NewMessageModel input)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
using BotSharp.Abstraction.Options;
|
||||
using BotSharp.Abstraction.Users.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BotSharp.OpenAPI.Controllers;
|
||||
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
public class DashboardController : ControllerBase
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly IUserIdentity _user;
|
||||
|
||||
public DashboardController(IServiceProvider services,
|
||||
IUserIdentity user,
|
||||
BotSharpOptions options)
|
||||
{
|
||||
_services = services;
|
||||
_user = user;
|
||||
|
||||
}
|
||||
#region User Components
|
||||
[HttpGet("/dashboard/components")]
|
||||
public async Task<UserDashboardModel> GetComponents(string userId)
|
||||
{
|
||||
var userService = _services.GetRequiredService<IUserService>();
|
||||
var dashboardProfile = await userService.GetDashboard(userId);
|
||||
if (dashboardProfile == null) return new UserDashboardModel();
|
||||
var result = new UserDashboardModel
|
||||
{
|
||||
ConversationList = dashboardProfile.ConversationList.Select(
|
||||
x => new UserDashboardConversationModel
|
||||
{
|
||||
Name = x.Name,
|
||||
ConversationId = x.ConversationId,
|
||||
Instruction = x.Instruction
|
||||
}
|
||||
).ToList()
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
[HttpPost("/dashboard/component/conversation")]
|
||||
public async Task UpdateDashboardConversationInstruction(string userId, UserDashboardConversationModel dashConv)
|
||||
{
|
||||
if (string.IsNullOrEmpty(dashConv.Name) && string.IsNullOrEmpty(dashConv.Instruction))
|
||||
{
|
||||
return;
|
||||
}
|
||||
var newDashConv = new DashboardConversation
|
||||
{
|
||||
Id = Guid.Empty.ToString(),
|
||||
ConversationId = dashConv.ConversationId
|
||||
};
|
||||
if (!string.IsNullOrEmpty(dashConv.Name))
|
||||
{
|
||||
newDashConv.Name = dashConv.Name;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(dashConv.Instruction))
|
||||
{
|
||||
newDashConv.Instruction = dashConv.Instruction;
|
||||
}
|
||||
|
||||
var userService = _services.GetRequiredService<IUserService>();
|
||||
await userService.UpdateDashboardConversation(userId, newDashConv);
|
||||
return;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ public class ConversationViewModel
|
|||
[JsonPropertyName("agent_name")]
|
||||
public string AgentName { get; set; }
|
||||
|
||||
[JsonPropertyName("title")]
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
public UserViewModel User { get; set; } = new UserViewModel();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BotSharp.OpenAPI.ViewModels.Users;
|
||||
public class UserDashboardModel
|
||||
{
|
||||
|
||||
[JsonPropertyName("conversation_list")]
|
||||
public IList<UserDashboardConversationModel> ConversationList { get; set; } = [];
|
||||
}
|
||||
|
||||
public class UserDashboardConversationModel
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public string? Name { get; set; }
|
||||
|
||||
[JsonPropertyName("conversation_id")]
|
||||
public string? ConversationId { get; set; }
|
||||
|
||||
[JsonPropertyName("instruction")]
|
||||
public string? Instruction { get; set; }
|
||||
}
|
||||
|
|
@ -26,6 +26,8 @@ public class UserDocument : MongoBase
|
|||
public DateTime CreatedTime { get; set; }
|
||||
public DateTime UpdatedTime { get; set; }
|
||||
|
||||
public Dashboard? Dashboard { get; set; }
|
||||
|
||||
public User ToUser()
|
||||
{
|
||||
return new User
|
||||
|
|
|
|||
|
|
@ -317,4 +317,51 @@ public partial class MongoRepository
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void AddDashboardConversation(string userId, string conversationId)
|
||||
{
|
||||
var user = _dc.Users.AsQueryable()
|
||||
.FirstOrDefault(x => x.Id == userId || (x.ExternalId != null && x.ExternalId == userId));
|
||||
if (user == null) return;
|
||||
var curDash = user.Dashboard ?? new Dashboard();
|
||||
curDash.ConversationList.Add(new DashboardConversation
|
||||
{
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
ConversationId = conversationId
|
||||
});
|
||||
|
||||
var filter = Builders<UserDocument>.Filter.Eq(x => x.Id, userId);
|
||||
var update = Builders<UserDocument>.Update.Set(x => x.Dashboard, curDash)
|
||||
.Set(x => x.UpdatedTime, DateTime.UtcNow);
|
||||
}
|
||||
|
||||
public void RemoveDashboardConversation(string userId, string conversationId)
|
||||
{
|
||||
var user = _dc.Users.AsQueryable()
|
||||
.FirstOrDefault(x => x.Id == userId || (x.ExternalId != null && x.ExternalId == userId));
|
||||
if (user == null || user.Dashboard == null || user.Dashboard.ConversationList.IsNullOrEmpty()) return;
|
||||
var curDash = user.Dashboard;
|
||||
var unpinConv = user.Dashboard.ConversationList.FirstOrDefault(
|
||||
x => string.Equals(x.ConversationId, conversationId, StringComparison.OrdinalIgnoreCase));
|
||||
if (unpinConv == null) return;
|
||||
curDash.ConversationList.Remove(unpinConv);
|
||||
|
||||
var filter = Builders<UserDocument>.Filter.Eq(x => x.Id, userId);
|
||||
var update = Builders<UserDocument>.Update.Set(x => x.Dashboard, curDash)
|
||||
.Set(x => x.UpdatedTime, DateTime.UtcNow);
|
||||
}
|
||||
|
||||
public void UpdateDashboardConversation(string userId, DashboardConversation dashConv)
|
||||
{
|
||||
var user = _dc.Users.AsQueryable()
|
||||
.FirstOrDefault(x => x.Id == userId || (x.ExternalId != null && x.ExternalId == userId));
|
||||
if (user == null || user.Dashboard == null || user.Dashboard.ConversationList.IsNullOrEmpty()) return;
|
||||
var curIdx = user.Dashboard.ConversationList.ToList().FindIndex(
|
||||
x => string.Equals(x.ConversationId, dashConv.ConversationId, StringComparison.OrdinalIgnoreCase));
|
||||
if (curIdx < 0) return;
|
||||
|
||||
var filter = Builders<UserDocument>.Filter.Eq(x => x.Id, userId);
|
||||
var update = Builders<UserDocument>.Update.Set(x => x.Dashboard.ConversationList[curIdx], dashConv)
|
||||
.Set(x => x.UpdatedTime, DateTime.UtcNow);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue