conjur-asset-ui 1.3.2 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/.jshintrc +41 -0
  4. data/CHANGELOG.md +7 -0
  5. data/Gemfile +3 -1
  6. data/README.md +38 -4
  7. data/Rakefile +69 -1
  8. data/TODO.md +31 -0
  9. data/bower.json +98 -0
  10. data/conjur-asset-ui.gemspec +3 -3
  11. data/features/navigation_bar.feature +31 -0
  12. data/features/step_definitions/custom_step.rb +32 -0
  13. data/features/support/env.rb +38 -0
  14. data/features/support/hooks.rb +30 -0
  15. data/features/support/world.rb +17 -0
  16. data/gulpfile.js +139 -0
  17. data/lib/conjur/command/ui.rb +1 -1
  18. data/lib/conjur/webserver/server.rb +14 -8
  19. data/lib/conjur-asset-ui-version.rb +1 -1
  20. data/package.json +47 -0
  21. data/preprocessor.js +7 -0
  22. data/public/_client_libs.html +1 -16
  23. data/public/build/css/styles.css +87 -0
  24. data/public/build/css/vendor.css +5 -0
  25. data/public/build/fonts/glyphicons-halflings-regular.eot +0 -0
  26. data/public/{fonts → build/fonts}/glyphicons-halflings-regular.svg +47 -47
  27. data/public/{fonts → build/fonts}/glyphicons-halflings-regular.ttf +0 -0
  28. data/public/build/fonts/glyphicons-halflings-regular.woff +0 -0
  29. data/public/build/js/app.min.js +4 -0
  30. data/public/build/js/vendor.min.js +23 -0
  31. data/public/build/maps/app.min.js.map +1 -0
  32. data/public/build/maps/vendor.min.js.map +1 -0
  33. data/public/css/styles.less +246 -17
  34. data/public/index.html.erb +11 -10
  35. data/public/js/init.js +186 -97
  36. data/public/js/lib/sorted-set.no-require.js +3 -28
  37. data/public/js/models/groupRecord.js +14 -12
  38. data/public/js/models/hostRecord.js +13 -8
  39. data/public/js/models/layerRecord.js +14 -12
  40. data/public/js/models/namespace.js +2 -0
  41. data/public/js/models/policyList.js +3 -1
  42. data/public/js/models/policyRecord.js +8 -8
  43. data/public/js/models/record.js +59 -27
  44. data/public/js/models/resourceList.js +28 -10
  45. data/public/js/models/userList.js +7 -2
  46. data/public/js/models/userRecord.js +14 -9
  47. data/public/js/models/variableList.js +18 -7
  48. data/public/js/models/variableRecord.js +18 -14
  49. data/public/js/routers.js +74 -37
  50. data/public/js/views/annotations.js +39 -28
  51. data/public/js/views/audit.js +31 -25
  52. data/public/js/views/breadcrumbs.js +62 -0
  53. data/public/js/views/chart.js +617 -0
  54. data/public/js/views/dashboard.js +144 -65
  55. data/public/js/views/generic.js +16 -9
  56. data/public/js/views/group.js +103 -55
  57. data/public/js/views/groups.js +3 -7
  58. data/public/js/views/host.js +192 -56
  59. data/public/js/views/hosts.js +2 -6
  60. data/public/js/views/layer.js +136 -82
  61. data/public/js/views/layers.js +2 -6
  62. data/public/js/views/mixins/search.js +12 -5
  63. data/public/js/views/mixins/tabs.js +95 -55
  64. data/public/js/views/navSearch.js +16 -5
  65. data/public/js/views/owned.js +14 -8
  66. data/public/js/views/permissions.js +244 -178
  67. data/public/js/views/policies.js +2 -4
  68. data/public/js/views/policy.js +65 -38
  69. data/public/js/views/resource.js +54 -34
  70. data/public/js/views/role.js +59 -37
  71. data/public/js/views/searchResults.js +205 -138
  72. data/public/js/views/sections.js +226 -0
  73. data/public/js/views/time.js +38 -13
  74. data/public/js/views/user.js +288 -59
  75. data/public/js/views/users.js +2 -7
  76. data/public/js/views/variable.js +293 -53
  77. data/public/js/views/variables.js +4 -8
  78. metadata +34 -56
  79. data/.git-hooks/pre_commit/ensure_livescript_compiled.rb +0 -31
  80. data/.overcommit.yml +0 -5
  81. data/compile_ls +0 -6
  82. data/livescript/views/audit.ls +0 -136
  83. data/public/_client_code.html +0 -42
  84. data/public/css/bootstrap.css +0 -7
  85. data/public/fonts/glyphicons-halflings-regular.eot +0 -0
  86. data/public/fonts/glyphicons-halflings-regular.woff +0 -0
  87. data/public/js/lib/JSXTransformer.js +0 -10862
  88. data/public/js/lib/async.js +0 -958
  89. data/public/js/lib/backbone.js +0 -2
  90. data/public/js/lib/bootstrap.js +0 -6
  91. data/public/js/lib/date.extensions.js +0 -141
  92. data/public/js/lib/less.js +0 -16
  93. data/public/js/lib/moment.js +0 -7768
  94. data/public/js/lib/prelude-browser-min.js +0 -1
  95. data/public/js/lib/react-bootstrap.js +0 -5346
  96. data/public/js/lib/react-bootstrap.min.js +0 -4
  97. data/public/js/lib/underscore-min.js +0 -6
  98. data/public/js/lib/underscore.string.min.js +0 -1
  99. data/public/js/main.js +0 -57
  100. data/vendor/prelude-ls/.gitignore +0 -2
  101. data/vendor/prelude-ls/.travis.yml +0 -3
  102. data/vendor/prelude-ls/CHANGELOG.md +0 -81
  103. data/vendor/prelude-ls/LICENSE +0 -22
  104. data/vendor/prelude-ls/Makefile +0 -50
  105. data/vendor/prelude-ls/README.md +0 -15
  106. data/vendor/prelude-ls/browser/prelude-browser-min.js +0 -1
  107. data/vendor/prelude-ls/browser/prelude-browser.js +0 -1172
  108. data/vendor/prelude-ls/lib/Func.js +0 -40
  109. data/vendor/prelude-ls/lib/List.js +0 -602
  110. data/vendor/prelude-ls/lib/Num.js +0 -129
  111. data/vendor/prelude-ls/lib/Obj.js +0 -153
  112. data/vendor/prelude-ls/lib/Str.js +0 -68
  113. data/vendor/prelude-ls/lib/index.js +0 -164
  114. data/vendor/prelude-ls/package.json +0 -50
  115. data/vendor/prelude-ls/package.ls +0 -46
  116. data/vendor/prelude-ls/src/Func.ls +0 -17
  117. data/vendor/prelude-ls/src/List.ls +0 -299
  118. data/vendor/prelude-ls/src/Num.ls +0 -83
  119. data/vendor/prelude-ls/src/Obj.ls +0 -61
  120. data/vendor/prelude-ls/src/Str.ls +0 -32
  121. data/vendor/prelude-ls/src/index.ls +0 -56
  122. data/vendor/prelude-ls/test/Func.ls +0 -36
  123. data/vendor/prelude-ls/test/List.ls +0 -751
  124. data/vendor/prelude-ls/test/Num.ls +0 -258
  125. data/vendor/prelude-ls/test/Obj.ls +0 -145
  126. data/vendor/prelude-ls/test/Prelude.ls +0 -49
  127. data/vendor/prelude-ls/test/Str.ls +0 -208
  128. data/vendor/prelude-ls/test/browser.html +0 -5
