Skip to content

Commit f2d0500

Browse files
committed
feat: Implement Profile Tab in DevIndex Controls (#9112)
1 parent 5c77e33 commit f2d0500

3 files changed

Lines changed: 162 additions & 0 deletions

File tree

apps/devindex/view/home/ControlsContainer.mjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as selection from '../../../../src/selection/grid/_export.mjs';
22
import CheckBox from '../../../../src/form/field/CheckBox.mjs';
33
import Container from '../../../../src/container/Base.mjs';
44
import Country from '../../../../src/form/field/Country.mjs';
5+
import Profile from './ProfileContainer.mjs';
56
import Radio from '../../../../src/form/field/Radio.mjs';
67
import TabContainer from '../../../../src/tab/Container.mjs';
78

@@ -28,6 +29,7 @@ class ControlsContainer extends Container {
2829
module : TabContainer,
2930
cls : ['devindex-controls-container-content'],
3031
dragResortable: true,
32+
reference : 'controls-tab-container',
3133

3234
headerToolbar: {
3335
sortZoneConfig: {
@@ -94,6 +96,10 @@ class ControlsContainer extends Container {
9496
reference: 'count-rows-label',
9597
style : {marginTop: '1em'}
9698
}]
99+
}, {
100+
module : Profile,
101+
header : {text: 'Profile'},
102+
reference: 'profile-container'
97103
}, {
98104
module: Container,
99105
header: {text: 'Selection'},

apps/devindex/view/home/MainContainerController.mjs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ class MainContainerController extends Controller {
1919
onComponentConstructed() {
2020
let me = this;
2121

22+
// Setup Grid Listeners
23+
let grid = me.getReference('grid');
24+
if (grid) {
25+
grid.on('select', me.onGridSelect, me);
26+
}
27+
2228
Neo.Main.getByPath({
2329
path : 'location.search',
2430
windowId: me.windowId
@@ -38,6 +44,29 @@ class MainContainerController extends Controller {
3844
}
3945
})
4046
}
47+
48+
/**
49+
* @param {Object} data
50+
*/
51+
onGridSelect(data) {
52+
let me = this,
53+
record = data.record,
54+
controls = me.getReference('controls'),
55+
profile = controls?.down({reference: 'profile-container'}),
56+
tabContainer = controls?.down({reference: 'controls-tab-container'});
57+
58+
if (record && profile) {
59+
profile.updateRecord(record);
60+
61+
if (tabContainer) {
62+
tabContainer.activeIndex = 1; // Switch to Profile Tab
63+
}
64+
65+
if (controls && !controls.cls.includes('neo-expanded')) {
66+
controls.addCls('neo-expanded');
67+
}
68+
}
69+
}
4170
}
4271

4372
export default Neo.setupClass(MainContainerController);
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import Container from '../../../../src/container/Base.mjs';
2+
import Image from '../../../../src/component/Image.mjs';
3+
import Label from '../../../../src/component/Label.mjs';
4+
5+
/**
6+
* @class DevIndex.view.home.ProfileContainer
7+
* @extends Neo.container.Base
8+
*/
9+
class ProfileContainer extends Container {
10+
static config = {
11+
/**
12+
* @member {String} className='DevIndex.view.home.ProfileContainer'
13+
* @protected
14+
*/
15+
className: 'DevIndex.view.home.ProfileContainer',
16+
/**
17+
* @member {Object} layout={ntype:'vbox',align:'stretch'}
18+
*/
19+
layout: {ntype: 'vbox', align: 'stretch'},
20+
/**
21+
* @member {Object[]} items
22+
*/
23+
items: [{
24+
ntype : 'component',
25+
cls : ['profile-header'],
26+
height: 100,
27+
style : {marginBottom: '1em'},
28+
vdom : {
29+
cn: [{
30+
tag: 'div', cls: ['profile-avatar-wrapper'], cn: [
31+
{tag: 'img', cls: ['profile-avatar'], flag: 'avatar'}
32+
]
33+
}, {
34+
tag: 'div', cls: ['profile-names'], cn: [
35+
{tag: 'div', cls: ['profile-name'], flag: 'name'},
36+
{tag: 'div', cls: ['profile-login'], flag: 'login'}
37+
]
38+
}]
39+
}
40+
}, {
41+
module : Label,
42+
cls : ['profile-bio'],
43+
reference: 'profile-bio',
44+
style : {
45+
fontStyle : 'italic',
46+
lineHeight: '1.4',
47+
whiteSpace: 'normal'
48+
},
49+
text: ''
50+
}, {
51+
ntype : 'container',
52+
layout: 'vbox',
53+
style : {marginTop: '1em'},
54+
items : [{
55+
ntype: 'label',
56+
style: {fontWeight: 'bold'},
57+
text : 'Details'
58+
}, {
59+
ntype : 'label',
60+
reference: 'profile-location',
61+
text : ''
62+
}, {
63+
ntype : 'label',
64+
reference: 'profile-company',
65+
text : ''
66+
}]
67+
}, {
68+
ntype : 'container',
69+
reference: 'profile-orgs',
70+
layout : {ntype: 'hbox', wrap: true},
71+
style : {gap: '5px', marginTop: '1em'},
72+
items : []
73+
}]
74+
}
75+
76+
/**
77+
* @param {Object} record
78+
*/
79+
updateRecord(record) {
80+
let me = this,
81+
vdom = me.items[0].vdom,
82+
bio = me.getReference('profile-bio'),
83+
loc = me.getReference('profile-location'),
84+
comp = me.getReference('profile-company'),
85+
orgs = me.getReference('profile-orgs'),
86+
avatar, name, login;
87+
88+
avatar = me.getVdomChild(vdom, 'avatar');
89+
name = me.getVdomChild(vdom, 'name');
90+
login = me.getVdomChild(vdom, 'login');
91+
92+
avatar.src = record.avatar_url || '';
93+
name.html = record.name || '';
94+
login.html = `@${record.login}`;
95+
96+
me.items[0].vdom = vdom;
97+
me.items[0].update();
98+
99+
bio.text = record.bio || 'No bio available.';
100+
loc.text = record.location ? `📍 ${record.location}` : '';
101+
comp.text = record.company ? `🏢 ${record.company}` : '';
102+
103+
// Update Orgs
104+
if (record.organizations && Array.isArray(record.organizations)) {
105+
orgs.removeAll();
106+
if (record.organizations.length > 0) {
107+
orgs.add({ntype: 'label', text: 'Organizations:', width: '100%', style: {fontWeight: 'bold', marginBottom: '5px'}});
108+
109+
record.organizations.forEach(org => {
110+
orgs.add({
111+
module: Image,
112+
alt : org.login,
113+
height: 32,
114+
src : org.avatar_url,
115+
title : org.login,
116+
width : 32,
117+
style : {borderRadius: '4px'}
118+
})
119+
});
120+
}
121+
} else {
122+
orgs.removeAll();
123+
}
124+
}
125+
}
126+
127+
export default Neo.setupClass(ProfileContainer);

0 commit comments

Comments
 (0)