Welcome to Community Week 2025! Join us to learn, connect, and be recognized as we celebrate the spirit of Community and the power of AI. Get the details  

Org Chart Widget with Modal

dagarson
Tera Guru

Hello I am trying to build a portal org chart widget with a popup modal. the idea is that when you click the menu next to the persons name.

dagarson_0-1747758520025.png

this widget will popup with the persons info

dagarson_1-1747758573130.png

I've been working on this for a while and just cant seem to find the problem. when I click the menu it just pops up like this

dagarson_2-1747758625837.png

Here is my code for the org chart widget

<div class="org-chart">
  <!-- Manager -->
  <div class="user-card manager-card">
    <div class="kebab-menu" ng-click="openMenu($event, data.user)">&#8942;</div>
    <div class="card-content">
      <div class="avatar-wrapper">
        <div ng-if="!data.user.photo" class="initials">{{getInitials(data.user.name)}}</div>
      </div>
      <div class="info">
        <div class="name">{{data.user.name}}</div>
        <div class="title">{{data.user.title}}</div>
      </div>
    </div>
  </div>

  <div class="line"></div>

  <!-- Reports -->
  <div class="reports-container">
    <div class="user-card report-card" ng-repeat="rep in data.reports">
      <div class="kebab-menu" ng-click="openMenu($event, rep)">&#8942;</div>
      <div class="card-content">
        <div class="avatar-wrapper">
          <div ng-if="!rep.photo" class="initials">{{getInitials(rep.name)}}</div>
        </div>
        <div class="info">
          <div class="name">{{rep.name}}</div>
          <div class="title">{{rep.title}}</div>
        </div>
      </div>
    </div>
  </div>
</div>

<!-- Optional hidden instance -->
<div style="display: none;">
  <sp-widget widget="data.employeeDetailsWidget"></sp-widget>
</div>

 

//Client script 
function($scope, $uibModal) {
  $scope.getInitials = function(fullName) {
    if (!fullName) return '';
    let names = fullName.trim().split(' ');
    let initials = names[0].charAt(0);
    if (names.length > 1) {
      initials += names[names.length - 1].charAt(0);
    }
    return initials.toUpperCase();
  };

  $scope.openMenu = function(event, user) {
    event.stopPropagation();
console.log("Opening modal for user sys_id:", user.sys_id);

$scope.openMenu = function(event, user) {
  event.stopPropagation();

  $uibModal.open({
    size: 'lg',
    windowClass: 'employee-details-modal',
    template: `
      <div class="modal-header">
        <h4 class="modal-title">Employee Details</h4>
        <button type="button" class="close" ng-click="close()">×</button>
      </div>
      <div class="modal-body">
        <sp-widget widget="data.modalWidget"></sp-widget>
      </div>
    `,
    controller: function($scope, $uibModalInstance) {
      $scope.data = {
        modalWidget: {
          sys_id: 'a73327b683e56a104e1bc296feaad3e6', // Your widget sys_id
          options: {
            user_sys_id: user.sys_id
          }
        }
      };

      $scope.close = function() {
        $uibModalInstance.dismiss();
      };
    }
  });
};

  };
}

//Server Script
(function() {
  var currentUser = gs.getUserID();

  var userGR = new GlideRecord('sys_user');
  if (userGR.get(currentUser)) {
    data.user = {
      name: userGR.name.toString(),
      title: userGR.title.toString(),
      photo: userGR.photo ? userGR.photo.toString() : '',
      sys_id: userGR.getUniqueValue()
    };
  }

  data.reports = [];
  var repGR = new GlideRecord('sys_user');
  repGR.addQuery('manager', currentUser);
  repGR.query();
  while (repGR.next()) {
    data.reports.push({
      name: repGR.name.toString(),
      title: repGR.title.toString(),
      photo: repGR.photo ? repGR.photo.toString() : '',
      sys_id: repGR.getUniqueValue()
    });
  }

  // Optional: define hidden widget instance (unused, safe fallback)
  data.employeeDetailsWidget = {
    sys_id: 'e08f190a83a166104e1bc296feaad334',
    options: {
      user_sys_id: currentUser
    }
  };
})();

And the script for the modal widget

<div class="modal-header">
  <h4 class="modal-title">{{data.name}}</h4>
  <button type="button" class="close" ng-click="close()">×</button>
</div>

<div class="modal-body">
  <div class="employee-details">
    <div class="header-container">
      <div class="user-avatar">
        <img ng-if="data.profileImage" ng-src="{{data.profileImage}}" alt="User photo" />
        <div ng-if="!data.profileImage" class="avatar-initials">{{data.initials}}</div>
      </div>
      <div class="user-info">
        <h2 class="user-name">{{data.name}}</h2>
        <p class="user-title">{{data.title}}</p>
      </div>
    </div>

    <div class="contact-info">
      <div class="contact-item">
        <div class="contact-label"><span class="location-icon"></span> Location:</div>
        <div class="contact-value">{{data.location}}</div>
      </div>
      <div class="contact-item">
        <div class="contact-label">📧 Email:</div>
        <div class="contact-value">
          <a href="mailto:{{data.email}}">{{data.email}}</a>
        </div>
      </div>
      <div class="contact-item">
        <div class="contact-label">📞 Work phone:</div>
        <div class="contact-value">{{data.phone}}</div>
      </div>
    </div>
  </div>
</div>
//Server script
(function() {
  var userId;

  if (typeof input !== 'undefined' && input.options && input.options.user_sys_id) {
    userId = input.options.user_sys_id;
  } else if (typeof options !== 'undefined' && options.user_sys_id) {
    userId = options.user_sys_id;
  } else {
    userId = gs.getUserID(); // fallback to logged-in user
  }

  var userGR = new GlideRecord('sys_user');
  if (!userGR.get(userId)) {
    data.name = "Invalid user";
    return;
  }

  data.name = userGR.getDisplayValue();
  data.title = userGR.title + '';
  data.email = userGR.email + '';
  data.phone = userGR.phone + '';
  data.location = userGR.location ? userGR.location.getDisplayValue() : 'Not specified';

  var names = data.name.trim().split(' ');
  data.initials = names.length >= 2
    ? names[0].charAt(0) + names[names.length - 1].charAt(0)
    : data.name.substring(0, 2);
  data.initials = data.initials.toUpperCase();

  var photo = new GlideUser(userGR.sys_id.toString()).getPhoto();
  data.profileImage = (photo && photo.indexOf("photo.do") !== -1) ? photo : null;
})();

 

Any Assistance would be appreciated.

0 REPLIES 0