@@ -1,14 +1,12 @@
1
1
  /** @jsx React.DOM */
2
+ /* global conjur, React */
2
3
 
3
4
  (function(conjur, React) {
4
5
  'use strict';
5
6
 
6
7
  var GenericList = conjur.views.GenericList;
7
8
 
8
- var PolicyBox = this.PolicyBox = React.createClass({
9
- /*getInitialState: function() {
10
- return { currentNamespace: "", members: [] };
11
- },*/
9
+ this.PolicyBox = React.createClass({
12
10
  render: function() {
13
11
  return (
14
12
  <div className="policyBox">
@@ -1,43 +1,70 @@
1
1
  /** @jsx React.DOM */
2
+ /* global conjur, React, ReactBootstrap, _ */
2
3
 
3
- var Policy = React.createClass({
4
- mixins: [conjur.views.mixins.Tab],
5
- render: function() {
6
- var policy = this.props.data.policy;
7
- var id = policy.id.split(':')[2];
8
-
9
- //TODO: policy loader
10
- //TODO in CLI: why not save text of policy as an annotation?
11
- var overview_tab =
12
- <TabPane key="overview" tab="Overview">
13
- <dl className="dl-horizontal">
14
- <dt>Owner</dt>
15
- <dd><RoleLink id={policy.id}/></dd>
16
- </dl>
17
- </TabPane>;
18
-
19
- var permissions_tab = this.permissions_tab(policy.id);
20
- var memberships_tab = this.memberships_tab(policy.id);
21
- var annotations_tab = this.annotations_tab();
22
- var owned_tab = this.owned_tab();
23
-
24
- var audit_tab =
25
- <TabPane key="audit" tab="Recent Activity">
4
+ (function(conjur, React, ReactBootstrap, _) {
5
+ 'use strict';
6
+
7
+ var TabbedArea = ReactBootstrap.TabbedArea,
8
+ TabPane = ReactBootstrap.TabPane,
9
+ Tab = conjur.views.mixins.Tab,
10
+ RoleLink = conjur.views.RoleLink,
11
+ AuditBox = window.AuditBox;
12
+
13
+ this.Policy = React.createClass({
14
+ mixins: [Tab],
15
+
16
+ render: function() {
17
+ var policy = this.props.data.policy,
18
+ id = policy.id.split(':')[2];
19
+
20
+ //TODO: policy loader
21
+ //TODO in CLI: why not save text of policy as an annotation?
22
+ var overviewTab = (
23
+ <TabPane key="overview" tab="Overview">
24
+ <dl className="dl-horizontal">
25
+ <dt>Owner</dt>
26
+ <dd><RoleLink id={this.props.data.owner}/></dd>
27
+ </dl>
28
+ </TabPane>
29
+ );
30
+
31
+ var permissionsTab = this.permissionsTab(policy.id),
32
+ membershipsTab = this.membershipsTab(policy.id),
33
+ annotationsTab = this.annotationsTab(),
34
+ ownedTab = this.ownedTab();
35
+
36
+ var auditTab = (
37
+ <TabPane key="audit" tab="Recent Activity">
26
38
  <div className="audit auditGroup">
27
39
  <AuditBox roles={[policy.id]} tabview={true} />
28
40
  </div>
29
- </TabPane>;
30
- var tabs = _.compact( [ overview_tab, owned_tab, memberships_tab, permissions_tab,
31
- annotations_tab, audit_tab
32
- ] );
33
-
34
- return (
35
- <div className="policy">
36
- <h2>Policy {id}</h2>
37
- <TabbedArea defaultActiveKey="overview">
38
- {tabs}
39
- </TabbedArea>
40
- </div>
41
- );
42
- }
43
- });
41
+ </TabPane>
42
+ );
43
+
44
+ var tabs = _.compact([
45
+ overviewTab,
46
+ ownedTab,
47
+ membershipsTab,
48
+ permissionsTab,
49
+ annotationsTab,
50
+ auditTab
51
+ ]);
52
+
53
+ return (
54
+ <div className="policy">
55
+ <h2>Policy {id}</h2>
56
+ <TabbedArea defaultActiveKey="overview">
57
+ {tabs}
58
+ </TabbedArea>
59
+ </div>
60
+ );
61
+ }
62
+ });
63
+
64
+ }).bind(conjur.views)
65
+ (
66
+ conjur,
67
+ React,
68
+ ReactBootstrap,
69
+ _
70
+ );
@@ -1,39 +1,59 @@
1
1
  /** @jsx React.DOM */
2
+ /* global conjur, React, _ */
2
3
 
3
- /**
4
- Renders a link to the resource with id given by this.props.data.
5
-
6
- Includes a slick little icon for the following kinds:
7
- TODO which kinds?
8
- **/
9
- var ResourceLink = React.createClass({
10
- render: function(){
11
- var resourceId = this.props.id || this.props.data.id || this.props.data;
12
-
13
- var tokens = resourceId.split(':');
14
- var kind = tokens[1];
15
- var id = tokens[tokens.length - 1];
16
- var text = this.props.text || id;
17
-
18
- var known_types=['user','group','layer','host','variable','policy'];
19
- var resource_is_known = _.contains(known_types, kind);
20
-
21
- // we shouldn't build links to for unsupported resources
22
- var href = "/ui/" + conjur.utils.pluralize(kind) + "/" + encodeURIComponent(id);
23
- var classes = [ 'resource-link' ];
24
- if( !this.props.noIcon ) {
25
- if (resource_is_known) {
26
- classes.push(kind);
27
- } else {
28
- classes.push('abstract');
29
- if (text==id) {
30
- text=[kind,text].join(":"); // prepend kind to id
4
+ (function(conjur, React, _) {
5
+ 'use strict';
6
+
7
+ /**
8
+ Renders a link to the resource with id given by this.props.data.
9
+
10
+ Includes a slick little icon for the following kinds:
11
+ TODO which kinds?
12
+ **/
13
+ this.ResourceLink = React.createClass({
14
+ render: function() {
15
+ var resourceId = this.props.id || this.props.data.id || this.props.data;
16
+
17
+ // guard against misuse such as https://github.com/conjurinc/conjur-asset-ui/issues/78
18
+ if (resourceId === undefined) {
19
+ return React.DOM.em({}, 'undefined');
20
+ }
21
+
22
+ var tokens = resourceId.split(':'),
23
+ kind = tokens[1],
24
+ id = tokens[tokens.length - 1],
25
+ text = this.props.text || id;
26
+
27
+ var knownTypes = ['user', 'group', 'layer', 'host', 'variable', 'policy'],
28
+ resourceIsKnown = _.contains(knownTypes, kind);
29
+
30
+ // we shouldn't build links to for unsupported resources
31
+ var href = '/ui/' + conjur.utils.pluralize(kind) + '/' + window.encodeURIComponent(id);
32
+ var classes = ['resource-link'];
33
+
34
+ if (!this.props.noIcon) {
35
+ if (resourceIsKnown) {
36
+ classes.push(kind);
37
+ } else {
38
+ classes.push('abstract');
39
+
40
+ if (text === id) {
41
+ text = [kind, text].join(':'); // prepend kind to id
42
+ }
43
+ }
44
+ } else if (text === id) {
45
+ text = [kind, text].join(':'); // prepend kind to id
31
46
  }
47
+
48
+ return (
49
+ <a className={classes.join(' ')} href={href}>{text}</a>
50
+ );
32
51
  }
33
- } else if (text==id) {
34
- text=[kind,text].join(":"); // prepend kind to id
35
- }
52
+ });
36
53
 
37
- return <a className={classes.join(' ')} href={href}>{text}</a>
38
- }
39
- });
54
+ }).bind(conjur.views)
55
+ (
56
+ conjur,
57
+ React,
58
+ _
59
+ );
@@ -1,41 +1,63 @@
1
1
  /** @jsx React.DOM */
2
+ /* global conjur, React, _ */
2
3
 
3
- /** render a link to the role represented by this.props.id
4
- Example: <RoleLink id="ci:user:jon"/>
5
- */
6
- var RoleLink = React.createClass({
7
- render: function() {
8
- var tokens = this.props.id.split(":");
9
- var kind = tokens[1];
10
- var id = tokens[tokens.length-1];
11
- if (tokens.length==1) { // just username
12
- kind="user";
13
- id=tokens[0];
14
- }
15
-
16
- // TODO: shouldn't point to unknown types
17
- var href = "/ui/" + conjur.utils.pluralize(kind) + "/" + encodeURIComponent(id);
18
- var classes = ["role-link"];
19
-
20
- var known_types=['user','group','layer','host','policy'];
21
- var kind_is_known = _.contains(known_types, kind);
22
- var text = id;
23
-
24
- if( !this.props.noIcon ) {
25
- if (kind_is_known) {
26
- classes.push(kind);
27
- } else {
28
- classes.push('abstract'); // we have no picture for abstract role yet
29
- if (text==id) {
30
- text=[kind,text].join(":"); // prepend kind to id
4
+ (function(conjur, React, _) {
5
+ 'use strict';
6
+
7
+ /** render a link to the role represented by this.props.id
8
+ Example: <RoleLink id='ci:user:jon'/>
9
+ */
10
+ this.RoleLink = React.createClass({
11
+ render: function() {
12
+ // guard against misuse such as https://github.com/conjurinc/conjur-asset-ui/issues/78
13
+ if (this.props.id === undefined) {
14
+ return React.DOM.em({}, 'undefined');
15
+ }
16
+
17
+ var tokens = this.props.id.split(':'),
18
+ kind = tokens[1],
19
+ id = tokens[tokens.length-1],
20
+ href,
21
+ classes = ['role-link'],
22
+ knownTypes = ['user', 'group', 'layer', 'host', 'policy'],
23
+ kindIsKnown,
24
+ text;
25
+
26
+ if (tokens.length === 1) { // just username
27
+ kind = 'user';
28
+ id = tokens[0];
29
+ }
30
+
31
+ // TODO: shouldn't point to unknown types
32
+ href = '/ui/' + conjur.utils.pluralize(kind) + '/' + window.encodeURIComponent(id);
33
+ kindIsKnown = _.contains(knownTypes, kind);
34
+ text = id;
35
+
36
+ if (!this.props.noIcon) {
37
+ if (kindIsKnown) {
38
+ classes.push(kind);
39
+ } else {
40
+ classes.push('abstract'); // we have no picture for abstract role yet
41
+
42
+ if (text === id) {
43
+ text = [kind, text].join(':'); // prepend kind to id
44
+ }
45
+ }
46
+ } else if (text === id) {
47
+ text = [kind, text].join(':'); // prepend kind to id
31
48
  }
49
+
50
+ return (
51
+ <a className={classes.join(' ')} href={href}>
52
+ {text}
53
+ </a>
54
+ );
32
55
  }
33
- } else if (text==id) {
34
- text=[kind,text].join(":"); // prepend kind to id
35
- }
36
-
37
- return <a className={classes.join(' ')} href={href}>
38
- {text}
39
- </a>;
40
- }
41
- });
56
+ });
57
+
58
+ }).bind(conjur.views)
59
+ (
60
+ conjur,
61
+ React,
62
+ _
63
+ );
@@ -1,145 +1,212 @@
1
1
  /**@jsx React.DOM*/
2
+ /* global conjur, React, jQuery, _ */
2
3
 
3
- var SearchGroupTitle = React.createClass({
4
- render: function(){
5
- return <span>{this.title()}</span>
6
- },
7
-
8
- title: function(){
9
- var words = this.props.data.kind.replace(/[-_]/, ' ').split(' ');
10
- words[words.length - 1] = conjur.utils.pluralize(words[words.length - 1]);
11
- return words.map(_.str.capitalize).join(' ') + ' (' + this.props.data.items.length + ')';
12
- }
13
- });
14
-
15
- var SearchGroupHeading = React.createClass({
16
- render: function(){
17
- var targetId = "#search-collapse-" + this.props.data.kind;
18
- return <div className="panel-heading">
19
- <h4 className="panel-title">
20
- <a data-toggle="collapse" data-target={targetId}
21
- className={'group-heading' + this.props.data.kind}>
22
- <SearchGroupTitle data={this.props.data} />
23
- </a>
24
- </h4>
25
- </div>;
26
- },
27
-
28
- title: function(){
29
- var words = this.props.data.kind.replace(/[-_]/, ' ').split(' ');
30
- words[words.length - 1] = conjur.utils.pluralize(words[words.length - 1]);
31
- return words.map(_.str.capitalize).join(' ') + ' (' + this.props.data.items.length + ')';
32
- }
33
- });
34
-
35
- var SearchResultItem = React.createClass({
36
- render: function(){
37
- return <div className="item">
38
- <h4> { this.titleLink() } </h4>
39
- <div className="details">
40
- <strong> ID: </strong> <ResourceLink data={this.props.data.id} noIcon="true"/>
41
- <strong> Owner: </strong> <RoleLink id={this.props.data.owner} noIcon="true"/>
42
- </div>
43
- <div className="comment">
44
- {this.commentText()}
45
- </div>
46
- </div>;
47
- },
48
-
49
- commentText: function(){
50
- var annots = this.annotationsMap();
51
- return annots['description'] || "";
52
- },
53
-
54
- titleLink: function(){
55
- var annots = this.annotationsMap();
56
- return <ResourceLink data={this.props.data.id} text={annots['name']}/>
57
- },
58
-
59
- annotationsMap: function(){
60
- if(this._annotationsMap) return this._annotationsMap;
61
- var map = this._annotationsMap = {};
62
- (this.props.data.annotations || []).forEach(function(a){
63
- map[a.name] = a.value;
4
+
5
+ (function(conjur, React, $, _) {
6
+ 'use strict';
7
+
8
+ var ResourceLink = conjur.views.ResourceLink,
9
+ RoleLink = conjur.views.RoleLink;
10
+
11
+ var SearchGroupTitle = React.createClass({
12
+ render: function() {
13
+ return (
14
+ <span>{this.title()}</span>
15
+ );
16
+ },
17
+
18
+ title: function() {
19
+ var words = this.props.data.kind.replace(/[-_]/, ' ').split(' ');
20
+
21
+ words[words.length - 1] = conjur.utils.pluralize(words[words.length - 1]);
22
+
23
+ return (
24
+ words.map(_.str.capitalize).join(' ') + ' (' + this.props.data.items.length + ')'
25
+ );
26
+ }
64
27
  });
65
- return map;
66
- }
67
- });
68
-
69
- // accepts props like data: { kind:"", items:[] }
70
- var SearchGroup = React.createClass({
71
- render: function(){
72
- var id = "search-group-" + this.props.data.kind;
73
- var items = this.props.data.items.map(function(r){
74
- return <SearchResultItem data={r}/>
75
- })
76
- return <div id={id} className="panel panel-default search-group">
77
- <SearchGroupHeading data={this.props.data}/>
78
- <div id={"search-collapse-" + this.props.data.kind} className="panel-collapse collapse in">
79
- <div className="panel-body">
80
- {items}
81
- </div>
82
- </div>
83
- </div>;
84
- }
85
- });
86
-
87
- var SearchResults = React.createClass({
88
- render: function() {
89
- var results = this.props.data.results;
90
- var grouped = _.groupBy(results, function(r){
91
- return r.id.split(':')[1];
28
+
29
+ var SearchGroupHeading = React.createClass({
30
+ render: function() {
31
+ var targetId = '#search-collapse-' + this.props.data.kind;
32
+
33
+ return (
34
+ <div className="panel-heading">
35
+ <h4 className="panel-title">
36
+ <a data-toggle="collapse"
37
+ data-target={targetId}
38
+ className={'group-heading' + this.props.data.kind}>
39
+ <SearchGroupTitle data={this.props.data} />
40
+ </a>
41
+ </h4>
42
+ </div>
43
+ );
44
+ },
45
+
46
+ title: function() {
47
+ var words = this.props.data.kind.replace(/[-_]/, ' ').split(' ');
48
+
49
+ words[words.length - 1] = conjur.utils.pluralize(words[words.length - 1]);
50
+
51
+ return (
52
+ words.map(_.str.capitalize).join(' ') + ' (' + this.props.data.items.length + ')'
53
+ );
54
+ }
92
55
  });
93
- // Don't care about these
94
- delete grouped['environment-variables']
95
- delete grouped['notification']
96
- delete grouped['queue']
97
-
98
- var groups = _.map(grouped,function(items, key){
99
- var data = {items:items, kind: key}; // - prevent editor barfing
100
- return <SearchGroup data={data}/>
56
+
57
+ var SearchResultItem = React.createClass({
58
+ render: function() {
59
+ return (
60
+ <div className="item">
61
+ <h4>{this.titleLink()}</h4>
62
+ <div className="details">
63
+ <strong> ID: </strong> <ResourceLink data={this.props.data.id}
64
+ noIcon="true" />
65
+ <strong> Owner: </strong> <RoleLink id={this.props.data.owner}
66
+ noIcon="true" />
67
+ </div>
68
+ <div className="comment">
69
+ {this.commentText()}
70
+ </div>
71
+ </div>
72
+ );
73
+ },
74
+
75
+ commentText: function() {
76
+ var annots = this.annotationsMap();
77
+
78
+ return annots.description || '';
79
+ },
80
+
81
+ titleLink: function(){
82
+ var annots = this.annotationsMap();
83
+
84
+ return (
85
+ <ResourceLink data={this.props.data.id} text={annots.name} />
86
+ );
87
+ },
88
+
89
+ annotationsMap: function(){
90
+ if (this._annotationsMap) {
91
+ return this._annotationsMap;
92
+ }
93
+
94
+ var map = this._annotationsMap = {};
95
+
96
+ (this.props.data.annotations || []).forEach(function(a) {
97
+ map[a.name] = a.value;
98
+ });
99
+
100
+ return map;
101
+ }
101
102
  });
102
- var scores = {
103
- 'policy': 1,
104
- 'layer': 2,
105
- 'group': 3,
106
- 'host': 4,
107
- 'user': 5,
108
- 'variable': 6,
109
- 'key_pair': 7
110
- };
111
- groups.sort(function(a, b) {
112
- return ( scores[a.props.data.kind] || 100 ) - ( scores[b.props.data.kind] || 100 );
103
+
104
+ // accepts props like data: { kind:"", items:[] }
105
+ var SearchGroup = React.createClass({
106
+ render: function() {
107
+ var id = 'search-group-' + this.props.data.kind;
108
+
109
+ var items = this.props.data.items.map(function(r) {
110
+ return (
111
+ <SearchResultItem data={r}/>
112
+ );
113
+ });
114
+
115
+ return (
116
+ <div id={id} className="panel panel-default search-group">
117
+ <SearchGroupHeading data={this.props.data}/>
118
+ <div id={'search-collapse-' + this.props.data.kind}
119
+ className="panel-collapse collapse in">
120
+ <div className="panel-body">
121
+ {items}
122
+ </div>
123
+ </div>
124
+ </div>
125
+ );
126
+ }
113
127
  });
114
- var toc = groups.map(function(g) {
115
- var gid = "#search-group-" + g.props.data.kind;
116
- return <div className="toc-item">
117
- <a href={gid}><SearchGroupTitle data={g.props.data} /></a>
118
- </div>
128
+
129
+ var SearchResults = this.SearchResults = React.createClass({
130
+ render: function() {
131
+ var results = this.props.data.results;
132
+
133
+ var grouped = _.groupBy(results, function(r) {
134
+ return r.id.split(':')[1];
135
+ });
136
+
137
+ // Don't care about these
138
+ delete grouped['environment-variables'];
139
+ delete grouped.notification;
140
+ delete grouped.queue;
141
+
142
+ var groups = _.map(grouped, function(items, key) {
143
+ var data = {items: items, kind: key}; // - prevent editor barfing
144
+ return <SearchGroup data={data}/>;
145
+ });
146
+
147
+ var scores = {
148
+ 'policy': 1,
149
+ 'layer': 2,
150
+ 'group': 3,
151
+ 'host': 4,
152
+ 'user': 5,
153
+ 'variable': 6,
154
+ 'key_pair': 7
155
+ };
156
+
157
+ groups.sort(function(a, b) {
158
+ return (
159
+ (scores[a.props.data.kind] || 100) -
160
+ (scores[b.props.data.kind] || 100)
161
+ );
162
+ });
163
+
164
+ var toc = groups.map(function(g) {
165
+ var gid = '#search-group-' + g.props.data.kind;
166
+
167
+ return (
168
+ <div className="toc-item">
169
+ <a href={gid}><SearchGroupTitle data={g.props.data} /></a>
170
+ </div>
171
+ );
172
+ });
173
+
174
+ var heading = 'Found ' + this.props.data.results.length +
175
+ ' resources matching "' + this.props.data.search + '"';
176
+
177
+ return (
178
+ <div id="searchResults">
179
+ <div className="searchResults">
180
+ <h3> { heading } </h3>
181
+ <div className="search-results-toc">
182
+ {toc}
183
+ </div>
184
+ <div className="search-results">
185
+ {groups}
186
+ </div>
187
+ </div>
188
+ </div>
189
+ );
190
+ }
119
191
  });
120
- var heading = "Found " + this.props.data.results.length +
121
- " resources matching \"" + this.props.data.search + "\"";
122
- return (
123
- <div id="searchResults">
124
- <div className="searchResults">
125
- <h3> { heading } </h3>
126
- <div className="search-results-toc">
127
- {toc}
128
- </div>
129
- <div className="search-results">
130
- {groups}
131
- </div>
132
- </div>
133
- </div>
134
- );
135
- }
136
- });
137
-
138
- SearchResults.search = function(search, container){
139
- container = container || document.getElementById('content');
140
- $.get(conjur.app.endpoints.authz("resources", {search: search.replace('-',' ')}), function(results){
141
-
142
- var data = {search: search, results: results};
143
- React.renderComponent(<SearchResults data={data}/>, container);
144
- });
145
- }
192
+
193
+ SearchResults.search = function(search, container) {
194
+ container = container || document.getElementById('content');
195
+
196
+ $.get(
197
+ conjur.app.endpoints.authz('resources', {search: search.replace('-',' ')}),
198
+ function(results) {
199
+ var data = {search: search, results: results};
200
+ React.renderComponent(<SearchResults data={data}/>, container);
201
+ }
202
+ );
203
+ };
204
+
205
+
206
+ }).bind(conjur.views)
207
+ (
208
+ conjur,
209
+ React,
210
+ jQuery,
211
+ _
212
+ );