summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
author=Corey Hulen <corey@hulen.com>2016-03-17 09:51:45 -0700
committer=Corey Hulen <corey@hulen.com>2016-03-17 09:51:45 -0700
commit5273559ca101d8ae4a55104f18081ab011e5068c (patch)
treef152b638101b224ffc59ed000e384b651915266a
parent074f15f761ff50388b58e35e8354c139c06a807e (diff)
parent128204b47a9ff89bf2bea97cd21d3b8892151e69 (diff)
downloadchat-5273559ca101d8ae4a55104f18081ab011e5068c.tar.gz
chat-5273559ca101d8ae4a55104f18081ab011e5068c.tar.bz2
chat-5273559ca101d8ae4a55104f18081ab011e5068c.zip
Fixing merge
-rw-r--r--.sass-lint.yml178
-rw-r--r--Godeps/Godeps.json4
-rw-r--r--Godeps/_workspace/src/github.com/NYTimes/gziphandler/LICENSE.md13
-rw-r--r--Godeps/_workspace/src/github.com/NYTimes/gziphandler/README.md52
-rw-r--r--Godeps/_workspace/src/github.com/NYTimes/gziphandler/gzip.go140
-rw-r--r--Makefile17
-rw-r--r--api/command.go94
-rw-r--r--api/command_test.go5
-rw-r--r--config/config.json5
-rwxr-xr-xdocker/2.1/docker-entry.sh2
-rw-r--r--i18n/en.json8
-rw-r--r--i18n/es.json4
-rw-r--r--model/client.go7
-rw-r--r--model/command.go33
-rw-r--r--model/config.go10
-rw-r--r--store/sql_command_store.go1
-rw-r--r--web/web.go16
-rw-r--r--webapp/Makefile19
-rw-r--r--webapp/components/center_panel.jsx5
-rw-r--r--webapp/components/code_preview.jsx101
-rw-r--r--webapp/components/more_channels.jsx2
-rw-r--r--webapp/components/new_channel_modal.jsx2
-rw-r--r--webapp/components/popover_list_members.jsx1
-rw-r--r--webapp/components/suggestion/command_provider.jsx4
-rw-r--r--webapp/components/suggestion/suggestion_box.jsx3
-rw-r--r--webapp/components/textbox.jsx1
-rw-r--r--webapp/components/user_settings/manage_command_hooks.jsx313
-rw-r--r--webapp/components/user_settings/user_settings_advanced.jsx4
-rw-r--r--webapp/components/user_settings/user_settings_display.jsx2
-rw-r--r--webapp/components/view_image.jsx17
-rw-r--r--webapp/i18n/en.json4
-rw-r--r--webapp/i18n/pt.json4
-rw-r--r--webapp/package.json6
-rw-r--r--webapp/root.jsx2
-rw-r--r--webapp/sass/base/_structure.scss30
-rw-r--r--webapp/sass/base/_typography.scss12
-rw-r--r--webapp/sass/components/_alerts.scss6
-rw-r--r--webapp/sass/components/_buttons.scss8
-rw-r--r--webapp/sass/components/_emoticons.scss12
-rw-r--r--webapp/sass/components/_error-bar.scss23
-rw-r--r--webapp/sass/components/_files.scss155
-rw-r--r--webapp/sass/components/_inputs.scss21
-rw-r--r--webapp/sass/components/_links.scss17
-rw-r--r--webapp/sass/components/_mentions.scss38
-rw-r--r--webapp/sass/components/_modal.scss269
-rw-r--r--webapp/sass/components/_oauth.scss14
-rw-r--r--webapp/sass/components/_popover.scss99
-rw-r--r--webapp/sass/components/_scrollbar.scss29
-rw-r--r--webapp/sass/components/_search.scss107
-rw-r--r--webapp/sass/components/_suggestion-list.scss20
-rw-r--r--webapp/sass/components/_tooltip.scss4
-rw-r--r--webapp/sass/components/_tutorial.scss115
-rw-r--r--webapp/sass/components/_videos.scss61
-rw-r--r--webapp/sass/layout/_content.scss45
-rw-r--r--webapp/sass/layout/_footer.scss6
-rw-r--r--webapp/sass/layout/_forms.scss20
-rw-r--r--webapp/sass/layout/_headers.scss141
-rw-r--r--webapp/sass/layout/_markdown.scss99
-rw-r--r--webapp/sass/layout/_navigation.scss58
-rw-r--r--webapp/sass/layout/_post-right.scss46
-rw-r--r--webapp/sass/layout/_post.scss480
-rw-r--r--webapp/sass/layout/_sidebar-left.scss111
-rw-r--r--webapp/sass/layout/_sidebar-menu.scss46
-rw-r--r--webapp/sass/layout/_sidebar-right.scss62
-rw-r--r--webapp/sass/layout/_webhooks.scss18
-rw-r--r--webapp/sass/responsive/_desktop.scss8
-rw-r--r--webapp/sass/responsive/_mobile.scss9
-rw-r--r--webapp/sass/responsive/_tablet.scss6
-rw-r--r--webapp/sass/routes/_access-history.scss6
-rw-r--r--webapp/sass/routes/_activity-log.scss22
-rw-r--r--webapp/sass/routes/_admin-console.scss106
-rw-r--r--webapp/sass/routes/_docs.scss6
-rw-r--r--webapp/sass/routes/_error-page.scss12
-rw-r--r--webapp/sass/routes/_loading.scss19
-rw-r--r--webapp/sass/routes/_settings.scss189
-rw-r--r--webapp/sass/routes/_signup.scss128
-rw-r--r--webapp/sass/routes/_statistics.scss45
-rw-r--r--webapp/sass/utils/_animations.scss14
-rw-r--r--webapp/sass/utils/_functions.scss14
-rw-r--r--webapp/sass/utils/_mixins.scss25
-rw-r--r--webapp/sass/utils/_module.scss2
-rw-r--r--webapp/sass/utils/_variables.scss12
-rw-r--r--webapp/utils/async_client.jsx6
-rw-r--r--webapp/utils/client.jsx5
-rw-r--r--webapp/utils/constants.jsx86
-rw-r--r--webapp/utils/markdown.jsx90
-rw-r--r--webapp/utils/syntax_hightlighting.jsx197
-rw-r--r--webapp/utils/text_formatting.jsx5
-rw-r--r--webapp/utils/utils.jsx3
-rw-r--r--webapp/webpack.config.js30
90 files changed, 2706 insertions, 1590 deletions
diff --git a/.sass-lint.yml b/.sass-lint.yml
new file mode 100644
index 000000000..71a68af11
--- /dev/null
+++ b/.sass-lint.yml
@@ -0,0 +1,178 @@
+# sass-lint config generated by make-sass-lint-config v0.1.1
+#
+# The following scss-lint Linters are not yet supported by sass-lint:
+# DisableLinterReason, ElsePlacement, PropertyCount, SelectorDepth
+# SpaceAroundOperator, TrailingWhitespace, UnnecessaryParentReference, Compass::*
+#
+# The following settings/values are unsupported by sass-lint:
+# Linter Indentation, option "allow_non_nested_indentation"
+# Linter Indentation, option "character"
+# Linter NestingDepth, option "ignore_parent_selectors"
+# Linter PropertySortOrder, option "min_properties"
+# Linter PropertySortOrder, option "separate_groups"
+# Linter SpaceBeforeBrace, option "allow_single_line_padding"
+# Linter VendorPrefix, option "identifier_list"
+
+files:
+ include: '**/*.scss'
+options:
+ formatter: stylish
+ merge-default-rules: false
+rules:
+ bem-depth:
+ - 1
+ - max-depth: 3
+ border-zero:
+ - 1
+ - convention: none
+ brace-style:
+ - 2
+ - allow-single-line: true
+ class-name-format:
+ - 1
+ - convention: hyphenatedbem
+ clean-import-paths:
+ - 1
+ - filename-extension: false
+ leading-underscore: false
+ empty-line-between-blocks:
+ - 2
+ - ignore-single-line-rulesets: true
+ extends-before-declarations: 1
+ extends-before-mixins: 1
+ final-newline:
+ - 1
+ - include: true
+ force-attribute-nesting: 1
+ force-element-nesting: 1
+ force-pseudo-nesting: 1
+ function-name-format:
+ - 1
+ - allow-leading-underscore: true
+ convention: hyphenatedlowercase
+ hex-length:
+ - 1
+ - style: short
+ hex-notation:
+ - 1
+ - style: lowercase
+ id-name-format:
+ - 1
+ - convention: hyphenatedbem
+ indentation:
+ - 2
+ - size: 4
+ leading-zero:
+ - 1
+ - include: false
+ mixin-name-format:
+ - 0
+ - allow-leading-underscore: true
+ convention: hyphenatedlowercase
+ mixins-before-declarations: 1
+ nesting-depth:
+ - 1
+ - max-depth: 4
+ no-color-keyword: 1
+ no-color-literals: 1
+ no-css-comments: 1
+ no-debug: 1
+ no-duplicate-properties: 1
+ no-empty-rulesets: 1
+ no-extends: 0
+ no-ids: 1
+ no-important: 1
+ no-invalid-hex: 1
+ no-mergeable-selectors: 1
+ no-misspelled-properties:
+ - 1
+ - extra-properties: ['overflow-scrolling', 'font-smoothing']
+ no-qualifying-elements:
+ - 1
+ - allow-element-with-attribute: false
+ allow-element-with-class: false
+ allow-element-with-id: false
+ no-trailing-zero: 1
+ no-transition-all: 0
+ no-url-protocols: 1
+ no-vendor-prefixes:
+ - 1
+ - additional-identifiers: []
+ excluded-identifiers: []
+ placeholder-in-extend: 1
+ placeholder-name-format:
+ - 1
+ - convention: hyphenatedlowercase
+ property-sort-order:
+ - 1
+ - ignore-custom-properties: false
+ property-units:
+ - 1
+ - global:
+ - ch
+ - em
+ - ex
+ - rem
+ - cm
+ - in
+ - mm
+ - pc
+ - pt
+ - px
+ - q
+ - vh
+ - vw
+ - vmin
+ - vmax
+ - deg
+ - grad
+ - rad
+ - turn
+ - ms
+ - s
+ - Hz
+ - kHz
+ - dpi
+ - dpcm
+ - dppx
+ - '%'
+ per-property: {}
+ quotes:
+ - 1
+ - style: single
+ shorthand-values:
+ - 1
+ - allowed-shorthands:
+ - 1
+ - 2
+ - 3
+ single-line-per-selector: 2
+ space-after-bang:
+ - 2
+ - include: false
+ space-after-colon:
+ - 2
+ - include: true
+ space-after-comma:
+ - 1
+ - include: true
+ space-before-bang:
+ - 2
+ - include: true
+ space-before-brace:
+ - 2
+ - include: true
+ space-before-colon: 1
+ space-between-parens:
+ - 2
+ - include: false
+ trailing-semicolon: 2
+ url-quotes: 1
+ variable-for-property:
+ - 0
+ - properties: []
+ variable-name-format:
+ - 1
+ - allow-leading-underscore: true
+ convention: hyphenatedlowercase
+ zero-unit: 1
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index 808d8dab1..f94cafc1c 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -6,6 +6,10 @@
],
"Deps": [
{
+ "ImportPath": "github.com/NYTimes/gziphandler",
+ "Rev": "a88790d49798560db24af70fb6a10a66e2549a72"
+ },
+ {
"ImportPath": "github.com/alecthomas/log4go",
"Rev": "8e9057c3b25c409a34c0b9737cdc82cbcafeabce"
},
diff --git a/Godeps/_workspace/src/github.com/NYTimes/gziphandler/LICENSE.md b/Godeps/_workspace/src/github.com/NYTimes/gziphandler/LICENSE.md
new file mode 100644
index 000000000..b7e2ecb63
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/NYTimes/gziphandler/LICENSE.md
@@ -0,0 +1,13 @@
+Copyright (c) 2015 The New York Times Company
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this library except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/Godeps/_workspace/src/github.com/NYTimes/gziphandler/README.md b/Godeps/_workspace/src/github.com/NYTimes/gziphandler/README.md
new file mode 100644
index 000000000..b1d55e26e
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/NYTimes/gziphandler/README.md
@@ -0,0 +1,52 @@
+Gzip Handler
+============
+
+This is a tiny Go package which wraps HTTP handlers to transparently gzip the
+response body, for clients which support it. Although it's usually simpler to
+leave that to a reverse proxy (like nginx or Varnish), this package is useful
+when that's undesirable.
+
+
+## Usage
+
+Call `GzipHandler` with any handler (an object which implements the
+`http.Handler` interface), and it'll return a new handler which gzips the
+response. For example:
+
+```go
+package main
+
+import (
+ "io"
+ "net/http"
+ "github.com/NYTimes/gziphandler"
+)
+
+func main() {
+ withoutGz := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "text/plain")
+ io.WriteString(w, "Hello, World")
+ })
+
+ withGz := gziphandler.GzipHandler(withoutGz)
+
+ http.Handle("/", withGz)
+ http.ListenAndServe("0.0.0.0:8000", nil)
+}
+```
+
+
+## Documentation
+
+The docs can be found at [godoc.org] [docs], as usual.
+
+
+## License
+
+[Apache 2.0] [license].
+
+
+
+
+[docs]: https://godoc.org/github.com/nytimes/gziphandler
+[license]: https://github.com/nytimes/gziphandler/blob/master/LICENSE.md
diff --git a/Godeps/_workspace/src/github.com/NYTimes/gziphandler/gzip.go b/Godeps/_workspace/src/github.com/NYTimes/gziphandler/gzip.go
new file mode 100644
index 000000000..d0c85c6d3
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/NYTimes/gziphandler/gzip.go
@@ -0,0 +1,140 @@
+package gziphandler
+
+import (
+ "compress/gzip"
+ "fmt"
+ "net/http"
+ "strconv"
+ "strings"
+ "sync"
+)
+
+const (
+ vary = "Vary"
+ acceptEncoding = "Accept-Encoding"
+ contentEncoding = "Content-Encoding"
+)
+
+type codings map[string]float64
+
+// The default qvalue to assign to an encoding if no explicit qvalue is set.
+// This is actually kind of ambiguous in RFC 2616, so hopefully it's correct.
+// The examples seem to indicate that it is.
+const DEFAULT_QVALUE = 1.0
+
+var gzipWriterPool = sync.Pool{
+ New: func() interface{} { return gzip.NewWriter(nil) },
+}
+
+// GzipResponseWriter provides an http.ResponseWriter interface, which gzips
+// bytes before writing them to the underlying response. This doesn't set the
+// Content-Encoding header, nor close the writers, so don't forget to do that.
+type GzipResponseWriter struct {
+ gw *gzip.Writer
+ http.ResponseWriter
+}
+
+// Write appends data to the gzip writer.
+func (w GzipResponseWriter) Write(b []byte) (int, error) {
+ return w.gw.Write(b)
+}
+
+// Flush flushes the underlying *gzip.Writer and then the underlying
+// http.ResponseWriter if it is an http.Flusher. This makes GzipResponseWriter
+// an http.Flusher.
+func (w GzipResponseWriter) Flush() {
+ w.gw.Flush()
+ if fw, ok := w.ResponseWriter.(http.Flusher); ok {
+ fw.Flush()
+ }
+}
+
+// GzipHandler wraps an HTTP handler, to transparently gzip the response body if
+// the client supports it (via the Accept-Encoding header).
+func GzipHandler(h http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Add(vary, acceptEncoding)
+
+ if acceptsGzip(r) {
+ // Bytes written during ServeHTTP are redirected to this gzip writer
+ // before being written to the underlying response.
+ gzw := gzipWriterPool.Get().(*gzip.Writer)
+ defer gzipWriterPool.Put(gzw)
+ gzw.Reset(w)
+ defer gzw.Close()
+
+ w.Header().Set(contentEncoding, "gzip")
+ h.ServeHTTP(GzipResponseWriter{gzw, w}, r)
+ } else {
+ h.ServeHTTP(w, r)
+ }
+ })
+}
+
+// acceptsGzip returns true if the given HTTP request indicates that it will
+// accept a gzippped response.
+func acceptsGzip(r *http.Request) bool {
+ acceptedEncodings, _ := parseEncodings(r.Header.Get(acceptEncoding))
+ return acceptedEncodings["gzip"] > 0.0
+}
+
+// parseEncodings attempts to parse a list of codings, per RFC 2616, as might
+// appear in an Accept-Encoding header. It returns a map of content-codings to
+// quality values, and an error containing the errors encounted. It's probably
+// safe to ignore those, because silently ignoring errors is how the internet
+// works.
+//
+// See: http://tools.ietf.org/html/rfc2616#section-14.3
+func parseEncodings(s string) (codings, error) {
+ c := make(codings)
+ e := make([]string, 0)
+
+ for _, ss := range strings.Split(s, ",") {
+ coding, qvalue, err := parseCoding(ss)
+
+ if err != nil {
+ e = append(e, err.Error())
+
+ } else {
+ c[coding] = qvalue
+ }
+ }
+
+ // TODO (adammck): Use a proper multi-error struct, so the individual errors
+ // can be extracted if anyone cares.
+ if len(e) > 0 {
+ return c, fmt.Errorf("errors while parsing encodings: %s", strings.Join(e, ", "))
+ }
+
+ return c, nil
+}
+
+// parseCoding parses a single conding (content-coding with an optional qvalue),
+// as might appear in an Accept-Encoding header. It attempts to forgive minor
+// formatting errors.
+func parseCoding(s string) (coding string, qvalue float64, err error) {
+ for n, part := range strings.Split(s, ";") {
+ part = strings.TrimSpace(part)
+ qvalue = DEFAULT_QVALUE
+
+ if n == 0 {
+ coding = strings.ToLower(part)
+
+ } else if strings.HasPrefix(part, "q=") {
+ qvalue, err = strconv.ParseFloat(strings.TrimPrefix(part, "q="), 64)
+
+ if qvalue < 0.0 {
+ qvalue = 0.0
+
+ } else if qvalue > 1.0 {
+ qvalue = 1.0
+ }
+ }
+ }
+
+ if coding == "" {
+ err = fmt.Errorf("empty content-coding")
+ }
+
+ return
+}
diff --git a/Makefile b/Makefile
index 4ae2c3b1f..ce12dbaf6 100644
--- a/Makefile
+++ b/Makefile
@@ -136,6 +136,7 @@ package:
tar -C dist -czf $(DIST_PATH).tar.gz mattermost
build-client:
+ mkdir -p webapp/dist/files
cd webapp && make build
go-test:
@@ -196,15 +197,10 @@ clean: stop-docker
rm -Rf $(DIST_ROOT)
go clean $(GOFLAGS) -i ./...
- rm -rf web/react/node_modules
- rm -f web/static/js/bundle*.js
- rm -f web/static/js/bundle*.js.map
- rm -f web/static/js/libs*.js
- rm -f web/static/css/styles.css
+ cd webapp && make clean
rm -rf api/data
rm -rf logs
- rm -rf web/sass-files/.sass-cache
rm -rf Godeps/_workspace/pkg/
@@ -220,14 +216,17 @@ nuke: | clean clean-docker
touch $@
-run: start-docker run-server run-client
+run: | start-docker run-client run-server
run-server: .prepare-go
@echo Starting go web server
$(GO) run $(GOFLAGS) mattermost.go -config=config.json &
-run-client: build-client
- @echo Starting react processo
+run-client:
+ @echo Starting client
+
+ mkdir -p webapp/dist/files
+ cd webapp && make run
@if [ "$(BUILD_ENTERPRISE)" = "true" ] && [ -d "$(ENTERPRISE_DIR)" ]; then \
cp ./config/config.json ./config/config.json.bak; \
diff --git a/api/command.go b/api/command.go
index 99fd05d7a..29cee070e 100644
--- a/api/command.go
+++ b/api/command.go
@@ -44,7 +44,7 @@ func InitCommand(r *mux.Router) {
sr := r.PathPrefix("/commands").Subrouter()
sr.Handle("/execute", ApiUserRequired(executeCommand)).Methods("POST")
- sr.Handle("/list", ApiUserRequired(listCommands)).Methods("GET")
+ sr.Handle("/list", ApiUserRequired(listCommands)).Methods("POST")
sr.Handle("/create", ApiUserRequired(createCommand)).Methods("POST")
sr.Handle("/list_team_commands", ApiUserRequired(listTeamCommands)).Methods("GET")
@@ -76,7 +76,9 @@ func listCommands(c *Context, w http.ResponseWriter, r *http.Request) {
} else {
teamCmds := result.Data.([]*model.Command)
for _, cmd := range teamCmds {
- if cmd.AutoComplete && !seen[cmd.Id] {
+ if cmd.ExternalManagement {
+ commands = append(commands, autocompleteCommands(c, cmd, r)...)
+ } else if cmd.AutoComplete && !seen[cmd.Id] {
cmd.Sanitize()
seen[cmd.Trigger] = true
commands = append(commands, cmd)
@@ -88,6 +90,92 @@ func listCommands(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(model.CommandListToJson(commands)))
}
+func autocompleteCommands(c *Context, cmd *model.Command, r *http.Request) []*model.Command {
+ props := model.MapFromJson(r.Body)
+ command := strings.TrimSpace(props["command"])
+ channelId := strings.TrimSpace(props["channelId"])
+ parts := strings.Split(command, " ")
+ trigger := parts[0][1:]
+ message := strings.Join(parts[1:], " ")
+
+ chanChan := Srv.Store.Channel().Get(channelId)
+ teamChan := Srv.Store.Team().Get(c.Session.TeamId)
+ userChan := Srv.Store.User().Get(c.Session.UserId)
+
+ var team *model.Team
+ if tr := <-teamChan; tr.Err != nil {
+ c.Err = tr.Err
+ return make([]*model.Command, 0, 32)
+ } else {
+ team = tr.Data.(*model.Team)
+ }
+
+ var user *model.User
+ if ur := <-userChan; ur.Err != nil {
+ c.Err = ur.Err
+ return make([]*model.Command, 0, 32)
+ } else {
+ user = ur.Data.(*model.User)
+ }
+
+ var channel *model.Channel
+ if cr := <-chanChan; cr.Err != nil {
+ c.Err = cr.Err
+ return make([]*model.Command, 0, 32)
+ } else {
+ channel = cr.Data.(*model.Channel)
+ }
+
+ l4g.Debug(fmt.Sprintf(utils.T("api.command.execute_command.debug"), trigger, c.Session.UserId))
+ p := url.Values{}
+ p.Set("token", cmd.Token)
+
+ p.Set("team_id", cmd.TeamId)
+ p.Set("team_domain", team.Name)
+
+ p.Set("channel_id", channelId)
+ p.Set("channel_name", channel.Name)
+
+ p.Set("user_id", c.Session.UserId)
+ p.Set("user_name", user.Username)
+
+ p.Set("command", "/"+trigger)
+ p.Set("text", message)
+ p.Set("response_url", "not supported yet")
+ p.Set("suggest", "true")
+
+ method := "POST"
+ if cmd.Method == model.COMMAND_METHOD_GET {
+ method = "GET"
+ }
+
+ tr := &http.Transport{
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections},
+ }
+ client := &http.Client{Transport: tr}
+
+ req, _ := http.NewRequest(method, cmd.URL, strings.NewReader(p.Encode()))
+ req.Header.Set("Accept", "application/json")
+ if cmd.Method == model.COMMAND_METHOD_POST {
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ }
+
+ if resp, err := client.Do(req); err != nil {
+ c.Err = model.NewLocAppError("command", "api.command.execute_command.failed.app_error", map[string]interface{}{"Trigger": trigger}, err.Error())
+ } else {
+ if resp.StatusCode == http.StatusOK {
+ response := model.CommandListFromJson(resp.Body)
+
+ return response
+
+ } else {
+ body, _ := ioutil.ReadAll(resp.Body)
+ c.Err = model.NewLocAppError("command", "api.command.execute_command.failed_resp.app_error", map[string]interface{}{"Trigger": trigger, "Status": resp.Status}, string(body))
+ }
+ }
+ return make([]*model.Command, 0, 32)
+}
+
func executeCommand(c *Context, w http.ResponseWriter, r *http.Request) {
props := model.MapFromJson(r.Body)
command := strings.TrimSpace(props["command"])
@@ -159,7 +247,7 @@ func executeCommand(c *Context, w http.ResponseWriter, r *http.Request) {
teamCmds := result.Data.([]*model.Command)
for _, cmd := range teamCmds {
- if trigger == cmd.Trigger {
+ if trigger == cmd.Trigger || cmd.ExternalManagement {
l4g.Debug(fmt.Sprintf(utils.T("api.command.execute_command.debug"), trigger, c.Session.UserId))
p := url.Values{}
diff --git a/api/command_test.go b/api/command_test.go
index 22e2bd666..8ca8b65b1 100644
--- a/api/command_test.go
+++ b/api/command_test.go
@@ -24,7 +24,10 @@ func TestListCommands(t *testing.T) {
Client.LoginByEmail(team.Name, user1.Email, "pwd")
- if results, err := Client.ListCommands(); err != nil {
+ channel1 := &model.Channel{DisplayName: "AA", Name: "aa" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
+ channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
+
+ if results, err := Client.ListCommands(channel1.Id, "/test"); err != nil {
t.Fatal(err)
} else {
commands := results.Data.([]*model.Command)
diff --git a/config/config.json b/config/config.json
index 8b58e64e4..1d54edccf 100644
--- a/config/config.json
+++ b/config/config.json
@@ -21,7 +21,8 @@
"SessionLengthSSOInDays": 30,
"SessionCacheInMinutes": 10,
"WebsocketSecurePort": 443,
- "WebsocketPort": 80
+ "WebsocketPort": 80,
+ "WebserverMode": "regular"
},
"TeamSettings": {
"SiteName": "Mattermost",
@@ -144,4 +145,4 @@
"Directory": "./data/",
"EnableDaily": false
}
-} \ No newline at end of file
+}
diff --git a/docker/2.1/docker-entry.sh b/docker/2.1/docker-entry.sh
index 6bd2a1263..14b9ccd9d 100755
--- a/docker/2.1/docker-entry.sh
+++ b/docker/2.1/docker-entry.sh
@@ -107,5 +107,5 @@ sleep 5
# ------------------------
echo starting platform
-cd /mattermost/bin
+cd /mattermost/mattermost/bin
./platform -config=/config_docker.json
diff --git a/i18n/en.json b/i18n/en.json
index a37773460..f14e0bbe0 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -3132,14 +3132,14 @@
"translation": "We encountered an error finding the account"
},
{
- "id": "store.sql_user.get_by_auth.other.app_error",
- "translation": "We encountered an error trying to find the account by authentication type."
- },
- {
"id": "store.sql_user.get_by_auth.missing_account.app_error",
"translation": "We couldn't find an existing account matching your authentication type for this team. This team may require an invite from the team owner to join."
},
{
+ "id": "store.sql_user.get_by_auth.other.app_error",
+ "translation": "We encountered an error trying to find the account by authentication type."
+ },
+ {
"id": "store.sql_user.get_by_username.app_error",
"translation": "We couldn't find an existing account matching your username for this team. This team may require an invite from the team owner to join."
},
diff --git a/i18n/es.json b/i18n/es.json
index 4622a1b12..894bf0c18 100644
--- a/i18n/es.json
+++ b/i18n/es.json
@@ -3080,6 +3080,10 @@
"translation": "No pudimos encontrar una cuenta existente que coincida con tu tipo de autenticación para este equipo. Es posible que necesites una invitación por parte del dueño del equipo para unirte."
},
{
+ "id": "store.sql_user.get_by_auth.other.app_error",
+ "translation": "Encontramos un error tratando de identificar la cuenta con este tipo de autenticación."
+ },
+ {
"id": "store.sql_user.get_by_username.app_error",
"translation": "No pudimos encontrar una cuenta existente que coincida con tu nombre de usuario para este equipo. Es posible que necesites una invitación por parte del dueño del equipo para unirte."
},
diff --git a/model/client.go b/model/client.go
index f5c8ad641..68cf11414 100644
--- a/model/client.go
+++ b/model/client.go
@@ -363,8 +363,11 @@ func (c *Client) Command(channelId string, command string, suggest bool) (*Resul
}
}
-func (c *Client) ListCommands() (*Result, *AppError) {
- if r, err := c.DoApiGet("/commands/list", "", ""); err != nil {
+func (c *Client) ListCommands(channelId string, command string) (*Result, *AppError) {
+ m := make(map[string]string)
+ m["command"] = command
+ m["channelId"] = channelId
+ if r, err := c.DoApiPost("/commands/list", MapToJson(m)); err != nil {
return nil, err
} else {
return &Result{r.Header.Get(HEADER_REQUEST_ID),
diff --git a/model/command.go b/model/command.go
index 56d88f13c..8e0b31583 100644
--- a/model/command.go
+++ b/model/command.go
@@ -14,22 +14,23 @@ const (
)
type Command struct {
- Id string `json:"id"`
- Token string `json:"token"`
- CreateAt int64 `json:"create_at"`
- UpdateAt int64 `json:"update_at"`
- DeleteAt int64 `json:"delete_at"`
- CreatorId string `json:"creator_id"`
- TeamId string `json:"team_id"`
- Trigger string `json:"trigger"`
- Method string `json:"method"`
- Username string `json:"username"`
- IconURL string `json:"icon_url"`
- AutoComplete bool `json:"auto_complete"`
- AutoCompleteDesc string `json:"auto_complete_desc"`
- AutoCompleteHint string `json:"auto_complete_hint"`
- DisplayName string `json:"display_name"`
- URL string `json:"url"`
+ Id string `json:"id"`
+ Token string `json:"token"`
+ CreateAt int64 `json:"create_at"`
+ UpdateAt int64 `json:"update_at"`
+ DeleteAt int64 `json:"delete_at"`
+ CreatorId string `json:"creator_id"`
+ TeamId string `json:"team_id"`
+ ExternalManagement bool `json:"external_management"`
+ Trigger string `json:"trigger"`
+ Method string `json:"method"`
+ Username string `json:"username"`
+ IconURL string `json:"icon_url"`
+ AutoComplete bool `json:"auto_complete"`
+ AutoCompleteDesc string `json:"auto_complete_desc"`
+ AutoCompleteHint string `json:"auto_complete_hint"`
+ DisplayName string `json:"display_name"`
+ URL string `json:"url"`
}
func (o *Command) ToJson() string {
diff --git a/model/config.go b/model/config.go
index 8f5865f28..e89ca78fd 100644
--- a/model/config.go
+++ b/model/config.go
@@ -21,6 +21,10 @@ const (
SERVICE_GITLAB = "gitlab"
SERVICE_GOOGLE = "google"
+
+ WEBSERVER_MODE_REGULAR = "regular"
+ WEBSERVER_MODE_GZIP = "gzip"
+ WEBSERVER_MODE_DISABLED = "disabled"
)
type ServiceSettings struct {
@@ -46,6 +50,7 @@ type ServiceSettings struct {
SessionCacheInMinutes *int
WebsocketSecurePort *int
WebsocketPort *int
+ WebserverMode *string
}
type SSOSettings struct {
@@ -391,6 +396,11 @@ func (o *Config) SetDefaults() {
*o.ServiceSettings.AllowCorsFrom = ""
}
+ if o.ServiceSettings.WebserverMode == nil {
+ o.ServiceSettings.WebserverMode = new(string)
+ *o.ServiceSettings.WebserverMode = "regular"
+ }
+
if o.ComplianceSettings.Enable == nil {
o.ComplianceSettings.Enable = new(bool)
*o.ComplianceSettings.Enable = false
diff --git a/store/sql_command_store.go b/store/sql_command_store.go
index 074a6e588..a35737bd7 100644
--- a/store/sql_command_store.go
+++ b/store/sql_command_store.go
@@ -34,6 +34,7 @@ func NewSqlCommandStore(sqlStore *SqlStore) CommandStore {
}
func (s SqlCommandStore) UpgradeSchemaIfNeeded() {
+ s.CreateColumnIfNotExists("Commands", "ExternalManagement", "tinyint(1)", "boolean", "0")
}
func (s SqlCommandStore) CreateIndexesIfNotExists() {
diff --git a/web/web.go b/web/web.go
index 86b642f3b..ff5040a4b 100644
--- a/web/web.go
+++ b/web/web.go
@@ -7,6 +7,8 @@ import (
"net/http"
"strings"
+ "github.com/NYTimes/gziphandler"
+
l4g "github.com/alecthomas/log4go"
"github.com/mattermost/platform/api"
"github.com/mattermost/platform/model"
@@ -23,11 +25,17 @@ func InitWeb() {
mainrouter := api.Srv.Router
- staticDir := utils.FindDir(CLIENT_DIR)
- l4g.Debug("Using client directory at %v", staticDir)
- mainrouter.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(staticDir))))
+ if *utils.Cfg.ServiceSettings.WebserverMode != "disabled" {
+ staticDir := utils.FindDir(CLIENT_DIR)
+ l4g.Debug("Using client directory at %v", staticDir)
+ if *utils.Cfg.ServiceSettings.WebserverMode == "gzip" {
+ mainrouter.PathPrefix("/static/").Handler(gziphandler.GzipHandler(http.StripPrefix("/static/", http.FileServer(http.Dir(staticDir)))))
+ } else {
+ mainrouter.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(staticDir))))
+ }
- mainrouter.Handle("/{anything:.*}", api.AppHandlerIndependent(root)).Methods("GET")
+ mainrouter.Handle("/{anything:.*}", api.AppHandlerIndependent(root)).Methods("GET")
+ }
}
var browsersNotSupported string = "MSIE/8;MSIE/9;MSIE/10;Internet Explorer/8;Internet Explorer/9;Internet Explorer/10;Safari/7;Safari/8"
diff --git a/webapp/Makefile b/webapp/Makefile
index 99f896e53..88ee625a4 100644
--- a/webapp/Makefile
+++ b/webapp/Makefile
@@ -1,4 +1,4 @@
-.PHONY: build test
+.PHONY: build test run clean
test:
@echo Checking for style guide compliance
@@ -12,7 +12,20 @@ test:
touch $@
-build: .npminstall
- @echo Building mattermost web client
+build: | .npminstall test
+ @echo Building mattermost Webapp
npm run build
+
+run: .npminstall
+ @echo Running mattermost Webapp for development
+
+ npm run run
+
+
+clean:
+ @echo Cleaning Webapp
+
+ rm -rf dist
+ rm -rf node_modules
+ rm .npminstall
diff --git a/webapp/components/center_panel.jsx b/webapp/components/center_panel.jsx
index 17e5e43d9..6c156f2a8 100644
--- a/webapp/components/center_panel.jsx
+++ b/webapp/components/center_panel.jsx
@@ -120,7 +120,10 @@ export default class CenterPanel extends React.Component {
id='app-content'
className='app__content'
>
- <div id='channel-header'>
+ <div
+ id='channel-header'
+ className='channel-header'
+ >
<ChannelHeader
user={this.state.user}
/>
diff --git a/webapp/components/code_preview.jsx b/webapp/components/code_preview.jsx
new file mode 100644
index 000000000..e769ae590
--- /dev/null
+++ b/webapp/components/code_preview.jsx
@@ -0,0 +1,101 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import $ from 'jquery';
+import * as syntaxHightlighting from 'utils/syntax_hightlighting.jsx';
+import Constants from 'utils/constants.jsx';
+import FileInfoPreview from './file_info_preview.jsx';
+
+import React from 'react';
+
+export default class CodePreview extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.updateStateFromProps = this.updateStateFromProps.bind(this);
+ this.handleReceivedError = this.handleReceivedError.bind(this);
+ this.handleReceivedCode = this.handleReceivedCode.bind(this);
+
+ this.state = {
+ code: '',
+ lang: '',
+ loading: true,
+ success: true
+ };
+ }
+
+ componentDidMount() {
+ this.updateStateFromProps(this.props);
+ }
+
+ componentWillReceiveProps(nextProps) {
+ if (this.props.fileUrl !== nextProps.fileUrl) {
+ this.updateStateFromProps(nextProps);
+ }
+ }
+
+ updateStateFromProps(props) {
+ var usedLanguage = syntaxHightlighting.getLang(props.filename);
+
+ if (!usedLanguage || props.fileInfo.size > Constants.CODE_PREVIEW_MAX_FILE_SIZE) {
+ this.setState({code: '', lang: '', loading: false, success: false});
+ return;
+ }
+
+ this.setState({code: '', lang: usedLanguage, loading: true});
+
+ $.ajax({
+ async: true,
+ url: props.fileUrl,
+ type: 'GET',
+ error: this.handleReceivedError,
+ success: this.handleReceivedCode
+ });
+ }
+
+ handleReceivedCode(data) {
+ const parsed = syntaxHightlighting.formatCode(this.state.lang, data, this.props.filename);
+ this.setState({code: parsed, loading: false, success: true});
+ }
+
+ handleReceivedError() {
+ this.setState({loading: false, success: false});
+ }
+
+ static support(filename) {
+ return typeof syntaxHightlighting.getLang(filename) !== 'undefined';
+ }
+
+ render() {
+ if (this.state.loading) {
+ return (
+ <div className='view-image__loading'>
+ <img
+ className='loader-image'
+ src='/static/images/load.gif'
+ />
+ </div>
+ );
+ }
+
+ if (!this.state.success) {
+ return (
+ <FileInfoPreview
+ filename={this.props.filename}
+ fileUrl={this.props.fileUrl}
+ fileInfo={this.props.fileInfo}
+ formatMessage={this.props.formatMessage}
+ />
+ );
+ }
+
+ return <div dangerouslySetInnerHTML={{__html: this.state.code}}/>;
+ }
+}
+
+CodePreview.propTypes = {
+ filename: React.PropTypes.string.isRequired,
+ fileUrl: React.PropTypes.string.isRequired,
+ fileInfo: React.PropTypes.object.isRequired,
+ formatMessage: React.PropTypes.func.isRequired
+};
diff --git a/webapp/components/more_channels.jsx b/webapp/components/more_channels.jsx
index fc047eaff..d0eeec1ef 100644
--- a/webapp/components/more_channels.jsx
+++ b/webapp/components/more_channels.jsx
@@ -160,7 +160,7 @@ export default class MoreChannels extends React.Component {
return (
<div
- className='modal fade'
+ className='modal fade more-channel__modal'
id='more_channels'
ref='modal'
tabIndex='-1'
diff --git a/webapp/components/new_channel_modal.jsx b/webapp/components/new_channel_modal.jsx
index 628687f27..f69eeed49 100644
--- a/webapp/components/new_channel_modal.jsx
+++ b/webapp/components/new_channel_modal.jsx
@@ -38,7 +38,7 @@ class NewChannelModal extends React.Component {
}
componentDidMount() {
if (Utils.isBrowserIE()) {
- $('body').addClass('browser--IE');
+ $('body').addClass('browser--ie');
}
}
handleSubmit(e) {
diff --git a/webapp/components/popover_list_members.jsx b/webapp/components/popover_list_members.jsx
index 81760eb6e..7d048019c 100644
--- a/webapp/components/popover_list_members.jsx
+++ b/webapp/components/popover_list_members.jsx
@@ -158,6 +158,7 @@ export default class PopoverListMembers extends React.Component {
<Popover
ref='memebersPopover'
title={title}
+ className='member-list__popover'
id='member-list-popover'
>
<div className='more-modal__list'>{popoverHtml}</div>
diff --git a/webapp/components/suggestion/command_provider.jsx b/webapp/components/suggestion/command_provider.jsx
index 36860fa66..204f52483 100644
--- a/webapp/components/suggestion/command_provider.jsx
+++ b/webapp/components/suggestion/command_provider.jsx
@@ -37,9 +37,9 @@ CommandSuggestion.propTypes = {
};
export default class CommandProvider {
- handlePretextChanged(suggestionId, pretext) {
+ handlePretextChanged(suggestionId, pretext, channelId) {
if (pretext.startsWith('/')) {
- AsyncClient.getSuggestedCommands(pretext, suggestionId, CommandSuggestion);
+ AsyncClient.getSuggestedCommands(pretext, channelId, suggestionId, CommandSuggestion);
}
}
}
diff --git a/webapp/components/suggestion/suggestion_box.jsx b/webapp/components/suggestion/suggestion_box.jsx
index e3ec63194..97c6c6cd9 100644
--- a/webapp/components/suggestion/suggestion_box.jsx
+++ b/webapp/components/suggestion/suggestion_box.jsx
@@ -111,7 +111,7 @@ export default class SuggestionBox extends React.Component {
handlePretextChanged(pretext) {
for (const provider of this.props.providers) {
- provider.handlePretextChanged(this.suggestionId, pretext);
+ provider.handlePretextChanged(this.suggestionId, pretext, this.props.channelId);
}
}
@@ -160,6 +160,7 @@ SuggestionBox.propTypes = {
value: React.PropTypes.string.isRequired,
onUserInput: React.PropTypes.func,
providers: React.PropTypes.arrayOf(React.PropTypes.object),
+ channelId: React.PropTypes.string,
// explicitly name any input event handlers we override and need to manually call
onChange: React.PropTypes.func,
diff --git a/webapp/components/textbox.jsx b/webapp/components/textbox.jsx
index 1a395072e..952026ed5 100644
--- a/webapp/components/textbox.jsx
+++ b/webapp/components/textbox.jsx
@@ -224,6 +224,7 @@ export default class Textbox extends React.Component {
style={{visibility: this.state.preview ? 'hidden' : 'visible'}}
listComponent={SuggestionList}
providers={this.suggestionProviders}
+ channelId={this.props.channelId}
/>
<div
ref='preview'
diff --git a/webapp/components/user_settings/manage_command_hooks.jsx b/webapp/components/user_settings/manage_command_hooks.jsx
index ce353ad64..9703664cc 100644
--- a/webapp/components/user_settings/manage_command_hooks.jsx
+++ b/webapp/components/user_settings/manage_command_hooks.jsx
@@ -4,9 +4,13 @@
import LoadingScreen from '../loading_screen.jsx';
import * as Client from 'utils/client.jsx';
+import * as Utils from 'utils/utils.jsx';
+import Constants from 'utils/constants.jsx';
import {intlShape, injectIntl, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'react-intl';
+const PreReleaseFeatures = Constants.PRE_RELEASE_FEATURES;
+
const holders = defineMessages({
requestTypePost: {
id: 'user.settings.cmds.request_type_post',
@@ -59,6 +63,7 @@ export default class ManageCommandCmds extends React.Component {
this.getCmds = this.getCmds.bind(this);
this.addNewCmd = this.addNewCmd.bind(this);
this.emptyCmd = this.emptyCmd.bind(this);
+ this.updateExternalManagement = this.updateExternalManagement.bind(this);
this.updateTrigger = this.updateTrigger.bind(this);
this.updateURL = this.updateURL.bind(this);
this.updateMethod = this.updateMethod.bind(this);
@@ -99,7 +104,7 @@ export default class ManageCommandCmds extends React.Component {
addNewCmd(e) {
e.preventDefault();
- if (this.state.cmd.trigger === '' || this.state.cmd.url === '') {
+ if (this.state.cmd.url === '' || (this.state.cmd.trigger === '' && !this.state.external_management)) {
return;
}
@@ -189,6 +194,12 @@ export default class ManageCommandCmds extends React.Component {
);
}
+ updateExternalManagement(e) {
+ var cmd = this.state.cmd;
+ cmd.external_management = e.target.checked;
+ this.setState(cmd);
+ }
+
updateTrigger(e) {
var cmd = this.state.cmd;
cmd.trigger = e.target.value;
@@ -270,11 +281,26 @@ export default class ManageCommandCmds extends React.Component {
);
}
+ let slashCommandAutocompleteDiv;
+ if (Utils.isFeatureEnabled(PreReleaseFeatures.SLASHCMD_AUTOCMP)) {
+ slashCommandAutocompleteDiv = (
+ <div className='padding-top x2'>
+ <strong>
+ <FormattedMessage
+ id='user.settings.cmds.external_management'
+ defaultMessage='External management: '
+ />
+ </strong><span className='word-break--all'>{cmd.external_management ? this.props.intl.formatMessage(holders.autocompleteYes) : this.props.intl.formatMessage(holders.autocompleteNo)}</span>
+ </div>
+ );
+ }
+
cmds.push(
<div
key={cmd.id}
className='webhook__item webcmd__item'
>
+ {slashCommandAutocompleteDiv}
{triggerDiv}
<div className='padding-top x2 webcmd__url'>
<strong>
@@ -416,43 +442,115 @@ export default class ManageCommandCmds extends React.Component {
</div>
);
- const disableButton = this.state.cmd.trigger === '' || this.state.cmd.url === '';
+ const disableButton = this.state.cmd.url === '' || (this.state.cmd.trigger === '' && !this.state.external_management);
- return (
- <div key='addCommandCmd'>
- <FormattedHTMLMessage
- id='user.settings.cmds.add_desc'
- defaultMessage='Create slash commands to send events to external integrations and receive a response. For example typing `/patient Joe Smith` could bring back search results from your internal health records management system for the name “Joe Smith”. Please see <a href="http://docs.mattermost.com/developer/slash-commands.html">Slash commands documentation</a> for detailed instructions. View all slash commands configured on this team below.'
- />
- <div><label className='control-label padding-top x2'>
- <FormattedMessage
- id='user.settings.cmds.add_new'
- defaultMessage='Add a new command'
- />
- </label></div>
- <div className='padding-top divider-light'></div>
- <div className='padding-top'>
+ let triggerInput;
+ if (!this.state.cmd.external_management) {
+ triggerInput = (
+ <div className='padding-top x2'>
+ <label className='control-label'>
+ <FormattedMessage
+ id='user.settings.cmds.trigger'
+ defaultMessage='Command Trigger Word: '
+ />
+ </label>
+ <div className='padding-top'>
+ <input
+ ref='trigger'
+ className='form-control'
+ value={this.state.cmd.trigger}
+ onChange={this.updateTrigger}
+ placeholder={this.props.intl.formatMessage(holders.addTriggerPlaceholder)}
+ />
+ </div>
+ <div className='padding-top'>
+ <FormattedMessage
+ id='user.settings.cmds.trigger_desc'
+ defaultMessage='Examples: /patient, /client, /employee Reserved: /echo, /join, /logout, /me, /shrug'
+ />
+ </div>
+ </div>
+ );
+ }
+ let slashCommandAutocompleteCheckbox;
+ if (Utils.isFeatureEnabled(PreReleaseFeatures.SLASHCMD_AUTOCMP)) {
+ slashCommandAutocompleteCheckbox = (
+ <div className='padding-top x2'>
+ <label className='control-label'>
+ <FormattedMessage
+ id='user.settings.cmds.external_management'
+ defaultMessage='External management: '
+ />
+ </label>
+ <div className='padding-top'>
+ <div className='checkbox'>
+ <label>
+ <input
+ type='checkbox'
+ checked={this.state.cmd.external_management}
+ onChange={this.updateExternalManagement}
+ />
+ <FormattedMessage
+ id='user.settings.cmds.slashCmd_autocmp'
+ defaultMessage='Enable external application to offer autocomplete'
+ />
+ </label>
+ </div>
+ </div>
+ </div>
+
+ );
+ }
+
+ let autoCompleteSettings;
+ if (!this.state.cmd.external_management) {
+ autoCompleteSettings = (
+ <div>
<div className='padding-top x2'>
<label className='control-label'>
<FormattedMessage
- id='user.settings.cmds.trigger'
- defaultMessage='Command Trigger Word: '
+ id='user.settings.cmds.auto_complete'
+ defaultMessage='Autocomplete: '
+ />
+ </label>
+ <div className='padding-top'>
+ <div className='checkbox'>
+ <label>
+ <input
+ type='checkbox'
+ checked={this.state.cmd.auto_complete}
+ onChange={this.updateAutoComplete}
+ />
+ <FormattedMessage
+ id='user.settings.cmds.auto_complete_help'
+ defaultMessage=' Show this command in the autocomplete list.'
+ />
+ </label>
+ </div>
+ </div>
+ </div>
+
+ <div className='padding-top x2'>
+ <label className='control-label'>
+ <FormattedMessage
+ id='user.settings.cmds.auto_complete_hint'
+ defaultMessage='Autocomplete Hint: '
/>
</label>
<div className='padding-top'>
<input
- ref='trigger'
+ ref='autoCompleteHint'
className='form-control'
- value={this.state.cmd.trigger}
- onChange={this.updateTrigger}
- placeholder={this.props.intl.formatMessage(holders.addTriggerPlaceholder)}
+ value={this.state.cmd.auto_complete_hint}
+ onChange={this.updateAutoCompleteHint}
+ placeholder={this.props.intl.formatMessage(holders.addAutoCompleteHintPlaceholder)}
/>
</div>
<div className='padding-top'>
<FormattedMessage
- id='user.settings.cmds.trigger_desc'
- defaultMessage='Examples: /patient, /client, /employee Reserved: /echo, /join, /logout, /me, /shrug'
+ id='user.settings.cmds.auto_complete_hint_desc'
+ defaultMessage='Optional hint in the autocomplete list about parameters needed for command.'
/>
</div>
</div>
@@ -460,6 +558,76 @@ export default class ManageCommandCmds extends React.Component {
<div className='padding-top x2'>
<label className='control-label'>
<FormattedMessage
+ id='user.settings.cmds.auto_complete_desc'
+ defaultMessage='Autocomplete Description: '
+ />
+ </label>
+ <div className='padding-top'>
+ <input
+ ref='autoCompleteDesc'
+ className='form-control'
+ value={this.state.cmd.auto_complete_desc}
+ onChange={this.updateAutoCompleteDesc}
+ placeholder={this.props.intl.formatMessage(holders.addAutoCompleteDescPlaceholder)}
+ />
+ </div>
+ <div className='padding-top'>
+ <FormattedMessage
+ id='user.settings.cmds.auto_complete_desc_desc'
+ defaultMessage='Optional short description of slash command for the autocomplete list.'
+ />
+ </div>
+ </div>
+
+ <div className='padding-top x2'>
+ <label className='control-label'>
+ <FormattedMessage
+ id='user.settings.cmds.display_name'
+ defaultMessage='Descriptive Label: '
+ />
+ </label>
+ <div className='padding-top'>
+ <input
+ ref='displayName'
+ className='form-control'
+ value={this.state.cmd.display_name}
+ onChange={this.updateDisplayName}
+ placeholder={this.props.intl.formatMessage(holders.addDisplayNamePlaceholder)}
+ />
+ </div>
+ <div className='padding-top'>
+ <FormattedMessage
+ id='user.settings.cmds.cmd_display_name'
+ defaultMessage='Brief description of slash command to show in listings.'
+ />
+ </div>
+ {addError}
+ </div>
+ </div>
+ );
+ }
+
+ return (
+ <div key='addCommandCmd'>
+ <FormattedHTMLMessage
+ id='user.settings.cmds.add_desc'
+ defaultMessage='Create slash commands to send events to external integrations and receive a response. For example typing `/patient Joe Smith` could bring back search results from your internal health records management system for the name “Joe Smith”. Please see <a href="http://docs.mattermost.com/developer/slash-commands.html">Slash commands documentation</a> for detailed instructions. View all slash commands configured on this team below.'
+ />
+ <div><label className='control-label padding-top x2'>
+ <FormattedMessage
+ id='user.settings.cmds.add_new'
+ defaultMessage='Add a new command'
+ />
+ </label></div>
+ <div className='padding-top divider-light'></div>
+ <div className='padding-top'>
+
+ {slashCommandAutocompleteCheckbox}
+ {triggerInput}
+
+ <div className='padding-top x2'>
+ <label className='control-label'>
+ <FormattedMessage
id='user.settings.cmds.url'
defaultMessage='Request URL: '
/>
@@ -560,102 +728,7 @@ export default class ManageCommandCmds extends React.Component {
</div>
</div>
- <div className='padding-top x2'>
- <label className='control-label'>
- <FormattedMessage
- id='user.settings.cmds.auto_complete'
- defaultMessage='Autocomplete: '
- />
- </label>
- <div className='padding-top'>
- <div className='checkbox'>
- <label>
- <input
- type='checkbox'
- checked={this.state.cmd.auto_complete}
- onChange={this.updateAutoComplete}
- />
- <FormattedMessage
- id='user.settings.cmds.auto_complete_help'
- defaultMessage=' Show this command in the autocomplete list.'
- />
- </label>
- </div>
- </div>
- </div>
-
- <div className='padding-top x2'>
- <label className='control-label'>
- <FormattedMessage
- id='user.settings.cmds.auto_complete_hint'
- defaultMessage='Autocomplete Hint: '
- />
- </label>
- <div className='padding-top'>
- <input
- ref='autoCompleteHint'
- className='form-control'
- value={this.state.cmd.auto_complete_hint}
- onChange={this.updateAutoCompleteHint}
- placeholder={this.props.intl.formatMessage(holders.addAutoCompleteHintPlaceholder)}
- />
- </div>
- <div className='padding-top'>
- <FormattedMessage
- id='user.settings.cmds.auto_complete_hint_desc'
- defaultMessage='Optional hint in the autocomplete list about parameters needed for command.'
- />
- </div>
- </div>
-
- <div className='padding-top x2'>
- <label className='control-label'>
- <FormattedMessage
- id='user.settings.cmds.auto_complete_desc'
- defaultMessage='Autocomplete Description: '
- />
- </label>
- <div className='padding-top'>
- <input
- ref='autoCompleteDesc'
- className='form-control'
- value={this.state.cmd.auto_complete_desc}
- onChange={this.updateAutoCompleteDesc}
- placeholder={this.props.intl.formatMessage(holders.addAutoCompleteDescPlaceholder)}
- />
- </div>
- <div className='padding-top'>
- <FormattedMessage
- id='user.settings.cmds.auto_complete_desc_desc'
- defaultMessage='Optional short description of slash command for the autocomplete list.'
- />
- </div>
- </div>
-
- <div className='padding-top x2'>
- <label className='control-label'>
- <FormattedMessage
- id='user.settings.cmds.display_name'
- defaultMessage='Descriptive Label: '
- />
- </label>
- <div className='padding-top'>
- <input
- ref='displayName'
- className='form-control'
- value={this.state.cmd.display_name}
- onChange={this.updateDisplayName}
- placeholder={this.props.intl.formatMessage(holders.addDisplayNamePlaceholder)}
- />
- </div>
- <div className='padding-top'>
- <FormattedMessage
- id='user.settings.cmds.cmd_display_name'
- defaultMessage='Brief description of slash command to show in listings.'
- />
- </div>
- {addError}
- </div>
+ {autoCompleteSettings}
<div className='padding-top x2 padding-bottom'>
<a
diff --git a/webapp/components/user_settings/user_settings_advanced.jsx b/webapp/components/user_settings/user_settings_advanced.jsx
index 7c496f57b..40897e8c9 100644
--- a/webapp/components/user_settings/user_settings_advanced.jsx
+++ b/webapp/components/user_settings/user_settings_advanced.jsx
@@ -51,6 +51,10 @@ const holders = defineMessages({
EMBED_TOGGLE: {
id: 'user.settings.advance.embed_toggle',
defaultMessage: 'Show toggle for all embed previews'
+ },
+ SLASHCMD_AUTOCMP: {
+ id: 'user.settings.advance.slashCmd_autocmp',
+ defaultMessage: 'Enable external application to offer slash command autocomplete'
}
});
diff --git a/webapp/components/user_settings/user_settings_display.jsx b/webapp/components/user_settings/user_settings_display.jsx
index 58d4493cb..3299588f7 100644
--- a/webapp/components/user_settings/user_settings_display.jsx
+++ b/webapp/components/user_settings/user_settings_display.jsx
@@ -195,7 +195,7 @@ export default class UserSettingsDisplay extends React.Component {
const showUsername = (
<FormattedMessage
id='user.settings.display.showUsername'
- defaultMessage='Show username (team default)'
+ defaultMessage='Show username (default)'
/>
);
const showNickname = (
diff --git a/webapp/components/view_image.jsx b/webapp/components/view_image.jsx
index e739fca30..7572f88ae 100644
--- a/webapp/components/view_image.jsx
+++ b/webapp/components/view_image.jsx
@@ -7,6 +7,7 @@ import * as Client from 'utils/client.jsx';
import * as Utils from 'utils/utils.jsx';
import AudioVideoPreview from './audio_video_preview.jsx';
import Constants from 'utils/constants.jsx';
+import CodePreview from './code_preview.jsx';
import FileInfoPreview from './file_info_preview.jsx';
import FileStore from 'stores/file_store.jsx';
import ViewImagePopoverBar from './view_image_popover_bar.jsx';
@@ -254,6 +255,15 @@ class ViewImageModal extends React.Component {
formatMessage={this.props.intl.formatMessage}
/>
);
+ } else if (CodePreview.support(filename)) {
+ content = (
+ <CodePreview
+ filename={filename}
+ fileUrl={fileUrl}
+ fileInfo={fileInfo}
+ formatMessage={this.props.intl.formatMessage}
+ />
+ );
} else {
content = (
<FileInfoPreview
@@ -311,18 +321,19 @@ class ViewImageModal extends React.Component {
<Modal
show={this.props.show}
onHide={this.props.onModalDismissed}
- className='image_modal'
+ className='modal-image'
dialogClassName='modal-image'
>
<Modal.Body
- modalClassName='image-body'
+ modalClassName='modal-image__body'
onClick={this.props.onModalDismissed}
>
<div
- className={'image-wrapper'}
+ className={'modal-image__wrapper'}
onClick={this.props.onModalDismissed}
>
<div
+ className='modal-back'
onMouseEnter={this.onMouseEnterImage}
onMouseLeave={this.onMouseLeaveImage}
onClick={(e) => e.stopPropagation()}
diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json
index 437271633..42e23b8e5 100644
--- a/webapp/i18n/en.json
+++ b/webapp/i18n/en.json
@@ -1126,6 +1126,7 @@
"tutorial_tip.seen": "Seen this before? ",
"upload_overlay.info": "Drop a file to upload it.",
"user.settings.advance.embed_preview": "Show preview snippet of links below message",
+ "user.settings.advance.slashCmd_autocmp": "Enable external application to offer slash command autocomplete",
"user.settings.advance.embed_toggle": "Show toggle for all embed previews",
"user.settings.advance.enabled": "enabled",
"user.settings.advance.feature": " Feature ",
@@ -1173,6 +1174,7 @@
"user.settings.cmds.url_desc": "The callback URL to receive the HTTP POST or GET event request when the slash command is run.",
"user.settings.cmds.username": "Response Username: ",
"user.settings.cmds.username_desc": "Choose a username override for responses for this slash command. Usernames can consist of up to 22 characters consisting of lowercase letters, numbers and they symbols \"-\", \"_\", and \".\" .",
+ "user.settings.cmds.slashCmd_autocmp": "Enable external application to offer autocomplete",
"user.settings.custom_theme.awayIndicator": "Away Indicator",
"user.settings.custom_theme.buttonBg": "Button BG",
"user.settings.custom_theme.buttonColor": "Button Text",
@@ -1209,7 +1211,7 @@
"user.settings.display.preferTime": "Select how you prefer time displayed.",
"user.settings.display.showFullname": "Show first and last name",
"user.settings.display.showNickname": "Show nickname if one exists, otherwise show first and last name",
- "user.settings.display.showUsername": "Show username (team default)",
+ "user.settings.display.showUsername": "Show username (default)",
"user.settings.display.teammateDisplay": "Teammate Name Display",
"user.settings.display.theme.customTheme": "Custom Theme",
"user.settings.display.theme.describe": "Open to manage your theme",
diff --git a/webapp/i18n/pt.json b/webapp/i18n/pt.json
index 0d8e5f4cb..17ffe1b16 100644
--- a/webapp/i18n/pt.json
+++ b/webapp/i18n/pt.json
@@ -1174,7 +1174,7 @@
"user.settings.display.preferTime": "Selecione como você prefere que a hora seja mostrada.",
"user.settings.display.showFullname": "Mostrar primeiro e último nome",
"user.settings.display.showNickname": "Mostras apelidos se um existir, caso contrário mostrar o primeiro e último nome",
- "user.settings.display.showUsername": "Mostrar nome de usuário (equipe padrão)",
+ "user.settings.display.showUsername": "Mostrar nome de usuário (padrão)",
"user.settings.display.teammateDisplay": "Nome de Exibição da Equipe de Trabalho",
"user.settings.display.theme.customTheme": "Tema Customizado",
"user.settings.display.theme.describe": "Abrir para gerenciar seu tema",
@@ -1313,4 +1313,4 @@
"web.footer.terms": "Termos",
"web.header.back": "Voltar",
"web.root.singup_info": "Toda comunicação em um só lugar, pesquisável e acessível em qualquer lugar"
-} \ No newline at end of file
+}
diff --git a/webapp/package.json b/webapp/package.json
index 0d88a6212..25003114e 100644
--- a/webapp/package.json
+++ b/webapp/package.json
@@ -31,7 +31,7 @@
"babel-loader": "6.2.4",
"babel-plugin-transform-runtime": "6.6.0",
"babel-polyfill": "6.7.2",
- "babel-preset-es2015": "6.6.0",
+ "babel-preset-es2015-webpack": "6.4.0",
"babel-preset-react": "6.5.0",
"babel-preset-stage-0": "6.5.0",
"eslint": "2.2.0",
@@ -39,6 +39,7 @@
"exports-loader": "0.6.3",
"extract-text-webpack-plugin": "1.0.1",
"file-loader": "0.8.5",
+ "url-loader": "0.5.7",
"html-loader": "0.4.3",
"copy-webpack-plugin": "1.1.1",
"css-loader": "0.23.1",
@@ -52,6 +53,7 @@
},
"scripts": {
"check": "eslint --ext \".jsx\" --ignore-pattern node_modules --quiet .",
- "build": "webpack --progress"
+ "build": "webpack --optimize-dedupe",
+ "run": "webpack --progress"
}
}
diff --git a/webapp/root.jsx b/webapp/root.jsx
index 8ebe51bd2..2ce220f1d 100644
--- a/webapp/root.jsx
+++ b/webapp/root.jsx
@@ -3,11 +3,11 @@
import $ from 'jquery';
-import 'sass/styles.scss';
import 'bootstrap/dist/css/bootstrap.css';
import 'jasny-bootstrap/dist/css/jasny-bootstrap.css';
import 'bootstrap-colorpicker/dist/css/bootstrap-colorpicker.css';
import 'google-fonts/google-fonts.css';
+import 'sass/styles.scss';
import React from 'react';
import ReactDOM from 'react-dom';
diff --git a/webapp/sass/base/_structure.scss b/webapp/sass/base/_structure.scss
index 56888f8dc..217488334 100644
--- a/webapp/sass/base/_structure.scss
+++ b/webapp/sass/base/_structure.scss
@@ -6,22 +6,24 @@ body {
}
body {
- width: 100%;
- height: 100%;
background: $bg--gray;
+ height: 100%;
position: relative;
+ width: 100%;
+}
- &.sticky {
- background: $bg--white;
+.sticky {
+ background: $white;
- > .container-fluid {
- overflow: auto;
- }
+ > .container-fluid {
+ overflow: auto;
+ }
- .inner-wrap {
- > .row.content {
- min-height: 100%;
+ .inner-wrap {
+ > .row {
+ &.content {
margin-bottom: -89px;
+ min-height: 100%;
}
}
}
@@ -30,9 +32,11 @@ body {
.inner-wrap {
height: 100%;
- > .row.main {
- height: 100%;
- position: relative;
+ > .row {
+ &.main {
+ height: 100%;
+ position: relative;
+ }
}
}
diff --git a/webapp/sass/base/_typography.scss b/webapp/sass/base/_typography.scss
index 676a2c405..f5795d862 100644
--- a/webapp/sass/base/_typography.scss
+++ b/webapp/sass/base/_typography.scss
@@ -6,20 +6,20 @@ strong {
}
a {
+ color: $primary-color;
cursor: pointer;
text-decoration: none;
word-break: break-word;
- color: $color--primary;
-}
-a:focus,
-a:hover {
- color: $color--primary--hover;
+ &:focus,
+ &:hover {
+ color: $primary-color--hover;
+ }
}
body {
+ @include font-smoothing;
font-family: 'Open Sans', sans-serif;
- -webkit-font-smoothing: antialiased;
}
.word-break--all {
diff --git a/webapp/sass/components/_alerts.scss b/webapp/sass/components/_alerts.scss
index 49ca3e8af..cb4c9c9e1 100644
--- a/webapp/sass/components/_alerts.scss
+++ b/webapp/sass/components/_alerts.scss
@@ -1,13 +1,13 @@
@charset 'UTF-8';
.alert {
- padding: 8px 12px;
@include border-radius($border-rad);
+ padding: 8px 12px;
}
.alert--confirm {
display: inline-block;
float: left;
- padding: 4px 10px;
margin: 1px 0 0 10px;
-} \ No newline at end of file
+ padding: 4px 10px;
+}
diff --git a/webapp/sass/components/_buttons.scss b/webapp/sass/components/_buttons.scss
index bb8efbb14..efef11ce9 100644
--- a/webapp/sass/components/_buttons.scss
+++ b/webapp/sass/components/_buttons.scss
@@ -5,19 +5,19 @@
@include border-radius($border-rad);
&.btn-primary {
+ background: $primary-color;
border-color: transparent;
- background: $color--primary;
&:hover,
&:focus,
&:active {
- background: $color--primary--hover;
+ background: $primary-color--hover;
}
}
&.btn-inactive {
+ background: $light-gray;
border-color: transparent;
- background: #707070;
- color: #fff;
+ color: $white;
}
}
diff --git a/webapp/sass/components/_emoticons.scss b/webapp/sass/components/_emoticons.scss
index 661b25d94..80a800863 100644
--- a/webapp/sass/components/_emoticons.scss
+++ b/webapp/sass/components/_emoticons.scss
@@ -1,27 +1,27 @@
@charset 'UTF-8';
.emoticon {
- width: 1.5em;
- height: 1.5em;
+ background-size: contain;
display: inline-block;
+ height: 1.5em;
margin-bottom: .25em;
- background-size: contain;
+ width: 1.5em;
}
.emoticon-suggestion {
@include clearfix;
- width: 100%;
- height: 30px;
cursor: pointer;
font-size: 13px;
+ height: 30px;
line-height: 30px;
+ width: 100%;
}
.emoticon-suggestion__image {
- width: 20px;
height: 20px;
margin: 6px 6px 0 5px;
padding: 0;
text-align: center;
vertical-align: top;
+ width: 20px;
}
diff --git a/webapp/sass/components/_error-bar.scss b/webapp/sass/components/_error-bar.scss
index 2b74a33ae..cda7d25bd 100644
--- a/webapp/sass/components/_error-bar.scss
+++ b/webapp/sass/components/_error-bar.scss
@@ -1,29 +1,28 @@
@charset 'UTF-8';
.error-bar {
- background-color: #09f;
- text-align: center;
- position: relative;
- color: #fff;
+ background-color: darken($primary-color, 5%);
+ color: $white;
+ padding: 5px 30px;
position: absolute;
+ text-align: center;
top: 0;
width: 100%;
z-index: 9999;
- padding: 5px 30px;
&__close {
- position: absolute;
- right: 0;
- top: 0;
- color: #fff;
+ color: $white;
+ font-family: 'Open Sans', sans-serif;
font-size: 20px;
font-weight: 600;
- text-decoration: none;
padding: 0 10px;
- font-family: 'Open Sans', sans-serif;
+ position: absolute;
+ right: 0;
+ text-decoration: none;
+ top: 0;
&:hover {
- color: #fff;
+ color: $white;
text-decoration: none;
}
}
diff --git a/webapp/sass/components/_files.scss b/webapp/sass/components/_files.scss
index b9e2b5f7d..5522c6db8 100644
--- a/webapp/sass/components/_files.scss
+++ b/webapp/sass/components/_files.scss
@@ -1,27 +1,31 @@
@charset 'UTF-8';
.file-preview__container {
- position: relative;
+ height: 100px;
margin: 1px 0 10px;
- width: 100%;
max-height: 100px;
- height: 100px;
- white-space: nowrap;
overflow-x: auto;
overflow-y: hidden;
+ position: relative;
+ white-space: nowrap;
+ width: 100%;
}
.file-preview {
+ @include clearfix;
+ border: 1px solid $light-gray;
display: inline-block;
- width: 120px;
height: 100px;
margin: 0 0 0 10px;
position: relative;
- border: 1px solid #ddd;
- @include clearfix;
+ width: 120px;
- &:hover .file-preview__remove:after {
- @include opacity(1);
+ &:hover {
+ .file-preview__remove {
+ &:after {
+ @include opacity(1);
+ }
+ }
}
&:first-child {
@@ -29,13 +33,13 @@
}
.spinner {
- position: absolute;
- top: 50%;
+ height: 32px;
left: 50%;
margin-left: -16px;
margin-top: -16px;
+ position: absolute;
+ top: 50%;
width: 32px;
- height: 32px;
}
}
@@ -46,14 +50,15 @@
}
.file-preview__remove {
- position: absolute;
- width: 100%;
height: 100%;
left: 0;
+ position: absolute;
top: 0;
+ width: 100%;
&:after {
- background: rgba(0, 0, 0, .4);
+ @include opacity(0);
+ @include alpha-property(background, $black, .4);
content: '';
height: 100%;
left: 0;
@@ -61,33 +66,31 @@
position: absolute;
top: 0;
width: 100%;
- @include opacity(0);
}
i {
- top: 5px;
- right: 5px;
- position: absolute;
- color: #fff;
+ color: $white;
cursor: pointer;
- z-index: 5;
opacity: inherit;
- text-shadow: 0 0px 3px #444;
- text-shadow: 0 0px 3px rgba(0, 0, 0, .7);
+ position: absolute;
+ right: 5px;
+ text-shadow: 0 0 3px alpha-color($black, .7);
+ top: 5px;
+ z-index: 5;
}
}
.image-comment {
background-position: left top;
background-repeat: no-repeat;
- width: 300px;
height: 300px;
+ width: 300px;
}
.file-icon {
- width: 100%;
height: 100%;
+ width: 100%;
&.audio {
@include file-icon('../images/icons/audio.png');
@@ -131,36 +134,30 @@
}
.post-image__column {
- position: relative;
- width: 240px;
- height: 100px;
+ border: 1px solid alpha-color($black, .2);
float: left;
+ height: 100px;
margin: 5px 10px 5px 0;
- border: 1px solid lightgrey;
-
- a {
- text-decoration: none;
- color: grey;
- }
+ position: relative;
+ width: 240px;
}
.post-image__load {
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: 20px 20px;
height: 100%;
width: 100%;
- background-size: 20px 20px;
- background-repeat: no-repeat;
- background-position: center;
- background-image: url('~images/load.gif');
}
.post-image {
- width: 100%;
- height: 100%;
- background-color: #fff;
+ background-color: $white;
background-repeat: no-repeat;
+ height: 100%;
overflow: hidden;
position: relative;
text-align: center;
+ width: 100%;
&.small {
background-position: center;
@@ -170,60 +167,59 @@
background-position: top left;
}
- .spinner.file__loading {
- position: absolute;
- left: 50%;
- margin-left: -16px;
- top: 50%;
- margin-top: -16px;
+ .spinner {
+ .file__loading {
+ left: 50%;
+ margin-left: -16px;
+ margin-top: -16px;
+ position: absolute;
+ top: 50%;
+ }
}
.file__loaded {
max-width: initial;
+
&.landscape,
&.quadrat {
height: 100px;
}
+
&.portrait {
width: 120px;
}
}
-
- &:hover .file-playback__controls.stop {
- @include opacity(1);
- }
}
.post-image__thumbnail {
+ @include cursor(zoom-in);
float: left;
- width: 50%;
height: 100%;
- cursor: zoom-in;
- cursor: -webkit-zoom-in;
+ width: 50%;
}
.post-image__details {
- float: left;
@include clearfix;
- word-break: break-word;
- width: 50%;
- height: 100%;
- background: white;
- border-left: 1px solid #ddd;
+ background: $white;
+ border-left: 1px solid $light-gray;
+ color: alpha-color($black, .8);
+ float: left;
font-size: 13px;
+ height: 100%;
padding: 7px;
- color: #333;
+ width: 50%;
+ word-break: break-word;
.post-image__name {
- margin-bottom: 3px;
display: block;
+ margin-bottom: 3px;
}
.post-image__download {
+ @include opacity(.7);
+ cursor: pointer;
display: inline-block;
padding-right: 7px;
- cursor: pointer;
- @include opacity(.7);
}
.post-image__type {
@@ -231,57 +227,56 @@
}
.post-image__size {
- margin-left: 4px;
@include opacity(.6);
+ margin-left: 4px;
}
}
.file-details__container {
@include display-flex;
- display: -ms-flexbox;
+ background: $white;
.file-details {
- width: 320px;
height: 270px;
padding: 14px;
text-align: left;
vertical-align: top;
+ width: 320px;
.file-details__name {
- color: #333;
+ color: alpha-color($black, .9);
font-size: 16px;
}
.file-details__info {
- color: grey;
+ color: alpha-color($black, .5);
}
}
+
.file-details__preview {
- width: 320px;
+ border-right: 1px solid $light-gray;
height: 270px;
- border-right: 1px solid #ddd;
vertical-align: center;
+ width: 320px;
// helper to center the image icon in the preview window
.file-details__preview-helper {
- height: 100%;
display: inline-block;
+ height: 100%;
vertical-align: middle;
}
}
}
.file-playback__controls {
- position: absolute;
- right: 5px;
+ @include single-transition(opacity, .6s);
bottom: 0;
- font-size: 22px;
cursor: pointer;
- z-index: 2;
- -webkit-transition: opacity .6s;
- -moz-transition: opacity .6s;
- -o-transition: opacity .6s;
+ font-size: 22px;
+ position: absolute;
+ right: 5px;
transition: opacity .6s;
+ z-index: 2;
&.stop {
@include opacity(0);
@@ -289,6 +284,6 @@
}
.view-image__loading {
- background: black;
+ background: $black;
min-height: 100px;
}
diff --git a/webapp/sass/components/_inputs.scss b/webapp/sass/components/_inputs.scss
index 5e3311182..42ab56128 100644
--- a/webapp/sass/components/_inputs.scss
+++ b/webapp/sass/components/_inputs.scss
@@ -15,12 +15,21 @@
&.no-resize {
resize: none;
}
+
+ &[disabled],
+ [readonly] {
+ @include alpha-property(background, $white, .1);
+ color: inherit;
+ cursor: auto;
+ }
}
-.form-control[disabled],
-.form-control[readonly],
-fieldset[disabled] .form-control {
- cursor: auto;
- background: rgba(#fff, .1);
- color: inherit;
+fieldset {
+ &[disabled] {
+ .form-control {
+ @include alpha-property(background, $white, .1);
+ color: inherit;
+ cursor: auto;
+ }
+ }
}
diff --git a/webapp/sass/components/_links.scss b/webapp/sass/components/_links.scss
index f31008b4f..3d7472670 100644
--- a/webapp/sass/components/_links.scss
+++ b/webapp/sass/components/_links.scss
@@ -1,23 +1,22 @@
@charset 'UTF-8';
a {
+ color: $primary-color;
cursor: pointer;
text-decoration: none;
word-break: break-word;
- color: $color--primary;
-}
-a:focus,
-a:hover {
- color: $color--primary--hover;
+ &:hover,
+ &:focus {
+ color: $primary-color--hover;
+ }
}
-.text-danger,
-a.text-danger {
- color: #e05f5d;
+.text-danger {
+ color: desaturate($red, 20%);
&:hover,
&:focus {
- color: #e05f5d;
+ color: desaturate($red, 20%);
}
}
diff --git a/webapp/sass/components/_mentions.scss b/webapp/sass/components/_mentions.scss
index 98efc599d..98ae7d320 100644
--- a/webapp/sass/components/_mentions.scss
+++ b/webapp/sass/components/_mentions.scss
@@ -1,24 +1,24 @@
@charset 'UTF-8';
.mention {
- color: #fff;
- background: $color--primary;
+ @include border-radius(3px);
+ background: $primary-color;
+ color: $white;
+ padding-bottom: 2px;
position: relative;
z-index: 10;
- padding-bottom: 2px;
- @include border-radius(3px);
}
.mentions__name {
- position: relative;
- width: 100%;
+ cursor: pointer;
+ font-size: 13px;
height: 36px;
- padding: 2px;
- z-index: 101;
line-height: 36px;
- font-size: 13px;
- cursor: pointer;
+ padding: 2px;
+ position: relative;
white-space: nowrap;
+ width: 100%;
+ z-index: 101;
.mention-align {
@include clearfix;
@@ -28,29 +28,29 @@
}
.mention__image {
- margin-right: 6px;
- height: 32px;
- width: 32px;
- line-height: 36px;
+ @include border-radius(32px);
display: block;
font-size: 20px;
+ height: 32px;
+ line-height: 36px;
+ margin-right: 6px;
text-align: center;
- @include border-radius(32px);
+ width: 32px;
.mention--align {
+ display: inline-block;
max-width: 80%;
overflow: hidden;
- display: inline-block;
- white-space: nowrap;
text-overflow: ellipsis;
+ white-space: nowrap;
}
}
.mention__fullname {
- color: grey;
+ color: $dark-gray;
padding-left: 10px;
}
.mention--highlight {
- background-color: #fff2bb;
+ background-color: $yellow;
}
diff --git a/webapp/sass/components/_modal.scss b/webapp/sass/components/_modal.scss
index a8e8a99f7..94378aabe 100644
--- a/webapp/sass/components/_modal.scss
+++ b/webapp/sass/components/_modal.scss
@@ -1,12 +1,24 @@
@charset 'UTF-8';
-#channel_members_modal .modal-body {
- min-height: 110px;
+.browser--ie {
+ .modal {
+ .modal-dialog {
+ @include translateY(0);
+ }
+ }
}
.modal-body {
- padding: 20px 15px;
overflow: auto;
+ padding: 20px 15px;
+
+ .edit-modal-body {
+ overflow: visible;
+
+ .suggestion-list__content {
+ max-height: 150px;
+ }
+ }
}
.more-table {
@@ -15,27 +27,23 @@
}
.modal {
+ color: alpha-color($black, .9);
width: 100%;
- color: #333;
- body.browser--IE & {
- .modal-dialog {
- @include translateY(0);
- }
- }
-
- &.image_modal {
- .modal-backdrop.in {
- @include opacity(.7);
+ &.modal-image {
+ .modal-backdrop {
+ &.in {
+ @include opacity(.7);
+ }
}
}
.custom-textarea {
+ border-color: $light-gray;
color: inherit;
- border-color: #ccc;
&:focus {
- border-color: #ccc;
+ border-color: $light-gray;
box-shadow: none;
}
}
@@ -44,15 +52,15 @@
font-size: 13px;
&.btn-default {
- border: none;
background: transparent;
+ border: none;
}
}
.info__label {
font-weight: 600;
- text-align: right;
padding-right: 0;
+ text-align: right;
}
.team-member-list {
@@ -60,21 +68,21 @@
}
.remove__member {
+ color: $dark-gray;
float: right;
- color: #999;
font-size: 20px;
line-height: 0;
padding: 6px;
&:hover {
- color: #e56565;
+ color: $red;
}
}
.modal-dialog {
- max-width: 95%;
margin-left: auto;
margin-right: auto;
+ max-width: 95%;
}
.modal-push-down {
@@ -82,51 +90,51 @@
}
.modal-next-bar {
+ height: 100%;
position: absolute;
- top: 0px;
right: 0;
- height: 100%;
+ top: 0;
}
.modal-header {
- border-radius: 0;
- background: $color--primary;
- color: #fff;
- padding: 15px 15px 11px;
- border: 1px solid #ddd;
- min-height: 56px;
+ @include border-radius(0);
@include clearfix;
+ background: $primary-color;
+ border: 1px solid $light-gray;
+ color: $white;
+ min-height: 56px;
+ padding: 15px 15px 11px;
.modal-title {
+ color: $bg--gray;
float: left;
font-size: 17px;
line-height: 27px;
- color: #f4f4f4;
.name {
+ color: $white;
font-weight: 600;
- color: #fff;
}
}
.modal-action {
- padding: 0;
margin: 0;
+ padding: 0;
}
- button.close {
- color: #fff;
+ .close {
@include opacity(1);
- z-index: 5;
- width: 30px;
+ @include single-transition(all, .25s, ease-in);
+ color: $white;
height: 30px;
line-height: 30px;
- @include single-transition(all, .25s, ease-in);
position: absolute;
right: 10px;
+ width: 30px;
+ z-index: 5;
&:hover {
- background: rgba(0, 0, 0, .1);
+ @include alpha-property(background, $black, .1);
}
span {
@@ -149,8 +157,8 @@
}
.no-channel-message {
- text-align: center;
padding: 2em 1em;
+ text-align: center;
.primary-message {
font-size: 1.25em;
@@ -168,46 +176,46 @@
}
.modal-chevron-icon {
- top: 50%;
font-size: 120%;
+ top: 50%;
}
.modal-prev-bar {
- position: absolute;
- top: 0px;
- left: 0;
height: 100%;
+ left: 0;
+ position: absolute;
+ top: 0;
}
- &#more_channels {
+ &.more-channel__modal {
.modal-body {
padding: 0;
}
}
.modal-image {
- position: relative;
- width: 100%;
height: 100%;
margin: 0 auto;
max-width: 100%;
+ position: relative;
+ width: 100%;
.modal-body {
@include clearfix;
- height: 100%;
display: table;
+ height: 100%;
+ max-height: 100%;
table-layout: fixed;
width: 100%;
- max-height: 100%;
}
- .image-wrapper {
- position: relative;
- max-width: 90%;
+ .modal-image__wrapper {
@include border-radius(3px);
display: table-cell;
- vertical-align: middle;
+ max-width: 90%;
+ position: relative;
text-align: center;
+ vertical-align: middle;
width: 100%;
&:hover {
@@ -215,33 +223,31 @@
}
&.default {
- width: 100%;
height: 80%;
+ width: 100%;
}
audio,
canvas,
progress,
video {
- max-width: 100%;
- height: auto;
display: block;
+ height: auto;
+ max-width: 100%;
}
.modal-close {
- background: url('../images/close.png') no-repeat;
+ @include single-transition(opacity, .6s);
@include background-size(100% 100%);
- width: 37px;
+ @include opacity(0);
+ background-image: url('../images/close.png');
+ cursor: pointer;
height: 37px;
position: absolute;
right: -13px;
top: -13px;
- @include opacity(0);
- -webkit-transition: opacity .6s;
- -moz-transition: opacity .6s;
- -o-transition: opacity .6s;
transition: opacity .6s;
- cursor: pointer;
+ width: 37px;
z-index: 9999;
&.modal-close--show {
@@ -250,99 +256,109 @@
}
> div {
+ display: inline-block;
min-height: 100px;
min-width: 320px;
- background: #fff;
- display: inline-block;
position: relative;
+ }
- &:hover .file-playback__controls.stop {
- @include opacity(1);
- }
+ code {
+ min-height: 130px;
+ min-width: 330px;
+ }
+
+ pre, code {
+ display: inline-block;
+ }
+
+ .post-body--code {
+ max-height: calc(100vh - 80px);
+ max-width: calc(100vw - 80px);
+ overflow: auto;
}
img {
- max-width: 100%;
max-height: 100%;
+ max-width: 100%;
}
- .spinner.file__loading {
- z-index: 2;
- position: absolute;
- left: 50%;
- margin-left: -16px;
- top: 50%;
- margin-top: -16px;
+ .spinner {
+ .file__loading {
+ left: 50%;
+ margin-left: -16px;
+ margin-top: -16px;
+ position: absolute;
+ top: 50%;
+ z-index: 2;
+ }
}
}
.modal-content {
+ background: alpha-color($black, 0);
+ border: none;
box-shadow: none;
- background: rgba(0, 0, 0, 0);
- width: 100%;
height: 100%;
padding: 0;
- border: none;
+ width: 100%;
}
- .image-body {
- vertical-align: middle;
+ .modal-image__body {
display: table-cell;
- text-align: center;
height: 100%;
+ overflow: visible;
padding: 0;
position: relative;
- overflow: visible;
+ text-align: center;
+ vertical-align: middle;
}
.image-control {
- width: 50px;
- height: 45px;
+ background: url('../images/prev.png') left no-repeat;
float: left;
- background: url(../images/prev.png) left no-repeat;
- top: 50%;
- position: relative;
+ height: 45px;
margin-top: -23px;
+ position: relative;
+ top: 50%;
+ width: 50px;
+
&.image-next {
+ background: url('../images/next.png') left no-repeat;
float: right;
- background: url(../images/next.png) left no-repeat;
}
}
.loader-image {
- position: absolute;
- top: 0;
bottom: 0;
left: 0;
- right: 0;
margin: auto;
+ position: absolute;
+ right: 0;
+ top: 0;
}
.loader-percent {
- position: absolute;
- top: 55px;
bottom: 0;
+ color: $dark-gray;
+ height: 20px;
left: 0;
- right: 0;
margin: auto;
- color: grey;
- height: 20px;
+ position: absolute;
+ right: 0;
+ top: 55px;
}
.modal-button-bar {
- position: absolute;
- bottom: -40px;
- left: 0px;
- right: 0px;
- background-color: #222;
+ @include single-transition(opacity, .6s);
@include border-radius(0 0 3px 3px);
@include opacity(0);
- -webkit-transition: opacity .6s;
- -moz-transition: opacity .6s;
- -o-transition: opacity .6s;
- transition: opacity .6s;
+ background-color: $black;
+ bottom: -40px;
+ left: 0;
line-height: 40px;
padding: 0 10px;
+ position: absolute;
+ right: 0;
&.footer--show {
@include opacity(1);
@@ -356,10 +372,10 @@
}
.text {
- vertical-align: middle;
bottom: 0;
- color: white;
+ color: $white;
margin-left: 5px;
+ vertical-align: middle;
}
.public-link {
@@ -376,11 +392,12 @@
}
.row--invite {
- margin-right: 40px;
@include clearfix;
+ margin-right: 40px;
.col-sm-6 {
padding: 0 0 0 15px;
+
&:first-child {
padding-left: 0;
}
@@ -389,26 +406,26 @@
.more-modal {
.user-list {
- overflow-y: auto;
- overflow-x: hidden;
margin-top: 10px;
+ overflow-x: hidden;
+ overflow-y: auto;
position: relative;
}
.modal-body {
- padding: 10px 0 20px;
overflow-x: hidden;
+ padding: 10px 0 20px;
}
.filter-row {
- margin: 10px 0;
@include clearfix;
+ margin: 10px 0;
}
.member-count {
- margin-top: 5px;
- float: right;
@include opacity(.8);
+ float: right;
+ margin-top: 5px;
}
.more-purpose {
@@ -416,21 +433,13 @@
}
}
-.modal-body.edit-modal-body {
- overflow: visible;
-
- .suggestion-list__content {
- max-height: 150px;
- }
-}
-
.more-modal__list {
- overflow: auto;
display: flex;
flex-direction: column;
+ overflow: auto;
.popover & {
- font-size: 0.95em;
+ font-size: .95em;
.more-modal__row {
padding: 5px 10px;
@@ -442,9 +451,9 @@
}
.more-modal__image {
+ @include border-radius(60px);
flex-grow: 0;
flex-shrink: 0;
- @include border-radius(60px);
margin-right: 8px;
}
@@ -462,33 +471,33 @@
}
.more-modal__name {
- font-weight: 600;
font-size: .95em;
- white-space: nowrap;
+ font-weight: 600;
overflow: hidden;
text-overflow: ellipsis;
+ white-space: nowrap;
}
.more-modal__description {
@include opacity(.7);
display: block;
- white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
+ white-space: nowrap;
}
.more-modal__row {
+ border-bottom: 1px solid;
display: flex;
padding: 8px 15px;
- border-bottom: 1px solid;
}
p {
+ @include opacity(.8);
font-size: .9em;
+ margin: 5px 0;
overflow: hidden;
text-overflow: ellipsis;
- @include opacity(.8);
- margin: 5px 0;
}
}
diff --git a/webapp/sass/components/_oauth.scss b/webapp/sass/components/_oauth.scss
index cd8382a5c..04840457c 100644
--- a/webapp/sass/components/_oauth.scss
+++ b/webapp/sass/components/_oauth.scss
@@ -1,18 +1,18 @@
@charset 'UTF-8';
.prompt {
- background: #fff;
- border: 1px solid #ddd;
- padding: 1em 2em 0;
+ background: $white;
+ border: 1px solid $light-gray;
margin: 50px auto;
max-width: 90%;
+ padding: 1em 2em 0;
width: 600px;
.prompt__heading {
+ display: table;
font-size: em(20px);
line-height: normal;
margin: 1em 0;
- display: table;
width: 100%;
> div {
@@ -26,13 +26,13 @@
}
.prompt__allow {
- margin: 1em 0;
font-size: em(24px);
+ margin: 1em 0;
}
.prompt__buttons {
- text-align: right;
- border-top: 1px solid #ddd;
+ border-top: 1px solid $dark-gray;
padding: 1.5em 0;
+ text-align: right;
}
}
diff --git a/webapp/sass/components/_popover.scss b/webapp/sass/components/_popover.scss
index de66b67a7..0b2769f77 100644
--- a/webapp/sass/components/_popover.scss
+++ b/webapp/sass/components/_popover.scss
@@ -3,32 +3,38 @@
.popover {
@include border-radius($border-rad);
- color: #333;
+ color: lighten($black, 25%);
&.bottom,
&.right,
&.top,
&.left {
- > .arrow:after {
- border-color: transparent;
+ > .arrow {
+ &:after {
+ border-color: transparent;
+ }
}
}
.popover-title {
- background: rgba(black, .05);
+ background: alpha-color($black, .05);
padding: 8px 10px;
}
.popover-content {
- p:last-child {
- margin-bottom: 5px;
+ p {
+ &:last-child {
+ margin-bottom: 5px;
+ }
}
}
}
-.channel-header__info .popover-content {
- max-height: 250px;
- overflow: auto;
+.channel-header__info {
+ .popover-content {
+ max-height: 250px;
+ overflow: auto;
+ }
}
.user-popover {
@@ -36,32 +42,35 @@
display: inline-block;
}
-.code-popover .popover-content {
- padding: 5px;
+.code-popover {
+ .popover-content {
+ padding: 5px;
+ }
}
.user-popover__image {
- margin: 0 0 10px;
@include border-radius(128px);
+ margin: 0 0 10px;
}
.user-popover__email {
+ display: block;
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
- display: block;
}
.search-help-popover {
- visibility: hidden;
- max-width: none;
- width: 100%;
- top: 36px;
@include single-transition(opacity, .3s, ease-in);
font-size: em(13px);
+ max-width: none;
+ top: 36px;
+ visibility: hidden;
+ width: 100%;
&.autocomplete {
display: block;
+
.popover-content {
padding: 10px;
position: relative;
@@ -69,65 +78,68 @@
}
.search-autocomplete__divider {
- margin: 10px 0 5px;
line-height: 21px;
+ margin: 10px 0 5px;
position: relative;
+
&:first-child {
margin-top: 5px;
}
- span {
+
+ > span {
+ background: $white;
display: inline-block;
padding-right: 10px;
- background: #fff;
- z-index: 5;
position: relative;
+ z-index: 5;
}
+
&:before {
+ @include opacity(.2);
+ background: $dark-gray;
content: '';
- position: absolute;
- width: 100%;
height: 1px;
- background: #ddd;
- top: 10px;
left: 0;
- @include opacity(.2);
+ position: absolute;
+ top: 10px;
+ width: 100%;
}
}
.search-autocomplete__item {
+ @include border-radius(2px);
cursor: pointer;
- padding: 6px 8px;
margin: 3px 0 0 5px;
- @include border-radius(2px);
- white-space: nowrap;
overflow: hidden;
+ padding: 6px 8px;
text-overflow: ellipsis;
+ white-space: nowrap;
&:hover {
- background: rgba(black, .1);
+ background: alpha-color($black, .1);
}
&.selected {
- background: rgba(black, .2);
+ background: alpha-color($black, .2);
}
.fa {
- margin-right: 5px;
@include opacity(.5);
+ margin-right: 5px;
}
.profile-img {
- margin-top: -1px;
height: 16px;
margin-right: 6px;
+ margin-top: -1px;
width: 16px;
}
}
&.bottom > .arrow {
- top: -18px;
border-width: 9px;
left: 30px;
+ top: -18px;
}
.popover-content {
@@ -142,9 +154,11 @@
ul {
padding-left: 17px;
+
span {
@include opacity(.8);
}
+
strong,
b {
@include opacity(1);
@@ -156,25 +170,28 @@
}
&.visible {
- visibility: visible;
@include opacity(1);
+ visibility: visible;
}
}
-#member-list-popover {
+.member-list__popover {
max-width: initial;
+
.popover-content {
- position: relative;
+ max-height: 350px;
padding: 0;
+ position: relative;
width: 260px;
- max-height: 350px;
+
.text-nowrap {
+ font-size: 13px;
+ line-height: 26px;
+ overflow: hidden;
padding: 6px 10px;
width: 100%;
- overflow: hidden;
- line-height: 26px;
- font-size: 13px;
}
+
.more__name {
margin-left: 6px;
max-width: 140px;
diff --git a/webapp/sass/components/_scrollbar.scss b/webapp/sass/components/_scrollbar.scss
index 4ecb38b1f..0bb0e7e21 100644
--- a/webapp/sass/components/_scrollbar.scss
+++ b/webapp/sass/components/_scrollbar.scss
@@ -1,28 +1,25 @@
@charset 'UTF-8';
-::-webkit-scrollbar
-{
- width: 8px; /* for vertical scrollbars */
- height: 8px; /* for horizontal scrollbars */
+::-webkit-scrollbar {
+ height: 8px; // for horizontal scrollbars
+ width: 8px; // for vertical scrollbars
}
-::-webkit-scrollbar-track
-{
- background: rgba(0, 0, 0, 0.1);
+::-webkit-scrollbar-track {
+ background: rgba(0, 0, 0, .1);
}
-::-webkit-scrollbar-thumb
-{
+::-webkit-scrollbar-thumb {
@include border-radius($border-rad * 2);
- background: rgba(0, 0, 0, 0.4);
+ background: rgba(0, 0, 0, .4);
}
-body{
- scrollbar-face-color: rgba(0, 0, 0, 0.1);
- scrollbar-shadow-color: #2D2C4D;
- scrollbar-highlight-color:#7D7E94;
+body {
scrollbar-3dlight-color: #7D7E94;
- scrollbar-darkshadow-color: #2D2C4D;
- scrollbar-track-color: rgba(0, 0, 0, 0.1);
scrollbar-arrow-color: #C1C1D1;
+ scrollbar-darkshadow-color: #2D2C4D;
+ scrollbar-face-color: rgba(0, 0, 0, .1);
+ scrollbar-highlight-color: #7D7E94;
+ scrollbar-shadow-color: #2D2C4D;
+ scrollbar-track-color: rgba(0, 0, 0, .1);
} \ No newline at end of file
diff --git a/webapp/sass/components/_search.scss b/webapp/sass/components/_search.scss
index faf0b8177..499c4fad4 100644
--- a/webapp/sass/components/_search.scss
+++ b/webapp/sass/components/_search.scss
@@ -1,15 +1,19 @@
@charset 'UTF-8';
-#channel-header .search-bar__container {
- padding: 0 9px 0 3px;
+.channel-header {
+ .search-bar__container {
+ padding: 0 9px 0 3px;
+ }
}
.search-bar__container {
- padding: 12px 8px 0 0;
@include flex(0 0 56px);
+ padding: 12px 8px 0 0;
- .sidebar--right.move--left & {
- padding-right: 42px;
+ .sidebar--right {
+ &.move--left & {
+ padding-right: 42px;
+ }
}
}
@@ -18,62 +22,60 @@
}
.search__clear {
+ @include single-transition(all, .2s, linear);
+ @include translateX(60px);
+ cursor: pointer;
display: none;
- position: absolute;
- right: 0;
line-height: 45px;
margin-right: 13px;
- @include single-transition(all, .2s, linear);
- @include translateX(60px);
+ position: absolute;
+ right: 0;
z-index: 5;
- cursor: pointer;
}
.search-item-snippet {
@include clearfix;
text-overflow: ellipsis;
+
+ ul,
+ ol {
+ padding-left: 20px;
+ }
}
.sidebar__collapse {
+ @include single-transition(all, .2s, linear);
+ @include translateX(0);
cursor: pointer;
- z-index: 5;
- fill: #fff;
- position: absolute;
- left: 0;
+ display: none;
+ fill: $white;
font-size: 35px;
- width: 49px;
- @include single-transition(all, .2s, linear);
- @include translateX(0px);
- text-align: center;
- padding-left: 1px;
+ left: 0;
line-height: 40px;
- display: none;
-}
-
-.search-item-snippet {
- ul,
- ol {
- padding-left: 20px;
- }
+ padding-left: 1px;
+ position: absolute;
+ text-align: center;
+ width: 49px;
+ z-index: 5;
}
.sidebar__search-icon {
- position: absolute;
- top: 15px;
- margin-left: 10px;
- font-size: 14px;
@include opacity(.5);
+ color: $dark-gray;
display: none;
- color: #777;
+ font-size: 14px;
+ margin-left: 10px;
+ position: absolute;
+ top: 15px;
}
.search__form {
position: relative;
.search-bar__container & {
- margin: 0;
- border: 1px solid #ddd;
@include border-radius(2px);
+ border: 1px solid $light-gray;
+ margin: 0;
width: 300px;
}
@@ -82,21 +84,21 @@
}
.search-bar {
+ box-shadow: none;
height: 40px;
padding-right: 30px;
- box-shadow: none;
.search-bar__container & {
- height: 30px;
border: none;
+ height: 30px;
}
}
.glyphicon-refresh-animate {
- top: 27px;
+ color: $dark-gray;
position: absolute;
right: 27px;
- color: #999;
+ top: 27px;
.search-bar__container & {
right: 7px;
@@ -106,30 +108,29 @@
}
.search-items-container {
- position: relative;
- overflow: auto;
- -webkit-overflow-scrolling: touch;
@include flex(1 1 auto);
+ -webkit-overflow-scrolling: touch;
height: calc(100% - 56px);
+ overflow: auto;
padding-top: 10px;
+ position: relative;
}
.search-results-header {
+ border-bottom: $border-gray;
+ color: #999999;
font-size: 1em;
- text-transform: uppercase;
- color: #999;
font-weight: 400;
- color: #888;
height: 44px;
line-height: 44px;
- padding: 0 10px 0 10px;
- border-bottom: $border-gray;
+ padding: 0 10px;
+ text-transform: uppercase;
}
.search-item__container {
.post {
- padding: 0 1em 1em;
margin: 0;
+ padding: 0 1em 1em;
&:first-child {
border: none;
@@ -137,17 +138,17 @@
.search-channel__name {
font-weight: 600;
- margin: 0 0 10px 0;
+ margin: 0 0 10px;
}
}
}
.search-item__jump {
+ @include opacity(.8);
+ font-size: 13px;
position: absolute;
right: 0;
- top: 0px;
- font-size: 13px;
- @include opacity(.8);
+ top: 0;
&:hover {
@include opacity(1);
@@ -155,9 +156,9 @@
}
.search-item__comment {
+ margin-right: 35px;
position: absolute;
right: 0;
- margin-right: 35px;
top: 0;
}
@@ -171,5 +172,5 @@
}
.search-highlight {
- background-color: #fff2bb;
+ background-color: $yellow;
}
diff --git a/webapp/sass/components/_suggestion-list.scss b/webapp/sass/components/_suggestion-list.scss
index 125a3cf32..0100026ca 100644
--- a/webapp/sass/components/_suggestion-list.scss
+++ b/webapp/sass/components/_suggestion-list.scss
@@ -1,9 +1,9 @@
@charset 'UTF-8';
.suggestion-list {
+ @extend %popover-box-shadow;
width: 100%;
z-index: 100;
- @extend %popover-box-shadow;
}
.suggestion-list--top {
@@ -11,31 +11,31 @@
}
.suggestion-list__content {
- width: 100%;
- max-height: 292px;
- background-color: #fff;
+ background-color: $white;
border: $border-gray;
+ max-height: 292px;
overflow-x: hidden;
overflow-y: scroll;
+ width: 100%;
.command {
- position: relative;
- width: 100%;
+ border-bottom: 1px solid $light-gray;
+ font-size: .95em;
line-height: 24px;
padding: 5px 10px 8px;
+ position: relative;
+ width: 100%;
z-index: 101;
- font-size: .95em;
- border-bottom: 1px solid #ddd;
.command__desc {
- margin-left: 5px;
@include opacity(.5);
line-height: normal;
+ margin-left: 5px;
}
}
}
.suggestion-list__content--top {
- position: absolute;
bottom: 0;
+ position: absolute;
}
diff --git a/webapp/sass/components/_tooltip.scss b/webapp/sass/components/_tooltip.scss
index 44c10edb9..5e71e3a7b 100644
--- a/webapp/sass/components/_tooltip.scss
+++ b/webapp/sass/components/_tooltip.scss
@@ -2,9 +2,9 @@
.tooltip {
.tooltip-inner {
- word-break: break-word;
font-size: 13px;
- padding: 3px 10px 4px;
font-weight: 500;
+ padding: 3px 10px 4px;
+ word-break: break-word;
}
}
diff --git a/webapp/sass/components/_tutorial.scss b/webapp/sass/components/_tutorial.scss
index f15919009..6545d7764 100644
--- a/webapp/sass/components/_tutorial.scss
+++ b/webapp/sass/components/_tutorial.scss
@@ -1,72 +1,76 @@
@charset 'UTF-8';
.tip-backdrop {
- background: rgba(black, .5);
+ background: alpha-color($black, .5);
+ height: 100%;
+ left: 0;
position: absolute;
top: 0;
- left: 0;
width: 100%;
- height: 100%;
z-index: 999;
}
.tip-overlay {
- width: 350px;
- max-width: 90%;
- position: absolute;
- background-color: #fff;
@include border-radius(3px);
+ background-color: $white;
+ max-width: 90%;
padding: 20px;
+ position: absolute;
+ width: 350px;
z-index: 1000;
.arrow {
+ border-color: transparent;
+ border-style: solid;
border-width: 10px;
- position: absolute;
display: block;
- width: 0;
height: 0;
- border-color: transparent;
- border-style: solid;
+ position: absolute;
+ width: 0;
}
&.tip-overlay--sidebar {
- max-width: 75%;
margin: 50px 0 0 10px;
+ max-width: 75%;
min-height: 330px;
+
.tutorial__footer {
- position: absolute;
- width: 100%;
bottom: 20px;
left: 0;
padding: 0 20px;
+ position: absolute;
+ width: 100%;
}
+
.arrow {
- top: 80px;
+ border-left-width: 0;
+ border-right-color: $white;
left: -10px;
margin-top: -10px;
- border-left-width: 0;
- border-right-color: #fff;
+ top: 80px;
}
}
&.tip-overlay--header {
margin: 10px 0 0 10px;
+
.arrow {
- top: 15px;
- left: -10px;
border-left-width: 0;
- border-right-color: #fff;
+ border-right-color: $white;
+ left: -10px;
+ top: 15px;
}
}
&.tip-overlay--chat {
margin-top: -10px;
+
.arrow {
- left: 50%;
- margin-left: -10px;
border-bottom-width: 0;
- border-top-color: #fff;
+ border-top-color: $white;
bottom: -10px;
+ left: 50%;
+ margin-left: -10px;
}
}
@@ -86,18 +90,18 @@
}
.btn {
- background: #ccc;
- color: #fff;
@include border-radius(3px);
+ background: alpha-color($black, .3);
border: none;
+ color: $white;
margin: 10px 0;
&:hover,
&:active,
&:focus {
- color: #fff;
+ background: alpha-color($black, .4);
border: none;
- background: #bbb;
+ color: $white;
}
}
@@ -110,81 +114,88 @@
}
.tutorial__circles {
- margin: 1.5em 0px -1.7em -4px;
+ margin: 1.5em 0 -1.7em -4px;
.circle {
- width: 7px;
height: 7px;
margin: 0 4px;
+ width: 7px;
}
}
}
.tip-button {
- z-index: 998;
+ cursor: pointer;
+ position: relative;
right: -10px;
top: -10px;
- position: relative;
- cursor: pointer;
+ z-index: 998;
}
.tip-div {
position: absolute;
- top: 0px;
- right: 0px;
+ right: 0;
+ top: 0;
&.tip-overlay--header {
- top: 21px;
right: 2px;
+ top: 21px;
+
.tip-button {
@include opacity(.8);
}
}
&.tip-overlay--sidebar {
- left: 0;
@include opacity(.8);
+ left: 0;
top: -9px;
}
}
.tutorial-steps__container {
- text-align: center;
- width: 100%;
display: table;
height: 100%;
+ text-align: center;
+ width: 100%;
+
.tutorial__content {
display: table-cell;
- vertical-align: middle;
- padding-bottom: 100px;
padding: 20px 40px 40px;
+ vertical-align: middle;
+
.tutorial__steps {
- position: relative;
+ display: inline-block;
+ margin-bottom: 50px;
max-width: 310px;
min-height: 370px;
- margin-bottom: 50px;
+ position: relative;
text-align: left;
- display: inline-block;
}
}
+
.tutorial__footer {
- position: absolute;
bottom: 0;
+ position: absolute;
}
+
h1 {
font-size: em(40px);
- margin: -20px 0 30px;
font-weight: 600;
+ margin: -20px 0 30px;
}
+
h3 {
font-size: em(24px);
- margin-bottom: 30px;
font-weight: 600;
+ margin-bottom: 30px;
}
+
.tutorial__circles {
- position: absolute;
bottom: 40px;
+ position: absolute;
}
+
.tutorial-skip {
margin-left: 13px;
}
@@ -192,17 +203,19 @@
.tutorial__circles {
margin: 2em 0;
+
.circle {
- width: 9px;
- height: 9px;
@include border-radius(9px);
@include opacity(.2);
- background: #000;
+ background: $black;
display: inline-block;
+ height: 9px;
margin: 0 5px;
+ width: 9px;
+
&.active {
- background: $color--primary;
@include opacity(1);
+ background: $primary-color;
}
}
}
diff --git a/webapp/sass/components/_videos.scss b/webapp/sass/components/_videos.scss
index 91db750bd..e009e6538 100644
--- a/webapp/sass/components/_videos.scss
+++ b/webapp/sass/components/_videos.scss
@@ -1,65 +1,68 @@
@charset 'UTF-8';
.video-div {
- position: relative;
- max-width: 480px;
margin-bottom: 8px;
+ max-width: 480px;
+ position: relative;
+
.video-thumbnail {
- max-width: 100%;
height: auto;
+ max-width: 100%;
}
+
.block {
- background-color: rgba(0,0,0,.5);
+ background-color: alpha-color($black, .5);
border-radius: 10px;
+ height: 150px;
+ left: 50%;
+ margin: -75px 0 0 -100px;
position: absolute;
top: 50%;
- left: 50%;
- margin-top: -100px;
width: 200px;
- margin: -75px 0 0 -100px;
- height: 150px;
}
}
.video-type {
@include opacity(.8);
font-size: 15px;
- margin: 0px;
- padding: 0px;
+ margin: 0;
+ padding: 0;
}
.video-title {
font-size: 15px;
margin-top: 3px;
}
+
.play-button {
- width: 100px;
+ @include border-radius(14px);
+ border: 4px solid alpha-color($white, .4);
height: 100px;
position: absolute;
- top: 26px;
right: 51px;
- border: 4px solid;
- border-color: rgba(255,255,255,.4);
- border-radius: 14px;
-}
-.play-button span {
- position: absolute;
- top: 10px;
- left: 20px;
- width: 0;
- height: 0;
- border-top: 36px solid transparent;
- border-bottom: 36px solid transparent;
- border-left: 60px solid rgba(255,255,255,.4);
+ top: 26px;
+ width: 100px;
+
+ span {
+ border-bottom: 36px solid transparent;
+ border-left: 60px solid alpha-color($white, .4);
+ border-top: 36px solid transparent;
+ height: 0;
+ left: 20px;
+ position: absolute;
+ top: 10px;
+ width: 0;
+ }
}
.img-div {
-moz-force-broken-image-icon: 1;
- position: relative;
- max-width: 450px;
- max-height: 500px;
- margin-bottom: 8px;
border-radius: 5px;
+ margin-bottom: 8px;
+ max-height: 500px;
+ max-width: 450px;
+ position: relative;
+
&.placeholder {
height: 500px;
}
diff --git a/webapp/sass/layout/_content.scss b/webapp/sass/layout/_content.scss
index 71bef0d7f..bbc09a80e 100644
--- a/webapp/sass/layout/_content.scss
+++ b/webapp/sass/layout/_content.scss
@@ -15,21 +15,22 @@
}
.app__content {
+ @include display-flex;
+ @include flex-direction(column);
+ background: $white;
height: 100%;
- padding-top: 50px;
margin-left: 220px;
+ padding-top: 50px;
position: relative;
- background: #fff;
- @include display-flex;
- @include flex-direction(column);
.channel__wrap & {
padding-top: 0;
}
}
+
#post-create {
@include flex(0 0 auto);
- background: #fff;
+ background: $white;
width: 100%;
z-index: 3;
}
@@ -37,12 +38,12 @@
#archive-link-home {
@include flex(0 0 auto);
cursor: pointer;
- padding: 10px 20px;
font-size: 13px;
+ padding: 10px 20px;
.fa {
- font-size: 11px;
@include opacity(.7);
+ font-size: 11px;
}
a {
@@ -50,36 +51,6 @@
}
}
-.post-list {
- .new-messages-hr {
- margin-top: 5px;
- margin-bottom: 0px;
- border: 0;
- border-top: 1px solid #f80;
- }
-
- .new-messages-text {
- margin-top: 2px;
- margin-bottom: 5px;
- color: #f80;
- text-align: center;
- }
-}
-
-.new-messages-hr {
- margin-top: 5px;
- margin-bottom: 0px;
- border: 0;
- border-top: 1px solid #f80;
-}
-
-.new-messages-text {
- margin-top: 2px;
- margin-bottom: 5px;
- color: #f80;
- text-align: center;
-}
-
.delete-message-text {
margin-top: 10px;
}
diff --git a/webapp/sass/layout/_footer.scss b/webapp/sass/layout/_footer.scss
index 5624e6376..36f1fbc70 100644
--- a/webapp/sass/layout/_footer.scss
+++ b/webapp/sass/layout/_footer.scss
@@ -1,22 +1,22 @@
@charset 'UTF-8';
.footer-pane {
- background: #eee;
+ background: $light-gray;
padding-bottom: 1em;
.footer-link {
padding: 0 1.5em;
&.copyright {
- color: #999;
+ color: $dark-gray;
padding-right: 0;
}
}
.footer-site-name {
- padding: 1.5em 0 1em;
font-size: 14px;
font-weight: bold;
+ padding: 1.5em 0 1em;
text-transform: uppercase;
}
}
diff --git a/webapp/sass/layout/_forms.scss b/webapp/sass/layout/_forms.scss
index 1f51603cc..259beeb57 100644
--- a/webapp/sass/layout/_forms.scss
+++ b/webapp/sass/layout/_forms.scss
@@ -6,32 +6,32 @@
}
.form__label {
- text-align: left;
- padding-right: 3px;
- font-weight: 600;
font-size: 1.1em;
+ font-weight: 600;
+ padding-right: 3px;
+ text-align: left;
&.light {
- font-weight: normal;
- color: #999;
+ color: $dark-gray;
font-size: 1.05em;
font-style: italic;
+ font-weight: normal;
padding-top: 2px;
}
}
.input__help {
+ @include opacity(.8);
color: inherit;
margin: 10px 0 0 10px;
word-break: break-word;
- @include opacity(.8);
&.dark {
@include opacity(1);
}
&.error {
- color: #a94442;
+ color: darken($red, 20%);
}
}
@@ -49,13 +49,9 @@
}
.help-block {
+ color: $dark-gray;
font-size: .95em;
margin: 10px 0 0;
- color: #999;
-}
-
-.disabled-input {
- background-color: #ddd !important;
}
.form-group {
diff --git a/webapp/sass/layout/_headers.scss b/webapp/sass/layout/_headers.scss
index 0a6b9f920..9b631d00f 100644
--- a/webapp/sass/layout/_headers.scss
+++ b/webapp/sass/layout/_headers.scss
@@ -1,6 +1,6 @@
@charset 'UTF-8';
-#channel-header {
+.channel-header {
@include flex(0 0 56px);
}
@@ -15,8 +15,8 @@
}
.header-dropdown__icon {
- font-size: 11px;
color: inherit;
+ font-size: 11px;
top: 3px;
}
@@ -31,12 +31,12 @@
word-break: break-word;
&.dropdown {
+ float: left;
max-width: 100%;
padding-right: 1em;
- float: left;
.header-dropdown__icon {
- color: #777;
+ color: $dark-gray;
}
a {
@@ -49,10 +49,11 @@
}
&.description {
- overflow: hidden;
- text-overflow: ellipsis;
margin-top: 2px;
max-height: 45px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+
.markdown-inline-img {
max-height: 45px;
}
@@ -65,14 +66,14 @@
}
.channel-intro {
+ border-bottom: 1px solid $light-gray;
margin: 0 auto 35px;
- padding: 0 1em 5px;
max-width: 1000px;
- border-bottom: 1px solid lightgrey;
+ padding: 0 1em 5px;
.intro-links {
- margin: 0 1.5em 10px 0;
display: inline-block;
+ margin: 0 1.5em 10px 0;
.fa {
margin-right: 5px;
@@ -80,28 +81,30 @@
}
.channel-intro-profile {
- margin-top: 5px;
margin-left: 63px;
+ margin-top: 5px;
}
.channel-intro-img {
float: left;
+
img {
@include border-radius(100px);
}
}
.channel-intro__title {
- font-weight: 600;
font-size: 20px;
+ font-weight: 600;
margin-bottom: 15px;
}
.channel-intro__content {
- background: #f7f7f7;
- padding: 10px 15px;
@include border-radius(3px);
+ background: $bg--gray;
+ padding: 10px 15px;
}
+
.channel-intro-text {
margin-top: 35px;
}
@@ -111,28 +114,28 @@
.sidebar--left,
.sidebar--menu {
.team__header {
- position: relative;
- padding: 9px 10px;
@include legacy-pie-clearfix;
+ padding: 9px 10px;
+ position: relative;
&:before {
@include single-transition(all, .05s, linear);
- content: '';
background: none;
- top: 0;
- left: 0;
- width: 100%;
+ content: '';
height: 100%;
+ left: 0;
position: absolute;
+ top: 0;
+ width: 100%;
}
&:hover {
&:before {
- background: rgba(black, .1);
+ @include alpha-property(background, $black, .1);
}
.user__name {
- color: #fff;
+ color: $white;
}
.navbar-right {
@@ -145,95 +148,88 @@
.navbar-right {
font-size: .85em;
position: absolute;
- top: 10px;
right: 22px;
+ top: 10px;
z-index: 5;
.dropdown-toggle {
+ @include opacity(.8);
@include single-transition(all, .1s, linear);
padding: 10px;
- @include opacity(.8);
}
.dropdown-menu {
- li a {
+ a {
+ overflow: hidden;
padding: 3px 20px;
text-overflow: ellipsis;
- overflow: hidden;
}
}
.dropdown__icon {
- fill: #fff;
+ fill: $white;
}
}
- .settings__link a:hover,
- a:visited,
- a:link,
- a:active {
- text-decoration: none;
- }
-
.user__picture {
- width: 36px;
- height: 36px;
- float: left;
@include border-radius(36px);
+ float: left;
+ height: 36px;
margin-right: 6px;
+ width: 36px;
}
.header__info {
- color: #fff;
@include clearfix;
+ color: $white;
padding-left: 2px;
- z-index: 1;
position: relative;
+ z-index: 1;
}
.team__name,
.user__name {
display: block;
- font-weight: 600;
font-size: 16px;
+ font-weight: 600;
max-width: 85%;
overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
text-decoration: none;
+ text-overflow: ellipsis;
+ white-space: nowrap;
}
.team__name {
+ float: left;
line-height: 22px;
margin-top: -2px;
- float: left;
}
.user__name {
@include single-transition(all, .1s, linear);
+ @include alpha-property(color, $white, .8);
font-size: 14px;
- line-height: 18px;
font-weight: 400;
- color: #eee;
- color: rgba(#fff, .8);
+ line-height: 18px;
}
> .nav {
> li {
> a {
+ background: none;
float: right;
- background: none !important;
padding: 2px;
+ }
- &.dropdown-toggle {
- line-height: 1.8;
- font-size: 1em;
- color: #fff;
- }
+ .dropdown-toggle {
+ color: $white;
+ font-size: 1em;
+ line-height: 1.8;
}
}
}
}
+
.search__clear {
display: none;
}
@@ -250,27 +246,29 @@
}
.channel-header {
- width: 100%;
border-left: none;
font-size: 14px;
line-height: 56px;
+ width: 100%;
#member_popover {
- width: 50px;
- color: #999;
+ color: #999999;
cursor: pointer;
+ width: 50px;
.fa {
- margin-left: 4px;
font-size: 16px;
+ margin-left: 4px;
}
}
&.alt {
margin: 0;
+
th {
font-weight: normal !important;
}
+
td {
border: none;
}
@@ -278,37 +276,39 @@
th {
text-align: center;
+
&:first-child {
- text-align: left !important;
border-left: none;
- width: 100%;
padding-left: 1em;
+ text-align: left !important;
+ width: 100%;
}
+
&:last-child {
width: 8.9%;
}
}
td {
- padding: 5px 25px 5px !important;
font-size: 13px;
+ padding: 5px 25px 5px !important;
text-align: center !important;
+
&:first-child {
text-align: left !important;
}
}
.heading {
- margin: 0;
- color: #555;
+ color: #555555;
+ display: inline-block;
font-size: 1.3em;
font-weight: 600;
+ margin: 0 4px 0 0;
+ max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
- max-width: 100%;
- display: inline-block;
vertical-align: middle;
- margin-right: 4px;
}
.caret {
@@ -318,13 +318,13 @@
.more {
color: #81848b;
display: inline-block;
- vertical-align: top;
- text-transform: capitalize;
font-size: 13px;
+ text-transform: capitalize;
+ vertical-align: top;
}
.disabled {
- color: #999;
+ color: #999999;
}
}
@@ -342,11 +342,11 @@
.channel-header__links {
font-family: 'Open Sans', sans-serif;
+ font-size: 22px;
height: 30px;
- width: 24px;
line-height: 26px;
margin-right: 9px;
- font-size: 22px;
+ width: 24px;
.channel__wrap.move--left & {
position: absolute;
@@ -355,14 +355,15 @@
}
> a {
- color: inherit;
- text-decoration: none;
@include opacity(.6);
@include single-transition(all, .1s, ease-in);
+ color: inherit;
+ text-decoration: none;
&:hover {
@include opacity(1);
}
+
&:focus {
color: inherit;
}
diff --git a/webapp/sass/layout/_markdown.scss b/webapp/sass/layout/_markdown.scss
index 307060ac3..b9acd8b5b 100644
--- a/webapp/sass/layout/_markdown.scss
+++ b/webapp/sass/layout/_markdown.scss
@@ -16,43 +16,77 @@
#post-list {
.markdown-inline-img {
-moz-force-broken-image-icon: 1;
- max-height: 500px;
height: 500px;
+ max-height: 500px;
}
}
.post-body--code {
+ overflow-x: auto;
+ overflow-y: hidden;
position: relative;
pre {
- margin-bottom: 0;
- word-break: normal;
- overflow: auto;
- word-wrap: normal;
+ border: 1px solid rgba(221,221,221,0.2);
+ border-radius: .25em;
+ margin: 0;
+ padding: 0px;
+ text-align: left;
+ white-space: nowrap;
+ }
+
+ code {
+ border: none;
+ white-space: pre;
+ }
+
+ td {
+ padding: 0 .5em;
+ vertical-align: top;
+ }
+
+ &:hover .post-body--code__language {
+ @include opacity(1);
}
}
.post-body--code__language {
- -webkit-transform: translate3d(0,0,0);
+ @include opacity(0);
+ @include translate3d(0, 0, 0);
+ background: #21586d;
+ border-radius: 0 .25em;
+ color: $white;
+ padding: 4px 10px 5px;
position: absolute;
- top: 0;
right: 0;
- color: #fff;
- background: #21586d;
- padding: 4px 10px 5px 10px;
- font-size: 13px;
- opacity: .7;
+ top: 0;
+ -webkit-transition: opacity 0.6s;
+ -moz-transition: opacity 0.6s;
+ -o-transition: opacity 0.6s;
+ transition: opacity 0.6s;
z-index: 5;
}
+.post-body--code__lineno {
+ border-right: 1px solid #aaa;
+ color: #aaa;
+ margin-right: .5em;
+ text-align: right;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ -o-user-select: none;
+ user-select: none;
+}
+
.post__body {
hr {
- height: 4px;
- padding: 0;
- margin: 15px 0 16px;
+ @include opacity(.2);
background-color: #e7e7e7;
border: 0 none;
- @include opacity(.2);
+ height: 4px;
+ margin: 15px 0 16px;
+ padding: 0;
}
code {
@@ -67,50 +101,53 @@
}
.markdown__table {
- background: #fff;
+ background: $white;
margin: 5px 0 10px;
th,
td {
- padding: 6px 13px;
border: 1px solid #ddd;
+ padding: 6px 13px;
}
tbody tr {
- background: #fff;
+ background: $white;
&:nth-child(2n) {
background-color: #f8f8f8;
}
}
}
+
blockquote {
border: none;
- position: relative;
font-size: 16px;
- padding: 10px 10px 10px 38px;
margin-bottom: 0;
+ padding: 10px 10px 10px 38px;
+ position: relative;
&:before {
+ @include opacity(.6);
+ content: '\f10d';
+ display: inline-block;
font-family: FontAwesome;
- font-weight: normal;
+ font-size: 20px;
font-style: normal;
- display: inline-block;
- text-decoration: inherit;
- content: '\f10d';
+ font-weight: normal;
left: 8px;
- top: 5px;
position: absolute;
- font-size: 20px;
- @include opacity(.6);
+ text-decoration: inherit;
+ top: 5px;
}
}
+
pre {
- border: none;
- margin: 5px 0;
color: inherit;
+ margin: 5px 0;
+ padding: 0;
}
+
code {
- background: #fff;
+ background: $white;
color: inherit;
}
diff --git a/webapp/sass/layout/_navigation.scss b/webapp/sass/layout/_navigation.scss
index 65c62cb17..87e4b4d27 100644
--- a/webapp/sass/layout/_navigation.scss
+++ b/webapp/sass/layout/_navigation.scss
@@ -7,14 +7,14 @@
#navbar {
input {
- margin: 0px 5px 0px 2px;
+ margin: 0 5px 0 2px;
}
.navbar-default {
- position: absolute;
+ background: $primary-color;
border: none;
min-height: 45px;
- background: $color--primary;
+ position: absolute;
.navbar-nav {
> li {
@@ -30,19 +30,19 @@
}
.navbar-toggle {
- width: 43px;
- float: left;
border-color: transparent;
border-radius: 0;
+ fill: $white;
+ float: left;
+ height: 44px;
+ line-height: 48px;
margin: 0;
padding: 0 10px;
- line-height: 48px;
- height: 44px;
+ width: 43px;
z-index: 5;
- fill: #fff;
.icon-bar {
- background: #fff;
+ background: $white;
width: 21px;
}
@@ -51,7 +51,7 @@
}
.icon--white {
- color: #fff;
+ color: $white;
}
&:hover,
@@ -62,16 +62,16 @@
}
.navbar-brand {
- padding: 0 .5em;
- height: 45px;
- line-height: 45px;
float: none;
font-size: 16px;
+ height: 45px;
+ line-height: 45px;
+ padding: 0 .5em;
.heading {
- margin-right: 3px;
+ color: $white;
font-weight: 600;
- color: #fff;
+ margin-right: 3px;
}
.header-dropdown__icon {
@@ -79,36 +79,36 @@
}
.dropdown-toggle {
- color: #fff;
+ color: $white;
}
.description {
+ color: $white;
display: inline-block;
margin-right: .5em;
- color: #fff;
&.info-popover {
- width: 19px;
- height: 19px;
- background: url('../images/info__icon.png');
@include background-size(100% 100%);
- vertical-align: middle;
- top: -1px;
- position: relative;
+ background: url('../images/info__icon.png');
cursor: pointer;
+ height: 19px;
+ position: relative;
+ top: -1px;
+ vertical-align: middle;
+ width: 19px;
}
}
}
}
.sidebar-channel {
- white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
+ white-space: nowrap;
span {
- white-space: nowrap;
margin-left: 2px;
+ white-space: nowrap;
}
}
@@ -117,11 +117,13 @@
}
.more-channel-table {
- width: 100%;
border: 1px solid #dbdbdc;
+ width: 100%;
+
td {
padding: 7px;
}
+
button {
width: 110px;
}
@@ -129,9 +131,9 @@
}
.badge-notify {
- background: red;
- position: absolute;
+ background: $red;
left: 4px;
+ position: absolute;
top: 3px;
z-index: 100;
}
diff --git a/webapp/sass/layout/_post-right.scss b/webapp/sass/layout/_post-right.scss
index 595577564..529f73995 100644
--- a/webapp/sass/layout/_post-right.scss
+++ b/webapp/sass/layout/_post-right.scss
@@ -27,8 +27,8 @@
.post {
&.post--root {
- padding-bottom: 1.2em;
border-bottom: 1px solid #ddd;
+ padding-bottom: 1.2em;
.post__body {
background: transparent !important;
@@ -37,8 +37,8 @@
.post__header {
.col__reply {
- top: 0;
text-align: right;
+ top: 0;
}
}
@@ -48,13 +48,13 @@
}
hr {
- margin-bottom: 0;
border: none;
+ margin-bottom: 0;
}
.post-create__container {
- width: 100%;
margin-top: 10px;
+ width: 100%;
.textarea-wrapper {
min-height: 100px;
@@ -70,48 +70,46 @@
.msg-typing {
@include opacity(.7);
+ display: block;
float: left;
- margin-top: 3px;
font-size: 13px;
- line-height: 20px;
- min-width: 1px;
- display: block;
height: 20px;
+ line-height: 20px;
+ margin-top: 3px;
max-width: 230px;
+ min-width: 1px;
}
.post-create-footer {
- width: 100%;
padding: 5px 0 10px;
+ width: 100%;
}
.post-right-comments-upload-in-progress {
- padding: 6px 0;
color: #a8adb7;
margin-right: 10px;
+ padding: 6px 0;
}
}
}
+
.post-right-header {
- font-size: 1em;
- text-transform: uppercase;
+ border-bottom: $border-gray;
color: #999;
+ font-size: 1em;
font-weight: 400;
- color: #888;
height: 39px;
padding: 10px 10px 0 15px;
- border-bottom: $border-gray;
+ text-transform: uppercase;
}
.post-right-root-container {
- padding: 5px 10px;
border-bottom: $border-gray;
-}
+ padding: 5px 10px;
-.post-right-root-container {
ul {
- padding-left: 0;
margin-bottom: 2px;
+ padding-left: 0;
}
}
@@ -131,19 +129,19 @@
}
.post-right-create-comment-container {
- padding: 5px;
- margin-bottom: 18px;
- position: absolute;
bottom: 0;
left: 0;
+ margin-bottom: 18px;
+ padding: 5px;
+ position: absolute;
width: 100%;
}
.post-right__scroll {
- position: relative;
- overflow: auto;
- -webkit-overflow-scrolling: touch;
@include flex(1 1 auto);
+ -webkit-overflow-scrolling: touch;
+ overflow: auto;
+ position: relative;
.file-preview__container {
margin-top: 5px;
diff --git a/webapp/sass/layout/_post.scss b/webapp/sass/layout/_post.scss
index ce055035d..9d5be239a 100644
--- a/webapp/sass/layout/_post.scss
+++ b/webapp/sass/layout/_post.scss
@@ -1,19 +1,20 @@
@charset 'UTF-8';
.custom-textarea {
- white-space: pre-wrap;
- word-wrap: break-word;
background: transparent;
- border: 1px solid #ccc;
- position: absolute;
- top: 0px;
+ border: 1px solid #cccccc;
height: auto;
- resize: none;
line-height: 20px;
min-height: 36px;
overflow-x: hidden;
+ position: absolute;
+ resize: none;
+ top: 0px;
+ white-space: pre-wrap;
+ word-wrap: break-word;
+
&:focus {
- border-color: #ccc;
+ border-color: #cccccc;
box-shadow: none;
}
}
@@ -24,23 +25,23 @@
}
.textarea-div {
- white-space: pre-wrap;
- word-wrap: normal;
+ border: 0;
color: rgba(0,0,0,0);
- position: absolute;
- top: 0px;
- word-break: break-word;
+ height: auto;
left: 1px;
line-height: 20px;
min-height: 36px;
- height: auto;
- border: 0;
+ position: absolute;
+ top: 0px;
+ white-space: pre-wrap;
+ word-break: break-word;
+ word-wrap: normal;
}
body.ios {
.textarea-div {
- padding: 7px 17px 7px 15px;
-webkit-overflow-scrolling: auto;
+ padding: 7px 17px 7px 15px;
}
}
@@ -49,133 +50,146 @@ body.ios {
}
.textarea-wrapper {
+ min-height: 36px;
position: relative;
+
.textbox-preview-area {
+ box-shadow: none;
+ left: 0;
position: absolute;
- z-index: 2;
top: 0;
- left: 0;
- box-shadow: none;
white-space: normal;
+ z-index: 2;
}
+
.help__text {
- right: 0;
- position: absolute;
- z-index: 3;
bottom: -23px;
- font-size: 13px;
cursor: pointer;
+ font-size: 13px;
+ position: absolute;
+ right: 0;
+ z-index: 3;
}
+
.textbox-preview-link {
margin-right: 8px;
}
- min-height: 36px;
}
.help_format_text {
- display: none !important;
- position: absolute;
+ @include opacity(0);
+ @include single-transition(all .2s ease);
bottom: -23px;
- left: 0px;
+ display: none !important;
+ font-size: .85em;
+ left: 0;
overflow: hidden;
+ position: absolute;
text-overflow: ellipsis;
- font-size: .85em;
- @include opacity(0);
- @include single-transition(all .2s ease);
b,
i,
code {
margin-right: 3px;
}
+
.textbox-preview-link {
- font-size: 13px;
cursor: pointer;
+ font-size: 13px;
margin-left: 15px;
}
}
.date-separator,
.new-separator {
- text-align: center;
height: 2em;
margin: 0;
position: relative;
+ text-align: center;
z-index: 0;
+
&:before,
&:after {
content: '';
+ display: none;
height: 1em;
- position: absolute;
left: 0;
+ position: absolute;
width: 100%;
- display: none;
}
+
&:before {
bottom: 0;
}
+
&:after {
top: 0;
}
+
&.hovered--after {
&:before {
background: #f5f5f5;
display: block;
}
}
+
&.hovered--before {
&:after {
background: #f5f5f5;
display: block;
}
}
+
.separator__hr {
- border-color: #ccc;
+ border-color: #cccccc;
margin: 0;
position: relative;
- z-index: 5;
top: 1em;
+ z-index: 5;
}
+
.separator__text {
- line-height: 2em;
- color: #555;
- background: #fff;
+ @include border-radius(50px);
+ background: #ffffff;
+ color: #555555;
display: inline-block;
- padding: 0 1em;
+ font-size: 13px;
font-weight: 700;
- @include border-radius(50px);
+ line-height: 2em;
+ padding: 0 1em;
position: relative;
z-index: 5;
- font-size: 13px;
}
}
+
.new-separator {
.separator__hr {
border-color: #ffaf53;
}
+
.separator__text {
- color: #f80;
+ color: #ff8800;
font-weight: normal;
}
}
.file-overlay {
+ color: #ffffff;
+ font-size: em(20px);
+ font-weight: 600;
+ height: 100%;
+ left: 0;
position: absolute;
+ text-align: center;
top: 0;
- left: 0;
width: 100%;
- height: 100%;
- text-align: center;
- color: #fff;
- font-size: em(20px);
- font-weight: 600;
z-index: 6;
.overlay__indent {
- background-color: rgba(0, 0, 0, .6);
- position: relative;
- height: 100%;
@include clearfix;
+ @include alpha-property(background-color, $black, .6);
+ height: 100%;
+ position: relative;
}
&.center-file-overlay {
@@ -186,11 +200,13 @@ body.ios {
&.right-file-overlay {
font-size: em(18px);
+
.overlay__circle {
- width: 300px;
height: 300px;
margin: -150px 0 0 -150px;
+ width: 300px;
}
+
.overlay__files {
margin: 60px auto 15px;
width: 150px;
@@ -198,16 +214,15 @@ body.ios {
}
.overlay__circle {
- background: #111;
- background: rgba(black, .7);
- width: 370px;
+ @include border-radius(500px);
+ @include alpha-property(background, $black, .7);
height: 370px;
+ left: 50%;
margin: -185px 0 0 -185px;
- @include border-radius(500px);
+ pointer-events: none;
position: absolute;
top: 50%;
- left: 50%;
- pointer-events: none;
+ width: 370px;
}
.overlay__files {
@@ -216,11 +231,11 @@ body.ios {
}
.overlay__logo {
- position: absolute;
- left: 50%;
+ @include opacity(.3);
bottom: 30px;
+ left: 50%;
margin-left: -50px;
- @include opacity(.3);
+ position: absolute;
}
.fa {
@@ -232,62 +247,64 @@ body.ios {
#post-list {
@include flex(1 1 auto);
- position: relative;
- overflow-y: hidden;
height: 100%;
+ overflow-y: hidden;
+ position: relative;
.inactive {
display: none;
}
.post-list-holder-by-time {
- background: #fff;
+ -webkit-overflow-scrolling: touch;
+ background: #ffffff;
+ height: 100%;
overflow-y: scroll;
- width: 100%;
padding: 1em 0 0;
position: absolute;
- height: 100%;
- -webkit-overflow-scrolling: touch;
+ width: 100%;
+
&.active {
display: inline;
}
}
.more-messages-text {
- margin: 5px 0 10px;
- display: block;
- text-align: center;
- outline: none;
border: none;
+ display: block;
font-size: 13px;
+ margin: 5px 0 10px;
+ outline: none;
+ text-align: center;
}
+
.beginning-messages-text {
- margin-top: 2px;
- margin-bottom: 5px;
+ color: grey;
display: block;
+ margin-bottom: 5px;
+ margin-top: 2px;
text-align: center;
- color: grey;
}
}
.post-list__timestamp {
- position: absolute;
- top: 8px;
- left: 50%;
- z-index: 50;
- width: 120px;
- text-align: center;
- background: $color--primary;
- color: #fff;
@include border-radius(3px);
- font-size: 12px;
- line-height: 25px;
- margin-left: -60px;
- -webkit-font-smoothing: initial;
+ @include opacity(0);
@include single-transition(all, .6s, ease);
@include translateY(-45px);
- @include opacity(0);
+ @include font-smoothing(initial);
+ background: $primary-color;
+ color: $white;
display: none;
+ font-size: 12px;
+ left: 50%;
+ line-height: 25px;
+ margin-left: -60px;
+ position: absolute;
+ text-align: center;
+ top: 8px;
+ width: 120px;
+ z-index: 50;
&.scrolling {
@include translateY(0);
@@ -296,147 +313,162 @@ body.ios {
}
.post-list__arrows {
+ @include opacity(0);
+ @include single-transition(all, .6s);
background-repeat: no-repeat;
- width: 40px;
- height: 40px;
- text-align: center;
- fill: #444;
- position: absolute;
bottom: 0;
+ display: none;
+ fill: #444444;
+ height: 40px;
left: 9px;
+ position: absolute;
+ text-align: center;
+ width: 40px;
z-index: 50;
- @include opacity(0);
- @include single-transition(all, .6s);
- display: none;
svg {
color: inherit;
- width: 28px;
height: 28px;
+ width: 28px;
}
&.scrolling {
- display: block;
@include opacity(1);
+ display: block;
}
}
.post-create__container {
form {
- width: 100%;
- padding: .5em 14px 0;
margin: 0 auto;
max-width: 1028px;
+ padding: .5em 14px 0;
+ width: 100%;
}
+
.post-create-body {
- position: relative;
padding: 0 0 2px;
+ position: relative;
+
.post-body__cell {
- vertical-align: top;
position: relative;
+ vertical-align: top;
+
&.scroll {
.btn-file {
right: 15px;
}
+
.custom-textarea {
padding-right: 43px;
}
}
}
+
.send-button {
- display: none;
+ @include single-transition(all, .15s);
cursor: pointer;
- padding-right: 4px;
- width: 45px;
- height: 37px;
+ display: none;
font-size: 18px;
+ height: 37px;
line-height: 37px;
- vertical-align: bottom;
+ padding-right: 4px;
text-align: center;
- @include single-transition(all, .15s);
+ vertical-align: bottom;
+ width: 45px;
+
&:active {
@include opacity(.75);
}
}
+
.custom-textarea {
- padding-top: 8px;
- padding-right: 28px;
- max-height: 162px !important;
line-height: 1.5;
+ max-height: 162px !important;
+ padding-right: 28px;
+ padding-top: 8px;
}
+
.textarea-div {
- padding-top: 8px;
- padding-right: 30px;
+ line-height: 1.5;
max-height: 163px !important;
overflow: auto;
- line-height: 1.5;
+ padding-right: 30px;
+ padding-top: 8px;
}
+
.btn-file {
- right: 0;
- position: absolute;
- top: 1px;
- color: #444;
@include opacity(.5);
@include single-transition(all, .15s);
+ color: #444444;
font-size: 16px;
padding: 7px 9px 6px;
+ position: absolute;
+ right: 0;
+ top: 1px;
+
&:hover,
&:active {
@include opacity(.9);
box-shadow: none;
}
}
+
textarea {
box-shadow: none;
}
}
+
.post-create-footer {
@include clearfix;
- padding: 3px 0 0 0;
font-size: 13px;
+ padding: 3px 0 0 0;
.control-label {
font-weight: normal;
margin-bottom: 0;
- top: -5px;
position: relative;
+ top: -5px;
}
}
+
.msg-typing {
- display: block;
@include opacity(.7);
- white-space: nowrap;
+ display: block;
+ font-size: .95em;
+ height: 20px;
margin-bottom: 5px;
overflow: hidden;
- font-size: .95em;
text-overflow: ellipsis;
- height: 20px;
+ white-space: nowrap;
}
}
.post-list__table {
display: table;
+ height: 100%;
+ min-height: 100%;
table-layout: fixed;
width: 100%;
- min-height: 100%;
- height: 100%;
+
.post-list__content {
display: table-cell;
vertical-align: bottom;
+
.dropdown-menu {
&.bottom {
- top: auto;
bottom: 25px;
+ top: auto;
}
}
}
}
.post {
- word-wrap: break-word;
+ @include legacy-pie-clearfix;
+ max-width: 100%;
padding: 8px .5em 0 1em;
position: relative;
- max-width: 100%;
- @include legacy-pie-clearfix;
+ word-wrap: break-word;
&:hover {
.dropdown,
@@ -445,6 +477,7 @@ body.ios {
.post__remove {
visibility: visible;
}
+
.permalink-icon {
visibility: visible;
}
@@ -455,9 +488,9 @@ body.ios {
}
p {
- margin: 0;
- line-height: 1.6em;
font-size: .97em;
+ line-height: 1.6em;
+ margin: 0;
white-space: pre-wrap;
&:last-child {
@@ -488,8 +521,8 @@ body.ios {
}
.post__header {
- margin: 0;
height: 0;
+ margin: 0;
.col__name {
display: none;
@@ -501,20 +534,13 @@ body.ios {
}
.post__time {
- top: 24px;
- }
-
- .post__time {
- font: normal normal normal FontAwesome;
- text-rendering: auto;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- position: absolute;
- top: -2px;
- left: -7px;
+ @include opacity(0);
font-size: 11px;
+ left: -7px;
line-height: 37px;
- @include opacity(0);
+ position: absolute;
+ text-rendering: auto;
+ top: -2px;
}
}
@@ -528,11 +554,9 @@ body.ios {
display: none;
}
}
- }
- &.post--comment {
.post__body {
- border-left: 4px solid #ddd;
+ border-left: 4px solid #dddddd;
}
}
}
@@ -562,12 +586,12 @@ body.ios {
}
.post__content {
+ display: table;
margin: 0 auto;
- position: relative;
max-width: 1000px;
- display: table;
- width: 100%;
+ position: relative;
table-layout: fixed;
+ width: 100%;
> div {
display: table-cell;
@@ -576,9 +600,9 @@ body.ios {
}
.post__header {
- padding: 0;
list-style: none;
margin-bottom: 2px;
+ padding: 0;
li {
display: inline-block;
@@ -586,12 +610,12 @@ body.ios {
}
.col__name {
- margin-right: 7px;
font-weight: 600;
+ margin-right: 7px;
.user-popover {
- max-width: 200px;
@include clearfix;
+ max-width: 200px;
text-overflow: ellipsis;
white-space: nowrap;
}
@@ -601,8 +625,8 @@ body.ios {
position: absolute;
right: 0;
top: 30px;
- width: 65px;
white-space: nowrap;
+ width: 65px;
}
.permalink-popover {
@@ -616,27 +640,29 @@ body.ios {
.btn {
font-size: 13px;
height: 30px;
- padding: 0 8px;
line-height: 30px;
+ padding: 0 8px;
}
}
}
.post__img {
width: 46px;
+
img {
- width: 36px;
+ @include border-radius(50px);
height: 36px;
vertical-align: inherit;
- @include border-radius(50px);
+ width: 36px;
}
}
.post__embed-container {
+ @include single-transition(max-height, .5, ease);
display: block;
max-height: 1000px;
- transition: max-height .5s ease;
overflow: hidden;
+
&[hidden] {
max-height: 0;
}
@@ -644,15 +670,15 @@ body.ios {
.dropdown {
display: inline-block;
- visibility: hidden;
margin-right: 5px;
top: -1px;
+ visibility: hidden;
.dropdown-menu {
- right: 0;
left: auto;
min-width: 130px;
padding: 2px 0;
+ right: 0;
li {
display: block;
@@ -667,27 +693,27 @@ body.ios {
.post__dropdown {
&:after {
content: '[...]';
- top: -1px;
position: relative;
+ top: -1px;
}
}
.post__remove {
- font-family: 'Open Sans', sans-serif;
- position: relative;
+ @include opacity(.5);
+ color: inherit;
display: inline-block;
- vertical-align: top;
- right: 15px;
- top: -5px;
+ font-family: 'Open Sans', sans-serif;
font-size: 20px;
- width: 20px;
+ font-weight: 600;
height: 20px;
line-height: 20px;
- font-weight: 600;
- visibility: hidden;
- color: inherit;
- @include opacity(.5);
+ position: relative;
+ right: 15px;
text-decoration: none;
+ top: -5px;
+ vertical-align: top;
+ visibility: hidden;
+ width: 20px;
&:hover {
@include opacity(.8);
@@ -695,10 +721,10 @@ body.ios {
}
.post__body {
- word-wrap: break-word;
- padding: .2em .5em;
@include legacy-pie-clearfix;
+ padding: .2em .5em;
width: calc(100% - 75px);
+ word-wrap: break-word;
p {
margin: 0 0 .4em;
@@ -725,6 +751,7 @@ body.ios {
p {
margin-bottom: 0;
}
+
li ul,
li ol {
padding: 0 0 0 20px;
@@ -745,8 +772,8 @@ body.ios {
}
li input[type='checkbox']:disabled {
- vertical-align: top;
cursor: default;
+ vertical-align: top;
}
}
@@ -766,21 +793,21 @@ body.ios {
}
.post__link {
- margin: 2px 0 5px;
font-size: 13px;
- text-overflow: ellipsis;
+ margin: 2px 0 5px;
overflow: hidden;
+ text-overflow: ellipsis;
white-space: nowrap;
}
.post__embed-visibility {
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-font-smoothing: antialiased;
cursor: pointer;
+ display: inline-block;
font: normal normal normal 14px/1 FontAwesome;
- text-rendering: auto;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
margin: 5px 0 10px;
- display: inline-block;
+ text-rendering: auto;
&:hover {
text-decoration: none;
@@ -807,8 +834,8 @@ body.ios {
.post-loading-gif {
height: 10px;
- width: 10px;
margin-top: 6px;
+ width: 10px;
}
.post-fail {
@@ -816,12 +843,12 @@ body.ios {
}
.post-waiting {
- color: #999;
+ color: #999999;
}
.permalink-icon {
+ color: $primary-color;
display: inline-block;
- color: $color--primary;
visibility: hidden;
}
@@ -830,16 +857,16 @@ body.ios {
margin-right: 6px;
visibility: hidden;
svg {
- width: 18px;
- top: 3px;
fill: inherit;
position: relative;
+ top: 3px;
+ width: 18px;
}
}
.comment-icon__container {
- fill: $color--primary;
display: inline-block;
+ fill: $primary-color;
visibility: hidden;
&:focus {
@@ -857,10 +884,10 @@ body.ios {
.comment-icon {
display: inline-block;
- top: 2px;
- position: relative;
- margin-right: 3px;
fill: inherit;
+ margin-right: 3px;
+ position: relative;
+ top: 2px;
}
path {
@@ -869,28 +896,30 @@ body.ios {
}
.web-embed-data {
- padding: 2px 0 0 10px;
- background: #f9f9f9;
- background: rgba(0, 0, 0, .05);
@include border-radius(2px);
+ @include alpha-property(background, $black, 0.05);
height: 50px;
overflow: hidden;
+ padding: 2px 0 0 10px;
text-overflow: ellipsis;
+
.embed-title {
- margin: 3px 0 1px;
- color: #555;
+ color: #555555;
font-weight: 600;
- white-space: nowrap;
- text-overflow: ellipsis;
+ margin: 3px 0 1px;
overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
}
+
.embed-description {
+ color: #888888;
margin: 0;
- white-space: nowrap;
- text-overflow: ellipsis;
overflow: hidden;
- color: #888;
+ text-overflow: ellipsis;
+ white-space: nowrap;
}
+
.embed-link {
display: none;
}
@@ -898,89 +927,104 @@ body.ios {
}
.bot-indicator {
+ border-radius: 2px;
font-family: inherit;
font-size: 11px;
- padding: 2px 4px;
- border-radius: 2px;
font-weight: 600;
margin: 0 0 0 -4px;
+ padding: 2px 4px;
}
.attachment {
.attachment__content {
- border-width: 1px;
- border-style: solid;
border-radius: 4px;
- padding: 2px 5px;
+ border-style: solid;
+ border-width: 1px;
margin: 0 0 5px 0;
+ padding: 2px 5px;
}
+
.attachment__thumb-pretext {
- border: 0 none;
background: transparent;
+ border: none;
+ margin-left: 5px;
}
+
.attachment__container {
- border-left-width: 4px;
border-left-style: solid;
+ border-left-width: 4px;
padding: 2px 0 2px 10px;
+
&.attachment__container--good {
border-left-color: #00c100;
}
+
&.attachment__container--warning {
border-left-color: #dede01;
}
+
&.attachment__container--danger {
border-left-color: #e40303;
}
}
+
.attachment__body {
float: left;
- width: 80%;
- padding-right: 5px;
overflow-x: auto;
overflow-y: hidden;
+ padding-right: 5px;
+ width: 80%;
+
&.attachment__body--no_thumb {
width: 100%;
}
}
+
.attachment__text p:last-of-type {
display: inline-block;
}
- .attachment__thumb-pretext {
- margin-left: 5px;
- }
+
.attachment__title {
+ font-size: 16px;
+ height: 22px;
+ line-height: 16px;
margin: 5px 0;
padding: 0;
- line-height: 16px;
- height: 22px;
- font-size: 16px;
+
a {
font-size: 16px;
}
}
+
.attachment__author-icon {
@include border-radius(50px);
+ height: 14px;
margin-right: 5px;
width: 14px;
- height: 14px;
}
+
.attachment__image {
- max-width: 100%;
margin-bottom: 1em;
+ max-width: 100%;
}
+
.attachment__thumb-container {
- width: 20%;
float: right;
+ width: 20%;
+
img {
max-height: 75px;
max-width: 100%;
}
}
+
.attachment___fields {
width: 100%;
+
.attachment___field-caption {
font-weight: 700;
}
+
.attachment___field p {
margin: 0;
}
@@ -992,6 +1036,6 @@ body.ios {
}
.permalink-popover {
- min-width: 320px;
margin-left: 50px !important;
+ min-width: 320px;
}
diff --git a/webapp/sass/layout/_sidebar-left.scss b/webapp/sass/layout/_sidebar-left.scss
index ece054a15..4c65d0a65 100644
--- a/webapp/sass/layout/_sidebar-left.scss
+++ b/webapp/sass/layout/_sidebar-left.scss
@@ -1,86 +1,97 @@
@charset 'UTF-8';
.sidebar--left {
+ background: #fafafa;
+ border-right: $border-gray;
+ height: 100%;
+ left: 0;
position: absolute;
width: 220px;
- left: 0;
- height: 100%;
- border-right: $border-gray;
- background: #fafafa;
z-index: 5;
&.sidebar--padded {
padding-top: 44px;
}
+
.dropdown-menu {
max-height: 400px;
+ max-width: 200px;
overflow-x: hidden;
overflow-y: auto;
- max-width: 200px;
width: 200px;
}
+
.search__form {
+ display: none;
margin: 0;
padding: 1em 1em 0;
- display: none;
}
+
.badge {
- background-color: $color--primary;
+ background-color: $primary-color;
position: absolute;
right: 10px;
top: 5px;
}
+
.status {
+ display: inline-block;
+ margin-right: 6px;
position: relative;
top: 1px;
- margin-right: 6px;
width: 12px;
- display: inline-block;
+
svg {
max-height: 14px;
}
+
i,
path,
ellipse {
@include opacity(.5);
+
&.online--icon,
&.away--icon {
@include opacity(1);
}
}
+
.fa-lock {
margin-left: 1px;
}
+
.fa-globe {
- top: -1px;
position: relative;
+ top: -1px;
}
}
+
.nav-pills__container {
+ -webkit-overflow-scrolling: touch;
height: calc(100% - 80px);
- position: relative;
overflow: auto;
- -webkit-overflow-scrolling: touch;
+ position: relative;
}
.nav-pills__unread-indicator {
- position: absolute;
- left: 0;
- right: 0;
- width: 72%;
- color: #fff;
- background: #2389d7;
@include border-radius(50px);
+ background: #2389d7;
+ color: #ffffff;
+ font-size: 13.5px;
+ left: 0;
margin: 0 auto;
padding: 3px 0 4px;
- font-size: 13.5px;
+ position: absolute;
+ right: 0;
text-align: center;
+ width: 72%;
z-index: 1;
}
.nav-pills__unread-indicator-top {
top: 66px;
}
+
.nav-pills__unread-indicator-bottom {
bottom: 20px;
}
@@ -91,71 +102,83 @@
margin: 0;
}
}
+
li {
> h4 {
+ color: #aaaaaa;
font-size: 1em;
- text-transform: uppercase;
- margin: 1.1em 0 .5em;
font-weight: 400;
- color: #aaa;
letter-spacing: -.3px;
+ margin: 1.1em 0 .5em;
padding: 0 10px 0 15px;
+ text-transform: uppercase;
}
+
> a {
- padding: 3px 10px 3px 25px;
- line-height: 1.5;
border-radius: 0;
- white-space: nowrap;
+ line-height: 1.5;
overflow: hidden;
+ padding: 3px 10px 3px 25px;
text-overflow: ellipsis;
+ white-space: nowrap;
+
&.has-badge {
padding-right: 30px;
}
+
&.has-close {
padding-right: 30px;
+
&:hover {
.btn-close {
- display: block;
@include opacity(.8);
+ display: block;
}
}
+
.btn-close {
+ @include opacity(0);
+ display: none;
font-family: 'Open Sans', sans-serif;
+ font-size: 20px;
+ font-weight: 600;
position: absolute;
right: 15px;
top: -1px;
- font-size: 20px;
- font-weight: 600;
- @include opacity(0);
- display: none;
+
&:hover {
@include opacity(1);
}
}
}
+
&.nav-more {
text-decoration: underline;
}
+
&.unread-title {
font-weight: 600;
}
+
}
+
&.active {
a {
&:before {
+ background: $black;
content: '';
+ height: 100%;
+ left: 0;
position: absolute;
top: 0;
- left: 0;
width: 5px;
- height: 100%;
- background: #000;
}
}
+
a,
a:hover,
a:focus {
- background-color: rgba(black, .1);
+ @include alpha-property(background-color, $black, .1);
border-radius: 0;
font-weight: 400;
position: relative;
@@ -163,35 +186,37 @@
}
}
}
+
.modal-title {
line-height: 2em;
}
.add-channel-btn {
+ color: #aaaaaa;
float: right;
- outline: none;
+ font-size: 22px;
+ font-weight: 700;
+ line-height: 18px;
margin: -2px 0 0 0;
- color: #aaa;
+ outline: none;
padding: 0 5px;
text-decoration: none;
- font-size: 22px;
- line-height: 18px;
- font-weight: 700;
+
&:hover {
- color: #666;
+ color: #666666;
}
}
}
.channel-loading-gif {
height: 15px;
- width: 15px;
margin-top: 2px;
+ width: 15px;
}
.join-channel-loading-gif {
- margin-top: 5px;
- margin-left: 10px;
height: 25px;
+ margin-left: 10px;
+ margin-top: 5px;
width: 25px;
}
diff --git a/webapp/sass/layout/_sidebar-menu.scss b/webapp/sass/layout/_sidebar-menu.scss
index 9438491f9..0cf60f328 100644
--- a/webapp/sass/layout/_sidebar-menu.scss
+++ b/webapp/sass/layout/_sidebar-menu.scss
@@ -1,69 +1,79 @@
@charset 'UTF-8';
.sidebar--menu {
- position: absolute;
- width: 220px;
- right: 0;
- height: 100%;
- border-right: $border-gray;
- padding: 0 0 2em 0;
background: #fafafa;
+ border-right: $border-gray;
display: none;
+ height: 100%;
+ padding: 0 0 2em;
+ position: absolute;
+ right: 0;
+ width: 220px;
+
.nav-pills__container {
padding-top: 5px;
}
+
.team__header {
+ @include legacy-pie-clearfix;
display: none;
padding: 0 15px;
- @include legacy-pie-clearfix;
+
a {
- color: #fff;
+ color: $white;
}
+
.navbar-right {
font-size: .85em;
margin: 16px -5px 0;
+
.dropdown-toggle {
padding: 0 10px;
}
+
.dropdown-menu {
li a {
- padding: 3 20px;
color: #555;
+ padding: 3 20px;
}
}
+
.dropdown__icon {
- width: 4px;
- height: 16px;
@include background-size(100% 100%);
display: inline-block;
+ height: 16px;
+ width: 4px;
}
}
+
.team__name {
float: left;
- line-height: 50px;
- font-weight: 600;
font-size: 1.2em;
+ font-weight: 600;
+ line-height: 50px;
max-width: 80%;
overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
text-decoration: none;
+ text-overflow: ellipsis;
+ white-space: nowrap;
}
}
+
.nav {
> li {
> a {
- font-size: 15px;
background: none !important;
color: inherit;
+ font-size: 15px;
line-height: 40px;
padding: 0 15px;
+
.fa,
.glyphicon {
- width: 25px;
- text-align: center;
left: -5px;
position: relative;
+ text-align: center;
+ width: 25px;
}
}
}
diff --git a/webapp/sass/layout/_sidebar-right.scss b/webapp/sass/layout/_sidebar-right.scss
index e1a7d7641..a7b631047 100644
--- a/webapp/sass/layout/_sidebar-right.scss
+++ b/webapp/sass/layout/_sidebar-right.scss
@@ -1,13 +1,13 @@
@charset 'UTF-8';
.sidebar--right {
- position: fixed;
- width: 400px;
+ @include translateX(400px);
+ background: $white;
height: 100%;
- right: 0px;
padding: 0;
- background: #fff;
- @include translateX(400px);
+ position: fixed;
+ right: 0;
+ width: 400px;
.post-body {
img {
@@ -26,39 +26,39 @@
}
.sidebar--right__content {
- height: 100%;
@include display-flex;
@include flex-direction(column);
+ height: 100%;
}
.sidebar--right__back {
- color: inherit;
@include opacity(.8);
- width: 30px;
- text-align: center;
- margin: 0 0 0 -14px;
- font-size: 13px;
+ color: inherit;
display: inline-block;
+ font-size: 13px;
+ margin: 0 0 0 -14px;
+ text-align: center;
+ width: 30px;
}
.sidebar-right__body {
+ @include border-radius(2px 0 0 0);
+ @include display-flex;
@include flex(1 1 auto);
+ @include flex-direction(column);
border-left: $border-gray;
border-top: $border-gray;
- @include display-flex;
- @include flex-direction(column);
height: calc(100% - 56px);
- @include border-radius(2px 0 0 0);
}
.sidebar__overlay {
- width: 100%;
- height: 100%;
- background-color: yellow;
@include opacity(.1);
+ background-color: $yellow;
+ height: 100%;
+ pointer-events: none;
position: absolute;
+ width: 100%;
z-index: 5;
- pointer-events: none;
}
.input-group {
@@ -66,17 +66,17 @@
}
.sidebar--right__close {
- margin: 11px 0 0 0;
- width: 22px;
- height: 22px;
- opacity: .5;
- font-size: 22px;
- line-height: 0;
+ @include single-transition(all, .2s, ease-in);
background: none;
+ border: none;
float: right;
+ font-size: 22px;
+ height: 22px;
+ line-height: 0;
+ margin: 11px 0 0;
+ opacity: .5;
outline: none;
- border: none;
- @include single-transition(all, .2s, ease-in);
+ width: 22px;
&:hover,
&:active {
@@ -90,14 +90,14 @@
}
.sidebar--right__header {
- font-size: 1em;
- text-transform: uppercase;
+ @include flex(0 0 44px);
+ border-bottom: $border-gray;
color: inherit;
+ font-size: 1em;
height: 44px;
- padding: 0 1em;
line-height: 44px;
- @include flex(0 0 44px);
- border-bottom: $border-gray;
+ padding: 0 1em;
+ text-transform: uppercase;
}
.sidebar--right__subheader {
diff --git a/webapp/sass/layout/_webhooks.scss b/webapp/sass/layout/_webhooks.scss
index d6e367218..ffd8dd7dc 100644
--- a/webapp/sass/layout/_webhooks.scss
+++ b/webapp/sass/layout/_webhooks.scss
@@ -1,11 +1,11 @@
@charset 'UTF-8';
.webhooks__container {
- background: rgba(black, .1);
- border: 1px solid;
@include border-radius(3px);
- padding: 0 13px 15px;
+ @include alpha-property(background, $black, .1);
+ border: 1px solid;
margin-top: 10px;
+ padding: 0 13px 15px;
}
.webhook__item {
@@ -19,16 +19,16 @@
}
.webhook__remove {
- position: absolute;
- right: -7px;
- top: 8px;
- width: 30px;
- height: 30px;
+ color: #e05f5d;
font-size: 22px;
font-weight: bold;
+ height: 30px;
+ position: absolute;
+ right: -7px;
text-align: center;
text-decoration: none;
- color: #e05f5d;
+ top: 8px;
+ width: 30px;
}
.webhook__url {
diff --git a/webapp/sass/responsive/_desktop.scss b/webapp/sass/responsive/_desktop.scss
index dcabb807f..ccd6f0226 100644
--- a/webapp/sass/responsive/_desktop.scss
+++ b/webapp/sass/responsive/_desktop.scss
@@ -32,21 +32,23 @@
.tip-overlay {
&.tip-overlay--chat {
margin: -10px 0 0 -10px;
+
.arrow {
- right: 15px;
left: auto;
+ right: 15px;
}
}
}
+
.inner-wrap {
&.move--left {
.file-overlay {
font-size: em(18px);
.overlay__circle {
- width: 300px;
height: 300px;
margin: -150px 0 0 -150px;
+ width: 300px;
}
.overlay__files {
@@ -62,4 +64,4 @@
.modal-lg {
width: 700px;
}
-} \ No newline at end of file
+}
diff --git a/webapp/sass/responsive/_mobile.scss b/webapp/sass/responsive/_mobile.scss
index 4a1397143..53ea6d329 100644
--- a/webapp/sass/responsive/_mobile.scss
+++ b/webapp/sass/responsive/_mobile.scss
@@ -519,7 +519,7 @@
.search-bar__container {
padding: 0;
@include flex(0 0 44px);
- background: $color--primary;
+ background: $primary-color;
color: #fff;
&.focused {
@@ -756,9 +756,11 @@
.app__content {
padding-top: 45px;
margin: 0;
+
.channel__wrap & {
padding-top: 45px;
}
+
#channel-header {
display: none;
}
@@ -775,11 +777,6 @@
.post-comments {
padding: 9px 21px 10px 10px !important;
}
-
- .post-image__column .post-image .file-playback__controls.stop,
- .image-wrapper > a .file-playback__controls.stop {
- @include opacity(1);
- }
}
@media screen and (max-width: 640px) {
diff --git a/webapp/sass/responsive/_tablet.scss b/webapp/sass/responsive/_tablet.scss
index 14641cfa5..0a725a558 100644
--- a/webapp/sass/responsive/_tablet.scss
+++ b/webapp/sass/responsive/_tablet.scss
@@ -2,9 +2,9 @@
@media screen and (max-width: 960px) {
.sidebar--right {
- z-index: 5;
- @include translateX(100%);
@include single-transition(all, .5s, ease);
+ @include translateX(100%);
+ z-index: 5;
&.move--left {
@include translateX(0);
@@ -32,4 +32,4 @@
.second-bar {
display: none;
}
-} \ No newline at end of file
+}
diff --git a/webapp/sass/routes/_access-history.scss b/webapp/sass/routes/_access-history.scss
index 7ede7b085..ea66f5f00 100644
--- a/webapp/sass/routes/_access-history.scss
+++ b/webapp/sass/routes/_access-history.scss
@@ -2,9 +2,9 @@
.access-history__table {
display: table;
- width: 100%;
- padding-top: 15px;
line-height: 1.6;
+ padding-top: 15px;
+ width: 100%;
&:first-child {
padding: 0;
@@ -16,8 +16,8 @@
}
.access__date {
- font-weight: 600;
font-size: 15px;
+ font-weight: 600;
width: 190px;
}
diff --git a/webapp/sass/routes/_activity-log.scss b/webapp/sass/routes/_activity-log.scss
index 6e8d0a925..d3400e29a 100644
--- a/webapp/sass/routes/_activity-log.scss
+++ b/webapp/sass/routes/_activity-log.scss
@@ -1,36 +1,27 @@
@charset 'UTF-8';
-@keyframes highlight {
- from {
- background: rgba(yellow, .5);
- }
- to {
- background: none;
- }
-}
-
.animation--highlight {
&:before {
- content: '';
animation: highlight 1.5s ease;
+ content: '';
+ height: 100%;
+ left: 0;
position: absolute;
top: 0;
- left: 0;
width: 100%;
- height: 100%;
}
}
.activity-log__table {
+ border-top: 1px solid $light-gray;
display: table;
- width: 100%;
line-height: 1.8;
- border-top: 1px solid #ddd;
padding: 15px 0;
+ width: 100%;
&:first-child {
- padding-top: 0;
border: none;
+ padding-top: 0;
}
> div {
@@ -49,6 +40,7 @@
.report__platform {
font-size: 15px;
font-weight: 600;
+
.fa {
margin-right: 6px;
}
diff --git a/webapp/sass/routes/_admin-console.scss b/webapp/sass/routes/_admin-console.scss
index aff1e8e8e..0b47e5ab6 100644
--- a/webapp/sass/routes/_admin-console.scss
+++ b/webapp/sass/routes/_admin-console.scss
@@ -15,26 +15,25 @@
}
h3 {
- font-weight: 600;
border-bottom: 1px solid #ddd;
- padding-bottom: .5em;
+ font-weight: 600;
margin: 1em 0;
+ padding-bottom: .5em;
}
.table {
- background: #fff;
+ background: $white;
}
.form-control {
- background-color: #fff;
+ background-color: $white;
border: 1px solid #ccc;
color: #555;
&:focus {
+ @include box-shadow(inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6));
border-color: #66afe9;
outline: 0;
- -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);
- box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);
}
}
@@ -42,7 +41,7 @@
color: #333;
&.btn-primary {
- background: #2389d7;
+ background: $primary-color;
&:hover,
&:focus,
@@ -53,7 +52,7 @@
}
.dropdown-menu {
- background: #fff;
+ background: $white;
border: 1px solid rgba(0,0,0,.15);
color: inherit;
}
@@ -86,38 +85,38 @@
> h4 {
background: #333;
- padding: 10px 10px;
margin: 1px 0 0;
+ padding: 10px;
.menu-icon--right {
- top: 6px;
right: 12px;
+ top: 6px;
}
}
}
.menu-icon--right {
- position: absolute;
- right: 10px;
- top: 3px;
font-size: 18px;
font-weight: 600;
- width: 20px;
height: 20px;
line-height: 20px;
+ position: absolute;
+ right: 10px;
text-align: center;
+ top: 3px;
+ width: 20px;
.fa {
+ color: $white;
font-size: 13px;
- right: -2px;
position: relative;
- color: #fff;
+ right: -2px;
}
}
&.nav__sub-menu {
+ @include font-smoothing(initial);
background: #111;
- -webkit-font-smoothing: auto;
&.padded {
padding: 5px 0;
@@ -125,30 +124,31 @@
li {
> a {
- font-size: 13px;
- padding: 5px 35px 5px 15px;
background: transparent;
color: #bbb;
+ font-size: 13px;
+ padding: 5px 35px 5px 15px;
&:hover {
- color: lighten($color--primary, 10);
+ color: lighten($primary-color, 10);
}
&.active {
- color: #fff;
+ color: $white;
font-weight: 600;
}
}
.nav-more {
- font-size: 13px;
- padding: 5px 15px;
background: transparent;
color: #bbb;
- display: block;
cursor: pointer;
+ display: block;
+ font-size: 13px;
+ padding: 5px 15px;
+
&:hover {
- color: lighten($color--primary, 10);
+ color: lighten($primary-color, 10);
}
}
}
@@ -166,13 +166,13 @@
}
.log__panel {
- overflow: scroll;
- width: 100%;
- height: 800px;
+ background-color: white;
border: 1px solid #ddd;
+ height: 800px;
margin-top: 10px;
+ overflow: scroll;
padding: 5px;
- background-color: white;
+ width: 100%;
}
.compliance__panel {
@@ -199,10 +199,10 @@
color: #333;
&.admin {
- overflow: auto;
background-color: #f1f1f1;
- padding: 0 20px 20px;
min-height: 600px;
+ overflow: auto;
+ padding: 0 20px 20px;
}
.wrapper--fixed {
@@ -213,9 +213,9 @@
margin-top: 40px;
.control-label {
- text-align: left;
- padding-right: 0;
font-weight: 600;
+ padding-right: 0;
+ text-align: left;
}
.form-group {
@@ -223,22 +223,25 @@
}
.file__upload {
- position: relative;
- margin: 0 10px 10px 0;
display: inline-block;
+ margin: 0 10px 10px 0;
+ position: relative;
input {
- position: absolute;
@include opacity(0);
- width: 100%;
height: 100%;
- z-index: 5;
- top: 0;
left: 0;
+ position: absolute;
+ top: 0;
+ width: 100%;
+ z-index: 5;
}
}
.help-text {
+ color: #777;
+ margin: 10px 0 0 15px;
+
&.no-margin {
margin: 0;
}
@@ -248,9 +251,6 @@
padding-left: 23px;
}
- margin: 10px 0 0 15px;
- color: #777;
-
.help-link {
margin-right: 5px;
}
@@ -262,10 +262,10 @@
.alert {
display: inline-block;
- padding: 5px 7px;
margin: 1em 0 0;
- top: 1px;
+ padding: 5px 7px;
position: relative;
+ top: 1px;
.fa {
margin-right: 5px;
@@ -274,11 +274,11 @@
}
.banner {
- background: #fff;
+ background: $white;
border: 1px solid #ddd;
- padding: .7em 1.5em;
font-size: .95em;
margin: 2em 0;
+ padding: .7em 1.5em;
.banner__heading {
font-size: 1.5em;
@@ -295,19 +295,19 @@
.popover {
border-radius: 3px;
- width: 100%;
font-size: .95em;
+ width: 100%;
}
.panel {
- border: none;
background-color: transparent;
+ border: none;
}
.panel-default {
> .panel-heading {
- padding: 10px 0;
background-color: transparent;
+ padding: 10px 0;
}
.panel-body {
@@ -324,9 +324,9 @@
line-height: 1.5;
a {
- text-decoration: none;
- display: block;
@include clearfix;
+ display: block;
+ text-decoration: none;
&.collapsed {
.fa-minus {
@@ -339,10 +339,10 @@
}
.fa {
- font-size: 18px;
+ color: #aaa;
float: right;
+ font-size: 18px;
margin-top: 8px;
- color: #aaa;
}
.fa-plus {
diff --git a/webapp/sass/routes/_docs.scss b/webapp/sass/routes/_docs.scss
index 24e96772b..9a205f8a2 100644
--- a/webapp/sass/routes/_docs.scss
+++ b/webapp/sass/routes/_docs.scss
@@ -5,15 +5,15 @@
padding-bottom: 20px;
> div {
- width: 1170px;
margin: 0 auto;
- padding: 0 15px;
max-width: 100%;
+ padding: 0 15px;
+ width: 1170px;
}
h1.markdown__heading {
border-bottom: 1px solid #ddd;
- padding-bottom: 1rem;
margin: 1em 0 1em;
+ padding-bottom: 1rem;
}
}
diff --git a/webapp/sass/routes/_error-page.scss b/webapp/sass/routes/_error-page.scss
index 8cd0716ca..438e60554 100644
--- a/webapp/sass/routes/_error-page.scss
+++ b/webapp/sass/routes/_error-page.scss
@@ -8,23 +8,23 @@ body {
}
.error__container {
- max-width: 800px;
- margin: 0 auto;
+ color: #555;
display: table-cell;
- vertical-align: top;
+ margin: 0 auto;
+ max-width: 800px;
padding: 5em 0;
text-align: left;
- color: #555;
+ vertical-align: top;
}
.error__icon {
- font-size: 4em;
color: #ccc;
+ font-size: 4em;
}
h2 {
- font-weight: 600;
font-size: 1.5em;
+ font-weight: 600;
margin: .8em 0 .5em;
}
diff --git a/webapp/sass/routes/_loading.scss b/webapp/sass/routes/_loading.scss
index 8d6552957..39f37b1b3 100644
--- a/webapp/sass/routes/_loading.scss
+++ b/webapp/sass/routes/_loading.scss
@@ -4,32 +4,32 @@
.loading-screen {
display: table;
- width: 100%;
height: 100%;
padding: 60px;
text-align: center;
+ width: 100%;
.loading__content {
display: table-cell;
- vertical-align: middle;
font-size: 0;
+ vertical-align: middle;
h3 {
+ display: inline-block;
font-size: 16px;
font-weight: 400;
- margin: 0 .2em 0;
- display: inline-block;
+ margin: 0 .2em;
}
.round {
- background-color: #444;
- width: 4px;
- height: 4px;
+ @include animation(move .75s infinite linear);
+ @include border-radius(10px);
+ background-color: #444444;
display: inline-block;
+ height: 4px;
margin: 0 2px;
opacity: .1;
- @include border-radius(10px);
- @include animation(move .75s infinite linear);
+ width: 4px;
}
@for $i from 1 through 3 {
@@ -42,6 +42,7 @@
from {
opacity: 1;
}
+
to {
opacity: .1;
}
diff --git a/webapp/sass/routes/_settings.scss b/webapp/sass/routes/_settings.scss
index 3c735be3c..1c3f2e308 100644
--- a/webapp/sass/routes/_settings.scss
+++ b/webapp/sass/routes/_settings.scss
@@ -2,41 +2,47 @@
.user-settings {
min-height: 300px;
+
.table-responsive {
- max-width: 560px;
max-height: 300px;
+ max-width: 560px;
}
}
.modal {
.settings-modal {
width: 800px;
+
.modal-back {
- width: 50px;
- height: 40px;
- top: 12px;
font-size: 27px;
font-weight: normal;
+ height: 40px;
+ left: 0;
line-height: 32px;
position: absolute;
- left: 0;
text-align: center;
+ top: 12px;
+ width: 50px;
+
.fa {
+ height: 100%;
+ left: 0;
line-height: inherit;
position: absolute;
width: 100%;
- height: 100%;
- left: 0;
}
}
+
.modal-body {
- padding: 0;
margin: 0 auto;
min-height: calc(100% - 62px);
+ padding: 0;
}
+
li {
list-style: none;
}
+
label {
font-weight: 600;
}
@@ -44,87 +50,110 @@
.no-padding--left {
padding-left: 0;
}
+
.padding-top {
padding-top: 7px;
+
&.x2 {
padding-top: 14px;
}
+
&.x3 {
padding-top: 21px;
}
}
+
.padding-bottom {
padding-bottom: 7px;
+
&.x2 {
padding-bottom: 14px;
}
+
&.x3 {
padding-bottom: 21px;
}
+
.control-label {
font-weight: 600;
+
&.text-left {
text-align: left;
}
}
}
+
.profile-img {
- width: 128px;
height: 128px;
+ width: 128px;
}
+
.settings-table {
- max-width: 1000px;
- margin: 0 auto;
display: table;
+ margin: 0 auto;
+ max-width: 1000px;
table-layout: fixed;
width: 100%;
+
> div {
display: table-cell;
vertical-align: top;
}
+
.nav {
position: fixed;
width: 179px;
+
&.position--top {
top: 57px;
}
}
+
.security-links {
margin-right: 20px;
+
.fa {
margin-right: 6px;
}
}
+
.settings-links {
width: 180px;
}
+
.settings-content {
- padding: 0px 20px 30px;
+ padding: 0 20px 30px;
+
.modal-header {
display: none;
}
+
.section-min {
padding: 1em 0;
margin-bottom: 0;
cursor: pointer;
position: relative;
@include clearfix;
+
&:hover {
background: #f9f9f9;
}
+
&:hover .fa {
display: inline-block;
}
+
&:hover .section-edit {
text-decoration: underline;
}
}
.section-max {
- background: rgba(black, .05);
- padding: 1em 0 1.3em;
- margin-bottom: 0;
@include clearfix;
+ @include alpha-property(background, $black, .05);
+ margin-bottom: 0;
+ padding: 1em 0 1.3em;
+
.section-title {
margin-bottom: 10px;
}
@@ -136,50 +165,54 @@
padding: 4px 5px;
width: 40px;
}
+
img {
border: 1px solid rgba(black, .15);
width: 29px;
}
}
+
.group--code {
+
select {
+ @include appearance(none);
+ appearance: none;
padding-right: 25px;
+
+ &::ms-expand {
+ display: none;
+ }
}
- select::-ms-expand {
- display: none;
- }
+
&:before {
- pointer-events: none;
- position: absolute;
- top: 11px;
- right: 50px;
- z-index: 5;
+ @include font-smoothing;
content: '\f0d7';
display: inline-block;
font: normal normal normal 14px/1 FontAwesome;
- font-size: inherit;
+ pointer-events: none;
+ position: absolute;
+ right: 50px;
text-rendering: auto;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- }
- select {
- -moz-appearance: none;
- -webkit-appearance: none;
- appearance: none;
+ top: 11px;
+ z-index: 5;
}
}
+
.premade-themes {
margin-bottom: 10px;
+
.theme-label {
font-weight: 400;
margin-top: 5px;
}
+
img {
border: 3px solid transparent;
}
+
.active {
img {
- border-color: $color--primary;
+ border-color: $primary-color;
}
}
}
@@ -197,12 +230,12 @@
}
.theme-elements__header {
- margin: 10px 20px 0px 0;
border-bottom: 1px solid #ccc;
- padding: 5px 0 10px;
+ cursor: pointer;
font-size: em(13.5px);
font-weight: 600;
- cursor: pointer;
+ margin: 10px 20px 0 0;
+ padding: 5px 0 10px;
.fa-minus {
display: none;
@@ -212,39 +245,41 @@
.fa-minus {
display: inline-block;
}
+
.fa-plus {
display: none;
}
}
.header__icon {
- float: right;
@include opacity(.5);
+ float: right;
}
}
.theme-elements__body {
- padding-top: 5px;
- display: none;
+ @include border-radius(0 0 3px 3px);
@include legacy-pie-clearfix;
- background: rgba(255, 255, 255, .05);
- padding: 20px 0 0 20px;
+ @include alpha-property(background-color, $white, .05);
+ display: none;
margin: 0 20px 0 0;
- @include border-radius(0 0 3px 3px);
+ padding: 20px 0 0 20px;
}
.custom-label {
- white-space: nowrap;
- font-weight: normal;
font-size: 12px;
- width: 100%;
+ font-weight: normal;
+ margin-bottom: 0;
overflow: hidden;
text-overflow: ellipsis;
- margin-bottom: 0;
+ white-space: nowrap;
+ width: 100%;
}
+
.input-group-addon {
background: transparent;
}
+
.radio {
label {
font-weight: 600;
@@ -253,32 +288,33 @@
}
.section-title {
- margin-bottom: 5px;
font-weight: 600;
+ margin-bottom: 5px;
padding-right: 50px;
}
.section-edit {
- text-align: right;
margin-bottom: 5px;
+ text-align: right;
+
.fa {
- margin-right: 5px;
- font-size: 12px;
@include opacity(.5);
display: none;
+ font-size: 12px;
+ margin-right: 5px;
&.fa-chevron-down {
- top: -1px;
margin-right: 0;
position: relative;
+ top: -1px;
}
}
}
.section-describe {
- @include opacity(.7);
- white-space: pre;
@include clearfix;
+ @include opacity(.7);
text-overflow: ellipsis;
+ white-space: pre;
}
.divider-dark {
@@ -290,8 +326,8 @@
}
.setting-list {
- padding: 0;
list-style-type: none;
+ padding: 0;
}
.setting-list__hint {
@@ -305,68 +341,77 @@
.setting-list-item {
margin-top: 7px;
}
+
.has-error {
color: #a94442;
}
.file-status {
+ color: #555;
font-size: 13px;
margin-top: 8px;
- color: #555;
}
.confirm-import {
- padding: 4px 10px;
margin: 10px 0;
+ padding: 4px 10px;
}
}
}
}
+
.nav-pills {
> li {
margin: 0;
+
a {
- padding: 8px 5px 8px 15px;
border-radius: 0;
color: #777;
+ padding: 8px 5px 8px 15px;
}
+
.glyphicon {
- width: 25px;
top: 2px;
+ width: 25px;
}
+
&:hover {
a {
- background-color: rgba(black, .1);
+ @include alpha-property(background-color, $black, .1);
}
}
+
&.active {
a {
- color: #111;
background-color: #e1e1e1;
+ color: #111;
+
&:before {
+ background: $black;
content: '';
+ height: 100%;
+ left: 0;
position: absolute;
top: 0;
- left: 0;
width: 5px;
- height: 100%;
- background: #000;
}
}
+
a,
a:hover,
a:focus {
- background-color: rgba(black, .1);
+ @include alpha-property(background-color, $black, .1);
border-radius: 0;
font-weight: 400;
- position: relative;
- white-space: nowrap;
overflow: hidden;
+ position: relative;
text-overflow: ellipsis;
+ white-space: nowrap;
}
}
}
}
+
h3 {
font-size: em(20px);
}
@@ -391,13 +436,15 @@
.member-div {
border-bottom: 1px solid lightgrey;
- position: relative;
- padding: 2px;
margin: 0;
+ padding: 2px;
+ position: relative;
width: 100%;
+
&:first-child {
border-top: 1px solid lightgrey;
}
+
.post-profile-img {
@include border-radius(50px);
margin-right: 8px;
@@ -407,14 +454,14 @@
.member-role,
.member-drop {
.fa {
- margin-right: 5px;
@include opacity(.5);
font-size: 12px;
+ margin-right: 5px;
}
.member-menu {
- top: -50%;
right: 110%;
+ top: -50%;
}
}
@@ -425,13 +472,13 @@
}
.member-menu {
- right: 0px;
left: auto;
+ right: 0;
}
.member-list {
- width: 100%;
overflow-x: visible;
+ width: 100%;
}
.member-page {
diff --git a/webapp/sass/routes/_signup.scss b/webapp/sass/routes/_signup.scss
index 53c59c222..09f8e4185 100644
--- a/webapp/sass/routes/_signup.scss
+++ b/webapp/sass/routes/_signup.scss
@@ -1,19 +1,19 @@
@charset 'UTF-8';
.signup-header {
- width: 100%;
+ background: $bg--gray;
line-height: 33px;
padding: 0 1em .2em;
- background: $bg--gray;
+ width: 100%;
.fa {
margin-right: 5px;
}
}
.signup-team__container {
- padding: 100px 0px 50px 0px;
- max-width: 380px;
margin: 0 auto;
+ max-width: 380px;
+ padding: 100px 0 50px;
position: relative;
&.padding--less {
@@ -21,7 +21,7 @@
}
.form-control:focus {
- @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6));
+ @include box-shadow(inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6));
}
h1,
@@ -39,16 +39,16 @@
}
h2 {
+ font-size: em(30px);
font-weight: 600;
- margin-bottom: .8em;
letter-spacing: -.5px;
- font-size: em(30px);
+ margin-bottom: .8em;
}
h3 {
- font-weight: 600;
- margin: 0 0 1.3em 0;
font-size: 1.5em;
+ font-weight: 600;
+ margin: 0 0 1.3em;
}
h4 {
@@ -66,7 +66,7 @@
}
p {
- color: #555;
+ color: #555555;
line-height: 1.5;
margin-bottom: 1em;
}
@@ -81,32 +81,32 @@
}
.form-control {
- text-align: left;
display: table-cell;
+ text-align: left;
width: 100%;
}
.input-group-addon {
- text-align: left;
- width: 50%;
display: table-cell;
overflow: hidden;
+ text-align: left;
text-overflow: ellipsis;
+ width: 50%;
}
}
}
.inner__content {
- padding: 0 1rem;
margin: 30px 0 20px;
+ padding: 0 1rem;
}
.block--gray {
+ @include border-radius(3px);
background: #f2f2f2;
display: inline-block;
- padding: .85em 1.2em;
font-weight: 600;
- @include border-radius(3px);
+ padding: .85em 1.2em;
}
form {
@@ -114,32 +114,32 @@
}
.signup-team-confirm__container {
- padding: 100px 0px 100px 0px;
+ padding: 100px 0;
}
.signup-team-logo {
display: none;
+ margin: 0 0 2em;
width: 210px;
- margin: 0 0 2em 0;
}
.signup-team-login {
- padding-bottom: 10px;
font-weight: 600;
+ padding-bottom: 10px;
}
.signup-team__name {
- margin: .5em 0 0;
font-size: 2.2em;
font-weight: 600;
+ margin: .5em 0 0;
padding-left: 1rem;
}
.signup-team__subdomain {
- margin: .2em 0 1.2em;
font-size: 1.5em;
- padding-left: 1rem;
font-weight: 300;
+ margin: .2em 0 1.2em;
+ padding-left: 1rem;
text-transform: uppercase;
}
@@ -148,21 +148,21 @@
}
.or__container {
+ background: #dddddd;
height: 1px;
- background: #ddd;
- text-align: left;
margin: 2em 0;
+ text-align: left;
span {
- width: 40px;
- top: -10px;
- position: relative;
+ background: #ffffff;
+ display: inline-block;
font-size: 1.14286em;
- line-height: 20px;
font-weight: 600;
- background: #fff;
- display: inline-block;
+ line-height: 20px;
+ position: relative;
text-align: center;
+ top: -10px;
+ width: 40px;
}
}
@@ -177,9 +177,9 @@
.btn {
font-size: 1em;
- padding: em(7px) em(15px);
font-weight: 600;
margin-right: 5px;
+ padding: em(7px) em(15px);
.fa {
font-size: 17px;
@@ -187,29 +187,29 @@
}
.icon {
- width: 18px;
- height: 18px;
- margin-right: 8px;
@include background-size(100% 100%);
display: inline-block;
+ height: 18px;
+ margin-right: 8px;
+ width: 18px;
}
&.btn-custom-login {
+ @include border-radius(2px);
+ color: $white;
display: block;
- min-width: 200px;
- width: 200px;
- padding: 0 1em;
- margin: 1em 1rem;
height: 40px;
line-height: 34px;
- color: #fff;
- @include border-radius(2px);
+ margin: 1em 1rem;
+ min-width: 200px;
+ padding: 0 1em;
+ width: 200px;
&.gitlab {
- background: #548;
+ background: #554488;
&:hover {
- background: darken(#548, 10%);
+ background: darken(#554488, 10%);
}
span {
@@ -250,10 +250,10 @@
}
&.email {
- background: #2389d7;
+ background: $primary-color;
&:hover {
- background: darken(#2389d7, 10%);
+ background: $primary-color--hover;
}
span {
@@ -269,15 +269,15 @@
}
&.btn-default {
- color: #444;
+ color: #444444;
}
.glyphicon {
&.glyphicon-ok,
&.glyphicon-refresh {
- margin-right: .5em;
- left: -2px;
font-size: .9em;
+ left: -2px;
+ margin-right: .5em;
}
&.glyphicon-chevron-right {
@@ -296,28 +296,29 @@
.has-error {
.control-label {
- background: #f2f2f2;
- padding: .7em 1em;
@include border-radius(3px);
- margin: 1em 0 0;
+ background: #f2f2f2;
+ color: #999999;
font-size: 14px;
font-weight: normal;
- color: #999;
+ margin: 1em 0 0;
+ padding: .7em 1em;
width: 100%;
&:before {
- @extend .fa;
+ @extend %font-awesome;
+ color: #aaaaaa;
content: '\f071';
margin-right: 4px;
- color: #aaa;
}
}
}
.reset-form {
@include border-radius(3px);
- position: relative;
font-size: .95em;
+ position: relative;
+
p {
color: inherit;
}
@@ -363,12 +364,12 @@
.black,
&.black {
- color: #000;
+ color: #000000;
}
}
.color--light {
- color: #777;
+ color: #777777;
}
.margin--extra {
@@ -381,9 +382,10 @@
}
.signup-team-all {
- margin: 0 0 20px;
- border: 1px solid #ddd;
@include border-radius(2px);
+ border: 1px solid #dddddd;
+ margin: 0 0 20px;
+
.signup-team-dir {
background: #fafafa;
border-top: 1px solid #d5d5d5;
@@ -395,25 +397,25 @@
a {
color: inherit;
display: block;
- padding: 0 15px;
- line-height: 3.5em;
- height: 3.5em;
font-size: 1.1em;
+ height: 3.5em;
+ line-height: 3.5em;
+ padding: 0 15px;
}
}
.signup-team-dir__name {
- white-space: nowrap;
float: left;
overflow: hidden;
text-overflow: ellipsis;
+ white-space: nowrap;
width: 90%;
}
.signup-team-dir__arrow {
+ color: #999999;
float: right;
font-size: .9em;
- color: #999;
line-height: 3.5em;
}
}
diff --git a/webapp/sass/routes/_statistics.scss b/webapp/sass/routes/_statistics.scss
index b48c137c3..797bc480b 100644
--- a/webapp/sass/routes/_statistics.scss
+++ b/webapp/sass/routes/_statistics.scss
@@ -2,45 +2,45 @@
.team_statistics {
.total-count {
+ @include border-radius(3px);
+ background: $white;
+ border: 1px solid $light-gray;
margin: 1em 0;
text-align: center;
- background: #fff;
- border: 1px solid #ddd;
width: 100%;
- @include border-radius(3px);
.title {
+ border-bottom: 1px solid $light-gray;
+ font-size: 13px;
font-weight: 400;
padding: 7px 10px;
- border-bottom: 1px solid #ddd;
text-align: left;
- font-size: 13px;
.fa {
+ color: #555555;
float: right;
- margin: 0px 0 0;
- color: #555;
font-size: 16px;
+ margin: 0;
}
}
.content {
+ color: #555555;
font-size: 30px;
font-weight: 600;
- color: #555;
- padding: .3em 0 .35em;
overflow: auto;
+ padding: .3em 0 .35em;
}
}
.total-count--day {
- width: 760px;
- height: 275px;
- border: 1px solid #ddd;
- padding: 5px 10px 10px 10px;
- margin: 10px 10px 10px 10px;
- background: #fff;
+ background: $white;
+ border: 1px solid $light-gray;
clear: both;
+ height: 275px;
+ margin: 10px;
+ padding: 5px 10px 10px;
+ width: 760px;
> div {
font-size: 18px;
@@ -50,8 +50,8 @@
.recent-active-users {
table {
- width: 100%;
table-layout: fixed;
+ width: 100%;
}
.content {
@@ -68,14 +68,15 @@
}
td {
- font-weight: 400;
- white-space: nowrap;
- text-overflow: ellipsis;
+ @include clearfix;
+ border-left: 1px solid $light-gray;
+ border-top: 1px solid $light-gray;
font-size: 13px;
- border-left: 1px solid #ddd;
- border-top: 1px solid #ddd;
+ font-weight: 400;
padding: 5px 5px 6px;
- @include clearfix;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+
&:first-child {
border-left: none;
}
diff --git a/webapp/sass/utils/_animations.scss b/webapp/sass/utils/_animations.scss
index 767e30847..ffdbcb219 100644
--- a/webapp/sass/utils/_animations.scss
+++ b/webapp/sass/utils/_animations.scss
@@ -1,19 +1,21 @@
@charset 'UTF-8';
-@-webkit-keyframes spin2 {
+@keyframes spin {
from {
- -webkit-transform: rotate(0deg);
+ transform: scale(1) rotate(0deg);
}
+
to {
- -webkit-transform: rotate(360deg);
+ transform: scale(1) rotate(360deg);
}
}
-@keyframes spin {
+@keyframes highlight {
from {
- transform: scale(1) rotate(0deg);
+ @include alpha-property(background, $yellow, .5);
}
+
to {
- transform: scale(1) rotate(360deg);
+ background: none;
}
}
diff --git a/webapp/sass/utils/_functions.scss b/webapp/sass/utils/_functions.scss
index 9013920fa..baedd72c5 100644
--- a/webapp/sass/utils/_functions.scss
+++ b/webapp/sass/utils/_functions.scss
@@ -4,6 +4,20 @@
@return #{$pixels/$context}em
}
+@function alpha-color($color, $amount) {
+ @return rgba($color, $amount)
+}
+
%popover-box-shadow {
@include box-shadow(rgba(black, .175) 1px -3px 12px);
+}
+
+%font-awesome {
+ display: inline-block;
+ font: normal normal normal 14px/1 FontAwesome;
+ font-size: inherit;
+ text-rendering: auto;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ transform: translate(0, 0);
} \ No newline at end of file
diff --git a/webapp/sass/utils/_mixins.scss b/webapp/sass/utils/_mixins.scss
index 28723e1a5..6e4488fca 100644
--- a/webapp/sass/utils/_mixins.scss
+++ b/webapp/sass/utils/_mixins.scss
@@ -1,8 +1,29 @@
@charset 'UTF-8';
@mixin file-icon($path) {
- background: #fff url($path);
+ @include background-size(60px auto);
+ background-color: $white;
+ background-image: url($path);
background-position: center;
background-repeat: no-repeat;
- @include background-size(60px auto);
}
+
+@mixin alpha-property($property, $color, $opacity) {
+ #{$property}: rgba($color, $opacity);
+}
+
+@mixin font-smoothing($value: antialiased) {
+ @if $value == antialiased {
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ }
+ @else {
+ -webkit-font-smoothing: subpixel-antialiased;
+ -moz-osx-font-smoothing: auto;
+ }
+}
+
+@mixin cursor($value) {
+ cursor: -webkit-$value;
+ cursor: zoom-$value;
+} \ No newline at end of file
diff --git a/webapp/sass/utils/_module.scss b/webapp/sass/utils/_module.scss
index e7f0c0c46..5dddcaef7 100644
--- a/webapp/sass/utils/_module.scss
+++ b/webapp/sass/utils/_module.scss
@@ -1,5 +1,5 @@
// Only for combining all the files in this folder
@import 'variables';
-@import 'animations';
@import 'functions';
@import 'mixins';
+@import 'animations';
diff --git a/webapp/sass/utils/_variables.scss b/webapp/sass/utils/_variables.scss
index 065c37a17..345ab11e8 100644
--- a/webapp/sass/utils/_variables.scss
+++ b/webapp/sass/utils/_variables.scss
@@ -1,10 +1,16 @@
@charset 'UTF-8';
// Color Variables
-$color--primary: rgb(35, 137, 215);
-$color--primary--hover: darken($color--primary, 10%);
+$primary-color: rgb(35, 137, 215);
+$primary-color--hover: darken($primary-color, 10%);
$bg--gray: rgb(245, 245, 245);
-$bg--white: rgb(255, 255, 255);
+$white: rgb(255, 255, 255);
+$black: rgb(0, 0, 0);
+$red: rgb(229, 101, 101);
+$yellow: rgb(255, 255, 0);
+$light-gray: rgba(0, 0, 0, .06);
+$gray: rgba(0, 0, 0, .3);
+$dark-gray: rgba(0, 0, 0, .5);
// Page Variables
$border-gray: 1px solid #ddd;
diff --git a/webapp/utils/async_client.jsx b/webapp/utils/async_client.jsx
index d3f91bb0e..2392b50b9 100644
--- a/webapp/utils/async_client.jsx
+++ b/webapp/utils/async_client.jsx
@@ -781,12 +781,12 @@ export function savePreferences(preferences, success, error) {
);
}
-export function getSuggestedCommands(command, suggestionId, component) {
- client.listCommands(
+export function getSuggestedCommands(command, channelId, suggestionId, component) {
+ client.listCommands({command: command, channelId: channelId},
(data) => {
var matches = [];
data.forEach((cmd) => {
- if (('/' + cmd.trigger).indexOf(command) === 0) {
+ if (('/' + cmd.trigger).indexOf(command) === 0 || cmd.external_management) {
let s = '/' + cmd.trigger;
let hint = '';
if (cmd.auto_complete_hint && cmd.auto_complete_hint.length !== 0) {
diff --git a/webapp/utils/client.jsx b/webapp/utils/client.jsx
index e29cf71d3..69bda4303 100644
--- a/webapp/utils/client.jsx
+++ b/webapp/utils/client.jsx
@@ -1031,12 +1031,13 @@ export function regenCommandToken(data, success, error) {
});
}
-export function listCommands(success, error) {
+export function listCommands(data, success, error) {
$.ajax({
url: '/api/v1/commands/list',
dataType: 'json',
contentType: 'application/json',
- type: 'GET',
+ type: 'POST',
+ data: JSON.stringify(data),
success,
error: function onError(xhr, status, err) {
var e = handleError('listCommands', xhr, status, err);
diff --git a/webapp/utils/constants.jsx b/webapp/utils/constants.jsx
index 0f7c9857d..4ee934e11 100644
--- a/webapp/utils/constants.jsx
+++ b/webapp/utils/constants.jsx
@@ -145,7 +145,7 @@ export default {
PRESENTATION_TYPES: ['ppt', 'pptx'],
SPREADSHEET_TYPES: ['xlsx', 'csv'],
WORD_TYPES: ['doc', 'docx'],
- CODE_TYPES: ['css', 'html', 'js', 'php', 'rb'],
+ CODE_TYPES: ['as', 'applescript', 'osascript', 'scpt', 'bash', 'sh', 'zsh', 'clj', 'boot', 'cl2', 'cljc', 'cljs', 'cljs.hl', 'cljscm', 'cljx', 'hic', 'coffee', '_coffee', 'cake', 'cjsx', 'cson', 'iced', 'cpp', 'c', 'cc', 'h', 'c++', 'h++', 'hpp', 'cs', 'csharp', 'css', 'd', 'di', 'dart', 'delphi', 'dpr', 'dfm', 'pas', 'pascal', 'freepascal', 'lazarus', 'lpr', 'lfm', 'diff', 'django', 'jinja', 'dockerfile', 'docker', 'erl', 'f90', 'f95', 'fsharp', 'fs', 'gcode', 'nc', 'go', 'groovy', 'handlebars', 'hbs', 'html.hbs', 'html.handlebars', 'hs', 'hx', 'java', 'jsp', 'js', 'jsx', 'json', 'jl', 'kt', 'ktm', 'kts', 'less', 'lisp', 'lua', 'mk', 'mak', 'md', 'mkdown', 'mkd', 'matlab', 'm', 'mm', 'objc', 'obj-c', 'ml', 'perl', 'pl', 'php', 'php3', 'php4', 'php5', 'php6', 'ps', 'ps1', 'pp', 'py', 'gyp', 'r', 'ruby', 'rb', 'gemspec', 'podspec', 'thor', 'irb', 'rs', 'scala', 'scm', 'sld', 'scss', 'st', 'sql', 'swift', 'tex', 'vbnet', 'vb', 'bas', 'vbs', 'v', 'veo', 'xml', 'html', 'xhtml', 'rss', 'atom', 'xsl', 'plist', 'yaml'],
PDF_TYPES: ['pdf'],
PATCH_TYPES: ['patch'],
ICON_FROM_TYPE: {
@@ -515,30 +515,64 @@ export default {
SPACE: 32,
TAB: 9
},
+ CODE_PREVIEW_MAX_FILE_SIZE: 500000, // 500 KB
HighlightedLanguages: {
- diff: 'Diff',
- apache: 'Apache',
- makefile: 'Makefile',
- http: 'HTTP',
- json: 'JSON',
- markdown: 'Markdown',
- javascript: 'JavaScript',
- css: 'CSS',
- nginx: 'nginx',
- objectivec: 'Objective-C',
- python: 'Python',
- xml: 'XML',
- perl: 'Perl',
- bash: 'Bash',
- php: 'PHP',
- coffeescript: 'CoffeeScript',
- cs: 'C#',
- cpp: 'C++',
- sql: 'SQL',
- go: 'Go',
- ruby: 'Ruby',
- java: 'Java',
- ini: 'ini'
+ actionscript: {name: 'ActionScript', extensions: ['as']},
+ applescript: {name: 'AppleScript', extensions: ['applescript', 'osascript', 'scpt']},
+ bash: {name: 'Bash', extensions: ['bash', 'sh', 'zsh']},
+ clojure: {name: 'Clojure', extensions: ['clj', 'boot', 'cl2', 'cljc', 'cljs', 'cljs.hl', 'cljscm', 'cljx', 'hic']},
+ coffeescript: {name: 'CoffeeScript', extensions: ['coffee', '_coffee', 'cake', 'cjsx', 'cson', 'iced']},
+ cpp: {name: 'C/C++', extensions: ['cpp', 'c', 'cc', 'h', 'c++', 'h++', 'hpp']},
+ cs: {name: 'C#', extensions: ['cs', 'csharp']},
+ css: {name: 'CSS', extensions: ['css']},
+ d: {name: 'D', extensions: ['d', 'di']},
+ dart: {name: 'Dart', extensions: ['dart']},
+ delphi: {name: 'Delphi', extensions: ['delphi', 'dpr', 'dfm', 'pas', 'pascal', 'freepascal', 'lazarus', 'lpr', 'lfm']},
+ diff: {name: 'Diff', extensions: ['diff', 'patch']},
+ django: {name: 'Django', extensions: ['django', 'jinja']},
+ dockerfile: {name: 'Dockerfile', extensions: ['dockerfile', 'docker']},
+ erlang: {name: 'Erlang', extensions: ['erl']},
+ fortran: {name: 'Fortran', extensions: ['f90', 'f95']},
+ fsharp: {name: 'F#', extensions: ['fsharp', 'fs']},
+ gcode: {name: 'G-Code', extensions: ['gcode', 'nc']},
+ go: {name: 'Go', extensions: ['go']},
+ groovy: {name: 'Groovy', extensions: ['groovy']},
+ handlebars: {name: 'Handlebars', extensions: ['handlebars', 'hbs', 'html.hbs', 'html.handlebars']},
+ haskell: {name: 'Haskell', extensions: ['hs']},
+ haxe: {name: 'Haxe', extensions: ['hx']},
+ java: {name: 'Java', extensions: ['java', 'jsp']},
+ javascript: {name: 'JavaScript', extensions: ['js', 'jsx']},
+ json: {name: 'JSON', extensions: ['json']},
+ julia: {name: 'Julia', extensions: ['jl']},
+ kotlin: {name: 'Kotlin', extensions: ['kt', 'ktm', 'kts']},
+ less: {name: 'Less', extensions: ['less']},
+ lisp: {name: 'Lisp', extensions: ['lisp']},
+ lua: {name: 'Lua', extensions: ['lua']},
+ makefile: {name: 'Makefile', extensions: ['mk', 'mak']},
+ markdown: {name: 'Markdown', extensions: ['md', 'mkdown', 'mkd']},
+ matlab: {name: 'Matlab', extensions: ['matlab', 'm']},
+ objectivec: {name: 'Objective C', extensions: ['mm', 'objc', 'obj-c']},
+ ocaml: {name: 'OCaml', extensions: ['ml']},
+ perl: {name: 'Perl', extensions: ['perl', 'pl']},
+ php: {name: 'PHP', extensions: ['php', 'php3', 'php4', 'php5', 'php6']},
+ powershell: {name: 'PowerShell', extensions: ['ps', 'ps1']},
+ puppet: {name: 'Puppet', extensions: ['pp']},
+ python: {name: 'Python', extensions: ['py', 'gyp']},
+ r: {name: 'R', extensions: ['r']},
+ ruby: {name: 'Ruby', extensions: ['ruby', 'rb', 'gemspec', 'podspec', 'thor', 'irb']},
+ rust: {name: 'Rust', extensions: ['rs']},
+ scala: {name: 'Scala', extensions: ['scala']},
+ scheme: {name: 'Scheme', extensions: ['scm', 'sld']},
+ scss: {name: 'SCSS', extensions: ['scss']},
+ smalltalk: {name: 'Smalltalk', extensions: ['st']},
+ sql: {name: 'SQL', extensions: ['sql']},
+ swift: {name: 'Swift', extensions: ['swift']},
+ tex: {name: 'TeX', extensions: ['tex']},
+ vbnet: {name: 'VB.Net', extensions: ['vbnet', 'vb', 'bas']},
+ vbscript: {name: 'VBScript', extensions: ['vbs']},
+ verilog: {name: 'Verilog', extensions: ['v', 'veo']},
+ xml: {name: 'HTML, XML', extensions: ['xml', 'html', 'xhtml', 'rss', 'atom', 'xsl', 'plist']},
+ yaml: {name: 'YAML', extensions: ['yaml']}
},
PostsViewJumpTypes: {
BOTTOM: 1,
@@ -561,6 +595,10 @@ export default {
EMBED_TOGGLE: {
label: 'embed_toggle',
description: 'Show toggle for all embed previews'
+ },
+ SLASHCMD_AUTOCMP: {
+ label: 'slashCmd_autocmp',
+ description: 'Enable external application to offer slash command autocomplete'
}
},
OVERLAY_TIME_DELAY: 400,
diff --git a/webapp/utils/markdown.jsx b/webapp/utils/markdown.jsx
index 635a39290..2cf1c5af0 100644
--- a/webapp/utils/markdown.jsx
+++ b/webapp/utils/markdown.jsx
@@ -1,65 +1,14 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import highlightJs from 'highlight.js/lib/highlight.js';
-import highlightJsDiff from 'highlight.js/lib/languages/diff.js';
-import highlightJsApache from 'highlight.js/lib/languages/apache.js';
-import highlightJsMakefile from 'highlight.js/lib/languages/makefile.js';
-import highlightJsHttp from 'highlight.js/lib/languages/http.js';
-import highlightJsJson from 'highlight.js/lib/languages/json.js';
-import highlightJsMarkdown from 'highlight.js/lib/languages/markdown.js';
-import highlightJsJavascript from 'highlight.js/lib/languages/javascript.js';
-import highlightJsCss from 'highlight.js/lib/languages/css.js';
-import highlightJsNginx from 'highlight.js/lib/languages/nginx.js';
-import highlightJsObjectivec from 'highlight.js/lib/languages/objectivec.js';
-import highlightJsPython from 'highlight.js/lib/languages/python.js';
-import highlightJsXml from 'highlight.js/lib/languages/xml.js';
-import highlightJsPerl from 'highlight.js/lib/languages/perl.js';
-import highlightJsBash from 'highlight.js/lib/languages/bash.js';
-import highlightJsPhp from 'highlight.js/lib/languages/php.js';
-import highlightJsCoffeescript from 'highlight.js/lib/languages/coffeescript.js';
-import highlightJsCs from 'highlight.js/lib/languages/cs.js';
-import highlightJsCpp from 'highlight.js/lib/languages/cpp.js';
-import highlightJsSql from 'highlight.js/lib/languages/sql.js';
-import highlightJsGo from 'highlight.js/lib/languages/go.js';
-import highlightJsRuby from 'highlight.js/lib/languages/ruby.js';
-import highlightJsJava from 'highlight.js/lib/languages/java.js';
-import highlightJsIni from 'highlight.js/lib/languages/ini.js';
-
-highlightJs.registerLanguage('diff', highlightJsDiff);
-highlightJs.registerLanguage('apache', highlightJsApache);
-highlightJs.registerLanguage('makefile', highlightJsMakefile);
-highlightJs.registerLanguage('http', highlightJsHttp);
-highlightJs.registerLanguage('json', highlightJsJson);
-highlightJs.registerLanguage('markdown', highlightJsMarkdown);
-highlightJs.registerLanguage('javascript', highlightJsJavascript);
-highlightJs.registerLanguage('css', highlightJsCss);
-highlightJs.registerLanguage('nginx', highlightJsNginx);
-highlightJs.registerLanguage('objectivec', highlightJsObjectivec);
-highlightJs.registerLanguage('python', highlightJsPython);
-highlightJs.registerLanguage('xml', highlightJsXml);
-highlightJs.registerLanguage('perl', highlightJsPerl);
-highlightJs.registerLanguage('bash', highlightJsBash);
-highlightJs.registerLanguage('php', highlightJsPhp);
-highlightJs.registerLanguage('coffeescript', highlightJsCoffeescript);
-highlightJs.registerLanguage('cs', highlightJsCs);
-highlightJs.registerLanguage('cpp', highlightJsCpp);
-highlightJs.registerLanguage('sql', highlightJsSql);
-highlightJs.registerLanguage('go', highlightJsGo);
-highlightJs.registerLanguage('ruby', highlightJsRuby);
-highlightJs.registerLanguage('java', highlightJsJava);
-highlightJs.registerLanguage('ini', highlightJsIni);
-
import * as TextFormatting from './text_formatting.jsx';
import * as Utils from './utils.jsx';
+import * as syntaxHightlighting from './syntax_hightlighting.jsx';
import marked from 'marked';
import katex from 'katex';
import 'katex/dist/katex.min.css';
-import Constants from 'utils/constants.jsx';
-const HighlightedLanguages = Constants.HighlightedLanguages;
-
function markdownImageLoaded(image) {
image.style.height = 'auto';
}
@@ -110,31 +59,11 @@ class MattermostMarkdownRenderer extends marked.Renderer {
this.formattingOptions = formattingOptions;
}
- code(code, language, escaped) {
+ code(code, language) {
let usedLanguage = language || '';
usedLanguage = usedLanguage.toLowerCase();
- // treat html as xml to prevent injection attacks
- if (usedLanguage === 'html') {
- usedLanguage = 'xml';
- }
-
- if (HighlightedLanguages[usedLanguage]) {
- const parsed = highlightJs.highlight(usedLanguage, code);
-
- return (
- '<div class="post-body--code">' +
- '<span class="post-body--code__language">' +
- HighlightedLanguages[usedLanguage] +
- '</span>' +
- '<pre>' +
- '<code class="hljs">' +
- parsed.value +
- '</code>' +
- '</pre>' +
- '</div>'
- );
- } else if (usedLanguage === 'tex' || usedLanguage === 'latex') {
+ if (usedLanguage === 'tex' || usedLanguage === 'latex') {
try {
const html = katex.renderToString(code, {throwOnError: false, displayMode: true});
@@ -144,13 +73,12 @@ class MattermostMarkdownRenderer extends marked.Renderer {
}
}
- return (
- '<pre>' +
- '<code class="hljs">' +
- (escaped ? code : TextFormatting.sanitizeHtml(code)) + '\n' +
- '</code>' +
- '</pre>'
- );
+ // treat html as xml to prevent injection attacks
+ if (usedLanguage === 'html') {
+ usedLanguage = 'xml';
+ }
+
+ return syntaxHightlighting.formatCode(usedLanguage, code);
}
codespan(text) {
diff --git a/webapp/utils/syntax_hightlighting.jsx b/webapp/utils/syntax_hightlighting.jsx
new file mode 100644
index 000000000..981ce6b35
--- /dev/null
+++ b/webapp/utils/syntax_hightlighting.jsx
@@ -0,0 +1,197 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import * as Utils from './utils.jsx';
+import * as TextFormatting from './text_formatting.jsx';
+import Constants from './constants.jsx';
+
+import hlJS from 'highlight.js/lib/highlight.js';
+
+import hljsActionscript from 'highlight.js/lib/languages/actionscript.js';
+import hljsApplescript from 'highlight.js/lib/languages/applescript.js';
+import hljsBash from 'highlight.js/lib/languages/bash.js';
+import hljsClojure from 'highlight.js/lib/languages/clojure.js';
+import hljsCoffeescript from 'highlight.js/lib/languages/coffeescript.js';
+import hljsCpp from 'highlight.js/lib/languages/cpp.js';
+import hljsCs from 'highlight.js/lib/languages/cs.js';
+import hljsCss from 'highlight.js/lib/languages/css.js';
+import hljsD from 'highlight.js/lib/languages/d.js';
+import hljsDart from 'highlight.js/lib/languages/dart.js';
+import hljsDelphi from 'highlight.js/lib/languages/delphi.js';
+import hljsDiff from 'highlight.js/lib/languages/diff.js';
+import hljsDjango from 'highlight.js/lib/languages/django.js';
+import hljsDockerfile from 'highlight.js/lib/languages/dockerfile.js';
+import hljsErlang from 'highlight.js/lib/languages/erlang.js';
+import hljsFortran from 'highlight.js/lib/languages/fortran.js';
+import hljsFsharp from 'highlight.js/lib/languages/fsharp.js';
+import hljsGcode from 'highlight.js/lib/languages/gcode.js';
+import hljsGo from 'highlight.js/lib/languages/go.js';
+import hljsGroovy from 'highlight.js/lib/languages/groovy.js';
+import hljsHandlebars from 'highlight.js/lib/languages/handlebars.js';
+import hljsHaskell from 'highlight.js/lib/languages/haskell.js';
+import hljsHaxe from 'highlight.js/lib/languages/haxe.js';
+import hljsJava from 'highlight.js/lib/languages/java.js';
+import hljsJavascript from 'highlight.js/lib/languages/javascript.js';
+import hljsJson from 'highlight.js/lib/languages/json.js';
+import hljsJulia from 'highlight.js/lib/languages/julia.js';
+import hljsKotlin from 'highlight.js/lib/languages/kotlin.js';
+import hljsLess from 'highlight.js/lib/languages/less.js';
+import hljsLisp from 'highlight.js/lib/languages/lisp.js';
+import hljsLua from 'highlight.js/lib/languages/lua.js';
+import hljsMakefile from 'highlight.js/lib/languages/makefile.js';
+import hljsMarkdown from 'highlight.js/lib/languages/markdown.js';
+import hljsMatlab from 'highlight.js/lib/languages/matlab.js';
+import hljsObjectivec from 'highlight.js/lib/languages/objectivec.js';
+import hljsOcaml from 'highlight.js/lib/languages/ocaml.js';
+import hljsPerl from 'highlight.js/lib/languages/perl.js';
+import hljsPhp from 'highlight.js/lib/languages/php.js';
+import hljsPowershell from 'highlight.js/lib/languages/powershell.js';
+import hljsPuppet from 'highlight.js/lib/languages/puppet.js';
+import hljsPython from 'highlight.js/lib/languages/python.js';
+import hljsR from 'highlight.js/lib/languages/r.js';
+import hljsRuby from 'highlight.js/lib/languages/ruby.js';
+import hljsRust from 'highlight.js/lib/languages/rust.js';
+import hljsScala from 'highlight.js/lib/languages/scala.js';
+import hljsScheme from 'highlight.js/lib/languages/scheme.js';
+import hljsScss from 'highlight.js/lib/languages/scss.js';
+import hljsSmalltalk from 'highlight.js/lib/languages/smalltalk.js';
+import hljsSql from 'highlight.js/lib/languages/sql.js';
+import hljsSwift from 'highlight.js/lib/languages/swift.js';
+import hljsTex from 'highlight.js/lib/languages/tex.js';
+import hljsVbnet from 'highlight.js/lib/languages/vbnet.js';
+import hljsVbscript from 'highlight.js/lib/languages/vbscript.js';
+import hljsVerilog from 'highlight.js/lib/languages/verilog.js';
+import hljsXml from 'highlight.js/lib/languages/xml.js';
+import hljsYaml from 'highlight.js/lib/languages/yaml.js';
+
+hlJS.registerLanguage('actionscript', hljsActionscript);
+hlJS.registerLanguage('applescript', hljsApplescript);
+hlJS.registerLanguage('bash', hljsBash);
+hlJS.registerLanguage('clojure', hljsClojure);
+hlJS.registerLanguage('coffeescript', hljsCoffeescript);
+hlJS.registerLanguage('cpp', hljsCpp);
+hlJS.registerLanguage('cs', hljsCs);
+hlJS.registerLanguage('css', hljsCss);
+hlJS.registerLanguage('d', hljsD);
+hlJS.registerLanguage('dart', hljsDart);
+hlJS.registerLanguage('delphi', hljsDelphi);
+hlJS.registerLanguage('diff', hljsDiff);
+hlJS.registerLanguage('django', hljsDjango);
+hlJS.registerLanguage('dockerfile', hljsDockerfile);
+hlJS.registerLanguage('erlang', hljsErlang);
+hlJS.registerLanguage('fortran', hljsFortran);
+hlJS.registerLanguage('fsharp', hljsFsharp);
+hlJS.registerLanguage('gcode', hljsGcode);
+hlJS.registerLanguage('go', hljsGo);
+hlJS.registerLanguage('groovy', hljsGroovy);
+hlJS.registerLanguage('handlebars', hljsHandlebars);
+hlJS.registerLanguage('haskell', hljsHaskell);
+hlJS.registerLanguage('haxe', hljsHaxe);
+hlJS.registerLanguage('java', hljsJava);
+hlJS.registerLanguage('javascript', hljsJavascript);
+hlJS.registerLanguage('json', hljsJson);
+hlJS.registerLanguage('julia', hljsJulia);
+hlJS.registerLanguage('kotlin', hljsKotlin);
+hlJS.registerLanguage('less', hljsLess);
+hlJS.registerLanguage('lisp', hljsLisp);
+hlJS.registerLanguage('lua', hljsLua);
+hlJS.registerLanguage('makefile', hljsMakefile);
+hlJS.registerLanguage('markdown', hljsMarkdown);
+hlJS.registerLanguage('matlab', hljsMatlab);
+hlJS.registerLanguage('objectivec', hljsObjectivec);
+hlJS.registerLanguage('ocaml', hljsOcaml);
+hlJS.registerLanguage('perl', hljsPerl);
+hlJS.registerLanguage('php', hljsPhp);
+hlJS.registerLanguage('powershell', hljsPowershell);
+hlJS.registerLanguage('puppet', hljsPuppet);
+hlJS.registerLanguage('python', hljsPython);
+hlJS.registerLanguage('r', hljsR);
+hlJS.registerLanguage('ruby', hljsRuby);
+hlJS.registerLanguage('rust', hljsRust);
+hlJS.registerLanguage('scala', hljsScala);
+hlJS.registerLanguage('scheme', hljsScheme);
+hlJS.registerLanguage('scss', hljsScss);
+hlJS.registerLanguage('smalltalk', hljsSmalltalk);
+hlJS.registerLanguage('sql', hljsSql);
+hlJS.registerLanguage('swift', hljsSwift);
+hlJS.registerLanguage('tex', hljsTex);
+hlJS.registerLanguage('vbnet', hljsVbnet);
+hlJS.registerLanguage('vbscript', hljsVbscript);
+hlJS.registerLanguage('verilog', hljsVerilog);
+hlJS.registerLanguage('xml', hljsXml);
+hlJS.registerLanguage('yaml', hljsYaml);
+
+const HighlightedLanguages = Constants.HighlightedLanguages;
+
+export function formatCode(lang, data, filename) {
+ var language = lang || '';
+ var parsed;
+ var header = '';
+
+ language = language.toLowerCase();
+
+ if (HighlightedLanguages[language]) {
+ var name = HighlightedLanguages[language].name;
+
+ if (filename) {
+ const fname = decodeURIComponent(Utils.getFileName(filename));
+ name = fname + ' - ' + name;
+ }
+
+ header = '<span class="post-body--code__language">' + name + '</span>';
+
+ try {
+ parsed = hlJS.highlight(language, data).value;
+ } catch (e) {
+ parsed = TextFormatting.sanitizeHtml(data);
+ }
+ } else {
+ parsed = TextFormatting.sanitizeHtml(data);
+ }
+
+ const lines = data.match(/\r\n|\r|\n|$/g).length;
+ var strlines = '';
+ for (var i = 1; i <= lines; i++) {
+ if (strlines) {
+ strlines += '\n' + i;
+ } else {
+ strlines += i;
+ }
+ }
+
+ return (
+ '<div class="post-body--code">' +
+ header +
+ '<pre>' +
+ '<code class="hljs">' +
+ '<table>' +
+ '<tbody>' +
+ '<tr>' +
+ '<td class="post-body--code__lineno">' + strlines + '</td>' +
+ '<td>' +
+ parsed +
+ '</td>' +
+ '</tr>' +
+ '</tbody>' +
+ '</table>' +
+ '</code>' +
+ '</pre>' +
+ '</div>'
+ );
+}
+
+export function getLang(filename) {
+ const fileInfo = Utils.splitFileLocation(filename);
+ var ext = fileInfo.ext;
+ if (!ext) {
+ return null;
+ }
+
+ ext = ext.toLowerCase();
+ for (var key in HighlightedLanguages) {
+ if (HighlightedLanguages[key].extensions.find((x) => x === ext)) {
+ return key;
+ }
+ }
+ return null;
+}
diff --git a/webapp/utils/text_formatting.jsx b/webapp/utils/text_formatting.jsx
index 9833b995c..4c8b5e24c 100644
--- a/webapp/utils/text_formatting.jsx
+++ b/webapp/utils/text_formatting.jsx
@@ -213,6 +213,11 @@ function highlightCurrentMentions(text, tokens) {
}
for (const mention of UserStore.getCurrentMentionKeys()) {
+ // occasionally we get an empty mention which matches a bunch of empty strings
+ if (!mention) {
+ continue;
+ }
+
output = output.replace(new RegExp(`(^|\\W)(${escapeRegex(mention)})\\b`, 'gi'), replaceCurrentMentionWithToken);
}
diff --git a/webapp/utils/utils.jsx b/webapp/utils/utils.jsx
index 686630a9b..12a7ff50e 100644
--- a/webapp/utils/utils.jsx
+++ b/webapp/utils/utils.jsx
@@ -680,7 +680,7 @@ export function applyTheme(theme) {
}
if (theme.centerChannelBg) {
- changeCss('.app__content, .markdown__table, .markdown__table tbody tr, .suggestion-list__content, .modal .modal-content', 'background:' + theme.centerChannelBg, 1);
+ changeCss('.app__content, .markdown__table, .markdown__table tbody tr, .suggestion-list__content, .modal .modal-content, .modal .modal-back', 'background:' + theme.centerChannelBg, 1);
changeCss('#post-list .post-list-holder-by-time', 'background:' + theme.centerChannelBg, 1);
changeCss('#post-create', 'background:' + theme.centerChannelBg, 1);
changeCss('.date-separator .separator__text, .new-separator .separator__text', 'background:' + theme.centerChannelBg, 1);
@@ -763,7 +763,6 @@ export function applyTheme(theme) {
if (theme.buttonBg) {
changeCss('.btn.btn-primary, .tutorial__circles .circle.active', 'background:' + theme.buttonBg, 1);
changeCss('.btn.btn-primary:hover, .btn.btn-primary:active, .btn.btn-primary:focus', 'background:' + changeColor(theme.buttonBg, -0.25), 1);
- changeCss('.file-playback__controls', 'color:' + changeColor(theme.buttonBg, -0.25), 1);
}
if (theme.buttonColor) {
diff --git a/webapp/webpack.config.js b/webapp/webpack.config.js
index 14abf6ffa..5e1df9bfe 100644
--- a/webapp/webpack.config.js
+++ b/webapp/webpack.config.js
@@ -17,20 +17,21 @@ module.exports = {
loaders: [
{
test: /\.jsx?$/,
- loader: 'babel-loader',
+ loader: 'babel',
exclude: /(node_modules|non_npm_dependencies)/,
query: {
- presets: ['react', 'es2015', 'stage-0'],
- plugins: ['transform-runtime']
+ presets: ['react', 'es2015-webpack', 'stage-0'],
+ plugins: ['transform-runtime'],
+ cacheDirectory: true
}
},
{
test: /\.json$/,
- loader: 'json-loader'
+ loader: 'json'
},
{
test: /(node_modules|non_npm_dependencies)\/.+\.(js|jsx)$/,
- loader: 'imports-loader',
+ loader: 'imports',
query: {
$: 'jquery',
jQuery: 'jquery'
@@ -46,7 +47,7 @@ module.exports = {
},
{
test: /\.(png|eot|tiff|svg|woff2|woff|ttf|gif)$/,
- loader: 'file-loader',
+ loader: 'file',
query: {
name: 'files/[hash].[ext]'
}
@@ -67,7 +68,22 @@ module.exports = {
htmlExtract,
new CopyWebpackPlugin([
{from: 'images/emoji', to: 'emoji'}
- ])
+ ]),
+ new webpack.optimize.UglifyJsPlugin({
+ 'screw-ie8': true,
+ mangle: {
+ toplevel: false
+ },
+ compress: {
+ warnings: false
+ },
+ comments: false
+ }),
+ new webpack.optimize.AggressiveMergingPlugin(),
+ new webpack.LoaderOptionsPlugin({
+ minimize: true,
+ debug: false
+ })
],
resolve: {
alias: {