[MM-33198] - Portal: Send admin welcome email after the installation is complete (#17043)
* [MM-33198] - Portal: Send admin welcome email after the installation is complete * Send cloud welcome email * Feedback impl-2 * Fix template * Temp undo * Update * make i18n-extract * Translations * Feedback impl-3 * More template fixes Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
8248477319
Коммит
05720f627b
@@ -386,6 +386,34 @@ func handleCWSWebhook(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.Err = nErr
|
||||
return
|
||||
}
|
||||
case model.EventTypeSendAdminWelcomeEmail:
|
||||
user, appErr := c.App.GetUserByUsername(event.CloudWorkspaceOwner.UserName)
|
||||
if appErr != nil {
|
||||
c.Err = model.NewAppError("Api4.handleCWSWebhook", appErr.Id, nil, appErr.Error(), appErr.StatusCode)
|
||||
return
|
||||
}
|
||||
|
||||
teams, appErr := c.App.GetAllTeams()
|
||||
if appErr != nil {
|
||||
c.Err = model.NewAppError("Api4.handleCWSWebhook", appErr.Id, nil, appErr.Error(), appErr.StatusCode)
|
||||
return
|
||||
}
|
||||
|
||||
team := teams[0]
|
||||
|
||||
subscription, err := c.App.Cloud().GetSubscription(user.Id)
|
||||
if err != nil {
|
||||
c.Err = model.NewAppError("Api4.handleCWSWebhook", "api.cloud.request_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if appErr := c.App.Srv().EmailService.SendCloudWelcomeEmail(user.Email, user.Locale, team.InviteId, subscription.GetWorkSpaceNameFromDNS(), subscription.DNS); appErr != nil {
|
||||
c.Err = appErr
|
||||
return
|
||||
}
|
||||
default:
|
||||
c.Err = model.NewAppError("Api4.handleCWSWebhook", "api.cloud.cws_webhook_event_missing_error", nil, "", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
ReturnStatusOK(w)
|
||||
|
||||
42
app/email.go
42
app/email.go
@@ -206,7 +206,10 @@ func (es *EmailService) SendSignInChangeEmail(email, method, locale, siteURL str
|
||||
return nil
|
||||
}
|
||||
|
||||
func (es *EmailService) sendWelcomeEmail(userID string, email string, verified bool, locale, siteURL, redirect string) *model.AppError {
|
||||
func (es *EmailService) sendWelcomeEmail(userID string, email string, verified bool, disableWelcomeEmail bool, locale, siteURL, redirect string) *model.AppError {
|
||||
if disableWelcomeEmail {
|
||||
return nil
|
||||
}
|
||||
if !*es.srv.Config().EmailSettings.SendEmailNotifications && !*es.srv.Config().EmailSettings.RequireEmailVerification {
|
||||
return model.NewAppError("SendWelcomeEmail", "api.user.send_welcome_email_and_forget.failed.error", nil, "Send Email Notifications and Require Email Verification is disabled in the system console", http.StatusInternalServerError)
|
||||
}
|
||||
@@ -256,6 +259,43 @@ func (es *EmailService) sendWelcomeEmail(userID string, email string, verified b
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendCloudWelcomeEmail sends the cloud version of the welcome email
|
||||
func (es *EmailService) SendCloudWelcomeEmail(userEmail, locale, teamInviteID, workSpaceName, dns string) *model.AppError {
|
||||
T := i18n.GetUserTranslations(locale)
|
||||
subject := T("api.templates.cloud_welcome_email.subject")
|
||||
|
||||
workSpacePath := fmt.Sprintf("https://%s.cloud.mattermost.com", workSpaceName)
|
||||
|
||||
bodyPage := es.newEmailTemplate("cloud_welcome_email", locale)
|
||||
bodyPage.Props["Title"] = T("api.templates.cloud_welcome_email.title", map[string]interface{}{"WorkSpace": workSpaceName})
|
||||
bodyPage.Props["SubTitle"] = T("api.templates.cloud_welcome_email.subtitle")
|
||||
bodyPage.Props["SubTitleInfo"] = T("api.templates.cloud_welcome_email.subtitle_info")
|
||||
bodyPage.Props["Info"] = T("api.templates.cloud_welcome_email.info")
|
||||
bodyPage.Props["Info2"] = T("api.templates.cloud_welcome_email.info2")
|
||||
bodyPage.Props["WorkSpacePath"] = workSpacePath
|
||||
bodyPage.Props["DNS"] = dns
|
||||
bodyPage.Props["InviteInfo"] = T("api.templates.cloud_welcome_email.invite_info")
|
||||
bodyPage.Props["InviteSubInfo"] = T("api.templates.cloud_welcome_email.invite_sub_info", map[string]interface{}{"WorkSpace": workSpaceName})
|
||||
bodyPage.Props["InviteSubInfoLink"] = fmt.Sprintf("%s/signup_user_complete/?id=%s", workSpacePath, teamInviteID)
|
||||
bodyPage.Props["AddAppsInfo"] = T("api.templates.cloud_welcome_email.add_apps_info")
|
||||
bodyPage.Props["AddAppsSubInfo"] = T("api.templates.cloud_welcome_email.add_apps_sub_info")
|
||||
bodyPage.Props["AppMarketPlace"] = T("api.templates.cloud_welcome_email.app_market_place")
|
||||
bodyPage.Props["AppMarketPlaceLink"] = "https://integrations.mattermost.com/"
|
||||
bodyPage.Props["DownloadMMInfo"] = T("api.templates.cloud_welcome_email.download_mm_info")
|
||||
bodyPage.Props["SignInSubInfo"] = T("api.templates.cloud_welcome_email.signin_sub_info")
|
||||
bodyPage.Props["MMApps"] = T("api.templates.cloud_welcome_email.mm_apps")
|
||||
bodyPage.Props["SignInSubInfo2"] = T("api.templates.cloud_welcome_email.signin_sub_info2")
|
||||
bodyPage.Props["DownloadMMAppsLink"] = "https://mattermost.com/download/"
|
||||
bodyPage.Props["Button"] = T("api.templates.cloud_welcome_email.button")
|
||||
bodyPage.Props["GettingStartedQuestions"] = T("api.templates.cloud_welcome_email.start_questions")
|
||||
|
||||
if err := es.sendMail(userEmail, subject, bodyPage.Render()); err != nil {
|
||||
return model.NewAppError("SendCloudWelcomeEmail", "api.user.send_cloud_welcome_email.error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (es *EmailService) sendPasswordChangeEmail(email, method, locale, siteURL string) *model.AppError {
|
||||
T := i18n.GetUserTranslations(locale)
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ func (a *App) CreateUserWithInviteId(user *model.User, inviteId, redirect string
|
||||
|
||||
a.AddDirectChannels(team.Id, ruser)
|
||||
|
||||
if err := a.Srv().EmailService.sendWelcomeEmail(ruser.Id, ruser.Email, ruser.EmailVerified, ruser.Locale, a.GetSiteURL(), redirect); err != nil {
|
||||
if err := a.Srv().EmailService.sendWelcomeEmail(ruser.Id, ruser.Email, ruser.EmailVerified, ruser.DisableWelcomeEmail, ruser.Locale, a.GetSiteURL(), redirect); err != nil {
|
||||
mlog.Warn("Failed to send welcome email on create user with inviteId", mlog.Err(err))
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ func (a *App) CreateUserAsAdmin(user *model.User, redirect string) (*model.User,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := a.Srv().EmailService.sendWelcomeEmail(ruser.Id, ruser.Email, ruser.EmailVerified, ruser.Locale, a.GetSiteURL(), redirect); err != nil {
|
||||
if err := a.Srv().EmailService.sendWelcomeEmail(ruser.Id, ruser.Email, ruser.EmailVerified, ruser.DisableWelcomeEmail, ruser.Locale, a.GetSiteURL(), redirect); err != nil {
|
||||
mlog.Warn("Failed to send welcome email to the new user, created by system admin", mlog.Err(err))
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ func (a *App) CreateUserFromSignup(user *model.User, redirect string) (*model.Us
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := a.Srv().EmailService.sendWelcomeEmail(ruser.Id, ruser.Email, ruser.EmailVerified, ruser.Locale, a.GetSiteURL(), redirect); err != nil {
|
||||
if err := a.Srv().EmailService.sendWelcomeEmail(ruser.Id, ruser.Email, ruser.EmailVerified, ruser.DisableWelcomeEmail, ruser.Locale, a.GetSiteURL(), redirect); err != nil {
|
||||
mlog.Warn("Failed to send welcome email on create user from signup", mlog.Err(err))
|
||||
}
|
||||
|
||||
@@ -333,6 +333,9 @@ func (a *App) createUser(user *model.User) (*model.User, *model.AppError) {
|
||||
|
||||
go a.UpdateViewedProductNoticesForNewUser(ruser.Id)
|
||||
ruser.Sanitize(map[string]bool{})
|
||||
|
||||
// Determine whether to send the created user a welcome email
|
||||
ruser.DisableWelcomeEmail = user.DisableWelcomeEmail
|
||||
return ruser, nil
|
||||
}
|
||||
|
||||
|
||||
76
i18n/en.json
76
i18n/en.json
@@ -479,6 +479,10 @@
|
||||
"id": "api.cloud.app_error",
|
||||
"translation": "Internal error during cloud api request."
|
||||
},
|
||||
{
|
||||
"id": "api.cloud.cws_webhook_event_missing_error",
|
||||
"translation": "Webhook event was not handled. Either it is missing or it is not valid."
|
||||
},
|
||||
{
|
||||
"id": "api.cloud.get_admins_emails.error",
|
||||
"translation": "Error getting system admins email."
|
||||
@@ -2678,6 +2682,74 @@
|
||||
"id": "api.templates.at_limit_title",
|
||||
"translation": "You’ve reached the user limit for the free tier "
|
||||
},
|
||||
{
|
||||
"id": "api.templates.cloud_welcome_email.add_apps_info",
|
||||
"translation": "Add apps to your workspace"
|
||||
},
|
||||
{
|
||||
"id": "api.templates.cloud_welcome_email.add_apps_sub_info",
|
||||
"translation": "Streamline your work with tools like Github, Google Calendar and Chrome. Explore all of the integrations we have on our"
|
||||
},
|
||||
{
|
||||
"id": "api.templates.cloud_welcome_email.app_market_place",
|
||||
"translation": "app marketplace."
|
||||
},
|
||||
{
|
||||
"id": "api.templates.cloud_welcome_email.button",
|
||||
"translation": "Open Mattermost"
|
||||
},
|
||||
{
|
||||
"id": "api.templates.cloud_welcome_email.download_mm_info",
|
||||
"translation": "Download the Mattermost App"
|
||||
},
|
||||
{
|
||||
"id": "api.templates.cloud_welcome_email.info",
|
||||
"translation": "Thanks for creating "
|
||||
},
|
||||
{
|
||||
"id": "api.templates.cloud_welcome_email.info2",
|
||||
"translation": "Make sure to save or bookmark your link for future use."
|
||||
},
|
||||
{
|
||||
"id": "api.templates.cloud_welcome_email.invite_info",
|
||||
"translation": "Invite people to your workspace"
|
||||
},
|
||||
{
|
||||
"id": "api.templates.cloud_welcome_email.invite_sub_info",
|
||||
"translation": "Share this link to invite your members to join {{.WorkSpace}}:"
|
||||
},
|
||||
{
|
||||
"id": "api.templates.cloud_welcome_email.mm_apps",
|
||||
"translation": "mobile and desktop apps"
|
||||
},
|
||||
{
|
||||
"id": "api.templates.cloud_welcome_email.signin_sub_info",
|
||||
"translation": "Sign into your workspace on our"
|
||||
},
|
||||
{
|
||||
"id": "api.templates.cloud_welcome_email.signin_sub_info2",
|
||||
"translation": "for the best experience on PC, Mac, iOS and Android."
|
||||
},
|
||||
{
|
||||
"id": "api.templates.cloud_welcome_email.start_questions",
|
||||
"translation": "Having questions about getting started? Email us at"
|
||||
},
|
||||
{
|
||||
"id": "api.templates.cloud_welcome_email.subject",
|
||||
"translation": "Congratulations!"
|
||||
},
|
||||
{
|
||||
"id": "api.templates.cloud_welcome_email.subtitle",
|
||||
"translation": "Set up your workspace"
|
||||
},
|
||||
{
|
||||
"id": "api.templates.cloud_welcome_email.subtitle_info",
|
||||
"translation": "Take the following steps to build out your teams and get the most out of your workspace."
|
||||
},
|
||||
{
|
||||
"id": "api.templates.cloud_welcome_email.title",
|
||||
"translation": "Congratulations - your {{.WorkSpace}} workspace is ready to go!"
|
||||
},
|
||||
{
|
||||
"id": "api.templates.copyright",
|
||||
"translation": "© 2020 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301"
|
||||
@@ -3546,6 +3618,10 @@
|
||||
"id": "api.user.saml.not_available.app_error",
|
||||
"translation": "SAML 2.0 is not configured or supported on this server."
|
||||
},
|
||||
{
|
||||
"id": "api.user.send_cloud_welcome_email.error",
|
||||
"translation": "Failed to send cloud welcome email"
|
||||
},
|
||||
{
|
||||
"id": "api.user.send_deactivate_email_and_forget.failed.error",
|
||||
"translation": "Failed to send the deactivate account email successfully"
|
||||
|
||||
@@ -3,11 +3,14 @@
|
||||
|
||||
package model
|
||||
|
||||
import "strings"
|
||||
|
||||
const (
|
||||
EventTypeFailedPayment = "failed-payment"
|
||||
EventTypeFailedPaymentNoCard = "failed-payment-no-card"
|
||||
JoinLimitation = "join"
|
||||
InviteLimitation = "invite"
|
||||
EventTypeFailedPayment = "failed-payment"
|
||||
EventTypeFailedPaymentNoCard = "failed-payment-no-card"
|
||||
EventTypeSendAdminWelcomeEmail = "send-admin-welcome-email"
|
||||
JoinLimitation = "join"
|
||||
InviteLimitation = "invite"
|
||||
)
|
||||
|
||||
// Product model represents a product on the cloud system.
|
||||
@@ -94,6 +97,11 @@ type Subscription struct {
|
||||
LastInvoice *Invoice `json:"last_invoice"`
|
||||
}
|
||||
|
||||
// GetWorkSpaceNameFromDNS returns the work space name. For example from test.mattermost.cloud.com, it returns test
|
||||
func (s *Subscription) GetWorkSpaceNameFromDNS() string {
|
||||
return strings.Split(s.DNS, ".")[0]
|
||||
}
|
||||
|
||||
// Invoice model represents a cloud invoice
|
||||
type Invoice struct {
|
||||
ID string `json:"id"`
|
||||
@@ -121,8 +129,9 @@ type InvoiceLineItem struct {
|
||||
}
|
||||
|
||||
type CWSWebhookPayload struct {
|
||||
Event string `json:"event"`
|
||||
FailedPayment *FailedPayment `json:"failed_payment"`
|
||||
Event string `json:"event"`
|
||||
FailedPayment *FailedPayment `json:"failed_payment"`
|
||||
CloudWorkspaceOwner *CloudWorkspaceOwner `json:"cloud_workspace_owner"`
|
||||
}
|
||||
|
||||
type FailedPayment struct {
|
||||
@@ -131,6 +140,10 @@ type FailedPayment struct {
|
||||
FailureMessage string `json:"failure_message"`
|
||||
}
|
||||
|
||||
// CloudWorkspaceOwner is part of the CWS Webhook payload that contains information about the user that created the workspace from the CWS
|
||||
type CloudWorkspaceOwner struct {
|
||||
UserName string `json:"username"`
|
||||
}
|
||||
type SubscriptionStats struct {
|
||||
RemainingSeats int `json:"remaining_seats"`
|
||||
IsPaidTier string `json:"is_paid_tier"`
|
||||
|
||||
@@ -98,6 +98,7 @@ type User struct {
|
||||
BotLastIconUpdate int64 `db:"-" json:"bot_last_icon_update,omitempty"`
|
||||
TermsOfServiceId string `db:"-" json:"terms_of_service_id,omitempty"`
|
||||
TermsOfServiceCreateAt int64 `db:"-" json:"terms_of_service_create_at,omitempty"`
|
||||
DisableWelcomeEmail bool `db:"-" json:"disable_welcome_email"`
|
||||
}
|
||||
|
||||
//msgp UserMap
|
||||
|
||||
116
templates/cloud_welcome_email.html
Обычный файл
116
templates/cloud_welcome_email.html
Обычный файл
@@ -0,0 +1,116 @@
|
||||
{{define "cloud_welcome_email"}}
|
||||
<head><link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400&display=swap" rel="stylesheet"></head>
|
||||
<body>
|
||||
<div
|
||||
style="display: flex; flex-direction: row; align-items: center; padding: 32px; position: relative; width: 724px; height: 1221.07px; background: #F7F7F7; margin: auto;">
|
||||
|
||||
<div
|
||||
style="display: flex; flex-direction: column; align-items: center; padding: 24px; position: static; width: 660px; height: 1157.07px; left: 32px; top: 32px; border-radius: 8px; background: #FFFFFF; color: #3D3C40; flex: none; order: 0; flex-grow: 0; margin: 0px 10px;">
|
||||
<div style="position: relative; width: 500px; margin-top: 20px; margin-bottom: 30px; display: flex; align-items: center;">
|
||||
<img src="{{.Props.WorkSpacePath}}/static/images/logo_email_blue.png" style="position: absolute; left: 188px; height: 21.7px;"
|
||||
alt="logo_email_blue">
|
||||
</div>
|
||||
<div style="margin-bottom: 30px;">
|
||||
<p
|
||||
style="position: static; width: 500px; height: 72px; left: 24px; top: 0px; font-family: Open Sans; font-style: normal; font-weight: 600; font-size: 28px; line-height: 36px; display: flex; align-items: center; letter-spacing: -0.02em; color: #3D3C40; flex: none; order: 0; flex-grow: 0; margin: 16px 0px;">
|
||||
{{.Props.Title}}
|
||||
</p>
|
||||
<p
|
||||
style="position: static; width: 485px; height: 48px; left: 24px; top: 0px; font-family: Open Sans; font-style: normal; font-weight: 400; font-size: 16px; line-height: 24px; color: #3D3C40; flex: none; order: 0; flex-grow: 0; margin: 0px 0px;">
|
||||
{{.Props.Info}} <a style="text-decoration: none; color: #6DA4EB;" target="_blank" rel="noopener noreferrer" href="{{.Props.WorkSpacePath}}">{{.Props.DNS}}.</a> {{.Props.Info2}}
|
||||
</p>
|
||||
<p>
|
||||
<a href="{{.Props.WorkSpacePath}}" target="_blank" rel="noopener noreferrer"
|
||||
style="display: flex; flex-direction: column; align-items: center; padding: 14px 24px; position: static; background: #166DE0; border-radius: 4px; flex: none; order: 0; flex-grow: 0; margin: 0px 150px; font-family: Open Sans; font-style: normal; font-weight: 600; font-size: 16px; line-height: 18px; color: #FFFFFF; text-decoration: none;">
|
||||
{{.Props.Button }}
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 30px;">
|
||||
<p
|
||||
style="position: static; width: 485px; height: 40px; left: 24px; top: 0px; font-family: Open Sans; font-weight: 600; font-size: 22px; line-height: 28px; color: #3D3C40; flex: none; order: 0; flex-grow: 0; margin: 0px 0px;">
|
||||
{{.Props.SubTitle}}
|
||||
</p>
|
||||
<p
|
||||
style="position: static; width: 492px; height: 40px; left: 0px; top: 36px; font-family: Open Sans; font-style: normal; font-weight: 400; font-size: 14px; line-height: 20px; color: #3D3C40; flex: none; order: 1; flex-grow: 0; margin: 0px 0px;">
|
||||
{{.Props.SubTitleInfo}}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div style="position: relative; margin-left: -15px; margin-bottom: 50px;">
|
||||
<span>
|
||||
<svg width="15" height="15" viewBox="0 0 18 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M3.2 13.5982C2.96 13.5982 2.75333 13.5116 2.58 13.3382C2.42 13.1649 2.34 12.9582 2.34 12.7182C2.34 12.5982 2.35333 12.5116 2.38 12.4582C2.42 12.2849 2.50667 12.1449 2.64 12.0382C2.68 11.9982 2.75333 11.9516 2.86 11.8982L5.44 10.3582C6.01333 10.7049 6.64667 10.8782 7.34 10.8782C8.03333 10.8782 8.66667 10.7049 9.24 10.3582L9.52 10.5382C9.76 10.0582 10.0933 9.60491 10.52 9.17824H10.5C10.94 8.60491 11.2733 7.93824 11.5 7.17824C11.74 6.41824 11.86 5.63824 11.86 4.83824C11.86 3.93157 11.6667 3.13157 11.28 2.43824C10.9067 1.74491 10.38 1.21157 9.7 0.838239C9.02 0.451572 8.23333 0.258239 7.34 0.258239C6.44667 0.258239 5.66 0.451572 4.98 0.838239C4.3 1.21157 3.76667 1.74491 3.38 2.43824C3.00667 3.13157 2.82 3.93157 2.82 4.83824C2.82 5.63824 2.93333 6.41824 3.16 7.17824C3.4 7.93824 3.73333 8.60491 4.16 9.17824L2.06 10.4382C1.63333 10.6516 1.29333 10.9649 1.04 11.3782C0.786667 11.7916 0.66 12.2316 0.66 12.6982C0.66 13.1649 0.773333 13.5982 1 13.9982C1.22667 14.3849 1.53333 14.6916 1.92 14.9182C2.32 15.1449 2.74667 15.2582 3.2 15.2582H9.68C9.38667 14.7649 9.18667 14.2116 9.08 13.5982H3.2ZM7.34 1.91824C8.18 1.91824 8.85333 2.15157 9.36 2.61824C9.92 3.13824 10.2 3.87824 10.2 4.83824C10.2 5.46491 10.1 6.09157 9.9 6.71824C9.7 7.34491 9.42 7.87824 9.06 8.31824C8.55333 8.91824 7.98 9.21824 7.34 9.21824C7.14 9.21824 6.92667 9.18491 6.7 9.11824C6.56667 9.06491 6.46667 9.01824 6.4 8.97824C6.18667 8.85824 6.01333 8.73157 5.88 8.59824C5.84 8.55824 5.78 8.49824 5.7 8.41824L5.6 8.31824L5.42 8.07824C5.34 7.95824 5.22 7.75157 5.06 7.45824C4.87333 7.07157 4.74667 6.71157 4.68 6.37824C4.62667 6.20491 4.57333 5.94491 4.52 5.59824C4.49333 5.27824 4.48 5.02491 4.48 4.83824C4.48 3.87824 4.76 3.13824 5.32 2.61824C5.82667 2.15157 6.5 1.91824 7.34 1.91824ZM13.16 9.41824H14.84V11.9182H17.34V13.5982H14.84V16.0982H13.16V13.5982H10.66V11.9182H13.16V9.41824Z"
|
||||
fill="#3D3C40" />
|
||||
</svg>
|
||||
</span>
|
||||
<span
|
||||
style="position: static; width: 492px; height: 30px; left: 5px; top: 36px; font-family: Open Sans; font-style: normal; font-weight: 600; font-size: 16px; line-height: 24px; color: #3D3C40; flex: none; order: 0; flex-grow: 0; margin: 0px 5px;">
|
||||
{{.Props.InviteInfo}}
|
||||
</span>
|
||||
<p
|
||||
style="position: static; width: 458px; height: 20px; left: 0px; top: 0px; font-family: Open Sans; font-style: normal; font-weight: 400; font-size: 14px; line-height: 20px; color: #3D3C40; flex: none; order: 1; flex-grow: 0; margin: 0px 0px; margin-left: 24px;">
|
||||
{{.Props.InviteSubInfo}}
|
||||
<a style="text-decoration: none; color: #6DA4EB;" target="_blank" rel="noopener noreferrer" href="{{.Props.InviteSubInfoLink}}">{{.Props.InviteSubInfoLink}}</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div style="position: relative; margin-left: -15px; margin-bottom: 50px;">
|
||||
<span>
|
||||
<svg width="15" height="15" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M14.18 8.21371L16.52 5.85371C16.6933 5.69371 16.78 5.50038 16.78 5.27372C16.78 5.03371 16.6933 4.83371 16.52 4.67371C16.36 4.51371 16.1667 4.43372 15.94 4.43372C15.7133 4.43372 15.5133 4.51371 15.34 4.67371L13 7.03372L10.04 4.07371L12.4 1.73371C12.56 1.56038 12.64 1.36038 12.64 1.13371C12.64 0.907048 12.56 0.713715 12.4 0.553715C12.24 0.380382 12.04 0.293715 11.8 0.293715C11.5733 0.293715 11.38 0.380382 11.22 0.553715L8.86 2.89371L6.5 0.553715C6.34 0.380382 6.14667 0.293715 5.92 0.293715C5.69333 0.293715 5.5 0.380382 5.34 0.553715H5.32C5.16 0.713715 5.08 0.913714 5.08 1.15371C5.08 1.38038 5.16 1.57371 5.32 1.73371L5.92 2.31371L3.26 4.97372C2.52667 5.70705 2.00667 6.56705 1.7 7.55371C1.42 8.51371 1.36667 9.49371 1.54 10.4937C1.71333 11.4804 2.11333 12.3737 2.74 13.1737L2.68 13.2137L0.92 14.9737C0.746667 15.147 0.66 15.347 0.66 15.5737C0.66 15.8004 0.746667 16.0004 0.92 16.1737C1.09333 16.347 1.28667 16.427 1.5 16.4137C1.72667 16.4137 1.92667 16.3337 2.1 16.1737L3.86 14.3937L3.9 14.3337C4.7 14.9604 5.59333 15.3604 6.58 15.5337C7.58 15.707 8.56 15.6537 9.52 15.3737C10.5067 15.067 11.3667 14.547 12.1 13.8137L14.76 11.1537L15.34 11.7537C15.5 11.9137 15.6933 11.9937 15.92 11.9937C16.16 11.9937 16.36 11.9137 16.52 11.7537V11.7337C16.6933 11.5737 16.78 11.3804 16.78 11.1537C16.78 10.927 16.6933 10.7337 16.52 10.5737L14.18 8.21371ZM10.92 12.6337C10.3333 13.2204 9.64667 13.6137 8.86 13.8137C8.07333 14.0137 7.28667 14.0137 6.5 13.8137C5.71333 13.6137 5.02667 13.2204 4.44 12.6337C3.85333 12.047 3.45333 11.3604 3.24 10.5737C3.04 9.78705 3.04 9.00038 3.24 8.21371C3.45333 7.42705 3.85333 6.74038 4.44 6.15372L7.1 3.49371L13.58 9.97371L10.92 12.6337Z"
|
||||
fill="#3D3C40" />
|
||||
</svg>
|
||||
</span>
|
||||
<span
|
||||
style="position: static; width: 492px; height: 30px; left: 5px; top: 36px; font-family: Open Sans; font-style: normal; font-weight: 600; font-size: 16px; line-height: 24px; color: #3D3C40; flex: none; order: 0; flex-grow: 0; margin: 0px 5px;">
|
||||
{{.Props.AddAppsInfo}}
|
||||
</span>
|
||||
<p
|
||||
style="position: static; width: 458px; height: 20px; left: 0px; top: 0px; font-family: Open Sans; font-style: normal; font-weight: 400; font-size: 14px; line-height: 20px; color: #3D3C40; flex: none; order: 1; flex-grow: 0; margin: 0px 0px; margin-left: 24px;">
|
||||
{{.Props.AddAppsSubInfo}} <a style="text-decoration: none; color: #6DA4EB;" target="_blank" rel="noopener noreferrer" href="{{.Props.AppMarketPlaceLink}}">{{.Props.AppMarketPlace}}</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div style="position: relative; margin-left: -15px; margin-bottom: 50px;">
|
||||
<span>
|
||||
<svg width="15" height="15" viewBox="0 0 12 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M11.84 14.0737H0.16V15.7337H11.84V14.0737ZM5.16 0.73373H6.84V9.23373L10.58 5.49373L11.76 6.65373L6 12.4137L0.26 6.65373L1.42 5.49373L5.16 9.23373V0.73373Z"
|
||||
fill="#3D3C40" />
|
||||
</svg>
|
||||
</span>
|
||||
<span
|
||||
style="position: static; width: 492px; height: 30px; left: 5px; top: 36px; font-family: Open Sans; font-style: normal; font-weight: 600; font-size: 16px; line-height: 24px; color: #3D3C40; flex: none; order: 0; flex-grow: 0; margin: 0px 5px;">
|
||||
{{.Props.DownloadMMInfo}}
|
||||
</span>
|
||||
<p
|
||||
style="position: static; width: 458px; height: 20px; left: 0px; top: 0px; font-family: Open Sans; font-style: normal; font-weight: 400; font-size: 14px; line-height: 20px; color: #3D3C40; flex: none; order: 1; flex-grow: 0; margin: 0px 0px; margin-left: 24px;">
|
||||
{{.Props.SignInSubInfo}} <a style="text-decoration: none; color: #6DA4EB;" target="_blank" rel="noopener noreferrer" href="{{.Props.DownloadMMAppsLink}}">{{.Props.MMApps}}</a> {{.Props.SignInSubInfo2}}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p
|
||||
style="position: static; width: 500px; height: 40px; left: 80px; top: 738.07px; font-family: Open Sans; font-style: normal; font-weight: 400; font-size: 14px; line-height: 20px; color: #3D3C40; flex: none; order: 3; flex-grow: 0; margin: 40px 0px;">
|
||||
{{.Props.GettingStartedQuestions}} <a style="text-decoration: none; color: #6DA4EB;" href="mailto:support@mattermost.com">support@mattermost.com.</a>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<img src="{{.Props.WorkSpacePath}}/static/images/invite_illustration.png" width="320px" alt="invite_illustration">
|
||||
</div>
|
||||
<div>
|
||||
<p
|
||||
style="font-family: Open Sans; font-style: normal; font-weight: 400; font-size: 12px; line-height: 16px; display: flex; align-items: center; text-align: center; color: rgba(61, 60, 64, 0.56); flex: none; order: 0; align-self: stretch; flex-grow: 0; margin: 10px 0px;">
|
||||
© 2020 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
|
||||
{{end}}
|
||||
Ссылка в новой задаче
Block a user