Получаем количество проектов BIM360 для каждого пользователя
Существует множество способов получения данных BIM 360 для создания разнообразных отчетов. Часто встречается вопрос, как получить количество или список проектов для конкретного пользователя. Это возможно реализовать с помощью комбинации BIM 360 API и Data Management API. Давайте разберемся, как получить эту информацию и создадим отчет с гистограммой.
Для этого:
1. Получим 2 legged access токен доступа, обязательно указав scopes: "account:read" и "data:read "
2. Получим перечень пользователей аккаунта BIM 360 (GET users)
3. Для каждого пользователя получим перечень проектов с помощью метода API GET projects, передав в запросе заголовок x-user-id со значением user.uid.
Вот, фактически и всё. С помощью простых манипуляций с JSON объединяем данные из пунктов 2 и 3. Но есть один нюанс. Количество пользователей аккаунта BIM 360 может быть достаточно большим и, соответственно, при получении проектов метод GET projects может вернуть результат "Превышен лимит количества запросов". Существуют разные способы обхода данной проблемы. В этой статье мы воспользуемся одним из самых простых.
Серверный код (пример на C#) для получения списка пользователей (имя и uid), предполагаем, что регион - US, получаем все страницы (до 100 пользователей на каждой странице):
- public async Task<JArray> GetUsers(string hubId, string accessToken, JArray users = null, int offset = 0)
- {
- users = (users == null ? new JArray() : users);
- RestClient client = new RestClient(BASE_URL);
- RestRequest request = new RestRequest("/hq/v1/accounts/{account_id}/users?limit={limit}&offset={offset}&field=name,uid", RestSharp.Method.GET);
- request.AddParameter("account_id", hubId.Replace("b.", string.Empty), ParameterType.UrlSegment);
- request.AddParameter("limit", 100);
- request.AddParameter("offset", offset);
- request.AddHeader("Authorization", "Bearer " + accessToken);
- IRestResponse response = await client.ExecuteTaskAsync(request);
- if (response.StatusCode != HttpStatusCode.OK) return null;
- JArray page = JArray.Parse(response.Content);
- users.Merge(page);
- if (page.Count >= 100) await GetUsers(hubId, accessToken, users, offset += 100);
- return users;
- }
Получаем проекты: есть большая вероятность превышения лимита количества запросов, поэтому в таком случае повторяем запрос через n секунд, значение n берем из полученного заголовка Retry-After.
- public async Task<JObject> GetProjectsAsync(string hubId, string userId, string accessToken, int attempt = 0)
- {
- RestClient client = new RestClient(BASE_URL);
- RestRequest request = new RestRequest("project/v1/hubs/{hubId}/projects", RestSharp.Method.GET);
- request.AddParameter("hubId", hubId, ParameterType.UrlSegment);
- request.AddHeader("Authorization", "Bearer " + accessToken);
- request.AddHeader("x-user-id", userId);
- IRestResponse response = await client.ExecuteTaskAsync(request);
- if (response.StatusCode == HttpStatusCode.OK)
- return JObject.Parse(response.Content);
- else if (response.StatusCode == HttpStatusCode.TooManyRequests)
- {
- if (attempt > 5) return null;
- int retryAfter = int.Parse(response.Headers.ToList().Find(h => h.Name == "Retry-After").Value.ToString());
- System.Threading.Thread.Sleep(retryAfter * 1000);
- return await GetProjectsAsync(hubId, userId, accessToken, ++attempt);
- }
- return null;
- }
Теперь создадим метод MVC-контроллера, принимающий hubId (или id аккаунта) и возвращающий список пользователей, отсортированный по количеству проектов:
- [HttpGet]
- [Route("api/forge/bim360/hubs/{hubId}/users")]
- public async Task<JArray> GetProjectByUser(string hubId)
- {
- TwoLeggedApi oauth = new TwoLeggedApi();
- dynamic bearer = await oauth.AuthenticateAsync(GetAppSetting("FORGE_CLIENT_ID"), GetAppSetting("FORGE_CLIENT_SECRET"), "client_credentials", new Scope[] { Scope.AccountRead, Scope.DataRead });
- JArray users = await GetUsers(hubId, bearer.access_token);
- foreach (dynamic user in users)
- {
- user.projects = new JArray();
- user.projects_count = 0;
- if (user.uid == null) continue; // not activated yet
- dynamic projects = await GetProjectsAsync(hubId, (string)user.uid, (string)bearer.access_token);
- if (projects == null) continue;
- foreach (dynamic project in projects.data)
- {
- dynamic projectInfo = new JObject();
- projectInfo.name = project.attributes.name;
- projectInfo.id = project.id;
- user.projects.Add(projectInfo);
- }
- user.projects_count = ((JArray)user.projects).Count;
- }
- return new JArray(users.OrderByDescending(u => (int)u["projects_count"]));
- }
Здесь предполагается, что в Вашем коде есть метод GetAppSettings, который возвращает Client Id и Client Secret приложения Forge.
С помощью Chartjs нарисуем гистограмму:
- <script>
- $(document).ready(function () {
- jQuery.ajax({
- url: '/api/forge/bim360/hubs/YOUR_ACCOUNT_ID_HERE/users',
- success: function (users) {
- var labels = [];
- var data = [];
- users.forEach(function (user) {
- if (user.projects_count <= 3) return;
- labels.push(user.name);
- data.push(user.projects_count);
- });
- var context = document.getElementById('projectsPerUser').getContext('2d');
- var barChart = new Chart(context, {
- type: 'bar',
- data: {
- labels: labels,
- datasets: [{
- label: 'Projects',
- data: data,
- backgroundColor: getRandomColor(data.length)
- }]
- },
- options: {
- responsive: true,
- legend: {
- position: 'top',
- },
- title: {
- display: true,
- text: 'BIM 360 user statistics'
- },
- scales: {
- yAxes: [{
- ticks: {
- beginAtZero: true
- }
- }]
- }
- }
- });
- }
- });
- });
- function getRandomColor(count) {
- var colors = [];
- for (var i = 0; i < count; i++) {
- var r = Math.round(Math.random() * 255); var g = Math.round(Math.random() * 255); var b = Math.round(Math.random() * 255);
- colors.push('rgba(' + r + ', ' + g + ', ' + b + ', 0.2)');
- }
- return colors;
- }
- </script>
- <div style="width:100%;">
- </div>
Источник: https://forge.autodesk.com/blog/get-number-bim-360-projects-user
Обсуждение: http://adn-cis.org/forum/index.php?topic=
Опубликовано 29.11.2019