diff options
Diffstat (limited to 'web')
-rw-r--r-- | web/react/components/admin_console/team_settings.jsx | 34 | ||||
-rw-r--r-- | web/react/components/create_comment.jsx | 24 | ||||
-rw-r--r-- | web/react/components/file_attachment.jsx | 158 | ||||
-rw-r--r-- | web/react/components/file_upload_overlay.jsx | 16 | ||||
-rw-r--r-- | web/react/components/team_signup_url_page.jsx | 10 | ||||
-rw-r--r-- | web/react/components/view_image.jsx | 89 | ||||
-rw-r--r-- | web/react/stores/post_store.jsx | 13 | ||||
-rw-r--r-- | web/react/utils/emoticons.jsx | 2 | ||||
-rw-r--r-- | web/react/utils/markdown.jsx | 11 | ||||
-rw-r--r-- | web/react/utils/text_formatting.jsx | 9 | ||||
-rw-r--r-- | web/react/utils/utils.jsx | 1 | ||||
-rw-r--r-- | web/sass-files/sass/partials/_files.scss | 39 | ||||
-rw-r--r-- | web/sass-files/sass/partials/_modal.scss | 13 | ||||
-rw-r--r-- | web/sass-files/sass/partials/_post.scss | 48 | ||||
-rw-r--r-- | web/sass-files/sass/partials/_responsive.scss | 23 | ||||
-rw-r--r-- | web/sass-files/sass/partials/_settings.scss | 3 | ||||
-rw-r--r-- | web/static/images/filesOverlay.png | bin | 0 -> 8392 bytes | |||
-rw-r--r-- | web/static/images/logoWhite.png | bin | 0 -> 5876 bytes |
18 files changed, 446 insertions, 47 deletions
diff --git a/web/react/components/admin_console/team_settings.jsx b/web/react/components/admin_console/team_settings.jsx index da4299714..9ecd14a1e 100644 --- a/web/react/components/admin_console/team_settings.jsx +++ b/web/react/components/admin_console/team_settings.jsx @@ -31,6 +31,7 @@ export default class TeamSettings extends React.Component { config.TeamSettings.RestrictCreationToDomains = ReactDOM.findDOMNode(this.refs.RestrictCreationToDomains).value.trim(); config.TeamSettings.EnableTeamCreation = ReactDOM.findDOMNode(this.refs.EnableTeamCreation).checked; config.TeamSettings.EnableUserCreation = ReactDOM.findDOMNode(this.refs.EnableUserCreation).checked; + config.TeamSettings.RestrictTeamNames = ReactDOM.findDOMNode(this.refs.RestrictTeamNames).checked; var MaxUsersPerTeam = 50; if (!isNaN(parseInt(ReactDOM.findDOMNode(this.refs.MaxUsersPerTeam).value, 10))) { @@ -209,6 +210,39 @@ export default class TeamSettings extends React.Component { </div> <div className='form-group'> + <label + className='control-label col-sm-4' + htmlFor='RestrictTeamNames' + > + {'Restrict Team Names: '} + </label> + <div className='col-sm-8'> + <label className='radio-inline'> + <input + type='radio' + name='RestrictTeamNames' + value='true' + ref='RestrictTeamNames' + defaultChecked={this.props.config.TeamSettings.RestrictTeamNames} + onChange={this.handleChange} + /> + {'true'} + </label> + <label className='radio-inline'> + <input + type='radio' + name='RestrictTeamNames' + value='false' + defaultChecked={!this.props.config.TeamSettings.RestrictTeamNames} + onChange={this.handleChange} + /> + {'false'} + </label> + <p className='help-text'>{'When true, You cannot create a team name with reserved words like www, admin, support, test, channel, etc'}</p> + </div> + </div> + + <div className='form-group'> <div className='col-sm-12'> {serverError} <button diff --git a/web/react/components/create_comment.jsx b/web/react/components/create_comment.jsx index 12d1af6ff..435c7d542 100644 --- a/web/react/components/create_comment.jsx +++ b/web/react/components/create_comment.jsx @@ -13,8 +13,10 @@ const MsgTyping = require('./msg_typing.jsx'); const FileUpload = require('./file_upload.jsx'); const FilePreview = require('./file_preview.jsx'); const Utils = require('../utils/utils.jsx'); + const Constants = require('../utils/constants.jsx'); const ActionTypes = Constants.ActionTypes; +const KeyCodes = Constants.KeyCodes; export default class CreateComment extends React.Component { constructor(props) { @@ -25,6 +27,7 @@ export default class CreateComment extends React.Component { this.handleSubmit = this.handleSubmit.bind(this); this.commentMsgKeyPress = this.commentMsgKeyPress.bind(this); this.handleUserInput = this.handleUserInput.bind(this); + this.handleArrowUp = this.handleArrowUp.bind(this); this.handleUploadStart = this.handleUploadStart.bind(this); this.handleFileUploadComplete = this.handleFileUploadComplete.bind(this); this.handleUploadError = this.handleUploadError.bind(this); @@ -158,6 +161,26 @@ export default class CreateComment extends React.Component { $('.post-right__scroll').perfectScrollbar('update'); this.setState({messageText: messageText}); } + handleArrowUp(e) { + if (e.keyCode === KeyCodes.UP && this.state.messageText === '') { + e.preventDefault(); + + const channelId = ChannelStore.getCurrentId(); + const lastPost = PostStore.getCurrentUsersLatestPost(channelId, this.props.rootId); + if (!lastPost) { + return; + } + + AppDispatcher.handleViewAction({ + type: ActionTypes.RECIEVED_EDIT_POST, + refocusId: '#reply_textbox', + title: 'Comment', + message: lastPost.message, + postId: lastPost.id, + channelId: lastPost.channel_id + }); + } + } handleUploadStart(clientIds) { let draft = PostStore.getCommentDraft(this.props.rootId); @@ -290,6 +313,7 @@ export default class CreateComment extends React.Component { <Textbox onUserInput={this.handleUserInput} onKeyPress={this.commentMsgKeyPress} + onKeyDown={this.handleArrowUp} messageText={this.state.messageText} createMessage='Add a comment...' initialText='' diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx index 307c543a2..4d4e8390c 100644 --- a/web/react/components/file_attachment.jsx +++ b/web/react/components/file_attachment.jsx @@ -10,9 +10,12 @@ export default class FileAttachment extends React.Component { super(props); this.loadFiles = this.loadFiles.bind(this); + this.playGif = this.playGif.bind(this); + this.stopGif = this.stopGif.bind(this); + this.addBackgroundImage = this.addBackgroundImage.bind(this); this.canSetState = false; - this.state = {fileSize: -1}; + this.state = {fileSize: -1, mime: '', playing: false, loading: false, format: ''}; } componentDidMount() { this.loadFiles(); @@ -28,15 +31,9 @@ export default class FileAttachment extends React.Component { var filename = this.props.filename; if (filename) { - var fileInfo = utils.splitFileLocation(filename); + var fileInfo = this.getFileInfoFromName(filename); var type = utils.getFileType(fileInfo.ext); - // This is a temporary patch to fix issue with old files using absolute paths - if (fileInfo.path.indexOf('/api/v1/files/get') !== -1) { - fileInfo.path = fileInfo.path.split('/api/v1/files/get')[1]; - } - fileInfo.path = utils.getWindowLocationOrigin() + '/api/v1/files/get' + fileInfo.path; - if (type === 'image') { var self = this; // Need this reference since we use the given "this" $('<img/>').attr('src', fileInfo.path + '_thumb.jpg?' + utils.getSessionIndex()).load(function loadWrapper(path, name) { @@ -58,11 +55,7 @@ export default class FileAttachment extends React.Component { $(imgDiv).addClass('normal'); } - var re1 = new RegExp(' ', 'g'); - var re2 = new RegExp('\\(', 'g'); - var re3 = new RegExp('\\)', 'g'); - var url = path.replace(re1, '%20').replace(re2, '%28').replace(re3, '%29'); - $(imgDiv).css('background-image', 'url(' + url + '_thumb.jpg?' + utils.getSessionIndex() + ')'); + self.addBackgroundImage(name, path); } }; }(fileInfo.path, filename)); @@ -93,6 +86,75 @@ export default class FileAttachment extends React.Component { return true; } + playGif(e, filename) { + var img = new Image(); + var fileUrl = utils.getFileUrl(filename); + + this.setState({loading: true}); + img.load(fileUrl); + img.onload = () => { + var state = {playing: true, loading: false}; + + switch (true) { + case img.width > img.height: + state.format = 'landscape'; + break; + case img.height > img.width: + state.format = 'portrait'; + break; + default: + state.format = 'quadrat'; + break; + } + + this.setState(state); + + // keep displaying background image for a short moment while browser is + // loading gif, to prevent white background flashing through + setTimeout(() => this.removeBackgroundImage.bind(this)(filename), 100); + }; + img.onError = () => this.setState({loading: false}); + + e.stopPropagation(); + } + stopGif(e, filename) { + this.setState({playing: false}); + this.addBackgroundImage(filename); + e.stopPropagation(); + } + getFileInfoFromName(name) { + var fileInfo = utils.splitFileLocation(name); + + // This is a temporary patch to fix issue with old files using absolute paths + if (fileInfo.path.indexOf('/api/v1/files/get') !== -1) { + fileInfo.path = fileInfo.path.split('/api/v1/files/get')[1]; + } + fileInfo.path = utils.getWindowLocationOrigin() + '/api/v1/files/get' + fileInfo.path; + + return fileInfo; + } + addBackgroundImage(name, path) { + var fileUrl = path; + + if (name in this.refs) { + if (!path) { + fileUrl = this.getFileInfoFromName(name).path; + } + + var imgDiv = ReactDOM.findDOMNode(this.refs[name]); + var re1 = new RegExp(' ', 'g'); + var re2 = new RegExp('\\(', 'g'); + var re3 = new RegExp('\\)', 'g'); + var url = fileUrl.replace(re1, '%20').replace(re2, '%28').replace(re3, '%29'); + + $(imgDiv).css('background-image', 'url(' + url + '_thumb.jpg?' + utils.getSessionIndex() + ')'); + } + } + removeBackgroundImage(name) { + if (name in this.refs) { + $(ReactDOM.findDOMNode(this.refs[name])).css('background-image', 'initial'); + } + } render() { var filename = this.props.filename; @@ -100,15 +162,71 @@ export default class FileAttachment extends React.Component { var fileUrl = utils.getFileUrl(filename); var type = utils.getFileType(fileInfo.ext); - var thumbnail; - if (type === 'image') { - thumbnail = ( + var playbackControls = ''; + var loadedFile = ''; + var loadingIndicator = ''; + if (this.state.mime === 'image/gif') { + playbackControls = ( <div - ref={filename} - className='post__load' - style={{backgroundImage: 'url(/static/images/load.gif)'}} + className='file-playback-controls play' + onClick={(e) => this.playGif(e, filename)} + > + {"►"} + </div> + ); + } + if (this.state.playing) { + loadedFile = ( + <img + className={'file__loaded ' + this.state.format} + src={fileUrl} + /> + ); + playbackControls = ( + <div + className='file-playback-controls stop' + onClick={(e) => this.stopGif(e, filename)} + > + {"■"} + </div> + ); + } + if (this.state.loading) { + loadingIndicator = ( + <img + className='spinner file__loading' + src='/static/images/load.gif' /> ); + playbackControls = ''; + } + + var thumbnail; + if (type === 'image') { + if (this.state.playing) { + thumbnail = ( + <div + ref={filename} + className='post__load' + style={{backgroundImage: 'url(/static/images/load.gif)'}} + > + {playbackControls} + {loadedFile} + </div> + ); + } else { + thumbnail = ( + <div + ref={filename} + className='post__load' + style={{backgroundImage: 'url(/static/images/load.gif)'}} + > + {loadingIndicator} + {playbackControls} + {loadedFile} + </div> + ); + } } else { thumbnail = <div className={'file-icon ' + utils.getIconClassName(type)}/>; } @@ -119,7 +237,7 @@ export default class FileAttachment extends React.Component { filename, function success(data) { if (this.canSetState) { - this.setState({fileSize: parseInt(data.size, 10)}); + this.setState({fileSize: parseInt(data.size, 10), mime: data.mime}); } }.bind(this), function error() {} diff --git a/web/react/components/file_upload_overlay.jsx b/web/react/components/file_upload_overlay.jsx index 4fcee6cb0..d991dd625 100644 --- a/web/react/components/file_upload_overlay.jsx +++ b/web/react/components/file_upload_overlay.jsx @@ -12,9 +12,19 @@ export default class FileUploadOverlay extends React.Component { return ( <div className={overlayClass}> - <div> - <i className='fa fa-upload'></i> - <span>Drop a file to upload it.</span> + <div className='overlay__circle'> + <img + className='overlay__files' + src='/static/images/filesOverlay.png' + alt='Files' + /> + <span><i className='fa fa-upload'></i>{'Drop a file to upload it.'}</span> + <img + className='overlay__logo' + src='/static/images/logoWhite.png' + width='100' + alt='Logo' + /> </div> </div> ); diff --git a/web/react/components/team_signup_url_page.jsx b/web/react/components/team_signup_url_page.jsx index 67e4c9dd7..6d333aed6 100644 --- a/web/react/components/team_signup_url_page.jsx +++ b/web/react/components/team_signup_url_page.jsx @@ -40,10 +40,12 @@ export default class TeamSignupUrlPage extends React.Component { return; } - for (let index = 0; index < Constants.RESERVED_TEAM_NAMES.length; index++) { - if (cleanedName.indexOf(Constants.RESERVED_TEAM_NAMES[index]) === 0) { - this.setState({nameError: 'URL is taken or contains a reserved word'}); - return; + if (global.window.mm_config.RestrictTeamNames === 'true') { + for (let index = 0; index < Constants.RESERVED_TEAM_NAMES.length; index++) { + if (cleanedName.indexOf(Constants.RESERVED_TEAM_NAMES[index]) === 0) { + this.setState({nameError: 'URL is taken or contains a reserved word'}); + return; + } } } diff --git a/web/react/components/view_image.jsx b/web/react/components/view_image.jsx index 766edf0ac..92d7cd835 100644 --- a/web/react/components/view_image.jsx +++ b/web/react/components/view_image.jsx @@ -38,7 +38,10 @@ export default class ViewImageModal extends React.Component { progress: progress, images: {}, fileSizes: {}, - showFooter: false + fileMimes: {}, + showFooter: false, + isPlaying: {}, + isLoading: {} }; } handleNext(e) { @@ -122,6 +125,36 @@ export default class ViewImageModal extends React.Component { this.setState({loaded}); } } + playGif(e, filename, fileUrl) { + var isLoading = this.state.isLoading; + var isPlaying = this.state.isPlaying; + + isLoading[filename] = fileUrl; + this.setState({isLoading}); + + var img = new Image(); + img.load(fileUrl); + img.onload = () => { + delete isLoading[filename]; + isPlaying[filename] = fileUrl; + this.setState({isPlaying, isLoading}); + }; + img.onError = () => { + delete isLoading[filename]; + this.setState({isLoading}); + }; + + e.stopPropagation(); + e.preventDefault(); + } + stopGif(e, filename) { + var isPlaying = this.state.isPlaying; + delete isPlaying[filename]; + this.setState({isPlaying}); + + e.stopPropagation(); + e.preventDefault(); + } componentDidMount() { $(window).on('keyup', this.handleKeyPress); @@ -154,6 +187,10 @@ export default class ViewImageModal extends React.Component { var fileType = Utils.getFileType(fileInfo.ext); if (fileType === 'image') { + if (filename in this.state.isPlaying) { + return this.state.isPlaying[filename]; + } + // This is a temporary patch to fix issue with old files using absolute paths if (fileInfo.path.indexOf('/api/v1/files/get') !== -1) { fileInfo.path = fileInfo.path.split('/api/v1/files/get')[1]; @@ -189,12 +226,62 @@ export default class ViewImageModal extends React.Component { var fileType = Utils.getFileType(fileInfo.ext); if (fileType === 'image') { + if (!(filename in this.state.fileMimes)) { + Client.getFileInfo( + filename, + (data) => { + if (this.canSetState) { + var fileMimes = this.state.fileMimes; + fileMimes[filename] = data.mime; + this.setState(fileMimes); + } + }, + () => {} + ); + } + + var playbackControls = ''; + if (this.state.fileMimes[filename] === 'image/gif' && !(filename in this.state.isLoading)) { + if (filename in this.state.isPlaying) { + playbackControls = ( + <div + className='file-playback-controls stop' + onClick={(e) => this.stopGif(e, filename)} + > + {"■"} + </div> + ); + } else { + playbackControls = ( + <div + className='file-playback-controls play' + onClick={(e) => this.playGif(e, filename, fileUrl)} + > + {"►"} + </div> + ); + } + } + + var loadingIndicator = ''; + if (this.state.isLoading[filename] === fileUrl) { + loadingIndicator = ( + <img + className='spinner file__loading' + src='/static/images/load.gif' + /> + ); + playbackControls = ''; + } + // image files just show a preview of the file content = ( <a href={fileUrl} target='_blank' > + {loadingIndicator} + {playbackControls} <img style={{maxHeight: this.state.imgHeight}} ref='image' diff --git a/web/react/stores/post_store.jsx b/web/react/stores/post_store.jsx index b073ca68d..4a9314b31 100644 --- a/web/react/stores/post_store.jsx +++ b/web/react/stores/post_store.jsx @@ -230,7 +230,7 @@ class PostStoreClass extends EventEmitter { getPosts(channelId) { return BrowserStore.getItem('posts_' + channelId); } - getCurrentUsersLatestPost(channelId) { + getCurrentUsersLatestPost(channelId, rootId) { const userId = UserStore.getCurrentId(); var postList = makePostListNonNull(this.getPosts(channelId)); var i = 0; @@ -239,8 +239,15 @@ class PostStoreClass extends EventEmitter { for (i; i < len; i++) { if (postList.posts[postList.order[i]].user_id === userId) { - lastPost = postList.posts[postList.order[i]]; - break; + if (rootId) { + if (postList.posts[postList.order[i]].root_id === rootId || postList.posts[postList.order[i]].id === rootId) { + lastPost = postList.posts[postList.order[i]]; + break; + } + } else { + lastPost = postList.posts[postList.order[i]]; + break; + } } } diff --git a/web/react/utils/emoticons.jsx b/web/react/utils/emoticons.jsx index 7b43e48b4..aabddcffd 100644 --- a/web/react/utils/emoticons.jsx +++ b/web/react/utils/emoticons.jsx @@ -133,7 +133,7 @@ export function handleEmoticons(text, tokens) { const alias = `MM_EMOTICON${index}`; tokens.set(alias, { - value: `<img align="absmiddle" alt=${match} class="emoji" src=${getImagePathForEmoticon(name)} title=${match} />`, + value: `<img align="absmiddle" alt="${match}" class="emoji" src="${getImagePathForEmoticon(name)}" title="${match}" />`, originalText: match }); diff --git a/web/react/utils/markdown.jsx b/web/react/utils/markdown.jsx index 2813798d2..7a4e70054 100644 --- a/web/react/utils/markdown.jsx +++ b/web/react/utils/markdown.jsx @@ -11,6 +11,7 @@ export class MattermostMarkdownRenderer extends marked.Renderer { super(options); this.heading = this.heading.bind(this); + this.paragraph = this.paragraph.bind(this); this.text = this.text.bind(this); this.formattingOptions = formattingOptions; @@ -53,11 +54,17 @@ export class MattermostMarkdownRenderer extends marked.Renderer { } paragraph(text) { + let outText = text; + + if (!('emoticons' in this.options) || this.options.emoticon) { + outText = TextFormatting.doFormatEmoticons(text); + } + if (this.formattingOptions.singleline) { - return `<p class="markdown__paragraph-inline">${text}</p>`; + return `<p class="markdown__paragraph-inline">${outText}</p>`; } - return super.paragraph(text); + return super.paragraph(outText); } table(header, body) { diff --git a/web/react/utils/text_formatting.jsx b/web/react/utils/text_formatting.jsx index d79aeed68..5c2e68f1e 100644 --- a/web/react/utils/text_formatting.jsx +++ b/web/react/utils/text_formatting.jsx @@ -69,6 +69,15 @@ export function doFormatText(text, options) { return output; } +export function doFormatEmoticons(text) { + const tokens = new Map(); + + let output = Emoticons.handleEmoticons(text, tokens); + output = replaceTokens(output, tokens); + + return output; +} + export function sanitizeHtml(text) { let output = text; diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index 53e328384..c72c3f32c 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -544,6 +544,7 @@ export function applyTheme(theme) { if (theme.buttonBg) { changeCss('.btn.btn-primary', '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/web/sass-files/sass/partials/_files.scss b/web/sass-files/sass/partials/_files.scss index 01057423d..d3ab3b9f8 100644 --- a/web/sass-files/sass/partials/_files.scss +++ b/web/sass-files/sass/partials/_files.scss @@ -133,12 +133,34 @@ height: 100%; background-color: #FFF; background-repeat: no-repeat; + overflow: hidden; + position: relative; + text-align: center; &.small { background-position: center; } &.normal { background-position: top left; } + .spinner.file__loading { + position: absolute; + left: 50%; + margin-left: -16px; + top: 50%; + margin-top: -16px; + } + .file__loaded { + max-width: initial; + &.landscape, &.quadrat { + height: 100px; + } + &.portrait { + width: 120px; + } + } + &:hover .file-playback-controls.stop { + @include opacity(1); + } } .post-image__thumbnail { float: left; @@ -215,3 +237,20 @@ } } } + +.file-playback-controls { + position: absolute; + right: 5px; + bottom: 0; + font-size: 22px; + cursor: pointer; + z-index: 2; + -webkit-transition: opacity 0.6s; + -moz-transition: opacity 0.6s; + -o-transition: opacity 0.6s; + transition: opacity 0.6s; + + &.stop { + @include opacity(0); + } +} diff --git a/web/sass-files/sass/partials/_modal.scss b/web/sass-files/sass/partials/_modal.scss index 5570b5ce4..1dcdbf348 100644 --- a/web/sass-files/sass/partials/_modal.scss +++ b/web/sass-files/sass/partials/_modal.scss @@ -228,11 +228,24 @@ background: #FFF; display: table-cell; vertical-align: middle; + position: relative; + + &:hover .file-playback-controls.stop { + @include opacity(1); + } } img { max-width: 100%; max-height: 100%; } + .spinner.file__loading { + z-index: 2; + position: absolute; + left: 50%; + margin-left: -16px; + top: 50%; + margin-top: -16px; + } } .modal-content{ box-shadow: none; diff --git a/web/sass-files/sass/partials/_post.scss b/web/sass-files/sass/partials/_post.scss index 0f3cc0ef6..6ecc0d965 100644 --- a/web/sass-files/sass/partials/_post.scss +++ b/web/sass-files/sass/partials/_post.scss @@ -119,20 +119,52 @@ body.ios { background-color: rgba(0, 0, 0, 0.6); text-align: center; color: #FFF; - display: table; - font-size: 1.7em; + font-size: em(20px); font-weight: 600; z-index: 6; - > div { - display: table-cell; - vertical-align: middle; + &.right-file-overlay { + font-size: em(18px); + .overlay__circle { + width: 300px; + height: 300px; + margin: -150px 0 0 -150px; + } + .overlay__files { + margin: 60px auto 15px; + width: 150px; + } } - .fa { + .overlay__circle { + background: #111; + background: rgba(black, 0.7); + width: 370px; + height: 370px; + margin: -185px 0 0 -185px; + @include border-radius(500px); + position: absolute; + top: 50%; + left: 50%; + } + + .overlay__files { display: block; - font-size: 2em; - margin: 0 0 0.3em; + margin: 75px auto 20px; + } + + .overlay__logo { + position: absolute; + left: 50%; + bottom: 30px; + margin-left: -50px; + @include opacity(0.3); + } + + .fa { + display: inline-block; + font-size: 1.1em; + margin-right: 8px; } } diff --git a/web/sass-files/sass/partials/_responsive.scss b/web/sass-files/sass/partials/_responsive.scss index 09ac2047c..c8bb24f3a 100644 --- a/web/sass-files/sass/partials/_responsive.scss +++ b/web/sass-files/sass/partials/_responsive.scss @@ -199,9 +199,6 @@ } @media screen and (max-width: 960px) { - .center-file-overlay { - font-size: 1.5em; - } .post { .post-header .post-header-col.post-header__reply { .comment-icon__container__hide { @@ -278,8 +275,17 @@ display: block; } } - .center-file-overlay { - font-size: 1.3em; + .file-overlay { + font-size: em(18px); + .overlay__circle { + width: 300px; + height: 300px; + margin: -150px 0 0 -150px; + } + .overlay__files { + margin: 60px auto 15px; + width: 150px; + } } .date-separator, .new-separator { &.hovered--after { @@ -639,6 +645,9 @@ } &.has-close { .btn-close { + width: 40px; + text-align: center; + right: 0; display: block; @include opacity(0.5); } @@ -749,6 +758,10 @@ .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) { .access-history__table { diff --git a/web/sass-files/sass/partials/_settings.scss b/web/sass-files/sass/partials/_settings.scss index c4591d7b6..bc53dc0e4 100644 --- a/web/sass-files/sass/partials/_settings.scss +++ b/web/sass-files/sass/partials/_settings.scss @@ -103,6 +103,9 @@ text-overflow: ellipsis; margin-bottom: 0; } + .input-group-addon { + background: transparent; + } .radio { label { font-weight: 600; diff --git a/web/static/images/filesOverlay.png b/web/static/images/filesOverlay.png Binary files differnew file mode 100644 index 000000000..d24da7626 --- /dev/null +++ b/web/static/images/filesOverlay.png diff --git a/web/static/images/logoWhite.png b/web/static/images/logoWhite.png Binary files differnew file mode 100644 index 000000000..11bbd4632 --- /dev/null +++ b/web/static/images/logoWhite.png |