diff --git a/pkg/api/api.go b/pkg/api/api.go
index 6e8fe57fddf..7ad4ae73b4c 100644
--- a/pkg/api/api.go
+++ b/pkg/api/api.go
@@ -22,7 +22,7 @@ func Register(r *macaron.Macaron) {
r.Post("/login", bind(dtos.LoginCommand{}), wrap(LoginPost))
r.Get("/login/:name", OAuthLogin)
r.Get("/login", LoginView)
- r.Get("/invite", Index)
+ r.Get("/invite/:code", Index)
// authed views
r.Get("/profile/", reqSignedIn, Index)
diff --git a/pkg/api/dtos/invite.go b/pkg/api/dtos/invite.go
index bc674aa2a75..495acce8da9 100644
--- a/pkg/api/dtos/invite.go
+++ b/pkg/api/dtos/invite.go
@@ -10,9 +10,10 @@ type AddInviteForm struct {
}
type InviteInfo struct {
- Email string `json:"email"`
- Name string `json:"name"`
- Username string `json:"username"`
+ Email string `json:"email"`
+ Name string `json:"name"`
+ Username string `json:"username"`
+ InvitedBy string `json:"invitedBy"`
}
type CompleteInviteForm struct {
diff --git a/pkg/api/org_invite.go b/pkg/api/org_invite.go
index 52f0ce78de4..f4c64e8db7d 100644
--- a/pkg/api/org_invite.go
+++ b/pkg/api/org_invite.go
@@ -78,7 +78,7 @@ func AddOrgInvite(c *middleware.Context, inviteDto dtos.AddInviteForm) Response
"OrgName": c.OrgName,
"Email": c.Email,
"LinkUrl": setting.ToAbsUrl("invite/" + cmd.Code),
- "InvitedBy": util.StringsFallback2(c.Name, c.Email),
+ "InvitedBy": util.StringsFallback3(c.Name, c.Email, c.Login),
},
}
@@ -114,13 +114,14 @@ func GetInviteInfoByCode(c *middleware.Context) Response {
return ApiError(500, "Failed to get invite", err)
}
- info := dtos.InviteInfo{
- Email: query.Result.Email,
- Name: query.Result.Name,
- Username: query.Result.Email,
- }
+ invite := query.Result
- return Json(200, &info)
+ return Json(200, dtos.InviteInfo{
+ Email: invite.Email,
+ Name: invite.Name,
+ Username: invite.Email,
+ InvitedBy: util.StringsFallback3(invite.InvitedByName, invite.InvitedByLogin, invite.InvitedByEmail),
+ })
}
func CompleteInvite(c *middleware.Context, completeInvite dtos.CompleteInviteForm) Response {
diff --git a/pkg/models/temp_user.go b/pkg/models/temp_user.go
index cf20517921c..9aab24f48fc 100644
--- a/pkg/models/temp_user.go
+++ b/pkg/models/temp_user.go
@@ -70,18 +70,21 @@ type GetTempUsersForOrgQuery struct {
type GetTempUserByCodeQuery struct {
Code string
- Result *TempUser
+ Result *TempUserDTO
}
type TempUserDTO struct {
- Id int64 `json:"id"`
- Name string `json:"name"`
- Email string `json:"email"`
- Role string `json:"role"`
- InvitedBy string `json:"invitedBy"`
- Code string `json:"code"`
- Url string `json:"url"`
- EmailSent bool `json:"emailSent"`
- EmailSentOn time.Time `json:"emailSentOn"`
- Created time.Time `json:"createdOn"`
+ Id int64 `json:"id"`
+ Name string `json:"name"`
+ Email string `json:"email"`
+ Role string `json:"role"`
+ InvitedByLogin string `json:"invitedByLogin"`
+ InvitedByEmail string `json:"invitedByEmail"`
+ InvitedByName string `json:"invitedByName"`
+ Code string `json:"code"`
+ Status TempUserStatus `json:"status"`
+ Url string `json:"url"`
+ EmailSent bool `json:"emailSent"`
+ EmailSentOn time.Time `json:"emailSentOn"`
+ Created time.Time `json:"createdOn"`
}
diff --git a/pkg/services/sqlstore/temp_user.go b/pkg/services/sqlstore/temp_user.go
index 0931cd2b1df..df1bdd96127 100644
--- a/pkg/services/sqlstore/temp_user.go
+++ b/pkg/services/sqlstore/temp_user.go
@@ -56,10 +56,13 @@ func GetTempUsersForOrg(query *m.GetTempUsersForOrgQuery) error {
tu.name as name,
tu.role as role,
tu.code as code,
+ tu.status as status,
tu.email_sent as email_sent,
tu.email_sent_on as email_sent_on,
tu.created as created,
- u.login as invited_by
+ u.login as invited_by_login,
+ u.name as invited_by_name,
+ u.email as invited_by_email
FROM ` + dialect.Quote("temp_user") + ` as tu
LEFT OUTER JOIN ` + dialect.Quote("user") + ` as u on u.id = tu.invited_by_user_id
WHERE tu.org_id=? AND tu.status =? ORDER BY tu.created desc`
@@ -71,8 +74,26 @@ func GetTempUsersForOrg(query *m.GetTempUsersForOrgQuery) error {
}
func GetTempUserByCode(query *m.GetTempUserByCodeQuery) error {
- var user m.TempUser
- has, err := x.Table("temp_user").Where("code=?", query.Code).Get(&user)
+ var rawSql = `SELECT
+ tu.id as id,
+ tu.email as email,
+ tu.name as name,
+ tu.role as role,
+ tu.code as code,
+ tu.status as status,
+ tu.email_sent as email_sent,
+ tu.email_sent_on as email_sent_on,
+ tu.created as created,
+ u.login as invited_by_login,
+ u.name as invited_by_name,
+ u.email as invited_by_email
+ FROM ` + dialect.Quote("temp_user") + ` as tu
+ LEFT OUTER JOIN ` + dialect.Quote("user") + ` as u on u.id = tu.invited_by_user_id
+ WHERE tu.code=?`
+
+ var tempUser m.TempUserDTO
+ sess := x.Sql(rawSql, query.Code)
+ has, err := sess.Get(&tempUser)
if err != nil {
return err
@@ -80,6 +101,6 @@ func GetTempUserByCode(query *m.GetTempUserByCodeQuery) error {
return m.ErrTempUserNotFound
}
- query.Result = &user
+ query.Result = &tempUser
return err
}
diff --git a/pkg/services/sqlstore/temp_user_test.go b/pkg/services/sqlstore/temp_user_test.go
index ad3681c2071..6b550799e73 100644
--- a/pkg/services/sqlstore/temp_user_test.go
+++ b/pkg/services/sqlstore/temp_user_test.go
@@ -32,6 +32,14 @@ func TestTempUserCommandsAndQueries(t *testing.T) {
So(len(query.Result), ShouldEqual, 1)
})
+ Convey("Should be able to get temp users by code", func() {
+ query := m.GetTempUserByCodeQuery{Code: "asd"}
+ err = GetTempUserByCode(&query)
+
+ So(err, ShouldBeNil)
+ So(query.Result.Name, ShouldEqual, "hello")
+ })
+
Convey("Should be able update status", func() {
cmd2 := m.UpdateTempUserStatusCommand{Code: "asd", Status: m.TmpUserRevoked}
err := UpdateTempUserStatus(&cmd2)
diff --git a/pkg/util/strings.go b/pkg/util/strings.go
index 277e5e036c8..7e503a99118 100644
--- a/pkg/util/strings.go
+++ b/pkg/util/strings.go
@@ -6,3 +6,13 @@ func StringsFallback2(val1 string, val2 string) string {
}
return val2
}
+
+func StringsFallback3(val1 string, val2 string, val3 string) string {
+ if val1 != "" {
+ return val1
+ }
+ if val2 != "" {
+ return val2
+ }
+ return val3
+}
diff --git a/public/app/controllers/invitedCtrl.js b/public/app/controllers/invitedCtrl.js
index e3e36d56463..0b4a096fb1b 100644
--- a/public/app/controllers/invitedCtrl.js
+++ b/public/app/controllers/invitedCtrl.js
@@ -20,7 +20,8 @@ function (angular, config) {
$scope.formModel.username = invite.email;
$scope.formModel.inviteCode = $routeParams.code;
- $scope.greeting = invite.name || invite.email;
+ $scope.greeting = invite.name || invite.email || invite.username;
+ $scope.invitedBy = invite.invitedBy;
});
};
diff --git a/public/app/partials/signup_invited.html b/public/app/partials/signup_invited.html
index e4b5e9dc7a8..329d1fee1bf 100644
--- a/public/app/partials/signup_invited.html
+++ b/public/app/partials/signup_invited.html
@@ -14,8 +14,8 @@
Hello {{greeting}}.
-
-
{{.InvitedBy}} has invited you to join the
{{contextSrv.user.orgName}} organization in Grafana.Please complete the following to accept your invitation and continue:
+
+ {{invitedBy}} has invited you to join the {{contextSrv.user.orgName}} organization in Grafana.Please complete the following to accept your invitation and continue:
-
diff --git a/public/css/less/grafana.less b/public/css/less/grafana.less
index 2ec921cb267..163cb7d792e 100644
--- a/public/css/less/grafana.less
+++ b/public/css/less/grafana.less
@@ -1,3 +1,4 @@
+@import "type.less";
@import "login.less";
@import "submenu.less";
@import "graph.less";
@@ -277,11 +278,6 @@
}
}
-.long-tag {
- width: 90%;
- margin: 0 auto;
-}
-
.confirm-modal {
max-width: 500px;
@@ -371,7 +367,7 @@
}
.body-copy-emphasis {
- color: @headingsColor;
+ color: @headingsColor;
}
.signup-page-container {
diff --git a/public/css/less/type.less b/public/css/less/type.less
new file mode 100644
index 00000000000..1d833792484
--- /dev/null
+++ b/public/css/less/type.less
@@ -0,0 +1,247 @@
+//
+// Typography
+// --------------------------------------------------
+
+
+// Body text
+// -------------------------
+
+p {
+ margin: 0 0 @baseLineHeight / 2;
+}
+.lead {
+ margin-bottom: @baseLineHeight;
+ font-size: @baseFontSize * 1.5;
+ font-weight: 200;
+ line-height: @baseLineHeight * 1.5;
+}
+
+
+// Emphasis & misc
+// -------------------------
+
+// Ex: 14px base font * 85% = about 12px
+small { font-size: 85%; }
+
+strong { font-weight: 500; }
+em { font-style: italic; color: @headingsColor; }
+cite { font-style: normal; }
+
+// Utility classes
+.muted { color: @grayLight; }
+a.muted:hover,
+a.muted:focus { color: darken(@grayLight, 10%); }
+
+.text-warning { color: @warningText; }
+a.text-warning:hover,
+a.text-warning:focus { color: darken(@warningText, 10%); }
+
+.text-error { color: @errorText; }
+a.text-error:hover,
+a.text-error:focus { color: darken(@errorText, 10%); }
+
+.text-info { color: @infoText; }
+a.text-info:hover,
+a.text-info:focus { color: darken(@infoText, 10%); }
+
+.text-success { color: @successText; }
+a.text-success:hover,
+a.text-success:focus { color: darken(@successText, 10%); }
+
+.text-left { text-align: left; }
+.text-right { text-align: right; }
+.text-center { text-align: center; }
+
+
+// Headings
+// -------------------------
+
+h1, h2, h3, h4, h5, h6 {
+ margin: (@baseLineHeight / 2) 0;
+ font-family: @headingsFontFamily;
+ font-weight: @headingsFontWeight;
+ line-height: @baseLineHeight;
+ color: @headingsColor;
+ text-rendering: optimizelegibility; // Fix the character spacing for headings
+ small {
+ font-weight: normal;
+ line-height: 1;
+ color: @grayLight;
+ }
+}
+
+h1,
+h2,
+h3 { line-height: @baseLineHeight * 2; }
+
+h1 { font-size: @baseFontSize * 2.00; } // ~38px
+h2 { font-size: @baseFontSize * 1.75; } // ~32px
+h3 { font-size: @baseFontSize * 1.50; } // ~24px
+h4 { font-size: @baseFontSize * 1.25; } // ~18px
+h5 { font-size: @baseFontSize; }
+h6 { font-size: @baseFontSize * 0.85; } // ~12px
+
+h1 small { font-size: @baseFontSize * 1.75; } // ~24px
+h2 small { font-size: @baseFontSize * 1.25; } // ~18px
+h3 small { font-size: @baseFontSize; }
+h4 small { font-size: @baseFontSize; }
+
+
+// Page header
+// -------------------------
+
+.page-header {
+ padding-bottom: (@baseLineHeight / 2) - 1;
+ margin: @baseLineHeight 0 (@baseLineHeight * 1.5);
+ border-bottom: 1px solid @grayLighter;
+}
+
+
+
+// Lists
+// --------------------------------------------------
+
+// Unordered and Ordered lists
+ul, ol {
+ padding: 0;
+ margin: 0 0 @baseLineHeight / 2 25px;
+}
+ul ul,
+ul ol,
+ol ol,
+ol ul {
+ margin-bottom: 0;
+}
+li {
+ line-height: @baseLineHeight;
+}
+
+// Remove default list styles
+ul.unstyled,
+ol.unstyled {
+ margin-left: 0;
+ list-style: none;
+}
+
+// Single-line list items
+ul.inline,
+ol.inline {
+ margin-left: 0;
+ list-style: none;
+ > li {
+ display: inline-block;
+ .ie7-inline-block();
+ padding-left: 5px;
+ padding-right: 5px;
+ }
+}
+
+// Description Lists
+dl {
+ margin-bottom: @baseLineHeight;
+}
+dt,
+dd {
+ line-height: @baseLineHeight;
+}
+dt {
+ font-weight: bold;
+}
+dd {
+ margin-left: @baseLineHeight / 2;
+}
+// Horizontal layout (like forms)
+.dl-horizontal {
+ .clearfix(); // Ensure dl clears floats if empty dd elements present
+ dt {
+ float: left;
+ width: @horizontalComponentOffset - 20;
+ clear: left;
+ text-align: right;
+ .text-overflow();
+ }
+ dd {
+ margin-left: @horizontalComponentOffset;
+ }
+}
+
+// MISC
+// ----
+
+// Horizontal rules
+hr {
+ margin: @baseLineHeight 0;
+ border: 0;
+ border-top: 1px solid @hrBorder;
+ border-bottom: 1px solid @white;
+}
+
+// Abbreviations and acronyms
+abbr[title],
+// Added data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257
+abbr[data-original-title] {
+ cursor: help;
+ border-bottom: 1px dotted @grayLight;
+}
+abbr.initialism {
+ font-size: 90%;
+ text-transform: uppercase;
+}
+
+// Blockquotes
+blockquote {
+ padding: 0 0 0 15px;
+ margin: 0 0 @baseLineHeight;
+ border-left: 5px solid @grayLighter;
+ p {
+ margin-bottom: 0;
+ font-size: @baseFontSize * 1.25;
+ font-weight: 300;
+ line-height: 1.25;
+ }
+ small {
+ display: block;
+ line-height: @baseLineHeight;
+ color: @grayLight;
+ &:before {
+ content: '\2014 \00A0';
+ }
+ }
+
+ // Float right with text-align: right
+ &.pull-right {
+ float: right;
+ padding-right: 15px;
+ padding-left: 0;
+ border-right: 5px solid @grayLighter;
+ border-left: 0;
+ p,
+ small {
+ text-align: right;
+ }
+ small {
+ &:before {
+ content: '';
+ }
+ &:after {
+ content: '\00A0 \2014';
+ }
+ }
+ }
+}
+
+// Quotes
+q:before,
+q:after,
+blockquote:before,
+blockquote:after {
+ content: "";
+}
+
+// Addresses
+address {
+ display: block;
+ margin-bottom: @baseLineHeight;
+ font-style: normal;
+ line-height: @baseLineHeight;
+}
diff --git a/public/vendor/bootstrap/less/bootstrap.less b/public/vendor/bootstrap/less/bootstrap.less
index a22c4b24756..758dbde9848 100644
--- a/public/vendor/bootstrap/less/bootstrap.less
+++ b/public/vendor/bootstrap/less/bootstrap.less
@@ -22,7 +22,6 @@
// Base CSS
@import "type.less";
-@import "code.less";
@import "forms.less";
@import "tables.less";
diff --git a/public/vendor/bootstrap/less/type.less b/public/vendor/bootstrap/less/type.less
index 109b09de44d..8b137891791 100644
--- a/public/vendor/bootstrap/less/type.less
+++ b/public/vendor/bootstrap/less/type.less
@@ -1,247 +1 @@
-//
-// Typography
-// --------------------------------------------------
-
-// Body text
-// -------------------------
-
-p {
- margin: 0 0 @baseLineHeight / 2;
-}
-.lead {
- margin-bottom: @baseLineHeight;
- font-size: @baseFontSize * 1.5;
- font-weight: 200;
- line-height: @baseLineHeight * 1.5;
-}
-
-
-// Emphasis & misc
-// -------------------------
-
-// Ex: 14px base font * 85% = about 12px
-small { font-size: 85%; }
-
-strong { font-weight: bold; }
-em { font-style: italic; }
-cite { font-style: normal; }
-
-// Utility classes
-.muted { color: @grayLight; }
-a.muted:hover,
-a.muted:focus { color: darken(@grayLight, 10%); }
-
-.text-warning { color: @warningText; }
-a.text-warning:hover,
-a.text-warning:focus { color: darken(@warningText, 10%); }
-
-.text-error { color: @errorText; }
-a.text-error:hover,
-a.text-error:focus { color: darken(@errorText, 10%); }
-
-.text-info { color: @infoText; }
-a.text-info:hover,
-a.text-info:focus { color: darken(@infoText, 10%); }
-
-.text-success { color: @successText; }
-a.text-success:hover,
-a.text-success:focus { color: darken(@successText, 10%); }
-
-.text-left { text-align: left; }
-.text-right { text-align: right; }
-.text-center { text-align: center; }
-
-
-// Headings
-// -------------------------
-
-h1, h2, h3, h4, h5, h6 {
- margin: (@baseLineHeight / 2) 0;
- font-family: @headingsFontFamily;
- font-weight: @headingsFontWeight;
- line-height: @baseLineHeight;
- color: @headingsColor;
- text-rendering: optimizelegibility; // Fix the character spacing for headings
- small {
- font-weight: normal;
- line-height: 1;
- color: @grayLight;
- }
-}
-
-h1,
-h2,
-h3 { line-height: @baseLineHeight * 2; }
-
-h1 { font-size: @baseFontSize * 2.00; } // ~38px
-h2 { font-size: @baseFontSize * 1.75; } // ~32px
-h3 { font-size: @baseFontSize * 1.50; } // ~24px
-h4 { font-size: @baseFontSize * 1.25; } // ~18px
-h5 { font-size: @baseFontSize; }
-h6 { font-size: @baseFontSize * 0.85; } // ~12px
-
-h1 small { font-size: @baseFontSize * 1.75; } // ~24px
-h2 small { font-size: @baseFontSize * 1.25; } // ~18px
-h3 small { font-size: @baseFontSize; }
-h4 small { font-size: @baseFontSize; }
-
-
-// Page header
-// -------------------------
-
-.page-header {
- padding-bottom: (@baseLineHeight / 2) - 1;
- margin: @baseLineHeight 0 (@baseLineHeight * 1.5);
- border-bottom: 1px solid @grayLighter;
-}
-
-
-
-// Lists
-// --------------------------------------------------
-
-// Unordered and Ordered lists
-ul, ol {
- padding: 0;
- margin: 0 0 @baseLineHeight / 2 25px;
-}
-ul ul,
-ul ol,
-ol ol,
-ol ul {
- margin-bottom: 0;
-}
-li {
- line-height: @baseLineHeight;
-}
-
-// Remove default list styles
-ul.unstyled,
-ol.unstyled {
- margin-left: 0;
- list-style: none;
-}
-
-// Single-line list items
-ul.inline,
-ol.inline {
- margin-left: 0;
- list-style: none;
- > li {
- display: inline-block;
- .ie7-inline-block();
- padding-left: 5px;
- padding-right: 5px;
- }
-}
-
-// Description Lists
-dl {
- margin-bottom: @baseLineHeight;
-}
-dt,
-dd {
- line-height: @baseLineHeight;
-}
-dt {
- font-weight: bold;
-}
-dd {
- margin-left: @baseLineHeight / 2;
-}
-// Horizontal layout (like forms)
-.dl-horizontal {
- .clearfix(); // Ensure dl clears floats if empty dd elements present
- dt {
- float: left;
- width: @horizontalComponentOffset - 20;
- clear: left;
- text-align: right;
- .text-overflow();
- }
- dd {
- margin-left: @horizontalComponentOffset;
- }
-}
-
-// MISC
-// ----
-
-// Horizontal rules
-hr {
- margin: @baseLineHeight 0;
- border: 0;
- border-top: 1px solid @hrBorder;
- border-bottom: 1px solid @white;
-}
-
-// Abbreviations and acronyms
-abbr[title],
-// Added data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257
-abbr[data-original-title] {
- cursor: help;
- border-bottom: 1px dotted @grayLight;
-}
-abbr.initialism {
- font-size: 90%;
- text-transform: uppercase;
-}
-
-// Blockquotes
-blockquote {
- padding: 0 0 0 15px;
- margin: 0 0 @baseLineHeight;
- border-left: 5px solid @grayLighter;
- p {
- margin-bottom: 0;
- font-size: @baseFontSize * 1.25;
- font-weight: 300;
- line-height: 1.25;
- }
- small {
- display: block;
- line-height: @baseLineHeight;
- color: @grayLight;
- &:before {
- content: '\2014 \00A0';
- }
- }
-
- // Float right with text-align: right
- &.pull-right {
- float: right;
- padding-right: 15px;
- padding-left: 0;
- border-right: 5px solid @grayLighter;
- border-left: 0;
- p,
- small {
- text-align: right;
- }
- small {
- &:before {
- content: '';
- }
- &:after {
- content: '\00A0 \2014';
- }
- }
- }
-}
-
-// Quotes
-q:before,
-q:after,
-blockquote:before,
-blockquote:after {
- content: "";
-}
-
-// Addresses
-address {
- display: block;
- margin-bottom: @baseLineHeight;
- font-style: normal;
- line-height: @baseLineHeight;
-}