Этот коммит содержится в:
=Corey Hulen
2015-09-24 12:12:27 -07:00
родитель a374419ad5 caa157a377
Коммит 8ad9a88bda
15 изменённых файлов: 111 добавлений и 121 удалений

Просмотреть файл

@@ -6,7 +6,6 @@ package api
import ( import (
l4g "code.google.com/p/log4go" l4g "code.google.com/p/log4go"
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
) )
// //
@@ -24,9 +23,6 @@ func ImportPost(post *model.Post) {
func ImportUser(user *model.User) *model.User { func ImportUser(user *model.User) *model.User {
user.MakeNonNil() user.MakeNonNil()
if len(user.Props["theme"]) == 0 {
user.AddProp("theme", utils.Cfg.TeamSettings.DefaultThemeColor)
}
if result := <-Srv.Store.User().Save(user); result.Err != nil { if result := <-Srv.Store.User().Save(user); result.Err != nil {
l4g.Error("Error saving user. err=%v", result.Err) l4g.Error("Error saving user. err=%v", result.Err)

Просмотреть файл

@@ -11,7 +11,6 @@
"TeamSettings": { "TeamSettings": {
"SiteName": "Mattermost", "SiteName": "Mattermost",
"MaxUsersPerTeam": 50, "MaxUsersPerTeam": 50,
"DefaultThemeColor": "#2389D7",
"EnableTeamCreation": true, "EnableTeamCreation": true,
"EnableUserCreation": true, "EnableUserCreation": true,
"RestrictCreationToDomains": "" "RestrictCreationToDomains": ""

Просмотреть файл

@@ -11,7 +11,6 @@
"TeamSettings": { "TeamSettings": {
"SiteName": "Mattermost", "SiteName": "Mattermost",
"MaxUsersPerTeam": 50, "MaxUsersPerTeam": 50,
"DefaultThemeColor": "#2389D7",
"EnableTeamCreation": true, "EnableTeamCreation": true,
"EnableUserCreation": true, "EnableUserCreation": true,
"RestrictCreationToDomains": "" "RestrictCreationToDomains": ""

Просмотреть файл

@@ -11,7 +11,6 @@
"TeamSettings": { "TeamSettings": {
"SiteName": "Mattermost", "SiteName": "Mattermost",
"MaxUsersPerTeam": 50, "MaxUsersPerTeam": 50,
"DefaultThemeColor": "#2389D7",
"EnableTeamCreation": true, "EnableTeamCreation": true,
"EnableUserCreation": true, "EnableUserCreation": true,
"RestrictCreationToDomains": "" "RestrictCreationToDomains": ""

Просмотреть файл

@@ -112,7 +112,6 @@ type PrivacySettings struct {
type TeamSettings struct { type TeamSettings struct {
SiteName string SiteName string
MaxUsersPerTeam int MaxUsersPerTeam int
DefaultThemeColor string
EnableTeamCreation bool EnableTeamCreation bool
EnableUserCreation bool EnableUserCreation bool
RestrictCreationToDomains string RestrictCreationToDomains string

Просмотреть файл

@@ -35,7 +35,7 @@ export default class ServiceSettings extends React.Component {
config.ServiceSettings.SegmentDeveloperKey = React.findDOMNode(this.refs.SegmentDeveloperKey).value.trim(); config.ServiceSettings.SegmentDeveloperKey = React.findDOMNode(this.refs.SegmentDeveloperKey).value.trim();
config.ServiceSettings.GoogleDeveloperKey = React.findDOMNode(this.refs.GoogleDeveloperKey).value.trim(); config.ServiceSettings.GoogleDeveloperKey = React.findDOMNode(this.refs.GoogleDeveloperKey).value.trim();
config.ServiceSettings.EnableOAuthServiceProvider = React.findDOMNode(this.refs.EnableOAuthServiceProvider).checked; //config.ServiceSettings.EnableOAuthServiceProvider = React.findDOMNode(this.refs.EnableOAuthServiceProvider).checked;
config.ServiceSettings.EnableIncomingWebhooks = React.findDOMNode(this.refs.EnableIncomingWebhooks).checked; config.ServiceSettings.EnableIncomingWebhooks = React.findDOMNode(this.refs.EnableIncomingWebhooks).checked;
config.ServiceSettings.EnableTesting = React.findDOMNode(this.refs.EnableTesting).checked; config.ServiceSettings.EnableTesting = React.findDOMNode(this.refs.EnableTesting).checked;
@@ -170,45 +170,12 @@ export default class ServiceSettings extends React.Component {
</div> </div>
</div> </div>
<div className='form-group'>
<label
className='control-label col-sm-4'
htmlFor='EnableOAuthServiceProvider'
>
{'Enable OAuth Service Provider: '}
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
<input
type='radio'
name='EnableOAuthServiceProvider'
value='true'
ref='EnableOAuthServiceProvider'
defaultChecked={this.props.config.ServiceSettings.EnableOAuthServiceProvider}
onChange={this.handleChange}
/>
{'true'}
</label>
<label className='radio-inline'>
<input
type='radio'
name='EnableOAuthServiceProvider'
value='false'
defaultChecked={!this.props.config.ServiceSettings.EnableOAuthServiceProvider}
onChange={this.handleChange}
/>
{'false'}
</label>
<p className='help-text'>{'When enabled Mattermost will act as an Oauth2 Provider. Changing this will require a server restart before taking effect.'}</p>
</div>
</div>
<div className='form-group'> <div className='form-group'>
<label <label
className='control-label col-sm-4' className='control-label col-sm-4'
htmlFor='EnableIncomingWebhooks' htmlFor='EnableIncomingWebhooks'
> >
{'EnableIncomingWebhooks: '} {'Enable Incoming Webhooks: '}
</label> </label>
<div className='col-sm-8'> <div className='col-sm-8'>
<label className='radio-inline'> <label className='radio-inline'>
@@ -291,6 +258,39 @@ export default class ServiceSettings extends React.Component {
} }
} }
// <div className='form-group'>
// <label
// className='control-label col-sm-4'
// htmlFor='EnableOAuthServiceProvider'
// >
// {'Enable OAuth Service Provider: '}
// </label>
// <div className='col-sm-8'>
// <label className='radio-inline'>
// <input
// type='radio'
// name='EnableOAuthServiceProvider'
// value='true'
// ref='EnableOAuthServiceProvider'
// defaultChecked={this.props.config.ServiceSettings.EnableOAuthServiceProvider}
// onChange={this.handleChange}
// />
// {'true'}
// </label>
// <label className='radio-inline'>
// <input
// type='radio'
// name='EnableOAuthServiceProvider'
// value='false'
// defaultChecked={!this.props.config.ServiceSettings.EnableOAuthServiceProvider}
// onChange={this.handleChange}
// />
// {'false'}
// </label>
// <p className='help-text'>{'When enabled Mattermost will act as an Oauth2 Provider. Changing this will require a server restart before taking effect.'}</p>
// </div>
// </div>
ServiceSettings.propTypes = { ServiceSettings.propTypes = {
config: React.PropTypes.object config: React.PropTypes.object
}; };

Просмотреть файл

@@ -28,7 +28,6 @@ export default class TeamSettings extends React.Component {
var config = this.props.config; var config = this.props.config;
config.TeamSettings.SiteName = React.findDOMNode(this.refs.SiteName).value.trim(); config.TeamSettings.SiteName = React.findDOMNode(this.refs.SiteName).value.trim();
config.TeamSettings.DefaultThemeColor = React.findDOMNode(this.refs.DefaultThemeColor).value.trim();
config.TeamSettings.RestrictCreationToDomains = React.findDOMNode(this.refs.RestrictCreationToDomains).value.trim(); config.TeamSettings.RestrictCreationToDomains = React.findDOMNode(this.refs.RestrictCreationToDomains).value.trim();
config.TeamSettings.EnableTeamCreation = React.findDOMNode(this.refs.EnableTeamCreation).checked; config.TeamSettings.EnableTeamCreation = React.findDOMNode(this.refs.EnableTeamCreation).checked;
config.TeamSettings.EnableUserCreation = React.findDOMNode(this.refs.EnableUserCreation).checked; config.TeamSettings.EnableUserCreation = React.findDOMNode(this.refs.EnableUserCreation).checked;
@@ -122,27 +121,6 @@ export default class TeamSettings extends React.Component {
</div> </div>
</div> </div>
<div className='form-group'>
<label
className='control-label col-sm-4'
htmlFor='DefaultThemeColor'
>
{'Default Theme Color:'}
</label>
<div className='col-sm-8'>
<input
type='text'
className='form-control'
id='DefaultThemeColor'
ref='DefaultThemeColor'
placeholder='Ex "#2389D7"'
defaultValue={this.props.config.TeamSettings.DefaultThemeColor}
onChange={this.handleChange}
/>
<p className='help-text'>{'Default theme color for team sites.'}</p>
</div>
</div>
<div className='form-group'> <div className='form-group'>
<label <label
className='control-label col-sm-4' className='control-label col-sm-4'

Просмотреть файл

@@ -36,7 +36,9 @@ export default class TeamSettingsModal extends React.Component {
const tabs = []; const tabs = [];
tabs.push({name: 'general', uiName: 'General', icon: 'glyphicon glyphicon-cog'}); tabs.push({name: 'general', uiName: 'General', icon: 'glyphicon glyphicon-cog'});
tabs.push({name: 'import', uiName: 'Import', icon: 'glyphicon glyphicon-upload'}); tabs.push({name: 'import', uiName: 'Import', icon: 'glyphicon glyphicon-upload'});
tabs.push({name: 'export', uiName: 'Export', icon: 'glyphicon glyphicon-download'});
// To enable export uncomment this line
//tabs.push({name: 'export', uiName: 'Export', icon: 'glyphicon glyphicon-download'});
return ( return (
<div <div

Просмотреть файл

@@ -107,23 +107,23 @@ export default class ManageIncomingHooks extends React.Component {
this.state.hooks.forEach((hook) => { this.state.hooks.forEach((hook) => {
const c = ChannelStore.get(hook.channel_id); const c = ChannelStore.get(hook.channel_id);
hooks.push( hooks.push(
<div> <div className='font--small'>
<div className='divider-light'></div> <div className='padding-top x2 divider-light'></div>
<span> <div className='padding-top x2'>
<strong>{'URL: '}</strong>{Utils.getWindowLocationOrigin() + '/hooks/' + hook.id} <strong>{'URL: '}</strong><span className='word-break--all'>{Utils.getWindowLocationOrigin() + '/hooks/' + hook.id}</span>
</span> </div>
<br/> <div className='padding-top'>
<span>
<strong>{'Channel: '}</strong>{c.name} <strong>{'Channel: '}</strong>{c.name}
</span> </div>
<br/> <div className='padding-top'>
<a <a
className={'btn btn-sm btn-primary'} className={'text-danger'}
href='#' href='#'
onClick={this.removeHook.bind(this, hook.id)} onClick={this.removeHook.bind(this, hook.id)}
> >
{'Remove'} {'Remove'}
</a> </a>
</div>
</div> </div>
); );
}); });
@@ -134,41 +134,38 @@ export default class ManageIncomingHooks extends React.Component {
} else if (hooks.length > 0) { } else if (hooks.length > 0) {
displayHooks = hooks; displayHooks = hooks;
} else { } else {
displayHooks = <label>{'None'}</label>; displayHooks = <label>{' None'}</label>;
} }
const existingHooks = ( const existingHooks = (
<div> <div className='padding-top x2'>
<label className='control-label'>{'Existing incoming webhooks'}</label> <label className='control-label padding-top x2'>{'Existing incoming webhooks'}</label>
<br/>
{displayHooks} {displayHooks}
</div> </div>
); );
return ( return (
<div <div key='addIncomingHook'>
key='addIncomingHook'
className='form-group'
>
<label className='control-label'>{'Add a new incoming webhook'}</label> <label className='control-label'>{'Add a new incoming webhook'}</label>
<br/> <div className='padding-top'>
<div>
<select <select
ref='channelName' ref='channelName'
className='form-control'
value={this.state.channelId} value={this.state.channelId}
onChange={this.updateChannelId} onChange={this.updateChannelId}
> >
{options} {options}
</select> </select>
<br/>
{serverError} {serverError}
<a <div className='padding-top'>
className={'btn btn-sm btn-primary' + disableButton} <a
href='#' className={'btn btn-sm btn-primary' + disableButton}
onClick={this.addNewHook} href='#'
> onClick={this.addNewHook}
{'Add'} >
</a> {'Add'}
</a>
</div>
</div> </div>
{existingHooks} {existingHooks}
</div> </div>

Просмотреть файл

@@ -40,7 +40,9 @@ export default class ViewImageModal extends React.Component {
}; };
} }
handleNext(e) { handleNext(e) {
e.stopPropagation(); if (e) {
e.stopPropagation();
}
var id = this.state.imgId + 1; var id = this.state.imgId + 1;
if (id > this.props.filenames.length - 1) { if (id > this.props.filenames.length - 1) {
id = 0; id = 0;
@@ -49,7 +51,9 @@ export default class ViewImageModal extends React.Component {
this.loadImage(id); this.loadImage(id);
} }
handlePrev(e) { handlePrev(e) {
e.stopPropagation(); if (e) {
e.stopPropagation();
}
var id = this.state.imgId - 1; var id = this.state.imgId - 1;
if (id < 0) { if (id < 0) {
id = this.props.filenames.length - 1; id = this.props.filenames.length - 1;

Просмотреть файл

@@ -5,15 +5,14 @@ const emoticonPatterns = {
smile: /:-?\)/g, // :) smile: /:-?\)/g, // :)
open_mouth: /:o/gi, // :o open_mouth: /:o/gi, // :o
scream: /:-o/gi, // :-o scream: /:-o/gi, // :-o
smirk: /[:;]-?]/g, // :] smirk: /:-?]/g, // :]
grinning: /[:;]-?d/gi, // :D grinning: /:-?d/gi, // :D
stuck_out_tongue_closed_eyes: /x-d/gi, // x-d stuck_out_tongue_closed_eyes: /x-d/gi, // x-d
stuck_out_tongue_winking_eye: /[:;]-?p/gi, // ;p stuck_out_tongue_winking_eye: /:-?p/gi, // :p
rage: /:-?[\[@]/g, // :@ rage: /:-?[\[@]/g, // :@
frowning: /:-?\(/g, // :( frowning: /:-?\(/g, // :(
sob: /:[']-?\(|:&#x27;\(/g, // :`( sob: /:[']-?\(|:&#x27;\(/g, // :`(
kissing_heart: /:-?\*/g, // :* kissing_heart: /:-?\*/g, // :*
wink: /;-?\)/g, // ;)
pensive: /:-?\//g, // :/ pensive: /:-?\//g, // :/
confounded: /:-?s/gi, // :s confounded: /:-?s/gi, // :s
flushed: /:-?\|/g, // :| flushed: /:-?\|/g, // :|

Просмотреть файл

@@ -44,6 +44,10 @@ body {
} }
} }
.word-break--all {
word-break: break-all;
}
a { a {
word-break: break-word; word-break: break-word;
color: $primary-color; color: $primary-color;

Просмотреть файл

@@ -11,6 +11,9 @@
} }
a, a:focus, a:hover { a, a:focus, a:hover {
color: #2389D7; color: #2389D7;
&.text-danger {
color: #a94442;
}
} }
.custom-textarea { .custom-textarea {
color: inherit; color: inherit;
@@ -20,11 +23,14 @@
box-shadow: none; box-shadow: none;
} }
} }
.btn.btn-primary { .btn {
background: #4285f4; font-size: 13px;
&:hover, &:focus, &:active { &.btn-primary {
background: $primary-color--hover; background: #4285f4;
color: #fff; &:hover, &:focus, &:active {
background: $primary-color--hover;
color: #fff;
}
} }
} }
.info__label { .info__label {

Просмотреть файл

@@ -32,6 +32,7 @@
} }
.settings-table { .settings-table {
display: table; display: table;
table-layout: fixed;
width: 100%; width: 100%;
> div { > div {
display: table-cell; display: table-cell;
@@ -125,6 +126,10 @@
} }
} }
.font--small {
font-size: 13px;
}
.section-describe { .section-describe {
color:grey; color:grey;
} }
@@ -155,8 +160,18 @@
.has-error { .has-error {
color: #a94442; color: #a94442;
} }
.padding-top {
padding-top: 7px;
&.x2 {
padding-top: 14px;
}
}
.control-label { .control-label {
color: #555; color: #555;
font-weight: 600;
&.text-left {
text-align: left;
}
} }
hr { hr {
border-color: #ccc; border-color: #ccc;

Просмотреть файл

@@ -145,14 +145,8 @@ func root(c *api.Context, w http.ResponseWriter, r *http.Request) {
return return
} }
if len(c.Session.UserId) == 0 { page := NewHtmlTemplatePage("signup_team", "Signup")
page := NewHtmlTemplatePage("signup_team", "Signup") page.Render(c, w)
page.Render(c, w)
} else {
page := NewHtmlTemplatePage("home", "Home")
page.Props["TeamURL"] = c.GetTeamURL()
page.Render(c, w)
}
} }
func signup(c *api.Context, w http.ResponseWriter, r *http.Request) { func signup(c *api.Context, w http.ResponseWriter, r *http.Request) {
@@ -175,8 +169,7 @@ func login(c *api.Context, w http.ResponseWriter, r *http.Request) {
var team *model.Team var team *model.Team
if tResult := <-api.Srv.Store.Team().GetByName(teamName); tResult.Err != nil { if tResult := <-api.Srv.Store.Team().GetByName(teamName); tResult.Err != nil {
l4g.Error("Couldn't find team name=%v, teamURL=%v, err=%v", teamName, c.GetTeamURL(), tResult.Err.Message) l4g.Error("Couldn't find team name=%v, teamURL=%v, err=%v", teamName, c.GetTeamURL(), tResult.Err.Message)
// This should probably do somthing nicer http.Redirect(w, r, api.GetProtocol(r)+"://"+r.Host, http.StatusTemporaryRedirect)
http.Redirect(w, r, "http://"+r.Host, http.StatusTemporaryRedirect)
return return
} else { } else {
team = tResult.Data.(*model.Team) team = tResult.Data.(*model.Team)