Changeset 249213 in webkit
- Timestamp:
- Aug 28, 2019, 12:36:23 PM (7 years ago)
- Location:
- trunk/Tools
- Files:
-
- 1 deleted
- 10 edited
-
ChangeLog (modified) (1 diff)
-
resultsdbpy/resultsdbpy/view/commit_view_unittest.py (modified) (4 diffs)
-
resultsdbpy/resultsdbpy/view/static/css/drawer.css (deleted)
-
resultsdbpy/resultsdbpy/view/static/js/drawer.js (modified) (3 diffs)
-
resultsdbpy/resultsdbpy/view/static/library/css/webkit.css (modified) (12 diffs)
-
resultsdbpy/resultsdbpy/view/templates/base.html (modified) (1 diff)
-
resultsdbpy/resultsdbpy/view/templates/commits.html (modified) (3 diffs)
-
resultsdbpy/resultsdbpy/view/templates/documentation.html (modified) (2 diffs)
-
resultsdbpy/resultsdbpy/view/templates/search.html (modified) (3 diffs)
-
resultsdbpy/resultsdbpy/view/templates/suite_results.html (modified) (3 diffs)
-
resultsdbpy/resultsdbpy/view/view_routes_unittest.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Tools/ChangeLog
r249208 r249213 1 2019-08-28 Jonathan Bedard <jbedard@apple.com> 2 3 results.webkit.org: Move drawer to the right, open by default 4 https://bugs.webkit.org/show_bug.cgi?id=200977 5 6 Rubber-stamped by Aakash Jain. 7 8 The drawer was both unpopular and not discoverable. After feedback from bot watchers, 9 moving the drawer to the right side of the screen, opening it by default and have it displace 10 instead of hide the main content. 11 12 * resultsdbpy/resultsdbpy/view/commit_view_unittest.py: 13 (CommitViewUnittest.test_drawer): Support new drawer style. 14 (CommitViewUnittest.test_range_slider): Ditto. 15 (CommitViewUnittest.test_one_line_switch): Ditto. 16 (CommitViewUnittest.test_branch_selection): Ditto. 17 * resultsdbpy/resultsdbpy/view/static/css/drawer.css: Removed. 18 * resultsdbpy/resultsdbpy/view/static/js/drawer.js: 19 (setEnableRecursive): Disable all elements underneath this one 20 (Drawer): Make drawer a sidebar. 21 * resultsdbpy/resultsdbpy/view/static/library/css/webkit.css: 22 (.header>.title, .topbar>.title): Overflow of titles should be hidden. 23 (:root): Move boldInverseColor into webkit.css. 24 (@media (prefers-color-scheme: dark)): 25 (.sidebar): Sidebars on mobile should behave like drawers. 26 (.sidebar.hidden): Add concept of hidden sidebar. 27 (.mobile-sidebar-control): Add a control to collapse sidebar that only exists on mobile. 28 (.mobile-sidebar-control.display): 29 (.main.under-topbar-with-actions): 30 (@media screen and (min-width: 600px) and (orientation: landscape)): 31 (.sidebar.left.hidden): 32 (.sidebar.right.hidden): 33 (.main.right.hidden): 34 (.main.left.hidden): 35 (@media screen and (min-width: 768px) and (orientation: landscape)): 36 (.sidebar.right): 37 (a.disabled): Add ability to disable a link. 38 (.desktop-control): Add a control which only exists on desktop. 39 * resultsdbpy/resultsdbpy/view/templates/base.html: Add hamburger drawer-button for mobile. 40 * resultsdbpy/resultsdbpy/view/templates/commits.html: Use main since Drawer is now a sidebar. 41 * resultsdbpy/resultsdbpy/view/templates/documentation.html: Ditto. 42 * resultsdbpy/resultsdbpy/view/templates/search.html: Ditto. 43 * resultsdbpy/resultsdbpy/view/templates/suite_results.html: Ditto. 44 * resultsdbpy/resultsdbpy/view/view_routes_unittest.py: 45 (WebSiteTestCase.toggle_drawer): Support new drawer style. 46 (WebSiteTestCase.find_input_with_name): Ditto. 47 1 48 2019-08-28 Keith Rollin <krollin@apple.com> 2 49 -
trunk/Tools/resultsdbpy/resultsdbpy/view/commit_view_unittest.py
r247628 r249213 65 65 driver.get(self.URL + '/commits') 66 66 time.sleep(.2) 67 self.assertNotIn('display', driver.find_element_by_class_name('drawer').get_attribute('class')) 68 67 self.assertNotIn('hidden', driver.find_element_by_class_name('sidebar').get_attribute('class')) 68 69 self.toggle_drawer(driver, assert_displayed=False) 69 70 self.toggle_drawer(driver, assert_displayed=True) 70 self.toggle_drawer(driver, assert_displayed=False)71 71 72 72 @WaitForDockerTestCase.mock_if_no_docker(mock_redis=FakeStrictRedis, mock_cassandra=MockCassandraContext) … … 159 159 self.assertEqual(5, len(commits['webkit'])) 160 160 161 self.toggle_drawer(driver, assert_displayed=True)162 163 161 controls = self.find_input_with_name(driver, 'Limit:').find_elements_by_tag_name('input') 164 162 self.assertEqual(3, len(controls)) … … 199 197 changelog = commits['safari'][0].find_element_by_tag_name('div') 200 198 self.assertEqual(line_1, changelog.text) 201 202 self.toggle_drawer(driver, assert_displayed=True)203 199 204 200 controls = self.find_input_with_name(driver, 'One-line:').find_elements_by_tag_name('span') … … 236 232 self.assertEqual(5, len(commits['webkit'])) 237 233 238 self.toggle_drawer(driver, assert_displayed=True)239 240 234 controls = self.find_input_with_name(driver, 'Branch').find_elements_by_tag_name('select') 241 235 self.assertEqual(1, len(controls)) -
trunk/Tools/resultsdbpy/resultsdbpy/view/static/js/drawer.js
r248995 r249213 26 26 import {Configuration} from '/assets/js/configuration.js' 27 27 28 function setEnableRecursive(element, state) { 29 element.disabled = !state; 30 if (!state) 31 element.classList.add("disabled"); 32 else 33 element.classList.remove("disabled"); 34 35 for (let node of element.children) 36 setEnableRecursive(node, state); 37 } 38 28 39 function Drawer(controls = []) { 29 const COLLAPSED = false; 30 const EXTENDED = true; 31 var drawerState = COLLAPSED; 40 const HIDDEN = false; 41 const VISIBLE = true; 42 let drawerState = VISIBLE; 43 let main = null; 44 45 const sidebarControl = document.getElementsByClassName('mobile-sidebar-control')[0]; 46 sidebarControl.classList.add('display'); 32 47 33 48 const drawerRef = REF.createRef({ 34 49 state: drawerState, 35 50 onStateUpdate: (element, state) => { 36 if (state) 37 element.classList.add("display"); 38 else 39 element.classList.remove("display"); 51 if (state) { 52 element.classList.remove("hidden"); 53 if (main) 54 main.classList.remove("hidden"); 55 } else { 56 element.classList.add("hidden"); 57 if (main) 58 main.classList.add("hidden"); 59 } 60 61 for (let node of element.children) { 62 if (node.classList.contains("list")) 63 setEnableRecursive(node, state); 64 } 65 }, 66 onElementMount: (element) => { 67 let candidates = document.getElementsByClassName("main"); 68 if (candidates.length) 69 main = candidates[0]; 70 71 sidebarControl.onclick = () => { 72 if (element.style.display) 73 element.style.display = null; 74 else 75 element.style.display = 'block'; 76 } 40 77 } 41 78 }); 79 42 80 const drawerControllerRef = REF.createRef({ 43 81 state: drawerState, 44 82 onStateUpdate: (element, state) => { 45 83 if (state) { 46 element.classList.remove("collapsed"); 47 element.classList.add("extended"); 48 } else { 49 element.classList.remove("extended"); 50 element.classList.add("collapsed"); 84 element.innerHTML = 'Collapse >'; 85 element.style.textAlign = 'center'; 86 } 87 else{ 88 element.innerHTML = '<'; 89 element.style.textAlign = 'left'; 51 90 } 52 91 }, … … 60 99 }); 61 100 62 return `<div class="drawer left under-topbar-with-actions unselectable" ref="${drawerRef}"> 101 return `<div class="sidebar right under-topbar-with-actions unselectable" ref="${drawerRef}"> 102 <button class="button desktop-control" ref="${drawerControllerRef}" style="width:96%; margin: 10px 2% 10px 2%;"></button> 63 103 ${controls.map(control => { 64 104 return `<div class="list"> … … 66 106 </div>`; 67 107 }).join('')} 68 </div> 69 <button class="drawer-control collapsed" ref="${drawerControllerRef}"><div></div></button>`; 108 </div>`; 70 109 } 71 110 -
trunk/Tools/resultsdbpy/resultsdbpy/view/static/library/css/webkit.css
r249161 r249213 92 92 --formLabelPadding: 14px; 93 93 --topZIndex: 100; 94 --boldInverseColor: var(--black); 94 95 } 95 96 … … 123 124 --borderColorSection: var(--blackDark); 124 125 --borderColorHard: var(--blackDarker); 126 --boldInverseColor: var(--white); 125 127 } 126 128 } … … 227 229 font-weight: 400; 228 230 flex: auto; 231 overflow: hidden; 229 232 } 230 233 … … 916 919 border-right: 1px solid var(--borderColorSection); 917 920 overflow-y: auto; 921 min-width: 250px; 922 background-color: var(--blurBackgroundColor); 923 -webkit-backdrop-filter: blur(5px) brightness(88%); 924 backdrop-filter: blur(5px) brightness(88%); 925 z-index: var(--topZIndex); 926 right: 0; 927 } 928 .sidebar.hidden { 929 display: none; 918 930 } 919 931 … … 929 941 } 930 942 943 .mobile-sidebar-control { 944 display: none; 945 float: right; 946 } 947 .mobile-sidebar-control.display { 948 display: block; 949 } 950 931 951 @media (prefers-color-scheme: dark) { 932 952 .sidebar { … … 954 974 } 955 975 976 .main.under-topbar-with-actions { 977 margin-top: calc(12px * 2 + var(--largeSize) * 1.3 + var(--smallSize) * 1.3 + 12px * 2); 978 } 979 956 980 @media screen and (min-width: 600px) and (orientation: landscape) { 957 981 .sidebar { 982 display: block; 958 983 width: 299px; 984 z-index: 0; 985 left: 0; 986 right: unset; 987 } 988 .sidebar.left.hidden { 959 989 display: block; 990 left: -249px; 991 } 992 .sidebar.right.hidden { 993 display: block; 994 right: -249px; 960 995 } 961 996 .sidebar.under-topbar-with-actions { … … 964 999 } 965 1000 1001 .mobile-sidebar-control.display { 1002 display: none; 1003 } 1004 966 1005 .main { 967 1006 margin-left: 299px; … … 973 1012 margin-right: 299px; 974 1013 } 1014 .main.right.hidden { 1015 margin-left: 50px; 1016 width: calc(100% - 50px); 1017 } 1018 .main.left.hidden { 1019 margin-left: 0; 1020 margin-right: 50px; 1021 width: calc(100% - 50px); 1022 } 975 1023 976 1024 .main.under-topbar-with-actions { … … 981 1029 @media screen and (min-width: 768px) and (orientation: landscape) { 982 1030 .sidebar { 1031 display: block; 983 1032 width: 310px; 1033 z-index: 0; 1034 left: 0; 1035 right: unset; 1036 } 1037 .sidebar.left.hidden { 984 1038 display: block; 1039 left: -260px; 1040 } 1041 .sidebar.right.hidden { 1042 display: block; 1043 right: -260px; 985 1044 } 986 1045 .sidebar.under-topbar-with-actions { … … 1005 1064 1006 1065 .sidebar.right { 1007 border-right: 0px; 1008 border-left: 1px; 1066 left: unset; 1009 1067 right: 0; 1010 1068 } … … 1752 1810 color: var(--grey); 1753 1811 } 1812 } 1813 1814 a.disabled { 1815 color: var(--grey); 1816 pointer-events: none; 1754 1817 } 1755 1818 … … 2595 2658 user-select: none; 2596 2659 } 2660 2661 .desktop-control { 2662 display: none; 2663 } 2664 2665 @media screen and (min-width: 600px) and (orientation: landscape) { 2666 .desktop-control { 2667 display: block; 2668 } 2669 } -
trunk/Tools/resultsdbpy/resultsdbpy/view/templates/base.html
r249124 r249213 36 36 <div class="header fixed"> 37 37 <div class="title"> 38 <div class="text large block">{{site_title}}</div> 38 <div class="text large block" style="width: calc(100% - 44px); overflow: hidden; white-space: nowrap; text-overflow: ellipsis;"> 39 {{site_title}} 40 </div> 41 <button style="width: 44px" class="button mobile-sidebar-control">☰</button> 39 42 </div> 40 43 <div class="actions"> -
trunk/Tools/resultsdbpy/resultsdbpy/view/templates/commits.html
r247664 r249213 27 27 {% block head %} 28 28 <link rel="stylesheet" type="text/css" href="assets/css/commit.css"> 29 <link rel="stylesheet" type="text/css" href="assets/css/drawer.css">30 29 31 30 <script type="module"> … … 105 104 OneLineSwitch(), 106 105 BranchSelector(() => {table.reload()}), 107 ])} ${table}`); 106 ])} 107 <div class="main left under-topbar-with-actions"> 108 <div class="content">${table}</div> 109 </div>`); 108 110 109 111 </script> … … 112 114 {% block content %} 113 115 114 <div class="content"id="app">116 <div id="app"> 115 117 </div> 116 118 -
trunk/Tools/resultsdbpy/resultsdbpy/view/templates/documentation.html
r247664 r249213 25 25 {% extends "base.html" %} 26 26 {% block head %} 27 <link rel="stylesheet" type="text/css" href="assets/css/drawer.css">28 27 29 28 <script type="module"> 30 29 31 import {DOM } from '/library/js/Ref.js';30 import {DOM, REF} from '/library/js/Ref.js'; 32 31 import {Expectations} from '/assets/js/timeline.js'; 33 32 … … 496 495 } 497 496 497 const sidebarControl = document.getElementsByClassName('mobile-sidebar-control')[0]; 498 sidebarControl.classList.add('display'); 499 500 const sidebarRef = REF.createRef({ 501 onElementMount: (element) => { 502 sidebarControl.onclick = () => { 503 if (element.style.display) 504 element.style.display = null; 505 else 506 element.style.display = 'block'; 507 } 508 } 509 }); 510 498 511 DOM.inject( 499 512 document.getElementById('app'), 500 `<div class="sidebar under-topbar-with-actions" >513 `<div class="sidebar under-topbar-with-actions" ref="${sidebarRef}"> 501 514 <div class="list"> 502 515 ${Object.keys(documentation).map((primary) => { -
trunk/Tools/resultsdbpy/resultsdbpy/view/templates/search.html
r248910 r249213 26 26 {% extends "base.html" %} 27 27 {% block head %} 28 <link rel="stylesheet" type="text/css" href="assets/css/drawer.css">29 28 <link rel="stylesheet" type="text/css" href="assets/css/search.css"> 30 29 <link rel="stylesheet" type="text/css" href="assets/css/timeline.css"> … … 228 227 ])} 229 228 230 ${SearchBar(function () { 231 const splitURL = document.URL.split('?'); 232 let params = queryToParams(splitURL[1]); 233 if (!params.suite) 234 params.suite = []; 235 if (!params.test) 236 params.test = []; 237 238 for (let i = 0; i < arguments.length; i++) { 239 let needToAdd = true; 240 if (!needToAdd) 241 continue; 242 243 let child = { 244 suite: arguments[i].suite, 245 test: arguments[i].test, 246 timeline: new TimelineFromEndpoint(`api/results/${arguments[i].suite}/${arguments[i].test}`), 247 } 248 249 view.ref.setState({prepending: [child]}); 250 params.suite.push(child.suite); 251 params.test.push(child.test); 252 } 253 const queryString = paramsToQuery(params); 254 window.history.pushState(queryString, '', splitURL[0] + '?' + queryString); 255 }, SUITES)} 256 ${view}` 229 <div class="main left under-topbar-with-actions"> 230 <div class="content"> 231 ${SearchBar(function () { 232 const splitURL = document.URL.split('?'); 233 let params = queryToParams(splitURL[1]); 234 if (!params.suite) 235 params.suite = []; 236 if (!params.test) 237 params.test = []; 238 239 for (let i = 0; i < arguments.length; i++) { 240 let needToAdd = true; 241 if (!needToAdd) 242 continue; 243 244 let child = { 245 suite: arguments[i].suite, 246 test: arguments[i].test, 247 timeline: new TimelineFromEndpoint(`api/results/${arguments[i].suite}/${arguments[i].test}`), 248 } 249 250 view.ref.setState({prepending: [child]}); 251 params.suite.push(child.suite); 252 params.test.push(child.test); 253 } 254 const queryString = paramsToQuery(params); 255 window.history.pushState(queryString, '', splitURL[0] + '?' + queryString); 256 }, SUITES)} 257 ${view} 258 </div> 259 </div>` 257 260 ); 258 261 … … 262 265 {% block content %} 263 266 264 <div class="content"id="app">267 <div id="app"> 265 268 </div> 266 269 -
trunk/Tools/resultsdbpy/resultsdbpy/view/templates/suite_results.html
r248910 r249213 26 26 {% extends "base.html" %} 27 27 {% block head %} 28 <link rel="stylesheet" type="text/css" href="assets/css/drawer.css">29 28 <link rel="stylesheet" type="text/css" href="assets/css/search.css"> 30 29 <link rel="stylesheet" type="text/css" href="assets/css/timeline.css"> … … 171 170 ConfigurationSelectors(() => {view.reload()}), 172 171 ])} 173 ${view} 174 `); 172 <div class="main left under-topbar-with-actions"> 173 <div class="content"> 174 ${view} 175 </div> 176 </div>`); 175 177 176 178 </script> … … 179 181 {% block content %} 180 182 181 <div class="content"id="app">183 <div id="app"> 182 184 </div> 183 185 -
trunk/Tools/resultsdbpy/resultsdbpy/view/view_routes_unittest.py
r247869 r249213 42 42 43 43 def toggle_drawer(self, driver, assert_displayed=None): 44 driver.find_element_by_class_name('drawer-control').click() 44 sidebar = driver.find_element_by_class_name('sidebar') 45 sidebar.find_elements_by_tag_name('button')[0].click() 45 46 time.sleep(.5) 46 47 if assert_displayed: 47 self.assert In('display', driver.find_element_by_class_name('drawer').get_attribute('class'))48 self.assertNotIn('hidden', sidebar.get_attribute('class')) 48 49 elif assert_displayed is False: 49 self.assert NotIn('display', driver.find_element_by_class_name('drawer').get_attribute('class'))50 self.assertIn('hidden', sidebar.get_attribute('class')) 50 51 51 52 def find_input_with_name(self, driver, name): 52 control = [label.parent for label in driver.find_element_by_class_name(' drawer').find_elements_by_tag_name('div') if label.find_element_by_tag_name('label').text == name][0]53 control = [label.parent for label in driver.find_element_by_class_name('sidebar').find_elements_by_tag_name('div') if label.find_element_by_tag_name('label').text == name][0] 53 54 self.assertIsNotNone(control) 54 55 return control … … 103 104 self.assertEqual(driver.title, 'Results Database') 104 105 title = driver.find_element_by_class_name('title').find_element_by_tag_name('div') 105 self.assertEqual(title.text , 'Results Database')106 self.assertEqual(title.text.lstrip().rstrip(), 'Results Database') 106 107 107 108 @WaitForDockerTestCase.mock_if_no_docker(mock_redis=FakeStrictRedis, mock_cassandra=MockCassandraContext)
Note:
See TracChangeset
for help on using the changeset viewer.