Type here to write a message and press Enter to post it.
Click the Attachment button to upload an image or a file.
", "create_post.write": "Write a message...", "create_team.agreement": "By proceeding to create your account and use {siteName}, you agree to our Terms of Service and Privacy Policy. If you do not agree, you cannot use {siteName}.", @@ -1370,6 +1372,8 @@ "post_delete.someone": "Someone deleted the message on which you tried to post a comment.", "post_focus_view.beginning": "Beginning of Channel Archives", "post_info.del": "Delete", + "post_info.mobile.flag": "Flag", + "post_info.mobile.unflag": "Unflag", "post_info.edit": "Edit", "post_info.permalink": "Permalink", "post_info.reply": "Reply", @@ -1393,14 +1397,19 @@ "rename_channel.title": "Rename Channel", "rhs_comment.comment": "Comment", "rhs_comment.del": "Delete", + "rhs_comment.mobile.flag": "Flag", + "rhs_comment.mobile.unflag": "Unflag", "rhs_comment.edit": "Edit", "rhs_comment.permalink": "Permalink", "rhs_header.backToResultsTooltip": "Back to Search Results", + "rhs_header.backToFlaggedTooltip": "Back to Flagged Posts", "rhs_header.closeSidebarTooltip": "Close Sidebar", "rhs_header.details": "Message Details", "rhs_header.expandSidebarTooltip": "Expand Sidebar", "rhs_header.shrinkSidebarTooltip": "Shrink Sidebar", "rhs_root.del": "Delete", + "rhs_root.mobile.flag": "Flag", + "rhs_root.mobile.unflag": "Unflag", "rhs_root.direct": "Direct Message", "rhs_root.edit": "Edit", "rhs_root.permalink": "Permalink", @@ -1409,6 +1418,7 @@ "search_bar.usage": "The Main Menu is where you can Invite New Members, access your Account Settings and set your Theme Color.
Team administrators can also access their Team Settings from this menu.
System administrators will find a System Console option to administrate the entire system.
", "sidebar_right_menu.accountSettings": "Account Settings", + "sidebar_right_menu.flagged": "Flagged Posts", "sidebar_right_menu.console": "System Console", "sidebar_right_menu.help": "Help", "sidebar_right_menu.inviteNew": "Invite New Member", diff --git a/webapp/sass/components/_search.scss b/webapp/sass/components/_search.scss index d259cfc20b6..11bcdb92d90 100644 --- a/webapp/sass/components/_search.scss +++ b/webapp/sass/components/_search.scss @@ -137,23 +137,31 @@ } } -.search-item__jump { - @include opacity(.8); +.col__controls { font-size: 13px; position: absolute; right: 0; top: 0; - &:hover { - @include opacity(1); - } -} + a { + @include opacity(.8); + vertical-align: top; -.search-item__comment { - margin-right: 35px; - position: absolute; - right: 0; - top: 0; + &:hover { + @include opacity(1); + } + } + + + .search-item__jump { + font-size: 13px; + position: relative; + top: 1px; + } + + .search-item__comment { + margin-right: 5px; + } } .search-item-time { diff --git a/webapp/sass/layout/_headers.scss b/webapp/sass/layout/_headers.scss index f2705fc0a2a..832bed50efa 100644 --- a/webapp/sass/layout/_headers.scss +++ b/webapp/sass/layout/_headers.scss @@ -43,6 +43,7 @@ } &:last-child { + padding-right: 8px; width: 8.9%; } } @@ -375,8 +376,17 @@ font-size: 22px; height: 30px; line-height: 26px; - margin-right: 9px; - width: 24px; + margin-right: 3px; + text-align: center; + width: 30px; + + th { + &:last-child { + div { + margin-right: 10px; + } + } + } .channel__wrap.move--left & { position: absolute; @@ -384,6 +394,15 @@ top: 14px; } + .icon__flag { + svg { + height: 18px; + position: relative; + top: 2px; + width: 19px; + } + } + > a { @include opacity(.6); @include single-transition(all, .1s, ease-in); diff --git a/webapp/sass/layout/_post.scss b/webapp/sass/layout/_post.scss index 605c0365817..8513f779a94 100644 --- a/webapp/sass/layout/_post.scss +++ b/webapp/sass/layout/_post.scss @@ -486,6 +486,7 @@ body.ios { &:hover { .dropdown, .comment-icon__container, + .flag-icon__container, .post__reply, .post__remove { visibility: visible; @@ -561,7 +562,7 @@ body.ios { .img-div { max-height: 150px; max-width: 150px; - } + } p { line-height: inherit; @@ -573,7 +574,7 @@ body.ios { ol, ul { - clear: both; + clear: both; padding-left: 20px; } } @@ -694,6 +695,13 @@ body.ios { } } + .flag-icon__container { + left: 36px; + margin-left: 5px; + position: absolute; + top: 8px; + } + .post__img { img { display: none; @@ -835,7 +843,9 @@ body.ios { } .post__img { - width: 42px; + padding-right: 10px; + text-align: right; + width: 53px; svg { height: 32px; @@ -1076,6 +1086,7 @@ body.ios { display: inline-block; margin-right: 6px; visibility: hidden; + svg { fill: inherit; position: relative; @@ -1115,6 +1126,36 @@ body.ios { } } + .flag-icon__container { + display: inline-block; + font-size: 12px; + margin-left: 7px; + position: relative; + top: 1px; + visibility: hidden; + + &.visible { + visibility: visible; + } + + path { + fill: inherit; + } + + .fa-star-o { + @include opacity(.8); + } + + &:focus { + outline: none; + } + + &.icon--visible { + visibility: visible; + } + + } + .web-embed-data { @include border-radius(2px); @include alpha-property(background, $black, 0.05); diff --git a/webapp/sass/layout/_sidebar-right.scss b/webapp/sass/layout/_sidebar-right.scss index fb57b614689..497cd3cea82 100644 --- a/webapp/sass/layout/_sidebar-right.scss +++ b/webapp/sass/layout/_sidebar-right.scss @@ -161,7 +161,7 @@ .sidebar--right__subheader { font-size: 1em; - padding: 1em 1em 0; + padding: 0.5em 1em 0; h4 { font-size: 1em; @@ -176,6 +176,13 @@ font-size: .95em; padding-bottom: 10px; } + + .usage__icon { + @include opacity(.6); + margin: 0 3px; + position: relative; + top: 1px; + } } .suggestion-list__content { diff --git a/webapp/sass/responsive/_mobile.scss b/webapp/sass/responsive/_mobile.scss index df615aa1310..c60233ae895 100644 --- a/webapp/sass/responsive/_mobile.scss +++ b/webapp/sass/responsive/_mobile.scss @@ -94,6 +94,16 @@ } } + &.same--root { + &.same--user { + .flag-icon__container { + left: auto; + position: relative; + top: 1px; + } + } + } + .post__content { padding: 0 10px 0 0; } @@ -182,7 +192,23 @@ } } + .star-icon__container { + left: auto; + position: relative; + top: auto; + + &:not(.visible) { + display: none; + } + } + &.same--root { + .star-icon__container { + left: auto; + position: relative; + top: auto; + } + &.same--user { .post__header { height: auto; diff --git a/webapp/sass/responsive/_tablet.scss b/webapp/sass/responsive/_tablet.scss index e6cb898fd78..bb3d7865255 100644 --- a/webapp/sass/responsive/_tablet.scss +++ b/webapp/sass/responsive/_tablet.scss @@ -116,7 +116,15 @@ .channel__wrap & { .post__time { font-size: .85em; - left: -70px; + left: -79px; + position: absolute; + text-align: right; + top: 6px; + width: 60px; + } + + .star-icon__container { + left: -65px; position: absolute; text-align: right; top: 6px; @@ -125,7 +133,7 @@ } &:not(.post--thread) { - padding: 5px .5em 0 70px; + padding: 5px .5em 0 72px; .post__link { margin: 4px 0 7px; @@ -197,11 +205,29 @@ } } + .flag-icon__container { + left: -21px; + position: absolute; + top: 7px; + } + + .sidebar--right & .flag-icon__container { + left: auto; + position: relative; + top: 1px; + } + &.same--root { &.same--user { - padding-left: 70px; + padding-left: 72px; padding-top: 0; + .flag-icon__container { + left: -19px; + position: absolute; + top: 7px; + } + .post__header { .col__reply { top: -1px; @@ -265,12 +291,16 @@ &:not(.post--compact) { .post__time { + display: inline-block; font-size: 11px; - left: -4px; - line-height: 37px; + left: -14px; + line-height: 34px; position: absolute; + text-align: right; text-rendering: auto; top: -2px; + width: 51px; + } } } diff --git a/webapp/stores/post_store.jsx b/webapp/stores/post_store.jsx index 1c9a877cf57..135563866a3 100644 --- a/webapp/stores/post_store.jsx +++ b/webapp/stores/post_store.jsx @@ -441,8 +441,8 @@ class PostStoreClass extends EventEmitter { return threadPosts; } - emitSelectedPostChange(fromSearch) { - this.emit(SELECTED_POST_CHANGE_EVENT, fromSearch); + emitSelectedPostChange(fromSearch, fromFlaggedPosts) { + this.emit(SELECTED_POST_CHANGE_EVENT, fromSearch, fromFlaggedPosts); } addSelectedPostChangeListener(callback) { @@ -599,7 +599,7 @@ PostStore.dispatchToken = AppDispatcher.register((payload) => { break; case ActionTypes.RECEIVED_POST_SELECTED: PostStore.storeSelectedPostId(action.postId); - PostStore.emitSelectedPostChange(action.from_search); + PostStore.emitSelectedPostChange(action.from_search, action.from_flagged_posts); break; default: } diff --git a/webapp/stores/search_store.jsx b/webapp/stores/search_store.jsx index dc08ca3a6a8..74159089562 100644 --- a/webapp/stores/search_store.jsx +++ b/webapp/stores/search_store.jsx @@ -18,6 +18,7 @@ class SearchStoreClass extends EventEmitter { this.searchResults = null; this.isMentionSearch = false; + this.isFlaggedPosts = false; this.searchTerm = ''; } @@ -77,6 +78,10 @@ class SearchStoreClass extends EventEmitter { return this.isMentionSearch; } + getIsFlaggedPosts() { + return this.isFlaggedPosts; + } + storeSearchTerm(term) { this.searchTerm = term; } @@ -85,9 +90,10 @@ class SearchStoreClass extends EventEmitter { return this.searchTerm; } - storeSearchResults(results, isMentionSearch) { + storeSearchResults(results, isMentionSearch, isFlaggedPosts) { this.searchResults = results; this.isMentionSearch = isMentionSearch; + this.isFlaggedPosts = isFlaggedPosts; } } @@ -98,7 +104,7 @@ SearchStore.dispatchToken = AppDispatcher.register((payload) => { switch (action.type) { case ActionTypes.RECEIVED_SEARCH: - SearchStore.storeSearchResults(action.results, action.is_mention_search); + SearchStore.storeSearchResults(action.results, action.is_mention_search, action.is_flagged_posts); SearchStore.emitSearchChange(); break; case ActionTypes.RECEIVED_SEARCH_TERM: diff --git a/webapp/tests/client_post.test.jsx b/webapp/tests/client_post.test.jsx index 3c6f05c9f30..3b9802fb4ca 100644 --- a/webapp/tests/client_post.test.jsx +++ b/webapp/tests/client_post.test.jsx @@ -197,5 +197,38 @@ describe('Client.Posts', function() { ); }); }); + + it('getFlaggedPosts', function(done) { + TestHelper.initBasic(() => { + var pref = {}; + pref.user_id = TestHelper.basicUser().id; + pref.category = 'flagged_post'; + pref.name = TestHelper.basicPost().id; + pref.value = 'true'; + + var prefs = []; + prefs.push(pref); + + TestHelper.basicClient().savePreferences( + prefs, + function() { + TestHelper.basicClient().getFlaggedPosts( + 0, + 2, + function(data) { + assert.equal(data.order[0], TestHelper.basicPost().id); + done(); + }, + function(err) { + done(new Error(err.message)); + } + ); + }, + function(err) { + done(new Error(err.message)); + } + ); + }); + }); }); diff --git a/webapp/utils/constants.jsx b/webapp/utils/constants.jsx index 812796ebb7f..dbdc3e9f1e1 100644 --- a/webapp/utils/constants.jsx +++ b/webapp/utils/constants.jsx @@ -51,7 +51,8 @@ export const Preferences = { COLLAPSE_DISPLAY: 'collapse_previews', COLLAPSE_DISPLAY_DEFAULT: 'false', USE_MILITARY_TIME: 'use_military_time', - CATEGORY_THEME: 'theme' + CATEGORY_THEME: 'theme', + CATEGORY_FLAGGED_POST: 'flagged_post' }; export const ActionTypes = keyMirror({ @@ -326,6 +327,8 @@ export const Constants = { OPEN_TEAM: 'O', MAX_POST_LEN: 4000, EMOJI_SIZE: 16, + FLAG_ICON_OUTLINE_SVG: "", + FLAG_ICON_SVG: "", ATTACHMENT_ICON_SVG: "", MATTERMOST_ICON_SVG: "", ONLINE_ICON_SVG: "", diff --git a/webapp/utils/utils.jsx b/webapp/utils/utils.jsx index 187c7d7f48a..9f8b1ef6c94 100644 --- a/webapp/utils/utils.jsx +++ b/webapp/utils/utils.jsx @@ -566,7 +566,8 @@ export function applyTheme(theme) { } if (theme.centerChannelColor) { - changeCss('.app__body .post-list__arrows', 'fill:' + changeOpacity(theme.centerChannelColor, 0.3), 1); + changeCss('.app__body .post-list__arrows, .app__body .post .flag-icon__container', 'fill:' + changeOpacity(theme.centerChannelColor, 0.3), 1); + changeCss('.app__body .channel-header__links .icon', 'stroke:' + theme.centerChannelColor, 1); changeCss('@media(min-width: 768px){.app__body .post:hover .post__header .col__reply, .app__body .post.post--hovered .post__header .col__reply', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 2); changeCss('.app__body .sidebar--left, .app__body .sidebar--right .sidebar--right__header, .app__body .suggestion-list__content .command', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1); changeCss('.app__body .post.post--system .post__body', 'color:' + changeOpacity(theme.centerChannelColor, 0.6), 1); @@ -638,7 +639,8 @@ export function applyTheme(theme) { if (theme.linkColor) { changeCss('.app__body a, .app__body a:focus, .app__body a:hover, .app__body .btn, .app__body .btn:focus, .app__body .btn:hover', 'color:' + theme.linkColor, 1); changeCss('.app__body .attachment .attachment__container', 'border-left-color:' + changeOpacity(theme.linkColor, 0.5), 1); - changeCss('.app__body .post .comment-icon__container, .app__body .post .post__reply', 'fill:' + theme.linkColor, 1); + changeCss('.app__body .channel-header__links .icon:hover, .app__body .post .flag-icon__container.visible, .app__body .post .comment-icon__container, .app__body .post .post__reply', 'fill:' + theme.linkColor, 1); + changeCss('.app__body .channel-header__links .icon:hover', 'stroke:' + theme.linkColor, 1); } if (theme.buttonBg) {